From a80c03a27d76de8c5891b527aaf86d672b6d7afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=AE=D1=80=D0=B8=D0=B9=20=D0=A7=D0=B5=D1=80=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE?= Date: Wed, 5 Nov 2025 18:29:49 +0300 Subject: [PATCH] first commit --- RPL/main.py | 163 +++++++++ data_sender.py | 11 + divs/jsonserver.py | 405 +++++++++++++++++++++++ divs/tcp_monitor.py | 34 ++ old/timer_MBA.py | 123 +++++++ old/timer_MBA_2.py | 143 ++++++++ old/timer_Megasport_test.py | 141 ++++++++ old/timer_megasport.py | 82 +++++ old/timer_megasport2.py | 70 ++++ old/timer_megasport3.py | 58 ++++ old/timer_megasport5.py | 261 +++++++++++++++ old/timer_megasport_rider.py | 25 ++ timer COM copy.py | 363 ++++++++++++++++++++ timer COM.py | 345 +++++++++++++++++++ timer COM3.py | 486 +++++++++++++++++++++++++++ timer GPT 1.py | 117 +++++++ timer NATA Kazan.py | 189 +++++++++++ timer_KAZ.py | 162 +++++++++ timer_MBA.py | 208 ++++++++++++ timer_NN.py | 171 ++++++++++ timer_NN_backup.py | 159 +++++++++ timer_NPORT_Deepron.py | 153 +++++++++ timer_NPORT_коньки.py | 128 ++++++++ timer_app.py | 92 ++++++ timer_app2.py | 326 ++++++++++++++++++ timer_app2_temp.py | 369 +++++++++++++++++++++ timer_app3.py | 415 +++++++++++++++++++++++ timer_app4.py | 620 +++++++++++++++++++++++++++++++++++ timer_china_tcp.py | 155 +++++++++ timer_chine.py | 119 +++++++ timer_chine_tcp.py | 165 ++++++++++ timer_exe.py | 169 ++++++++++ timer_hockey_balashikha.py | 107 ++++++ timer_jet.py | 203 ++++++++++++ timer_nata_test (2).py | 189 +++++++++++ timer_playground copy.py | 78 +++++ timer_playground.py | 87 +++++ timer_saratov.py | 141 ++++++++ timer_saratovCW.py | 160 +++++++++ timer_stramatel copy.py | 161 +++++++++ timer_stramatel.py | 160 +++++++++ 41 files changed, 7713 insertions(+) create mode 100644 RPL/main.py create mode 100644 data_sender.py create mode 100644 divs/jsonserver.py create mode 100644 divs/tcp_monitor.py create mode 100644 old/timer_MBA.py create mode 100644 old/timer_MBA_2.py create mode 100644 old/timer_Megasport_test.py create mode 100644 old/timer_megasport.py create mode 100644 old/timer_megasport2.py create mode 100644 old/timer_megasport3.py create mode 100644 old/timer_megasport5.py create mode 100644 old/timer_megasport_rider.py create mode 100644 timer COM copy.py create mode 100644 timer COM.py create mode 100644 timer COM3.py create mode 100644 timer GPT 1.py create mode 100644 timer NATA Kazan.py create mode 100644 timer_KAZ.py create mode 100644 timer_MBA.py create mode 100644 timer_NN.py create mode 100644 timer_NN_backup.py create mode 100644 timer_NPORT_Deepron.py create mode 100644 timer_NPORT_коньки.py create mode 100644 timer_app.py create mode 100644 timer_app2.py create mode 100644 timer_app2_temp.py create mode 100644 timer_app3.py create mode 100644 timer_app4.py create mode 100644 timer_china_tcp.py create mode 100644 timer_chine.py create mode 100644 timer_chine_tcp.py create mode 100644 timer_exe.py create mode 100644 timer_hockey_balashikha.py create mode 100644 timer_jet.py create mode 100644 timer_nata_test (2).py create mode 100644 timer_playground copy.py create mode 100644 timer_playground.py create mode 100644 timer_saratov.py create mode 100644 timer_saratovCW.py create mode 100644 timer_stramatel copy.py create mode 100644 timer_stramatel.py diff --git a/RPL/main.py b/RPL/main.py new file mode 100644 index 0000000..953727a --- /dev/null +++ b/RPL/main.py @@ -0,0 +1,163 @@ +import socket +import requests + + +def send_data(value): + url = "http://127.0.0.1:8088/API/" + par = "SetText" + if 'проверка' in value: + input = 34 + else: + input = 35 + if "-" in value: + params = { + "Function": par, + "Input": input, + "SelectedName": "СТрока1.Text", + "Value": value.split("-")[0].strip(), + } + requests.get(url, params=params) + params = { + "Function": par, + "Input": input, + "SelectedName": "Строка2.Text", + "Value": value.split("-")[1].strip(), + } + requests.get(url, params=params) + + +VOR = "VOR3" + +list_code = { + "101": "Приветствие", + "102": "Инфо", + "103": "Игра проходит без системы определения офсайдных линий", + "104": "Игра проходит без системы VAR", + "105": "Проверка", + "106": "проверка - Офсайд", + "107": "проверка - Возможно, офсайд", + "108": "проверка - Игра рукой", + "109": "проверка - Фол в атаке", + "110": "проверка - Симуляция", + "111": "Игра проходит с системой VAR", + "112": "Игра проходит с ограниченными техническими возможностями", + "113": "Объявление решения", + "114": "Неисправность системы объявления решений судьи", + "115": "Не используется система объявления решений судьи", + "116": "Решение подтверждено - офсайд", + "117": "Нет офсайда", + "118": "Возможно игра рукой в атаке", + "119": "проверка - Игра рукой в атаке", + "201": "проверка - Гол", + "202": "Решение подтверждено - гол", + "203": "Решение подтверждено - гол, нет офсайда", + "204": "Решение подтверждено - гол, нет фола", + "205": "Решение подтверждено - гол, нет игры рукой", + "206": "Решение подтверждено - гол, мяч в игре", + "207": "Решение подтверждено - гол, симуляция", + "208": "Решение подтверждено - гол, мяч пересек линию ворот", + "209": "Решение изменено - нет гола, офсайд", + "210": "Решение изменено - нет гола, фол", + "211": "Решение изменено - нет гола, игра рукой", + "212": "Решение изменено - нет гола, мяч не в игре", + "213": "Решение изменено - нет гола, мяч не пересек линию ворот", + "301": "проверка - Возможно, гол", + "302": "Решение подтверждено - нет гола", + "303": "Решение подтверждено - нет гола, офсайд", + "304": "Решение подтверждено - нет гола, фол", + "305": "Решение подтверждено - нет гола, игра рукой", + "306": "Решение подтверждено - нет гола, мяч не в игре", + "307": "Решение подтверждено - нет гола, мяч не пересек линию ворот", + "308": "Решение изменено - гол", + "309": "Решение изменено - гол, нет офсайда", + "310": "Решение изменено - гол, нет фола", + "311": "Решение изменено - гол, нет игры рукой", + "312": "Решение изменено - гол, мяч в игре", + "313": "Решение изменено - гол, симуляция", + "314": "Решение изменено - гол, мяч пересек линию ворот", + "401": "проверка - Пенальти", + "402": "Решение подтверждено - пенальти", + "403": "Решение подтверждено - пенальти, фол", + "404": "Решение подтверждено - пенальти, игра рукой", + "405": "Решение подтверждено - пенальти, фол в штрафной", + "406": "Решение подтверждено - пенальти, игра рукой в штрафной", + "407": "Решение изменено - нет пенальти, нет фола", + "408": "Решение изменено - нет пенальти, нет игры рукой", + "409": "Решение изменено - нет пенальти, фол за штрафной", + "410": "Решение изменено - нет пенальти, офсайд", + "411": "Решение изменено - нет пенальти, фол в атаке", + "412": "Решение изменено - нет пенальти, игра рукой в атаке", + "413": "Решение изменено - нет пенальти, мяч не в игре", + "414": "Решение изменено - нет пенальти, симуляция", + "501": "проверка - Возможно, пенальти", + "502": "Решение подтверждено - нет пенальти", + "503": "Решение подтверждено - нет пенальти, нет фола", + "504": "Решение подтверждено - нет пенальти, нет игры рукой", + "505": "Решение подтверждено - нет пенальти, фол за штрафной", + "506": "Решение подтверждено - нет пенальти, офсайд", + "507": "Решение подтверждено - нет пенальти, фол в атаке", + "508": "Решение подтверждено - нет пенальти, игра рукой в атаке", + "509": "Решение подтверждено - нет пенальти, мяч не в игре", + "510": "Решение подтверждено - нет пенальти, симуляция", + "511": "Решение изменено - пенальти", + "512": "Решение изменено - пенальти, фол", + "513": "Решение изменено - пенальти, игра рукой", + "514": "Решение изменено - пенальти, фол в штрафной", + "515": "Решение изменено - пенальти, игра рукой в штрафной", + "516": "Решение изменено – пенальти, нет симуляции", + "601": "проверка - Красная карточка", + "602": "Решение подтверждено - красная карточка", + "603": "Решение изменено - жёлтая карточка", + "604": "Решение изменено - нет карточки", + "701": "проверка - Возможно, красная карточка", + "702": "Решение подтверждено - нет красной карточки", + "703": "Решение изменено - красная карточка", + "704": "Решение изменено - жёлтая карточка", + "801": "проверка - Идентификация игрока", + "802": "Ошибочная идентификация игрока", +} + + +HOST = '127.0.0.1' # Принимаем соединения со всех интерфейсов +PORT = 60000 # Порт, который будем слушать + + +def start_tcp_server(): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket: + server_socket.bind((HOST, PORT)) + server_socket.listen(5) + print(f"Сервер запущен на {HOST}:{PORT}") + + while True: + client_socket, addr = server_socket.accept() + with client_socket: + print(f"Клиент подключился: {addr}") + while True: + data = client_socket.recv(1024) + if not data: + break + + try: + decoded = data.decode('utf-8') + print(f"Получено: {decoded}") + send_data(list_code[decoded.split("/")[2]]) + + # parts = decoded.split(", ") + # if len(parts) != 2: + # print("Неверный формат сообщения") + # continue + + # sender, code = parts + # if sender == VOR and code in list_code: + # send_data(list_code[code]) + # else: + # print("Неверный код или отправитель") + + except Exception as e: + print(f"Ошибка обработки данных: {e}") + + print(f"Отключение клиента: {addr}") + + +if __name__ == "__main__": + start_tcp_server() diff --git a/data_sender.py b/data_sender.py new file mode 100644 index 0000000..9e00fe9 --- /dev/null +++ b/data_sender.py @@ -0,0 +1,11 @@ +import requests + + +def send_data_to_ips(data, ip_list): + for ip in ip_list: + try: + url = f"{ip}/API/" + response = requests.post(url, json=data) + print(f"Data sent to {ip}: {response.status_code}") + except Exception as e: + print(f"Error sending data to {ip}: {e}") diff --git a/divs/jsonserver.py b/divs/jsonserver.py new file mode 100644 index 0000000..4492b47 --- /dev/null +++ b/divs/jsonserver.py @@ -0,0 +1,405 @@ +import json +from http.server import BaseHTTPRequestHandler, HTTPServer +import threading +import requests +import io +import asyncore + +jsonserver_hostname = "localhost" +jsonserver_port = 8800 + +#refserver_hostname = "192.168.68.150" +#refserver_port = 26700 +refserver_hostname = "192.168.190.78" +refserver_port = 4001 + +vMixAPI_address = 'http://localhost:8088/API/' +vMixAPI_TimerInputID = 'TIMER' +vMixAPI_TimerTextField = 'Clock .Text' +vMixAPI_Timer24InputID = 'TIMER' +vMixAPI_Timer24TextField = 'Title Text.Text' +vMixAPI_ColorPlace = '#C7A2E399' +vMixAPI_ColorNone = "#00000000" + +game_filename = 'game.json' +homeplayers_filename = 'homeplayers.json' +guestplayers_filename = 'guestplayers.json' + +Game = { + 'type': '', + 'home_name': '', + 'guest_name': '' +} + +GameHandFutsal = { + 'timer': '', + 'home_fouls': '', + 'guest_fouls': '', + 'home_points': '', + 'guest_points': '', + 'period': '', + 'home_penalties': '', + 'guest_penalties': '', + 'home_timeouts': '', + 'guest_timeouts': '', + 'horn': '', + 'timer_status': '', + 'home_penalty1_player': '', + 'home_penalty2_player': '', + 'home_penalty3_player': '', + 'home_penalty1_timer': '', + 'home_penalty2_timer': '', + 'home_penalty3_timer': '', + 'guest_penalty1_player': '', + 'guest_penalty2_player': '', + 'guest_penalty3_player': '', + 'guest_penalty1_timer': '', + 'guest_penalty2_timer': '', + 'guest_penalty3_timer': '' +} + +GameBasketball = { + 'ball_pos':'', + 'timer':'', + 'home_points':'', + 'guest_points':'', + 'period':'', + 'home_fouls':'', + 'guest_fouls':'', + 'home_timeouts':'', + 'guest_timeouts':'', + 'horn':'', + 'timer_status':'', + 'timeout_timer':'', + 'timer24':'', + 'horn24':'', + 'timer24_status':'', + 'timer24_display':'', +} + +HomePlayers = [{ + 'number': '', + 'name': '', + 'points': '', + 'fouls': '' +} for i in range(0, 16)] + +GuestPlayers = [{ + 'number': '', + 'name': '', + 'points': '', + 'fouls': '' +} for i in range(0, 16)] + + +def TimerSet(time): + #requests.get('{api_address}?Function=SetText&Input={input}&SelectedName={field}&Value={value}'.format(api_address=vMixAPI_address, input=vMixAPI_TimerInputID, field=vMixAPI_TimerTextField, value=time)) + pass + +def Timer24Set(time): + #requests.get('{api_address}?Function=SetText&Input={input}&SelectedName={field}&Value={value}'.format(api_address=vMixAPI_address, input=vMixAPI_TimerInputID, field=vMixAPI_TimerTextField, value=time)) + pass + + +def dc(v): + if isinstance(v, int): + return bytes([v]).decode() + else: + return bytes(v).decode() + + +def pn_ball_pos(v): + return 'home' if v == 0x31 else ('guset' if v == 0x32 else '') + +def pn_timer(v): + return dc(v[0:2]) + ':' + dc(v[2:4]) + +def pn_points(v): + return dc(v.strip()) + +def pn_period(v): + return dc(v) if v != 0x30 else 'O' + +def pn_teamfouls(v): + return dc(v) if v != 0x52 else 'red' + +def pn_timeouts(v): + return dc(v) + +def pn_horn(v): + return 1 if v == 0x31 else 0 + +def pn_startstop(v): + return 1 if v == 0x30 else 0 + +def pn_timertimeout(v): + return dc(v[0]) + ':' + dc(v[1:3]) + +def pn_timer24(v): + return dc(v) if 0x30 <= v[1] and v[1] <= 0x39 else dc(v[0]) + '.' + dc(v[1] - 0x10) + +def pn_display24(v): + return 1 if v != 0x30 else 0 + +def pn_playernumber(v): + return dc(v) + +def pn_playerfouls(v): + return dc(v) + +def pn_penalties(v): + return dc(v) + +def pn_name(v): + return v.decode('utf-16') + +def parce(pkg): + global GameHandFutsal, GameBasketball, HomePlayers, GuestPlayers + + if len(pkg) < 54: + print('Error: pkg too short') + return + if pkg[0] != 0xf8 or pkg[53] != 0x0d: + print('Error: Frame uncorrect') + return + + sport_code = pkg[1] + + if sport_code == 0x33 or sport_code == 0x37 or sport_code == 0x38: + GameBasketball.update({ + 'timer': pn_timer(pkg[4:8]), + 'horn': pn_horn(pkg[19]), + 'timer_status': pn_startstop(pkg[20]), + 'timer24': pn_timer24(pkg[48:50]), + 'horn24': pn_horn(pkg[50]), + 'timer24_status': pn_startstop(pkg[51]), + 'timer24_display': pn_display24(pkg[52]) + }) + + if GameBasketball['timer24_display'] == 0: + GameBasketball['timer24'] = ' ' + + if sport_code == 0x33: # BASKETBALL with individual fouls + Game['type'] = 'Basketball' + + GameBasketball.update({ + 'ball_pos': pn_ball_pos(pkg[3]), + 'home_points': pn_points(pkg[8:11]), + 'guest_points': pn_points(pkg[11:14]), + 'period': pn_period(pkg[14]), + 'home_fouls': pn_teamfouls(pkg[15]), + 'guest_fouls': pn_teamfouls(pkg[16]), + 'home_timeouts': pn_timeouts(pkg[17]), + 'guest_timeouts': pn_timeouts(pkg[18]), + 'timeout_timer': pn_timertimeout(bytes([pkg[21]]) + pkg[46:48]), + }) + + for i in range(0, 12): + HomePlayers[i]['fouls'] = pn_playerfouls(pkg[22 + i]) + for i in range(0, 12): + GuestPlayers[i]['fouls'] = pn_playerfouls(pkg[34 + i]) + + TimerSet(GameBasketball['timer']) + Timer24Set(GameBasketball['timer24']) + + + elif sport_code == 0x35: # HANDBALL/FUTSAL + Game['type'] = 'HandFutsal' + + GameHandFutsal.update({ + 'timer': pn_timer(pkg[4:8]), + 'home_fouls': pn_teamfouls(pkg[8]), + 'home_points': pn_points(pkg[9:11]), + 'guest_fouls': pn_teamfouls(pkg[11]), + 'guest_points': pn_points(pkg[12:14]), + 'period': pn_period(pkg[14]), + 'home_penalties': pn_penalties(pkg[15]), + 'guest_penalties': pn_penalties(pkg[16]), + 'home_timeouts': pn_timeouts(pkg[17]), + 'guest_timeouts': pn_timeouts(pkg[18]), + 'horn': pn_horn(pkg[19]), + 'timer_status': pn_startstop(pkg[20]), + 'home_penalty1_player': pn_playernumber(pkg[22:24]), + 'home_penalty2_player': pn_playernumber(pkg[27:29]), + 'home_penalty3_player': pn_playernumber(pkg[32:34]), + 'home_penalty1_timer': pn_playerfouls(pkg[24:27]), + 'home_penalty2_timer': pn_playerfouls(pkg[29:32]), + 'home_penalty3_timer': pn_playerfouls(pkg[34:37]), + 'guest_penalty1_player': pn_playernumber(pkg[37:39]), + 'guest_penalty2_player': pn_playernumber(pkg[42:44]), + 'guest_penalty3_player': pn_playernumber(pkg[47:49]), + 'guest_penalty1_timer': pn_playerfouls(pkg[39:42]), + 'guest_penalty2_timer': pn_playerfouls(pkg[44:47]), + 'guest_penalty3_timer': pn_playerfouls(pkg[49:52]) + }) + + elif sport_code == 0x36: # VOLLEYBALL + pass + + elif sport_code == 0x37: # Individual points - GUEST BASKET/HAND/HOCKEY/FUTSAL + for i in range(0, 13): + GuestPlayers[i]['points'] = pn_points(pkg[22 + 2*i : 24 + 2*i]) + for i in range(13, 16): + GuestPlayers[i]['points'] = pn_points(pkg[11 + 2*i : 13 + 2*i]) + print(GuestPlayers) + + elif sport_code == 0x38: # Individual points - HOME BASKET/HAND/HOCKEY/FUTSAL + for i in range(0, 13): + HomePlayers[i]['points'] = pn_points(pkg[22 + 2*i : 24 + 2*i]) + for i in range(13, 16): + HomePlayers[i]['points'] = pn_points(pkg[11 + 2*i : 13 + 2*i]) + + elif sport_code == 0x39: # TENNIS + pass + + elif sport_code == 0x3A: # TABLE TENNIS + pass + + elif sport_code == 0x3C: # HANDBALL with individual penalties + pass + + elif sport_code == 0x62: # GUEST NAME + if pkg[2] == 0x20: + Game['guest_name'] = pn_name(pkg[6:48]) + with open(game_filename, 'w', encoding='utf-8') as f: + json.dump(Game, f, ensure_ascii=False, indent=4) + else: + GuestPlayers[int(pkg[2])]['number'] = pn_playernumber(pkg[51:53]) + GuestPlayers[int(pkg[2])]['name'] = pn_name(pkg[3:23]) + with open(guestplayers_filename, 'w', encoding='utf-8') as f: + json.dump(GuestPlayers, f, ensure_ascii=False, indent=4) + + elif sport_code == 0x77: # HOME NAME + if pkg[2] == 0x20: + Game['home_name'] = pn_name(pkg[6:48]) + with open(game_filename, 'w', encoding='utf-8') as f: + json.dump(Game, f, ensure_ascii=False, indent=4) + else: + HomePlayers[int(pkg[2])]['number'] = pn_playernumber(pkg[51:53]) + HomePlayers[int(pkg[2])]['name'] = pn_name(pkg[3:23]) + with open(homeplayers_filename, 'w', encoding='utf-8') as f: + json.dump(HomePlayers, f, ensure_ascii=False, indent=4) + + elif sport_code == 0x4D: # MESSAGE + GameHandFutsal.update({ + 'timer': pn_timer(pkg[4:8]), + 'horn': pn_horn(pkg[19]), + 'timer_status': pn_startstop(pkg[20]), + 'timer24': pn_timer24(pkg[48:50]), + 'horn24': pn_horn(pkg[50]), + 'timer24_status': pn_startstop(pkg[51]), + 'timer24_display': pn_display24(pkg[52]) + }) + + elif sport_code == 0x41 or sport_code == 0x043: # MESSAGE CONFIGURATION + GameHandFutsal.update({ + 'timer': pn_timer(pkg[4:8]), + 'horn': pn_horn(pkg[19]), + 'timer_status': pn_startstop(pkg[20]), + 'timer24': pn_timer24(pkg[48:50]), + 'horn24': pn_horn(pkg[50]), + 'timer24_status': pn_startstop(pkg[51]), + 'timer24_display': pn_display24(pkg[52]) + }) + + else: + print('Error: Unknown sport code {}'.format(sport_code)) + + +class REFClient(asyncore.dispatcher): + buff = [] + + def __init__(self, host, port): + asyncore.dispatcher.__init__(self) + self.create_socket() + self.connect( (host, port) ) + + def handle_connect(self): + pass + #print('Connect to referee system is established') + + def handle_close(self): + self.close() + + def handle_read(self): + buff = self.recv(8192) + if len(buff) == 54: + parce(buff) + +class JSONServer(BaseHTTPRequestHandler): + def do_GET(self): + if self.path == '/Game': + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes(json.dumps([GameBasketball]), "utf-8")) + + elif self.path == '/GameBasketball': + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes(json.dumps([GameBasketball]), "utf-8")) + + elif self.path == '/GameHandFutsal': + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes(json.dumps([GameHandFutsal]), "utf-8")) + #GameHandFutsal + #self.wfile.write(bytes(json.dumps([GameHandFutsal]), "utf-8")) + + elif self.path == '/HomePlayers': + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes(json.dumps(HomePlayers), "utf-8")) + + elif self.path == '/GuestPlayers': + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes(json.dumps(GuestPlayers), "utf-8")) + + elif self.path == '/refresh': + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes('[{"refresh":"ok"}]', "utf-8")) + + with io.open('C:/Users/aksma/YandexDisk/workspace/_hd1/_gfx/multisport_452/data.bin', 'rb') as f: + parce(f.read()) + + else: + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes('[{"error":"bad path"}]', "utf-8")) + +if __name__ == "__main__": + + try: + with open(game_filename) as f: + Game = json.load(f) + with open(homeplayers_filename) as f: + HomePlayers = json.load(f) + with open(guestplayers_filename) as f: + GuestPlayers = json.load(f) + except: + pass + + webServer = HTTPServer((jsonserver_hostname, jsonserver_port), JSONServer) + print("Server started http://%s:%s" % (jsonserver_hostname, jsonserver_port)) + + client = REFClient(refserver_hostname, refserver_port) + + thread = threading.Thread(target=asyncore.loop, args=()) + thread.start() + print('Connect to referee system is established') + + try: + webServer.serve_forever() + except KeyboardInterrupt: + pass + + webServer.server_close() + print("Server stopped.") \ No newline at end of file diff --git a/divs/tcp_monitor.py b/divs/tcp_monitor.py new file mode 100644 index 0000000..9f02033 --- /dev/null +++ b/divs/tcp_monitor.py @@ -0,0 +1,34 @@ +import asyncore +from textwrap import wrap + +refserver_hostname = "79.172.5.168" +refserver_port = 4001 + +class REFClient(asyncore.dispatcher): + buff = '' + + def __init__(self, host, port): + asyncore.dispatcher.__init__(self) + self.create_socket() + self.connect( (host, port) ) + + def handle_connect(self): + pass + + def handle_close(self): + self.close() + + def handle_read(self): + hex = bytes.hex(self.recv(8192)) + hex = wrap(hex, 2) + print(' '.join(hex)) + +if __name__ == "__main__": + client = REFClient(refserver_hostname, refserver_port) + + try: + asyncore.loop() + except KeyboardInterrupt: + pass + + print("Server stopped.") \ No newline at end of file diff --git a/old/timer_MBA.py b/old/timer_MBA.py new file mode 100644 index 0000000..0e68524 --- /dev/null +++ b/old/timer_MBA.py @@ -0,0 +1,123 @@ +from socket import * +from datetime import datetime +import json +import time + +HOST = "10.0.0.57" # local +PORT = 50002 +ADDR = (HOST,PORT) + +PATH = "D:\\timer.json" + + +def connect(): + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect(ADDR) + data = "Hello, world" + data = str.encode(data) + tcp_socket.send(data) + data = bytes.decode(data) + data = tcp_socket.recv(1024) + # tcp_socket.close() + + return data + + +def save_log(name, data): + current_time = datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f") + message_with_time = f"[{current_time}] {data}" + with open(name, "a") as file: + file.write(message_with_time + "\n") + + +def formatted_data(data): + save_log("logs_mba.txt", data) + + # data_converted = list(data) + # data_formatted = [ + # str(hex_value // 16) + str(hex_value % 16) for hex_value in data_converted + # ] + # save_log("logs_mba_formatted.txt", data_formatted) + + +def parse(data_formatted): + # print(len(data_formatted)) + # print(data_formatted) + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + new_data = new_data[0] + + if len(data_formatted) > 30: + if data_formatted[17] == "010": + if data_formatted[-8] in ["01", "05"]: + timer_str = ( + f"{int(data_formatted[-7])}:{data_formatted[-6]}" + if int(data_formatted[-7]) != 0 + else f"{int(data_formatted[-6])}.{int(data_formatted[-5])}" + ) + new_data["timeGFX"] = timer_str + new_data["minutesGFX"] = int( + data_formatted[-7] + ) # [25] #data_formatted[17] = 010 - таймер data_formatted[-8] = 05 - овертайм, 06 - перерыв между основным временем и овертаймом, 01 - игровое время, 02 - перерыв между периодами + new_data["secondsGFX"] = data_formatted[-6] # [26] + else: + timer_str = f"{int(data_formatted[-7])}:{data_formatted[-6]}" + new_data["timeNotGame"] = timer_str + + if len(data_formatted) == 58: + new_data[ + "timeDel1" + ] = f"{int(data_formatted[26])}:{data_formatted[27]}" # data_formatted[17] = 24 - удаление + new_data["timeDel2"] = f"{int(data_formatted[41])}:{data_formatted[42]}" + + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + print(new_data) + except Exception: + pass + + +def main(): + with socket(AF_INET, SOCK_STREAM) as s: + s.connect((HOST, PORT)) + s.sendall(b"Hello, world") + data = s.recv(1024) + while True: + print(data) + data_new = formatted_data(data) + time.sleep(.1) + # parse(data) + + + + + +def read_logs(): + import time + with open("test_logs_balashikha_new.txt", "r") as file: + for line in file: + parts = line.strip().split("] ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = parts[1] + parse(eval(data)) + if len(eval(data)) > 30 and eval(data)[-7] == "00": + time.sleep(.1) + else: + time.sleep(1) + + +if __name__ == "__main__": + new_data = { + "timeGFX": "0:00", + "minutesGFX": "0", + "secondsGFX": "0", + "foul1": "0", + "foul2": "0", + "quarter": "0", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + main() + # read_logs() diff --git a/old/timer_MBA_2.py b/old/timer_MBA_2.py new file mode 100644 index 0000000..1213c18 --- /dev/null +++ b/old/timer_MBA_2.py @@ -0,0 +1,143 @@ +import sys +import json +from socket import * +from datetime import datetime +import time + + +host = "10.0.0.57" +port = 50002 +ADDR = (host, port) +PATH = "D:\\timer_basketball.json" + + +def save_log(name, data): + current_time = datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f") + message_with_time = f"[{current_time}] {data}" + with open(name, "a") as file: + file.write(message_with_time + "\n") + + +def parse(data): + data = data.split("/") + + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + new_data = new_data[0] + path_pic = "D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\VTB_Fouls for scoreboard smaller" + if len(data) > 10: + if data[4] == "NPR": + new_data["quarter"] = data[5] + if data[17] == "HCP": + new_data["points1"] = data[18] + if data[20] == "GCP": + new_data["points2"] = data[21] + if data[29] == "HCF": + new_data["foul1"] = data[30] + new_data["foul_pic1"] = path_pic + f"\Home тАУ {int(data[30])} Foul.png" + if data[32] == "GCF": + new_data["foul2"] = data[33] + new_data["foul_pic2"] = path_pic + f"\Away тАУ {int(data[33])} Foul.png" + else: + if data[1] == "TGI": + if data[2] != "0": + seconds = data[3] if len(data[3]) != 1 else f"0{data[3]}" + new_data["timeGFX"] = f"{data[2]}:{seconds}" + else: + millisec = data[4] + if millisec == "#": + millisec = "0" + new_data["timeGFX"] = f"{data[3]}.{millisec}" + elif data[1] == "NPR": + new_data["quarter"] = data[2] + elif data[1] == "HCP": + new_data["points1"] = data[2] + elif data[1] == "GCP": + new_data["points2"] = data[2] + elif data[1] == "HCF": + new_data["foul1"] = data[2] + new_data["foul_pic1"] = path_pic + f"\Home тАУ {int(data[2])} Foul.png" + elif data[1] == "GCF": + new_data["foul2"] = data[2] + new_data["foul_pic2"] = path_pic + f"\Away тАУ {int(data[2])} Foul.png" + elif data[1] == "TAI": + if data[2] not in ["0", "-1"]: + new_data["time_attackGFX"] = str(int(data[2])) + if int(data[2]) <= 5: + new_data["time_attac_pic"] = "" + else: + new_data["time_attac_pic"] = "empty" + + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + print(new_data) + if ":" in new_data["timeGFX"]: + time.sleep(.5) + else: + time.sleep(.1) + + except Exception: + pass + + +def read_logs(): + with open("logs_mba_1.txt", "r") as file: + for line in file: + parts = line.strip().split("] ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = parts[1] + + parse(data) + + # if len(eval(data)) > 30 and eval(data)[-7] == "00": + # time.sleep(.1) + # else: + # time.sleep(1) + + +def main(): + new_data = { + "timeGFX": "0:00", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + + + + + + # tcp_socket = socket(AF_INET, SOCK_STREAM) + # tcp_socket.connect(ADDR) + + # try: + # while True: + # data = str.encode("hello") + # tcp_socket.send(data) + # data = bytes.decode(data) + # data = tcp_socket.recv(1024) + # data = data.decode() + # save_log("logs_mba_1.txt", data) + # parse(data) + # except KeyboardInterrupt: + # tcp_socket.close() + # sys.exit(1) + + +if __name__ == "__main__": + try: + main() + read_logs() + except KeyboardInterrupt: + sys.exit(1) + diff --git a/old/timer_Megasport_test.py b/old/timer_Megasport_test.py new file mode 100644 index 0000000..a1f3948 --- /dev/null +++ b/old/timer_Megasport_test.py @@ -0,0 +1,141 @@ +import sys +import json +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii + +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def parse(line): + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + + if len(edata.split()) == 33: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + minutes = temp_new[6] + seconds = temp_new[7] + milliseconds = temp_new[8] + timer_str = ( + f"{minutes}:{seconds:02d}" + if minutes != 0 + else f"{seconds:02d}.{milliseconds}" + ) + active_temp = temp_new[ + 9 + ] # 133 - таймер идёт | 132 - таймер стоит | 128 - не игровое время стоит | 129 - не игровое время идёт + + if temp_new[-2] != 0: + time_attack = ( + temp_new[-4] if temp_new[-4] > 4 else f"{temp_new[-4]}.{temp_new[-3]}" + ) + else: + time_attack = "" # temp_new[-2] == 1 - таймер идёт | 2 - таймер стоит | 0 - таймер не отображён + + # print(f"{str(temp_new):<120}__{timer_str:<7}__{time_attack:<3}__") + else: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + + with open("timer_NN.csv", "a+") as file: + file.write(str(temp_new)) + file.write("\n") + with open("timer_NN_2.csv", "a+") as file: + file.write(str(temp_data)) + file.write("\n") + with open("timer_NN_3.csv", "a+") as file: + file.write(str(ddata)) + file.write("\n") + + # time.sleep(0.1) + + +def read_logs(): + with open("timer_NN_2023-12-20_18-17-29.log", "r") as file: + # with open("timer_NN_test.log", "r") as file: + temp_line = "" + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + parse(data) + time.sllep(.1) + + # if len(eval(data)) > 30 and eval(data)[-7] == "00": + # time.sleep(.1) + # else: + # time.sleep(1) + + +def main(): + # current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + # if not os.path.isdir("LOGS"): + # os.mkdir("LOGS") + + # LogFileName = f"LOGS/timer_Chine_tcp_{current_time}.log" + # logging.basicConfig( + # level=logging.DEBUG, + # format="%(asctime)s %(levelname)s %(message)s", + # filename=LogFileName, + # filemode="w", + # ) + # new_data = { + # "timeGFX": "0:00", + # "time_attackGFX": "", + # "quarter": "0", + # "points1": "0", + # "points2": "0", + # "foul1": "0", + # "foul2": "0", + # "foul_pic1": "", + # "foul_pic2": "", + # "time_attac_pic": "", + # } + # with open(PATH, "w", encoding="utf-8") as file: + # json.dump([new_data], file, ensure_ascii=False, indent=4) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + # logging.debug(data) + cdata = binascii.hexlify(data) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + print(edata) + # temp_data = edata.split() + # temp_new = [int(t, 16) for t in temp_data] + # timer = f"{temp_new[3]}:{temp_new[2]}" + # seconds = temp_new[5] + # milliseconds = str(temp_new[4])[0] + # print(f"data: {edata}", temp_new, timer, f"{seconds}.{milliseconds}") + # print(temp_new, timer, f"{seconds}.{milliseconds}") + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/old/timer_megasport.py b/old/timer_megasport.py new file mode 100644 index 0000000..b11935f --- /dev/null +++ b/old/timer_megasport.py @@ -0,0 +1,82 @@ +# import serial.tools.list_ports #pip install pyserial + +import serial +from datetime import datetime +import json + +# Configure the COM port +port = "COM8" # Replace with the appropriate COM port name +baudrate = 9600 +# baudrate = 19200 +PATH = "D:\\timer_basketball.json" + + + +def save_log(name, data): + current_time = datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f") + message_with_time = f"[{current_time}] {data}" + with open(name, "a") as file: + file.write(message_with_time + "\n") + + +def read_logs(): + import time + + with open("logs_megasport_formatted.txt", "r") as file: + for line in file: + parts = line.strip().split("] ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = parts[1] + parse(eval(data)) + + input() + # if len(eval(data)) > 30 and eval(data)[-7] == "00": + # time.sleep(0.1) + # else: + # time.sleep(1) + + +def parse(data_formatted): + print(len(data_formatted)) + if len(data_formatted) > 8: + print(data_formatted) + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + new_data = new_data[0] + + + +def main(): + try: + # Open the COM port + ser = serial.Serial(port, baudrate=baudrate) + print("Serial connection established.") + + while True: + line = ser.readline() + line = list(line) + line = [str(hex_value // 16) + str(hex_value % 16) for hex_value in line] + save_log("logs_balashikha_formatted.txt", line) + print(line) + + except serial.SerialException as se: + print("Serial port error:", str(se)) + + except KeyboardInterrupt: + exit(1) + + finally: + if ser.is_open: + ser.close() + print("Serial connection closed.") + + +if __name__ == "__main__": + # new_data = { + # "timeGFX": "0:00", + # } + # with open(PATH, "w", encoding="utf-8") as file: + # json.dump([new_data], file, ensure_ascii=False, indent=4) + main() + # read_logs() diff --git a/old/timer_megasport2.py b/old/timer_megasport2.py new file mode 100644 index 0000000..6f64764 --- /dev/null +++ b/old/timer_megasport2.py @@ -0,0 +1,70 @@ +import serial +from serial import SerialException +import logging +import time +import binascii + +SerialPort = "COM1" +BaudRate = 19200 +PackageByTime = 0.1 +PackageByLenght = 256 +BufferMax = 2000 +LogFileName = "megasport_new_4.log" + +logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(levelname)s %(message)s', + filename=LogFileName, + filemode="w") + +ser = serial.Serial() +ser.port = SerialPort +ser.baudrate = BaudRate +ser.bytesize = serial.EIGHTBITS +ser.parity = serial.PARITY_NONE +ser.stopbits = serial.STOPBITS_ONE +ser.timeout = PackageByTime +ser.xonxoff = False +ser.rtscts = False +ser.dsrdtr = False +ser.write_timeout = 2 + +start = b"\xe0\xe0\xe8\xe8\xe4\xe4\xf8" +finish = b"\r" +while True: + try: + print("Initializing") + ser.close() + ser.open() + if ser.is_open: + try: + RequestCount = 0 + print("Port Opening") + RetryCount = 0 + remainder_hex = b"" + while True: + response = ser.read(PackageByLenght) + print(response) + + logging.debug(response) + if len(response) > 0: + + StarterTime = time.time() * 1000 + response_hex = response.replace(b" ", b"") + try: + int(response_hex,16) + except ValueError: + response_hex = binascii.hexlify(response) + response_hex = response_hex.upper() + + response_hex = remainder_hex + response_hex + print(response_hex) + + except Exception as e1: + logging.error("error communicating...: " + str(e1)) + else: + print("Port Opening Failed... trying again in 5 seconds") + time.sleep(5) + ser.close() + except SerialException: + print("No port connected... trying again in 5 seconds") + time.sleep(5) diff --git a/old/timer_megasport3.py b/old/timer_megasport3.py new file mode 100644 index 0000000..3548f57 --- /dev/null +++ b/old/timer_megasport3.py @@ -0,0 +1,58 @@ +import serial +from serial import SerialException +import logging +import time +import binascii + +SerialPort = "COM1" +BaudRate = 19200 +PackageByTime = 0.1 +PackageByLenght = 256 +BufferMax = 2000 +LogFileName = "megasport_new_4.log" + +logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(levelname)s %(message)s', + filename=LogFileName, + filemode="w") + +ser = serial.Serial() +ser.port = SerialPort +ser.baudrate = BaudRate +ser.bytesize = serial.EIGHTBITS +ser.parity = serial.PARITY_NONE +ser.stopbits = serial.STOPBITS_ONE +ser.timeout = PackageByTime +ser.xonxoff = False +ser.rtscts = False +ser.dsrdtr = False +ser.write_timeout = 2 + +# start = b"\xf8" +# finish = b"\r" +while True: + try: + print("Initializing") + ser.close() + ser.open() + if ser.is_open: + try: + RequestCount = 0 + print("Port Opening") + RetryCount = 0 + remainder_hex = b"" + while True: + response = ser.read(PackageByLenght) + print(response) + logging.debug(response) + + + except Exception as e1: + logging.error("error communicating...: " + str(e1)) + else: + print("Port Opening Failed... trying again in 5 seconds") + time.sleep(5) + ser.close() + except SerialException: + print("No port connected... trying again in 5 seconds") + time.sleep(5) diff --git a/old/timer_megasport5.py b/old/timer_megasport5.py new file mode 100644 index 0000000..4a12113 --- /dev/null +++ b/old/timer_megasport5.py @@ -0,0 +1,261 @@ +import serial +from serial import SerialException +import datetime +import binascii +import logging +import time +import json + +import re + +# Configuration Data (later to be put in Panel2Net.conf) +# SerialPort: Name of RPi serial port receiving the panel data +# SerialPort = "COM1" +SerialPort = "COM2" +# BaudRate: Serial port speed (Baud, Default will be adjusted later) +BaudRate = 19200 +# PackageByTime: Time Duration until a package is closed +# and sent off (seconds) +PackageByTime = 0.1 +# PackageByLength* Length (in bytes) of data input +# until a package is closed and sent off +PackageByLength = 128 +# PackageByLength = 256 попробовать нужно !!!!!!!!!!!!!!!!!!!! +# PackageByLength = 80 + +# MaxBuffer before flushing (in order to avoid buffer overflow) +BufferMax = 2000 + + +# LogFileName: Name of LogFile +current_time = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") +LogFileName = f"timer_megasport5_{current_time}.log" +# LogFileSize Maximum Size of LogFile (in Mbytes) +LogFileSize = 10 +# LogLevel Minimum Severity Level to be logged (see severity in Logs) +LogLevel = "E" + +logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", +) + +def hexspace(string, length): + return ' '.join(string[i:i+length] for i in range(0,len(string),length)) + +ser = serial.Serial() +ser.port = SerialPort +ser.baudrate = BaudRate +ser.bytesize = serial.EIGHTBITS +# number of bits per bytes +ser.parity = serial.PARITY_NONE +# set parity check: no parity +ser.stopbits = serial.STOPBITS_ONE +# number of stop bits +ser.timeout = PackageByTime +# non-block read +ser.xonxoff = False +# disable software flow control +ser.rtscts = False +# disable hardware (RTS/CTS) flow control +ser.dsrdtr = False +# disable hardware (DSR/DTR) flow control +ser.writeTimeout = 2 +# timeout for write + +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) +new_data = { + "timeGFX": "0.0", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", +} +with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + + +while True: + try: + print("Initializing") + ser.close() + ser.open() + if ser.is_open: + try: + ser.reset_input_buffer() + # flush input buffer, discarding all its contents + ser.reset_output_buffer() + # flush output buffer, aborting current output + # and discard all that is in buffer + RequestCount = 0 + print("Port Opening") + # Initialise RetryCounter + RetryCount = 0 + # Initialise Variable to take remainder string + remainder_hex = b"" + + while True: + # Read from Serial Interface + response = ser.read(PackageByLength) + # print(response) + if len(response) > 0: + # In case there is something coming down the serial path + logging.debug(response) + + if response != b"": + data = response + # debug line + # f.write(data) + # f.write("\n") + + cdata = binascii.hexlify(data) + ddata = cdata.decode('utf-8') + ddata = ddata.upper() + print (ddata) + edata = hexspace(ddata, 2) + print (edata) + + + + # points1 = "" + # points2 = "" + # quarter = "" + # data_str = response.decode( + # "ascii", errors="ignore" + # ).replace("\r", "|") + # if len(data_str) == 53: + # pattern = r"^(3 0|7 |8 |69i553 |69i557 |69i558 |5:i553 )(.{4})" + # matches = re.findall(pattern, data_str) + # for match in matches: + # found_value = match[0] + # timer_str = match[1] + # if match[0] == "3 0": + # points1 = data_str[7:10].strip() + # points2 = data_str[10:13].strip() + # quarter = data_str[13:14].strip() + + # # print(f"Следующие 4 символа: {timer_str}, Найдено: {found_value}, {data_str}_____") + # else: + # pattern = r"(\|3 0|\|7 |\|8 |\|69i553 |\|69i557 |\|69i558 |\|5:i553 )(.{4})" + # matches = re.findall(pattern, data_str) + # # print(data_str) + # for match in matches: + # found_value = match[0] + # timer_str = match[1] + # if match[0] == "3 0": + # points1 = data_str[7:10].strip() + # points2 = data_str[10:13].strip() + # quarter = data_str[13:14].strip() + + # # print(f"Следующие 4 символа: {timer_str}, Найдено: {found_value}, {data_str}_____") + # pattern_attack = r"(.{5})\|" + # matches_attack = re.findall(pattern_attack, data_str) + # path_pic = r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + # try: + # if matches_attack[0][2:] == "030": + # time_attackGFX = "" + # time_attac_pic = path_pic + "\\24Sec_empty.png" + # else: + # hex_dict = { + # "I": 9, + # "H": 8, + # "G": 7, + # "F": 6, + # "E": 5, + # "D": 4, + # "C": 3, + # "B": 2, + # "A": 1, + # } + # time_attackGFX = matches_attack[0][:2] + # if time_attackGFX[-1] in [ + # "A", + # "B", + # "C", + # "D", + # "E", + # "F", + # "G", + # "H", + # "I", + # ]: + # first_character = time_attackGFX[0] + # second_character = time_attackGFX[1] + # time_attackGFX = str( + # int(first_character, 16) + # + hex_dict.get(second_character, 0) / 10.0 + # ) + # time_attac_pic = path_pic + "\\24Sec_Red.png" + # else: + # time_attac_pic = path_pic + "\\24Sec_Orange.png" + # except IndexError: + # pass + + # if timer_str[0] == " ": + # if timer_str == " 000": + # timer = "0.0" + # else: + # minites = timer_str[:2] + # seconds = timer_str[2:] + # timer = f"{int(minites)}:{seconds}".strip() + # elif timer_str[-1] == " ": + # seconds = timer_str[:2] + # milliseconds = timer_str[2:] + # timer = f"{int(seconds)}.{milliseconds}".strip() + # else: + # minites = timer_str[:2] + # seconds = timer_str[2:] + # timer = f"{int(minites)}:{seconds}".strip() + + # print( + # f"Следующие 4 символа: {timer_str}, {timer}, {time_attackGFX}, Найдено: {found_value}, {data_str}_____" + # ) + + # with open(PATH, "r", encoding="utf-8") as f: + # new_data = json.load(f) + # new_data = new_data[0] + # new_data["timeGFX"] = timer + # new_data["time_attackGFX"] = time_attackGFX + # new_data["time_attac_pic"] = time_attac_pic + # if points1: + # new_data["points1"] = points1 + # new_data["points2"] = points2 + # new_data["quarter"] = quarter + # try: + # with open(PATH, "w", encoding="utf-8") as file: + # json.dump( + # [new_data], file, ensure_ascii=False, indent=4 + # ) + # except Exception: + # pass + + else: + # In case nothing is coming down the serial interface + print( + "\rWaiting for serial input...", + end=" ", + flush=True, + ) + + # in case that the Serial Read or HTTP request fails + except Exception as e1: + print("error communicating...: " + str(e1)) + logging.error("error communicating...: " + str(e1)) + + else: + print("Port Opening Failed... trying again in 5 seconds") + time.sleep(0.1) + ser.close() + + except SerialException: + print("No port connected... trying again in 5 seconds") + time.sleep(0.1) diff --git a/old/timer_megasport_rider.py b/old/timer_megasport_rider.py new file mode 100644 index 0000000..2b61067 --- /dev/null +++ b/old/timer_megasport_rider.py @@ -0,0 +1,25 @@ +start = "\xf8" +finish = "\r" + +with open('megasport_new_5.txt', 'r') as file: + new_lines = [] + current_line = "" + capturing = False + + for line in file: + if start in line: + capturing = True + current_line = line[line.index(start):] + elif capturing: + if finish in line: + finish_idx = line.index(finish) + current_line += line[:finish_idx + len(finish)] + new_lines.append(current_line) + current_line = "" + capturing = False + else: + current_line += line + +with open('new_log.txt', 'w') as new_file: + for line in new_lines: + new_file.write(line + '\n') diff --git a/timer COM copy.py b/timer COM copy.py new file mode 100644 index 0000000..930386f --- /dev/null +++ b/timer COM copy.py @@ -0,0 +1,363 @@ +# vmix_serial_bridge.py +# pip install pyserial requests + +import time +import argparse +import urllib.parse +import requests +import serial +from serial.serialutil import SerialException +from serial.tools import list_ports +import re +from dataclasses import dataclass +from threading import Thread, Event +from queue import Queue, Empty + +VMIX_HOST = "http://127.0.0.1:8088" + +VMIX_TARGETS = { + "main_time": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "TIMER.Text", "SelectedIndex": None}, + "shot_clock": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "24sec.Text", "SelectedIndex": None}, + "quarter": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "QUARTER.Text", "SelectedIndex": None}, + "score_1": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "SCORE1.Text", "SelectedIndex": None}, + "score_2": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "SCORE2.Text", "SelectedIndex": None}, + "fouls_1": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "FOULS1.Text", "SelectedIndex": None}, + "fouls_2": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "FOULS2.Text", "SelectedIndex": None}, +} + +# ---------------- HTTP client ---------------- +class VmixClient: + def __init__(self, host: str, timeout: float = 0.01, retries: int = 3, backoff: float = 0.3): + self.host = host.rstrip("/") + self.timeout = timeout + self.retries = retries + self.backoff = backoff + self.session = requests.Session() + self.session.headers.update({"Connection": "keep-alive"}) + + def call(self, function: str, input_id: str, value: str, selected_name=None, selected_index=None) -> bool: + params = {"Function": function, "Input": input_id, "Value": value} + if selected_name: + params["SelectedName"] = selected_name + if selected_index is not None: + params["SelectedIndex"] = selected_index + url = f"{self.host}/api?{urllib.parse.urlencode(params, doseq=True, safe='')}" + for attempt in range(1, self.retries + 2): + try: + r = self.session.get(url, timeout=self.timeout) + print(r.status_code()) + r.raise_for_status() + return True + except requests.RequestException as e: + if attempt > self.retries: + print(f"[vMix] ERROR: {e} -> {url}") + return False + delay = self.backoff * attempt + print(f"[vMix] WARN attempt {attempt}: {e}. Retry in {delay:.2f}s") + time.sleep(delay) + +@dataclass +class VmixMessage: + field: str + value: str + +class VmixSender: + def __init__(self, client: VmixClient, dedupe: bool = False, max_queue: int = 2000): + self.client = client + self.queue: Queue[VmixMessage] = Queue(maxsize=max_queue) + self.stop_event = Event() + self.thread = Thread(target=self._run, name="vmix-sender", daemon=True) + self.dedupe = dedupe + self._last_sent: dict[str, str | None] = {} + + def start(self): self.thread.start() + def stop(self): self.stop_event.set(); self.thread.join(timeout=2) + + # VmixSender + def send(self, field: str, value: str | None): + if value is None: + return + if field not in VMIX_TARGETS: + return + if self.dedupe and self._last_sent.get(field) == value: + return + if self.dedupe: + self._last_sent[field] = value + try: + self.queue.put_nowait(VmixMessage(field, str(value))) + except Exception: + try: + _ = self.queue.get_nowait(); self.queue.task_done() + except Empty: + pass + self.queue.put_nowait(VmixMessage(field, str(value))) + + + def _run(self): + while not self.stop_event.is_set(): + try: + msg = self.queue.get(timeout=0.2) + except Empty: + continue + t = VMIX_TARGETS[msg.field] + ok = self.client.call(t["Function"], t["Input"], msg.value, t.get("SelectedName"), t.get("SelectedIndex")) + if ok: print(f"[vMix] {msg.field} <- {msg.value}") + self.queue.task_done() + +# ---------------- Parser ---------------- +def parse_time_5ch(chunk: str) -> str | None: + if len(chunk) != 5: return None + try: + if chunk[0:2] == "0 ": + return f"{int(chunk[1:3])}:{int(chunk[3:5]):02d}" + # elif len(chunk) == 5: + # return f"{int(chunk[1:3])}:{int(chunk[3:5]):02d}" + else: + return f"{int(chunk[1:3])}.{chunk[3]}" + except Exception: + return None + +def format_shot_clock_from_tail_number(n: int) -> str | None: + if n < 0: return "" + tail = n % 100 + if tail != 31: return "" # не обновлять + sec_tenths = n // 100 + return str(sec_tenths // 10) if sec_tenths >= 50 else f"{sec_tenths / 10:.1f}" + +@dataclass +class ParsedPacket: + main_time: str | None = None + score1: str | None = None + score2: str | None = None + quarter: str | None = None + shot_clock: str | None = None + +def parse_line(line: str) -> ParsedPacket | None: + clean = line.strip().replace("�", "") + print(clean) + # if not clean or len(clean) < 24: return None + try: + if clean[0] != "3": return None + except Exception: + return None + main_time_raw = clean[2:7] + main_time = parse_time_5ch(main_time_raw) + # print(main_time) + + score1 = clean[7:10].strip() + score2 = clean[10:13].strip() + + quarter = None + m = re.search(r"\s([1-5])\s\s\d{6}\s", clean) + if m: quarter = m.group(1) + + shot_clock = "" + tail = clean[-5:] + if tail.isdigit(): + shot_clock = format_shot_clock_from_tail_number(int(tail)) + return ParsedPacket( + main_time=main_time, + score1=score1 or None, + score2=score2 or None, + quarter=quarter, + shot_clock=shot_clock, + ) + +# ---------------- Serial reader ---------------- +EOLS = {"CR": b"\r", "LF": b"\n", "CRLF": b"\r\n"} + +def sniff_eol(sample: bytes) -> bytes: + # простейшая эвристика + if b"\r\n" in sample: return EOLS["CRLF"] + if b"\r" in sample and b"\n" not in sample: return EOLS["CR"] + if b"\n" in sample: return EOLS["LF"] + return EOLS["CR"] # дефолт + +class SerialReader: + def __init__(self, port: str, baud: int, newline: str, strip_ws: bool, sender: VmixSender, + send_quarter: bool, autoeol: bool, bytesize: int, parity: str, stopbits: float, + rtscts: bool, xonxoff: bool, dsrdtr: bool): + self.port = port + self.baud = baud + self.eol = EOLS.get(newline.upper(), b"\r") + self.strip_ws = strip_ws + self.sender = sender + self.send_quarter = send_quarter + self.autoeol = autoeol + self.bytesize = bytesize + self.parity = getattr(serial, f"PARITY_{parity.upper()}", serial.PARITY_NONE) + self.stopbits = {1: serial.STOPBITS_ONE, 1.5: serial.STOPBITS_ONE_POINT_FIVE, 2: serial.STOPBITS_TWO}[stopbits] + self.rtscts = rtscts + self.xonxoff = xonxoff + self.dsrdtr = dsrdtr + + def run(self): + while True: + try: + with serial.Serial( + self.port, + baudrate=self.baud, + timeout=0.01, + bytesize=self.bytesize, + parity=self.parity, + stopbits=self.stopbits, + rtscts=self.rtscts, + xonxoff=self.xonxoff, + dsrdtr=self.dsrdtr, + ) as ser: + print(f"[serial] OPEN {ser.port} @ {self.baud} ({self.bytesize}{self._parity_name()}{self._stopbits_name()})") + # сбросим линии и буферы + try: + ser.setDTR(True); ser.setRTS(True) + except Exception: pass + ser.reset_input_buffer(); ser.reset_output_buffer() + + buffer = bytearray() + last_feed = time.time() + # авто-детект EOL по первому куску + if self.autoeol: + chunk = ser.read(256) + if chunk: + self.eol = sniff_eol(chunk) + print(f"[serial] auto EOL = {self._eol_name(self.eol)}") + buffer.extend(chunk) + + while True: + chunk = ser.read(1024) + if chunk: + buffer.extend(chunk) + last_feed = time.time() + + # разбор по EOL + progressed = False + while True: + idx = buffer.find(self.eol) + if idx == -1: break + line = buffer[:idx] + del buffer[: idx + len(self.eol)] + text = self._decode(line, self.strip_ws) + if text: + self._process(text) + progressed = True + + # фолбэк: если долго не было EOL, попробуем отдать «как есть» + if not progressed and buffer and (time.time() - last_feed) > 0.5: + text = self._decode(buffer, self.strip_ws) + buffer.clear() + if text: + self._process(text) + + except SerialException as e: + print(f"[serial] ERROR open/read {self.port}: {e}. Retry in 3s...") + time.sleep(3) + except KeyboardInterrupt: + print("\n[serial] Stopped by user.") + return + except Exception as e: + print(f"[serial] UNEXPECTED: {e}. Retry in 3s...") + time.sleep(3) + + def _decode(self, raw: bytes, strip_ws: bool) -> str | None: + try: + text = raw.decode("utf-8", errors="replace") + except Exception: + text = raw.decode("latin-1", errors="replace") + if strip_ws: text = text.strip() + return text or None + + def _process(self, text: str): + pkt = parse_line(text) + if not pkt: + print(f"[serial] RAW: {text!r}") + return + if pkt.main_time is not None: self.sender.send("main_time", pkt.main_time) + if pkt.score1 is not None: self.sender.send("score_1", pkt.score1) + if pkt.score2 is not None: self.sender.send("score_2", pkt.score2) + if self.send_quarter and pkt.quarter is not None: + self.sender.send("quarter", pkt.quarter) + if pkt.shot_clock is not None: + self.sender.send("shot_clock", pkt.shot_clock) + + def _parity_name(self): return {"N":"N","E":"E","O":"O","M":"M","S":"S"}[self.parity] + def _stopbits_name(self): return {serial.STOPBITS_ONE:"1", serial.STOPBITS_ONE_POINT_FIVE:"1.5", serial.STOPBITS_TWO:"2"}[self.stopbits] + def _eol_name(self, e: bytes): return {b"\r":"CR", b"\n":"LF", b"\r\n":"CRLF"}.get(e, f"{e!r}") + +# ---------------- Probe (sniffer) ---------------- +def probe_port(port: str, baud: int, seconds: int, **kwargs): + print("[probe] Available ports:") + for p in list_ports.comports(): + print(f" - {p.device}: {p.description}") + try: + with serial.Serial(port, baudrate=baud, timeout=0.01) as ser: + print(f"[probe] OPEN {ser.port} @ {baud}. Sniffing {seconds}s...") + ser.reset_input_buffer() + t0 = time.time() + total = 0 + while time.time() - t0 < seconds: + b = ser.read(512) + if not b: continue + total += len(b) + print(f"[{len(b):03d} bytes] HEX: {b.hex(' ')}") + try: + txt = b.decode("utf-8") + except Exception: + txt = b.decode("latin-1", errors="replace") + print(f" TXT: {txt!r}") + print(f"[probe] Done. Total bytes: {total}") + except Exception as e: + print(f"[probe] ERROR: {e}") + +# ---------------- CLI ---------------- +def main(): + ap = argparse.ArgumentParser(description="COM -> vMix bridge with diagnostics") + ap.add_argument("--port", required=True, help="e.g. COM2 or /dev/ttyUSB0") + ap.add_argument("--baud", type=int, default=19200) + ap.add_argument("--newline", choices=["LF", "CRLF", "CR"], default="CR") + ap.add_argument("--autoeol", action="store_true", help="Auto-detect EOL from stream") + ap.add_argument("--no-strip", action="store_true") + ap.add_argument("--vmix-host", default=VMIX_HOST) + ap.add_argument("--timeout", type=float, default=0.01) + ap.add_argument("--retries", type=int, default=3) + ap.add_argument("--backoff", type=float, default=0.3) + ap.add_argument("--dedupe", action="store_true") + ap.add_argument("--send-quarter", action="store_true") + # serial low-level + ap.add_argument("--bytesize", type=int, choices=[5,6,7,8], default=8) + ap.add_argument("--parity", choices=["N","E","O","M","S"], default="N") + ap.add_argument("--stopbits", type=float, choices=[1,1.5,2], default=1) + ap.add_argument("--rtscts", action="store_true") + ap.add_argument("--xonxoff", action="store_true") + ap.add_argument("--dsrdtr", action="store_true") + # tools + ap.add_argument("--probe", type=int, metavar="SECONDS", help="Sniff raw bytes/text for N seconds and exit") + args = ap.parse_args() + + if args.probe: + probe_port(args.port, args.baud, args.probe) + return + + client = VmixClient(host=args.vmix_host, timeout=args.timeout, retries=args.retries, backoff=args.backoff) + sender = VmixSender(client=client, dedupe=args.dedupe); sender.start() + + reader = SerialReader( + port=args.port, + baud=args.baud, + newline=args.newline, + strip_ws=not args.no_strip, + sender=sender, + send_quarter=args.send_quarter, + autoeol=args.autoeol, + bytesize=args.bytesize, + parity=args.parity, + stopbits=args.stopbits, + rtscts=args.rtscts, + xonxoff=args.xonxoff, + dsrdtr=args.dsrdtr, + ) + try: + reader.run() + finally: + sender.stop() + +if __name__ == "__main__": + main() diff --git a/timer COM.py b/timer COM.py new file mode 100644 index 0000000..24d3648 --- /dev/null +++ b/timer COM.py @@ -0,0 +1,345 @@ +# serial_to_vmix.py +# pip install pyserial requests + +import time +import argparse +import socket +import urllib.parse +import requests +import serial +from serial.serialutil import SerialException + +# --------------------------- +# 1) ВАША функция отправки в vMix +# Замените содержимое по своему желанию. +# --------------------------- +# --- ВСТАВЬТЕ ВАШ serial_to_vmix.py вместо заглушки parse() --- + +import re +from dataclasses import dataclass, asdict + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + +VMIX_HOST = "http://127.0.0.1:8088" # адрес vMix Web Controller + +# куда писать поля в vMix — укажите свои Inputs/поля титров +# 1) В блоке VMIX_TARGETS добавьте цель для секундника: +VMIX_TARGETS = { + "main_time": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "TIMER.Text", "SelectedIndex": None}, + "shot_clock": {"Function": "SetText", "Input": "SCOREBUG","SelectedName": "24sec.Text", "SelectedIndex": None}, # ⬅️ ДОБАВЛЕНО + "quarter": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": None, "SelectedIndex": None}, + "score_1": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "SCORE1.Text", "SelectedIndex": None}, + "score_2": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "SCORE2.Text", "SelectedIndex": None}, + "fouls_1": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": None, "SelectedIndex": None}, + "fouls_2": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": None, "SelectedIndex": None}, +} + +def vmix_call(function: str, input_id: str, value: str, selected_name=None, selected_index=None, timeout=1.5): + params = {"Function": function, "Input": input_id, "Value": value} + if selected_name: + params["SelectedName"] = selected_name + if selected_index: + params["SelectedIndex"] = selected_index + url = f"{VMIX_HOST}/api?{urllib.parse.urlencode(params, doseq=True, safe='')}" + try: + r = session.get(url, timeout=timeout) + r.raise_for_status() + except requests.RequestException as e: + print(f"[vMix] HTTP ошибка: {e} -> {url}") + +# 2) В State замените shot_clock (int) на текстовый shot_clock (str), чтобы иногда писать десятые: +@dataclass +class State: + main_time: str | None = None # "M:SS" + shot_clock: str | None = None # ⬅️ теперь строка: "21" или "4.9" + quarter: int | None = None + score_1: int | None = None + score_2: int | None = None + fouls_1: int | None = None + fouls_2: int | None = None + timeouts_1: int | None = None + timeouts_2: int | None = None + + +class SmartBasketParser: + # строка «наша» если начинается с мусора и цифры 3, и содержит блок 0000 + full_line_guard = re.compile(r'^\D*3\b') + re_numbers = re.compile(r"\d+") + + def __init__(self): + self.state = State() + + @staticmethod + def _mmss_to_str(n: int) -> str: + """ + Универсальный форматтер: + - < 100 -> 'ss:0' + - 3 цифры, s<=59 -> 'M:SS' (MMSS) + - 3 цифры, s>59 -> 'ss:ms' (SSd, где ms = десятые) + - 4 цифры -> 'M:SS' (MMSS) + """ + if n < 0: + return "0:00" + + # только секунды + if n < 100: + ss = max(0, min(n, 59)) + return f"{ss}:0" + + # 3 цифры: либо M:SS, либо SS.d + if 100 <= n <= 999: + m = n // 100 + s = n % 100 + if s <= 59: + return f"{m}:{s:02d}" # 102 -> 1:02 + else: + ss = n // 10 # 199 -> 19 + d = n % 10 # 199 -> 9 + return f"{ss}.{d}" # 199 -> 19:9 + + # 4 цифры: MMSS + if 1000 <= n <= 5959: + m, s = divmod(n, 100) + if s >= 60: + m += s // 60 + s = s % 60 + return f"{m}:{s:02d}" + + # всё прочее не считаем временем + return "0:00" + + def _pick_main_time(self, nums: list[int]) -> str | None: + """ + В 'полной' строке основное время идёт сразу после ведущей '3'. + Если следом '0' — берём через один. + Примеры: + [3, 0, 58, 35, 35, 2200, 1, ...] -> 58:0 + [3, 199, 2, 13200, 1, ...] -> 19:9 + [3, 102, 35, 35, 0000, 1, ...] -> 1:02 + """ + if not nums: + return None + # nums[0] — это 3 + idx = 1 + if len(nums) > 1 and nums[1] == 0: + idx = 2 + if idx < len(nums): + t = nums[idx] + # считаем временем только разумные токены: секунды/3-цифр. спец./MMSS + if (0 <= t <= 59) or (100 <= t <= 999) or (1000 <= t <= 5959): + return self._mmss_to_str(t) + + # fallback (на всякий): ищем первый разумный токен до первого 4-значного блока + idx_flags = next((i for i, n in enumerate(nums) if len(str(n)) == 4), None) + search_upto = idx_flags if idx_flags is not None else len(nums) + for n in nums[:search_upto]: + if (0 <= n <= 59) or (100 <= n <= 999) or (1000 <= n <= 5959): + return self._mmss_to_str(n) + + return None + + @staticmethod + def _format_main_time_compact(n: int) -> str: + """ + Компактный формат 'MMSSd' (например, 13200 -> 13:20.0). + m = n // 1000 + s = (n // 10) % 100 + d = n % 10 (десятые) + Вывод: если m>0 -> 'M:SS', если m==0 -> 'SS:d' (как вы просили '< 1 мин — ss:ms'). + """ + if n < 0: + return "0:00" + m = n // 1000 + s = (n // 10) % 100 + d = n % 10 + if s >= 60: # подстраховка + m += s // 60 + s = s % 60 + if m > 0: + return f"{m}:{s:02d}" + else: + return f"{s}:{d}" + + def _format_shot_clock_from_tail_number(self, n: int) -> str | None: + """ + n — последнее число в строке (например, 21031). + Правило валидности: если последние две цифры == 31 — обновляем таймер, + если == 30 (или не 31) — не обновляем (возвращаем None). + Расчёт: отбрасываем две последние цифры -> n // 100 (секунды * 10). + >= 50 -> целые секунды ('21', '20', ...), иначе -> десятые ('4.9', ...). + """ + if n < 0: + return None + + tail = n % 100 + if tail != 31: + # 30 — специально игнорируем; всё, что не 31 — тоже игнорим + return None + + sec_tenths = n // 100 # «секунды × 10» + if sec_tenths >= 50: + return str(sec_tenths // 10) # «21», «20», ... + else: + return f"{sec_tenths / 10:.1f}" # «4.9», «4.8», ..., «0.0» + + + def _pick_scores_flags_and_quarter(self, nums: list[int]): + """ + Ищем последовательность: ... s1 s2 F1F2T1T2 Q ... + СЧЁТ ОБНОВЛЯЕМ ТОЛЬКО если нашли 4-значный блок флагов (1000..9999). + Если флагов нет — возвращаем None для счёта/флагов/четверти, + чтобы не перезатирать корректные прошлые значения. + """ + score1 = score2 = fouls1 = fouls2 = to1 = to2 = quarter = None + + # найдём первый 4-значный блок (флаги) + idx_flags = next((i for i, n in enumerate(nums) if 1000 <= n <= 9999), None) + if idx_flags is None: + # нет флагов -> ничего не обновляем + return score1, score2, fouls1, fouls2, to1, to2, quarter + + # перед флагами должны стоять два счёта + if idx_flags >= 2: + s1, s2 = nums[idx_flags - 2], nums[idx_flags - 1] + if 0 <= s1 <= 300 and 0 <= s2 <= 300: + score1, score2 = s1, s2 + + # разбираем флаги F1F2T1T2 + f = f"{nums[idx_flags]:04d}" + fouls1, fouls2, to1, to2 = map(int, f) + + # четверть — число сразу после флагов (1..10) + if idx_flags + 1 < len(nums): + q = nums[idx_flags + 1] + if 1 <= q <= 10: + quarter = q + + return score1, score2, fouls1, fouls2, to1, to2, quarter + + # 4) В parse_line() после nums = [...] добавьте вычисление секундника: + def parse_line(self, line: str) -> State | None: + if not (self.full_line_guard.search(line) and "0000" in line): + return None + + parts = self.re_numbers.findall(line) + if not parts: + return None + nums = [int(p) for p in parts] + + main_time_str = self._pick_main_time(nums) + s1, s2, f1, f2, to1, to2, q = self._pick_scores_flags_and_quarter(nums) + + # ⬇️ новый блок: секундник из последнего числа + # shot_clock_text = "" + # ⬇️ новый безопасный блок секундника + shot_clock_text = self.state.shot_clock # по умолчанию — предыдущее значение + if nums: # nums уже есть выше: nums = [int(p) for p in parts] + sc_new = self._format_shot_clock_from_tail_number(nums[-1]) + if sc_new is not None: + shot_clock_text = sc_new + + out = State( + main_time=main_time_str or self.state.main_time, + shot_clock=shot_clock_text, + score_1 = s1 if s1 is not None else self.state.score_1, + score_2 = s2 if s2 is not None else self.state.score_2, + fouls_1 = f1 if f1 is not None else self.state.fouls_1, + fouls_2 = f2 if f2 is not None else self.state.fouls_2, + timeouts_1 = to1 if to1 is not None else self.state.timeouts_1, + timeouts_2 = to2 if to2 is not None else self.state.timeouts_2, + quarter = q if q is not None else self.state.quarter, +) + return out + + def update_and_push(self, new_state: State): + old = self.state + for k, v in asdict(new_state).items(): + if getattr(old, k) != v and v is not None: + self._push_to_vmix(k, v) + self.state = new_state + + # 5) В _push_to_vmix оставьте как есть — он уже приводит value к строке. + # Если хотите реально отправлять в vMix — раскомментируйте vmix_call: + + def _push_to_vmix(self, key: str, value): + t = VMIX_TARGETS.get(key) + if not t: + return + # 👉 РАСКОММЕНТИРУЙТЕ для отправки в vMix + vmix_call( + function=t["Function"], + input_id=t["Input"], + value=str(value), + selected_name=t.get("SelectedName"), + selected_index=t.get("SelectedIndex"), + ) + # print(f"[push] {key} = {value}") + +_parser = SmartBasketParser() + +def parse(data: str): + print(data) + st = _parser.parse_line(data) + if st: + _parser.update_and_push(st) + else: + # полезно видеть, что игнорируем — закомментируйте, если мешает + print("[parse] пропуск строки (не формат �����3 + 0000)") + +# --------------------------- +# 2) Чтение из COM-порта и вызов parse +# --------------------------- +def read_loop(port: str, baud: int, newline: str, strip_whitespace: bool): + # мапинг для окончания строк в pyserial + eol = {"CRLF": b"\r\n", "LF": b"\n", "CR": b"\r"}.get(newline.upper(), b"\n") + + while True: + try: + with serial.Serial(port, baudrate=baud) as ser: + print(f"[serial] открыт {ser.port} @ {baud} бод. Ожидаю данные...") + buffer = bytearray() + while True: + chunk = ser.read(1024) + if not chunk: + continue + buffer.extend(chunk) + # разбираем по разделителю строк + while True: + idx = buffer.find(eol) + if idx == -1: + break + line = buffer[:idx] + del buffer[:idx + len(eol)] + try: + text = line.decode("utf-8", errors="replace") + except Exception: + text = line.decode("latin-1", errors="replace") + if strip_whitespace: + text = text.strip() + if text != "": + parse(text) + except SerialException as e: + print(f"[serial] не удалось открыть/читать {port}: {e}. Повтор через 3 сек...") + time.sleep(3) + except KeyboardInterrupt: + print("\n[serial] остановлено пользователем.") + break + except Exception as e: + print(f"[serial] непредвиденная ошибка: {e}. Повтор через 3 сек...") + time.sleep(3) + +def main(): + ap = argparse.ArgumentParser(description="Чтение COM и отправка в vMix через parse()") + ap.add_argument("--port", required=True, help="COM-порт, напр. COM3 (Windows) или /dev/ttyUSB0 (Linux)") + ap.add_argument("--baud", type=int, default=19200, help="Скорость, по умолчанию 19200") + ap.add_argument("--newline", choices=["LF", "CRLF", "CR"], default="CR", + help="Разделитель строк, по умолчанию LF") + ap.add_argument("--no-strip", action="store_true", + help="Не обрезать пробелы по краям (по умолчанию обрезаем)") + args = ap.parse_args() + + read_loop(args.port, args.baud, args.newline, strip_whitespace=not args.no_strip) + +if __name__ == "__main__": + main() diff --git a/timer COM3.py b/timer COM3.py new file mode 100644 index 0000000..064a117 --- /dev/null +++ b/timer COM3.py @@ -0,0 +1,486 @@ +# vmix_serial_bridge_optimized.py +# pip install pyserial requests + +""" +Оптимизированная версия COM -> vMix моста для максимально быстрой доставки +данных в vMix. Ключевые изменения: +- Немедленная обработка входящих байт: неблокирующее чтение с малой задержкой + (timeout) и мгновенная отправка строк при появлении EOL или коротком «простоя». +- Параметризуемые интервалы: --read-timeout, --idle-flush для тонкой настройки + задержки между получением и отправкой. +- Убраны лишние print'ы, добавлен флаг --verbose для отладки без штрафа к скорости. +- Дедупликация значений к vMix включаемая флагом (по умолчанию включена). +- Предкомпиляция регулярных выражений и мелкие микроптимизации парсера. +- Очередь отправки без блокировок и аккуратное «сбросить-старое-сообщение» поведение + на переполнении. + +Совместима с прежней CLI, но добавлены новые опции: + --read-timeout (сек, по умолчанию 0.03) + --idle-flush (сек, по умолчанию 0.06) + --max-chunk (байт, по умолчанию 512) + --verbose (подробные логи) + +Пример запуска: + python vmix_serial_bridge_optimized.py --port COM2 --baud 19200 --autoeol \ + --send-quarter --dedupe --read-timeout 0.02 --idle-flush 0.05 +""" + +import time +import argparse +import urllib.parse +import requests +import serial +from serial.serialutil import SerialException +from serial.tools import list_ports +import re +from dataclasses import dataclass +from threading import Thread, Event +from queue import Queue, Empty +from typing import Optional, Dict + +VMIX_HOST = "http://127.0.0.1:8088" + +VMIX_TARGETS = { + "main_time": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "TIMER.Text", "SelectedIndex": None}, + "shot_clock": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "24sec.Text", "SelectedIndex": None}, + "quarter": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "QUARTER.Text", "SelectedIndex": None}, + "score_1": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "SCORE1.Text", "SelectedIndex": None}, + "score_2": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "SCORE2.Text", "SelectedIndex": None}, + "fouls_1": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "FOULS1.Text", "SelectedIndex": None}, + "fouls_2": {"Function": "SetText", "Input": "SCOREBUG", "SelectedName": "FOULS2.Text", "SelectedIndex": None}, +} + +# ---------------- HTTP client ---------------- +class VmixClient: + def __init__(self, host: str, timeout: float = 0.01, retries: int = 2, backoff: float = 0.2): + self.host = host.rstrip("/") + self.timeout = timeout + self.retries = retries + self.backoff = backoff + self.session = requests.Session() + self.session.headers.update({"Connection": "keep-alive"}) + + def call(self, function: str, input_id: str, value: str, selected_name=None, selected_index=None) -> bool: + params = {"Function": function, "Input": input_id, "Value": value} + if selected_name: + params["SelectedName"] = selected_name + if selected_index is not None: + params["SelectedIndex"] = selected_index + url = f"{self.host}/api?{urllib.parse.urlencode(params, doseq=True, safe='')}" + for attempt in range(1, self.retries + 2): + try: + r = self.session.get(url, timeout=self.timeout) + r.raise_for_status() + return True + except requests.RequestException as e: + if attempt > self.retries: + return False + time.sleep(self.backoff * attempt) + return False + +@dataclass +class VmixMessage: + field: str + value: str + +class VmixSender: + def __init__(self, client: VmixClient, dedupe: bool = True, max_queue: int = 4096, verbose: bool = False): + self.client = client + self.queue: Queue[VmixMessage] = Queue(maxsize=max_queue) + self.stop_event = Event() + self.thread = Thread(target=self._run, name="vmix-sender", daemon=True) + self.dedupe = dedupe + self._last_sent: Dict[str, Optional[str]] = {} + self.verbose = verbose + + def start(self): + self.thread.start() + + def stop(self): + self.stop_event.set() + self.thread.join(timeout=2) + + def send(self, field: str, value: Optional[str]): + if value is None: + return + if field not in VMIX_TARGETS: + return + if self.dedupe and self._last_sent.get(field) == value: + return + if self.dedupe: + self._last_sent[field] = value + msg = VmixMessage(field, str(value)) + try: + self.queue.put_nowait(msg) + except Exception: + # Сбрасываем самое старое сообщение, чтобы не накапливать задержку + try: + _ = self.queue.get_nowait() + self.queue.task_done() + except Empty: + pass + self.queue.put_nowait(msg) + + def _run(self): + while not self.stop_event.is_set(): + try: + msg = self.queue.get(timeout=0.01) + except Empty: + continue + t = VMIX_TARGETS[msg.field] + ok = self.client.call(t["Function"], t["Input"], msg.value, t.get("SelectedName"), t.get("SelectedIndex")) + if self.verbose: + if ok: + print(f"[vMix] {msg.field} <- {msg.value}") + else: + print(f"[vMix] ERROR send {msg.field} <- {msg.value}") + self.queue.task_done() + +# ---------------- Parser ---------------- +_QUARTER_RE = re.compile(r"\s([1-5])\s\s\d{6}\s") + +def parse_time_5ch(chunk: str) -> Optional[str]: + if len(chunk) != 5: + return None + try: + if chunk[0:2] == "0 " or chunk[0:2] == " ": + print(f"{int(chunk[1:3])}:{int(chunk[3:5]):02d}") + return f"{int(chunk[1:3])}:{int(chunk[3:5]):02d}" + else: + return f"{int(chunk[1:3])}.{chunk[3]}" + except Exception: + return None + +def format_shot_clock_from_tail_number(n: str) -> str: + tail = n[-2:] + if tail == "30": + return "" # не обновлять + num = n[:2] + word_to_int = "ABCDEFGHI@" + if n[1] in word_to_int: + return f"{num[0]}.{word_to_int.index(num[1])+1 if num[1] != '@' else '0'}" + else: + return num + +@dataclass +class ParsedPacket: + main_time: Optional[str] = None + score1: Optional[str] = None + score2: Optional[str] = None + quarter: Optional[str] = None + shot_clock: Optional[str] = None + +def parse_line(line: str, verbose: bool = False) -> Optional[ParsedPacket]: + clean = line.strip().replace("�", "") + if len(clean) != 52: + clean = clean[-52:] + print(clean) + if not clean or clean[0] not in ["3", "7", "8"]: + return None + + # фиксированные позиции — всегда + main_time_raw = clean[2:7] + main_time = parse_time_5ch(main_time_raw) + + # score1/score2 есть только если строка начинается с "3" + score1 = None + score2 = None + if clean and clean[0] == "3": + s1 = clean[7:10].strip() + s2 = clean[10:13].strip() + if s1: + score1 = s1 + if s2: + score2 = s2 + + # четверть — всегда, если найдётся + quarter = None + m = _QUARTER_RE.search(clean) + if m: + quarter = m.group(1) + + # шот-клок — всегда, если хвост — число + shot_clock = None + tail = clean[-5:] + shot_clock = format_shot_clock_from_tail_number(tail) + + return ParsedPacket( + main_time=main_time, + score1=score1, + score2=score2, + quarter=quarter, + shot_clock=shot_clock, + )# ---------------- Serial reader ---------------- +EOLS = {"CR": b"\r", "LF": b"\n", "CRLF": b"\r\n"} + + +def sniff_eol(sample: bytes) -> bytes: + if b"\r\n" in sample: + return EOLS["CRLF"] + if b"\r" in sample and b"\n" not in sample: + return EOLS["CR"] + if b"\n" in sample: + return EOLS["LF"] + return EOLS["CR"] + +class SerialReader: + def __init__( + self, + port: str, + baud: int, + newline: str, + strip_ws: bool, + sender: VmixSender, + send_quarter: bool, + autoeol: bool, + bytesize: int, + parity: str, + stopbits: float, + rtscts: bool, + xonxoff: bool, + dsrdtr: bool, + read_timeout: float = 0.03, + idle_flush: float = 0.06, + max_chunk: int = 512, + verbose: bool = False, + ): + self.port = port + self.baud = baud + self.eol = EOLS.get(newline.upper(), b"\r") + self.strip_ws = strip_ws + self.sender = sender + self.send_quarter = send_quarter + self.autoeol = autoeol + self.bytesize = bytesize + self.parity = getattr(serial, f"PARITY_{parity.upper()}", serial.PARITY_NONE) + self.stopbits = {1: serial.STOPBITS_ONE, 1.5: serial.STOPBITS_ONE_POINT_FIVE, 2: serial.STOPBITS_TWO}[stopbits] + self.rtscts = rtscts + self.xonxoff = xonxoff + self.dsrdtr = dsrdtr + self.read_timeout = max(0.0, float(read_timeout)) + self.idle_flush = max(0.0, float(idle_flush)) + self.max_chunk = max(1, int(max_chunk)) + self.verbose = verbose + + def run(self): + while True: + try: + with serial.Serial( + self.port, + baudrate=self.baud, + timeout=self.read_timeout, # КЛЮЧЕВОЕ: неблокирующее чтение + write_timeout=0.01, + bytesize=self.bytesize, + parity=self.parity, + stopbits=self.stopbits, + rtscts=self.rtscts, + xonxoff=self.xonxoff, + dsrdtr=self.dsrdtr, + ) as ser: + # if self.verbose: + # print( + # f"[serial] OPEN {ser.port} @ {self.baud} ({self.bytesize}{self._parity_name()}{self._stopbits_name()})" + # ) + try: + ser.setDTR(True) + ser.setRTS(True) + except Exception: + pass + ser.reset_input_buffer() + ser.reset_output_buffer() + + buffer = bytearray() + last_feed = time.time() + + # Авто-детект EOL: быстрый сэмпл + if self.autoeol: + sample_t0 = time.time() + while time.time() - sample_t0 < 0.15: # ~150 мс + n = ser.in_waiting + if n: + chunk = ser.read(min(n, self.max_chunk)) + if chunk: + buffer.extend(chunk) + if buffer: + self.eol = sniff_eol(buffer) + if self.verbose: + print(f"[serial] auto EOL = {self._eol_name(self.eol)}") + break + + while True: + n = ser.in_waiting + if n: + chunk = ser.read(min(n, self.max_chunk)) + else: + # читаем «минимум 1 байт», чтобы не спиниться + chunk = ser.read(1) + + if chunk: + buffer.extend(chunk) + last_feed = time.time() + + progressed = False + while True: + idx = buffer.find(self.eol) + if idx == -1: + break + line = buffer[:idx] + del buffer[: idx + len(self.eol)] + text = self._decode(line, self.strip_ws) + if text: + self._process(text) + progressed = True + + # Если нет EOL и давно не приходили байты — отдаём накопленное + if not progressed and buffer and (time.time() - last_feed) >= self.idle_flush: + text = self._decode(buffer, self.strip_ws) + buffer.clear() + if text: + self._process(text) + + except SerialException as e: + if self.verbose: + print(f"[serial] ERROR open/read {self.port}: {e}. Retry in 0.5s...") + time.sleep(0.5) + except KeyboardInterrupt: + if self.verbose: + print("\n[serial] Stopped by user.") + return + except Exception as e: + if self.verbose: + print(f"[serial] UNEXPECTED: {e}. Retry in 0.5s...") + time.sleep(0.5) + + def _decode(self, raw: bytes, strip_ws: bool) -> Optional[str]: + try: + text = raw.decode("utf-8", errors="replace") + except Exception: + text = raw.decode("latin-1", errors="replace") + if strip_ws: + text = text.strip() + return text or None + + def _process(self, text: str): + pkt = parse_line(text, verbose=self.verbose) + if not pkt: + if self.verbose: + print(f"[serial] RAW: {text!r}") + return + if pkt.main_time is not None: + self.sender.send("main_time", pkt.main_time) + if pkt.score1 is not None: + self.sender.send("score_1", pkt.score1) + if pkt.score2 is not None: + self.sender.send("score_2", pkt.score2) + if self.send_quarter and pkt.quarter is not None: + self.sender.send("quarter", pkt.quarter) + if pkt.shot_clock is not None: + self.sender.send("shot_clock", pkt.shot_clock) + + def _parity_name(self): + return {"N": "N", "E": "E", "O": "O", "M": "M", "S": "S"}[self.parity] + + def _stopbits_name(self): + return { + serial.STOPBITS_ONE: "1", + serial.STOPBITS_ONE_POINT_FIVE: "1.5", + serial.STOPBITS_TWO: "2", + }[self.stopbits] + + def _eol_name(self, e: bytes): + return {b"\r": "CR", b"\n": "LF", b"\r\n": "CRLF"}.get(e, f"{e!r}") + + +# ---------------- Probe (sniffer) ---------------- + +def probe_port(port: str, baud: int, seconds: int, **kwargs): + print("[probe] Available ports:") + for p in list_ports.comports(): + print(f" - {p.device}: {p.description}") + try: + with serial.Serial(port, baudrate=baud) as ser: + print(f"[probe] OPEN {ser.port} @ {baud}. Sniffing {seconds}s...") + ser.reset_input_buffer() + t0 = time.time() + total = 0 + while time.time() - t0 < seconds: + b = ser.read(512) + if not b: + continue + total += len(b) + print(f"[{len(b):03d} bytes] HEX: {b.hex(' ')}") + try: + txt = b.decode("utf-8") + except Exception: + txt = b.decode("latin-1", errors="replace") + print(f" TXT: {txt!r}") + print(f"[probe] Done. Total bytes: {total}") + except Exception as e: + print(f"[probe] ERROR: {e}") + + +# ---------------- CLI ---------------- + +def main(): + ap = argparse.ArgumentParser(description="COM -> vMix bridge (optimized)") + ap.add_argument("--port", required=True, help="e.g. COM2 or /dev/ttyUSB0") + ap.add_argument("--baud", type=int, default=19200) + ap.add_argument("--newline", choices=["LF", "CRLF", "CR"], default="CR") + ap.add_argument("--autoeol", action="store_true", help="Auto-detect EOL from stream") + ap.add_argument("--no-strip", action="store_true") + ap.add_argument("--vmix-host", default=VMIX_HOST) + ap.add_argument("--timeout", type=float, default=0.01) + ap.add_argument("--retries", type=int, default=2) + ap.add_argument("--backoff", type=float, default=0.2) + ap.add_argument("--dedupe", action="store_true", help="Deduplicate values before sending to vMix") + ap.add_argument("--send-quarter", action="store_true") + ap.add_argument("--read-timeout", type=float, default=0.03, help="Serial read timeout (s)") + ap.add_argument("--idle-flush", type=float, default=0.06, help="Flush partial line after idle (s)") + ap.add_argument("--max-chunk", type=int, default=512, help="Max bytes per read()") + ap.add_argument("--verbose", action="store_true") + # serial low-level + ap.add_argument("--bytesize", type=int, choices=[5, 6, 7, 8], default=8) + ap.add_argument("--parity", choices=["N", "E", "O", "M", "S"], default="N") + ap.add_argument("--stopbits", type=float, choices=[1, 1.5, 2], default=1) + ap.add_argument("--rtscts", action="store_true") + ap.add_argument("--xonxoff", action="store_true") + ap.add_argument("--dsrdtr", action="store_true") + # tools + ap.add_argument("--probe", type=int, metavar="SECONDS", help="Sniff raw bytes/text for N seconds and exit") + args = ap.parse_args() + + if args.probe: + probe_port(args.port, args.baud, args.probe) + return + + client = VmixClient(host=args.vmix_host, timeout=args.timeout, retries=args.retries, backoff=args.backoff) + sender = VmixSender(client=client, dedupe=args.dedupe or True, verbose=args.verbose) + sender.start() + + reader = SerialReader( + port=args.port, + baud=args.baud, + newline=args.newline, + strip_ws=not args.no_strip, + sender=sender, + send_quarter=args.send_quarter, + autoeol=args.autoeol, + bytesize=args.bytesize, + parity=args.parity, + stopbits=args.stopbits, + rtscts=args.rtscts, + xonxoff=args.xonxoff, + dsrdtr=args.dsrdtr, + read_timeout=args.read_timeout, + idle_flush=args.idle_flush, + max_chunk=args.max_chunk, + verbose=args.verbose, + ) + try: + reader.run() + finally: + sender.stop() + + +if __name__ == "__main__": + main() diff --git a/timer GPT 1.py b/timer GPT 1.py new file mode 100644 index 0000000..5a39d21 --- /dev/null +++ b/timer GPT 1.py @@ -0,0 +1,117 @@ +# serial_to_vmix.py +# pip install pyserial requests + +import time +import argparse +import socket +import urllib.parse +import requests +import serial +from serial.serialutil import SerialException + +# --------------------------- +# 1) ВАША функция отправки в vMix +# Замените содержимое по своему желанию. +# --------------------------- +def parse(data: str): + """ + Пользовательская обработка/отправка данных в vMix. + Здесь просто печатаем; замените на вашу логику. + """ + print(f"[parse] {data}") + +# ---- ПРИМЕРЫ реализации parse (раскомментируйте нужное) ---- +# Пример A: отправка через vMix HTTP API (SetText в определённый input/title) +# def parse(data: str): +# vmix_host = "http://127.0.0.1:8088" # адрес vMix Web Controller +# function = "SetText" +# input_id = "1" # замените на ваш Input (номер/имя/строка GUID) +# selected_title = None # если нужно указать конкретный Title layer: "TitleName.xaml" +# field = None # если нужно указать конкретное текстовое поле в титре +# +# params = { +# "Function": function, +# "Input": input_id, +# "Value": data +# } +# if selected_title: +# params["SelectedName"] = selected_title +# if field: +# params["SelectedIndex"] = field +# +# # важно: корректно кодируем Value +# url = f"{vmix_host}/api?{urllib.parse.urlencode(params, doseq=True, safe='')}" +# try: +# r = requests.get(url, timeout=2) +# r.raise_for_status() +# except requests.RequestException as e: +# print(f"[parse][HTTP] ошибка запроса к vMix: {e}") + +# Пример B: отправка одной строки в vMix TCP (порт 8099) — например, выполнить функцию +# def parse(data: str): +# vmix_tcp_host = "127.0.0.1" +# vmix_tcp_port = 8099 +# # пример: выполнить SetText +# cmd = f"FUNCTION SetText Input=1 Value=\"{data}\"\r\n" +# try: +# with socket.create_connection((vmix_tcp_host, vmix_tcp_port), timeout=2) as s: +# s.sendall(cmd.encode("utf-8")) +# except OSError as e: +# print(f"[parse][TCP] ошибка сокета к vMix: {e}") + +# --------------------------- +# 2) Чтение из COM-порта и вызов parse +# --------------------------- +def read_loop(port: str, baud: int, newline: str, strip_whitespace: bool): + # мапинг для окончания строк в pyserial + eol = {"CRLF": b"\r\n", "LF": b"\n", "CR": b"\r"}.get(newline.upper(), b"\n") + + while True: + try: + with serial.Serial(port, baudrate=baud, timeout=1) as ser: + print(f"[serial] открыт {ser.port} @ {baud} бод. Ожидаю данные...") + buffer = bytearray() + while True: + chunk = ser.read(1024) + if not chunk: + continue + buffer.extend(chunk) + # разбираем по разделителю строк + while True: + idx = buffer.find(eol) + if idx == -1: + break + line = buffer[:idx] + del buffer[:idx + len(eol)] + try: + text = line.decode("utf-8", errors="replace") + except Exception: + text = line.decode("latin-1", errors="replace") + if strip_whitespace: + text = text.strip() + if text != "": + parse(text) + except SerialException as e: + print(f"[serial] не удалось открыть/читать {port}: {e}. Повтор через 3 сек...") + time.sleep(3) + except KeyboardInterrupt: + print("\n[serial] остановлено пользователем.") + break + except Exception as e: + print(f"[serial] непредвиденная ошибка: {e}. Повтор через 3 сек...") + time.sleep(3) + +def main(): + ap = argparse.ArgumentParser(description="Чтение COM и отправка в vMix через parse()") + ap.add_argument("--port", required=True, help="COM-порт, напр. COM3 (Windows) или /dev/ttyUSB0 (Linux)") + ap.add_argument("--baud", type=int, default=19200, help="Скорость, по умолчанию 9600") + ap.add_argument("--newline", choices=["LF", "CRLF", "CR"], default="CR", + help="Разделитель строк, по умолчанию LF") + ap.add_argument("--no-strip", action="store_true", + help="Не обрезать пробелы по краям (по умолчанию обрезаем)") + args = ap.parse_args() + + read_loop(args.port, args.baud, args.newline, strip_whitespace=not args.no_strip) + +if __name__ == "__main__": + main() diff --git a/timer NATA Kazan.py b/timer NATA Kazan.py new file mode 100644 index 0000000..d7e26bb --- /dev/null +++ b/timer NATA Kazan.py @@ -0,0 +1,189 @@ +import sys +import json +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii +import requests + + +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def send_data(name, value): + url = "http://127.0.0.1:8088/API/" + par = "SetText" if name.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": 33, + "SelectedName": name, + "Value": value, + } + session.get(url, params=params) + +def parse_new(line): + try: + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + except json.decoder.JSONDecodeError: + new_data = [ + { + "timeGFX": "0:00", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + "timeout1": "0", + "timeout2": "0", + } + ] + + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + # print(temp) + for i in temp: + if "7D 4A C0 0A" in i: #основной таймер + minutes = int(i.split()[-5], ) + seconds = int(i.split()[-4], ) + milliseconds = int(i.split()[-3], ) + timer_str = ( + f"{minutes}:{seconds:02d}" if minutes != 0 else f"{seconds}.{milliseconds}" + ) + send_data("TIMER.Text", timer_str) + + # print(i.split()[-7], i) + # if i.split()[-7] == "13" or i.split()[-7] == "10": + # new_data[0]["timeGFX"] = timer_str + elif "7D 4A C0 07" in i: #Счет + if i.split()[-7] == "06": #Счет первой команды + score1 = int(i.split()[-4], 16) + # new_data[0]["points1"] = score1 + send_data("SCORE1.Text", score1) + elif i.split()[-7] == "07": #Счет второй команды + score2 = int(i.split()[-4], 16) + send_data("SCORE2.Text", score2) + # new_data[0]["points2"] = score2 + else: + print("[СЧЁТ] == НЕПОНЯТНО") + elif "7D 4A C0 06" in i: #Информация + if i.split()[-6] == "09": #фолы первой команды + foul1 = int(i.split()[-3], 16) + # new_data[0]["foul1"] = foul1 + send_data("fouls1.Source", f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Away_{foul1}.png") + elif i.split()[-6] == "0A": #фолы второй команды + foul2 = int(i.split()[-3], 16) + send_data("fouls2.Source", f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Away_{foul2}.png") + # new_data[0]["foul2"] = foul2 + elif i.split()[-6] == "0E": #тайм-аут первой команды + time_out1 = int(i.split()[-3], 16) + # new_data[0]["timeout1"] = time_out1 + elif i.split()[-6] == "0F": #тайм-аут второй команды + time_out2 = int(i.split()[-3], 16) + # new_data[0]["timeout2"] = time_out2 + elif i.split()[-6] == "08": #четверть + quarter = int(i.split()[-3], 16) + # new_data[0]["quarter"] = quarter + + elif "79 84 C0 0A" in i: #24 секунды + print(i) + seconds = int(i.split()[-4]) + milliseconds = int(i.split()[-3]) + if seconds < int(5): + time_attack = f"{seconds}.{milliseconds}" + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Red.png" + else: + time_attack = seconds + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Empty.png" + if time_attack == "0.0": + time_attack = "" + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Empty.png" + send_data("24sec.Text", time_attack) + # send_data("24SECBACKGROUND.Source", timer_pic) + + # print(time_attack) + elif "89 4E C8 05" in i: + if i.split()[-3] == "05": #таймер 24 секунд выключен + time_attack = "" + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Empty.png" + send_data("24sec.Text", time_attack) + # send_data("24SECBACKGROUND.Source", timer_pic) + # data = { + # "TIMER.Text": timer_str, + # "ATTACK.Text": time_attack, + # "Score_Home.Text": score1, + # "Score_Away.Text": score2, + # "fouls1.Source": f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Home_{foul1}.png", + # "fouls2.Source": f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Away_{foul2}.png", + # "24SECBACKGROUND.Source": timer_pic, + # } + +def read_logs(): + with open( + r"C:\Users\soule\Downloads\Telegram Desktop\timer_Megasport_Nport_2024-03-05_20-00-17.log", + "r", + ) as file: + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + if b"\xf83" in data or b"\xf88" in data or b"\xf87" in data: + parse(data) + time.sleep(0.1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_Nata_Nport_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + parse_new(data) + logging.debug(data) + + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_KAZ.py b/timer_KAZ.py new file mode 100644 index 0000000..5e511f5 --- /dev/null +++ b/timer_KAZ.py @@ -0,0 +1,162 @@ +import sys +import json +from socket import * +from datetime import datetime +import time +import os +# import logging + + +VERSION = "версия 2" # от 02.04.2024 + +host = "192.168.127.254" +port = 1993 +ADDR = (host, port) +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def save_log(name, data): + current_time = datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f") + message_with_time = f"[{current_time}] {data}" + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + with open(f"LOGS/{name}", "a") as file: + file.write(message_with_time + "\n") + + +def parse(data, score1, score2): + data = data.split("/") + + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + new_data = new_data[0] + path_pic = r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + # print(data) + diff1, diff2 = 0, 0 + try: + if len(data) > 10: + if data[4] == "NPR": + new_data["quarter"] = data[5] + if data[17] == "HCP": + new_data["points1"] = data[18] + if score1 != new_data["points1"]: + diff1 = int(new_data["points1"]) - int(score1) + score1 = new_data["points1"] + if data[20] == "GCP": + new_data["points2"] = data[21] + if score2 != new_data["points2"]: + diff2 = int(new_data["points2"]) - int(score2) + score2 = new_data["points2"] + if data[29] == "HCF": + new_data["foul1"] = data[30] + new_data["foul_pic1"] = path_pic + f"\\Home_{int(data[30])}.png" + if data[32] == "GCF": + new_data["foul2"] = data[33] + new_data["foul_pic2"] = path_pic + f"\\Away_{int(data[33])}.png" + else: + if data[1] == "TGI": + if data[2] != "0": + seconds = data[3] if len(data[3]) != 1 else f"0{data[3]}" + new_data["timeGFX"] = f"{data[2]}:{seconds}" + else: + millisec = data[4] + if not millisec.isdigit(): + millisec = "0" + new_data["timeGFX"] = f"{data[3]}.{millisec}" + elif data[1] == "NPR": + new_data["quarter"] = data[2] + elif data[1] == "HCP": + new_data["points1"] = data[2] + if score1 != new_data["points1"]: + diff1 = int(new_data["points1"]) - int(score1) + score1 = new_data["points1"] + elif data[1] == "GCP": + new_data["points2"] = data[2] + if score2 != new_data["points2"]: + diff2 = int(new_data["points2"]) - int(score2) + score2 = new_data["points2"] + elif data[1] == "HCF": + new_data["foul1"] = data[2] + new_data["foul_pic1"] = path_pic + f"\\Home_{int(data[2])}.png" + if len(data) > 4 and data[4] == "GCF": + new_data["foul2"] = data[2] + new_data["foul_pic2"] = path_pic + f"\\Away_{int(data[2])}.png" + elif data[1] == "GCF": + new_data["foul2"] = data[2] + new_data["foul_pic2"] = path_pic + f"\\Away_{int(data[2])}.png" + elif data[1] == "TAI": + if data[2] not in ["0", "-1"]: + new_data["time_attackGFX"] = str(int(data[2])) + elif data[2] == "-1": + new_data["time_attackGFX"] = "" + new_data["time_attac_pic"] = path_pic + "\\24Sec_empty.png" + if 0 < int(data[2]) <= 5: + new_data["time_attac_pic"] = path_pic + "\\24Sec_Red.png" + else: + if int(data[2]) in [0, -1]: + new_data["time_attac_pic"] = path_pic + "\\24Sec_empty.png" + else: + new_data["time_attac_pic"] = path_pic + "\\24Sec_Orange.png" + + print(f'{diff1}, {diff2}, {new_data["timeGFX"]:<5}, {new_data["time_attackGFX"]:<3}, {new_data["points1"]:<3}, {new_data["points2"]:<3}, {new_data["foul1"]:<2}, {new_data["foul2"]:<2}') + except Exception as ex: + print(ex) + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + # if ":" in new_data["timeGFX"]: + # time.sleep(.5) + # else: + # time.sleep(.1) + + except Exception: + pass + + return score1, score2 + + +def main(): + current_time = datetime.now().strftime("%d-%m-%Y_%H-%M-%S") + + new_data = { + "timeGFX": "0:00", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect(ADDR) + score1, score2 = 0, 0 + + try: + while True: + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + data = tcp_socket.recv(1024) + data = data.decode("utf-8", errors="ignore") + print(data) + + save_log(f"logs_mba_{VERSION}_{current_time}.txt", data) + score1, score2 = parse(data, score1, score2) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_MBA.py b/timer_MBA.py new file mode 100644 index 0000000..89b9c2c --- /dev/null +++ b/timer_MBA.py @@ -0,0 +1,208 @@ +import sys +import json +from socket import * +from datetime import datetime +import time +import os +# import logging +import requests + + +VERSION = "версия 2" # от 02.04.2024 + +host = "10.0.0.57" +port = 50002 +ADDR = (host, port) +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + +def save_log(name, data): + current_time = datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f") + message_with_time = f"[{current_time}] {data}" + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + with open(f"LOGS/{name}", "a") as file: + file.write(message_with_time + "\n") + + +def send_data(name, value): + url = "http://127.0.0.1:8088/API/" + par = "SetText" if name.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": 41, + # "Input": "SCOREBUG", + "SelectedName": name, + "Value": value, + } + session.get(url, params=params) + + +def parse(data, score1, score2): + data = data.split("/") + + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + new_data = new_data[0] + path_pic = r"D:\графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ ФИНАЛ ЧЕТЫРЕХ\FOULS" + # print(data) + diff1, diff2 = 0, 0 + if len(data) > 10: + if data[4] == "NPR": + new_data["quarter"] = data[5] + if data[17] == "HCP": + new_data["points1"] = data[18] + if score1 != new_data["points1"]: + diff1 = int(new_data["points1"]) - int(score1) + score1 = new_data["points1"] + if data[20] == "GCP": + new_data["points2"] = data[21] + if score2 != new_data["points2"]: + diff2 = int(new_data["points2"]) - int(score2) + score2 = new_data["points2"] + if data[29] == "HCF": + new_data["foul1"] = data[30] + new_data["foul_pic1"] = path_pic + f"\\FOULS_{int(data[30])}.png" + if data[32] == "GCF": + new_data["foul2"] = data[33] + new_data["foul_pic2"] = path_pic + f"\\FOULS_{int(data[33])}.png" + else: + if data[1] == "TGI": + if data[2] != "0": + seconds = data[3] if len(data[3]) != 1 else f"0{data[3]}" + new_data["timeGFX"] = f"{data[2]}:{seconds}" + else: + millisec = data[4] + if not millisec.isdigit(): + millisec = "0" + new_data["timeGFX"] = f"{data[3]}.{millisec}" + elif data[1] == "NPR": + new_data["quarter"] = data[2] + elif data[1] == "HCP": + new_data["points1"] = data[2] + if score1 != new_data["points1"]: + diff1 = int(new_data["points1"]) - int(score1) + score1 = new_data["points1"] + elif data[1] == "GCP": + new_data["points2"] = data[2] + if score2 != new_data["points2"]: + diff2 = int(new_data["points2"]) - int(score2) + score2 = new_data["points2"] + elif data[1] == "HCF": + new_data["foul1"] = data[2] + new_data["foul_pic1"] = path_pic + f"\\FOULS_{int(data[2])}.png" + if len(data) > 4 and data[4] == "GCF": + new_data["foul2"] = data[2] + new_data["foul_pic2"] = path_pic + f"\\FOULS_{int(data[2])}.png" + elif data[1] == "GCF": + new_data["foul2"] = data[2] + new_data["foul_pic2"] = path_pic + f"\\FOULS_{int(data[2])}.png" + elif data[1] == "TAI": + if data[2] not in ["0", "-1"]: + new_data["time_attackGFX"] = str(int(data[2])) + elif data[2] == "-1": + new_data["time_attackGFX"] = "" + new_data["time_attac_pic"] = path_pic + "\\24Sec_empty.png" + if 0 < int(data[2]) <= 5: + new_data["time_attac_pic"] = path_pic + "\\24Sec_Red.png" + else: + if int(data[2]) in [0, -1]: + new_data["time_attac_pic"] = path_pic + "\\24Sec_empty.png" + else: + new_data["time_attac_pic"] = path_pic + "\\24Sec_Orange.png" + send_data("Timer.Text", new_data["timeGFX"]) + send_data("Score_Team1.Text", new_data["points1"]) + send_data("Score_Team2.Text", new_data["points2"]) + send_data("Timer24sec.Text", new_data["time_attackGFX"]) + send_data("FOULS_TEAM_A.Source", new_data["foul_pic1"]) + send_data("FOULS_TEAM_B.Source", new_data["foul_pic2"]) + + print(f'{diff1}, {diff2}, {new_data["timeGFX"]:<5}, {new_data["time_attackGFX"]:<3}, {new_data["points1"]:<3}, {new_data["points2"]:<3}, {new_data["foul1"]:<2}, {new_data["foul2"]:<2}') + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + # if ":" in new_data["timeGFX"]: + # time.sleep(.5) + # else: + # time.sleep(.1) + + except Exception: + pass + + return score1, score2 + + +def read_logs(): + score1, score2 = 0, 0 + new_data = { + "timeGFX": "0:00", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + with open("D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\logs_mba_3.txt", "r") as file: + for line in file: + parts = line.strip().split("] ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = parts[1] + score1, score2 = parse(data, score1, score2) + time.sleep(.1) + + +def main(): + current_time = datetime.now().strftime("%d-%m-%Y_%H-%M-%S") + + new_data = { + "timeGFX": "0:00", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect(ADDR) + score1, score2 = 0, 0 + + try: + while True: + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + data = tcp_socket.recv(1024) + data = data.decode("utf-8", errors="ignore") + print(data) + + save_log(f"logs_mba_{VERSION}_{current_time}.txt", data) + score1, score2 = parse(data, score1, score2) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_NN.py b/timer_NN.py new file mode 100644 index 0000000..887eedc --- /dev/null +++ b/timer_NN.py @@ -0,0 +1,171 @@ +import sys +import json +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii +import requests + +HOST = "192.168.0.7" +PORT = 40004 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def timer(line): + temp_new = [int(t, 16) for t in line.split()] + minutes = temp_new[4] + seconds = temp_new[5] + milliseconds = temp_new[6] + timer_str = ( + f"{minutes}:{seconds:02d}" if minutes != 0 else f"{seconds}.{milliseconds}" + ) + return timer_str + + +def attack_time(line): + temp_new = [int(t, 16) for t in line.split()] + path_pic = r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + if temp_new[7] != 2: + seconds = temp_new[5] + milliseconds = temp_new[6] + if int(seconds) > 4: + if int(milliseconds) >= 5: + seconds = int(seconds) + 1 + else: + seconds = seconds + time_attack = seconds + else: + time_attack = f"{seconds}.{milliseconds}" + if time_attack == "0.0": + time_attack = "" + # time_attack = ( + # temp_new[5] + # if temp_new[5] > 4 + # else f"{temp_new[5]}.{temp_new[6]}" + # if f"{temp_new[5]}.{temp_new[6]}" != "0.0" + # else "" + # ) + path_pic = path_pic + ( + "\\24Sec_Orange.png" + if temp_new[5] > 4 + else ( + "\\24Sec_Red.png" + if f"{temp_new[5]}.{temp_new[6]}" != "0.0" + else "\\24Sec_empty.png" + ) + ) + else: + time_attack = "" # temp_new[-2] == 1 - таймер идёт | 2 - таймер стоит | 0 - таймер не отображён + path_pic = path_pic + "\\24Sec_empty.png" + return time_attack, path_pic + +def send_data(name, value): + url = "http://127.0.0.1:8088/API/" + par = "SetText" if name.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + # "Input": 41, + "Input": "SCOREBUG", + "SelectedName": name, + "Value": value, + } + session.get(url, params=params) + +def parse(line): + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + + temp_line = "" + line = "" + if len(edata.split()) in [2, 31, 32, 1]: + if temp_line == "": + temp_line = edata + else: + line = temp_line + edata + temp_line = "" + else: + line = edata + + data = line.split("FE FF") + path_pic_foul = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + ) + diff1, diff2 = 0, 0 + for d in data: + if d != "": + temp_d = d.strip() + if "08 01" in temp_d[:5] and str(temp_d.split()[-2])[0] == "8": + timer_str = timer(temp_d) + send_data("TIMER.Text", timer_str) + aaaaa = temp_d.split()[-2] + elif "08 03" in temp_d[:5]: + time_attack, path_pic = attack_time(temp_d) + send_data("24sec.Text", time_attack) + aaaa = temp_d.split()[-2], int(temp_d.split()[-2], 16) + elif "0D 1F" in temp_d[:5]: + send_data("SCORE1.Text", int(temp_d.split()[2], 16)) + send_data("SCORE2.Text", int(temp_d.split()[3], 16)) + + +def read_logs(): + + score1, score2 = 0, 0 + with open("timer_NN_1.log", "r") as file: + # with open("timer_NN_test.log", "r") as file: + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + parse(data) + time.sleep(0.1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_NN_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + print(data) + logging.debug(data) + parse(data) + + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_NN_backup.py b/timer_NN_backup.py new file mode 100644 index 0000000..2ff2b08 --- /dev/null +++ b/timer_NN_backup.py @@ -0,0 +1,159 @@ +import sys +import json +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii + +HOST = "192.168.0.7" +PORT = 40004 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def parse(line): + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + path_pic = r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + + if len(edata.split()) in [32, 33, 40]: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + minutes = temp_new[6] + seconds = temp_new[7] + milliseconds = temp_new[8] + timer_str = ( + f"{minutes}:{seconds:02d}" + if minutes != 0 + else f"{seconds}.{milliseconds}" + ) + active_temp = temp_new[ + 9 + ] # 133 - таймер идёт | 132 - таймер стоит | 128 - не игровое время стоит | 129 - не игровое время идёт + + if temp_new[31] not in [2]: + time_attack = ( + temp_new[29] if temp_new[29] > 4 else f"{temp_new[29]}.{temp_new[30]}" if f"{temp_new[29]}.{temp_new[30]}" != "0.0" else "" + ) + path_pic = path_pic + ("\\24Sec_Orange.png" if temp_new[29] > 4 else "\\24Sec_Red.png" if f"{temp_new[29]}.{temp_new[30]}" != "0.0" else "\\24Sec_empty.png") + else: + time_attack = "" # temp_new[-2] == 1 - таймер идёт | 2 - таймер стоит | 0 - таймер не отображён + path_pic = path_pic + "\\24Sec_empty.png" + + # print(f"{str(temp_new):<120}__{timer_str:<7}__{time_attack:<3}__") + new_data[0]["timeGFX"] = timer_str + new_data[0]["time_attackGFX"] = time_attack + new_data[0]["time_attac_pic"] = path_pic + else: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + timer_str = "99:99" + time_attack = "99:99" + + + print(len(edata.split()), f"{str(edata):<120}__{timer_str:<7}__{time_attack:<3}__") + + + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump(new_data, file, ensure_ascii=False, indent=4) + # if ":" in new_data["timeGFX"]: + # time.sleep(.5) + # else: + # time.sleep(.1) + + except Exception: + pass + + + # with open("timer_NN.csv", "a+") as file: + # file.write(str(temp_new)) + # file.write("\n") + # with open("timer_NN_2.csv", "a+") as file: + # file.write(str(temp_data)) + # file.write("\n") + # with open("timer_NN_3.csv", "a+") as file: + # file.write(str(ddata)) + # file.write("\n") + + # time.sleep(0.1) + + +def read_logs(): + with open("timer_NN_1.log", "r") as file: + # with open("timer_NN_test.log", "r") as file: + temp_line = "" + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + parse(data) + time.sleep(.05) + + # if len(eval(data)) > 30 and eval(data)[-7] == "00": + # time.sleep(.1) + # else: + # time.sleep(1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_NN_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + new_data = { + "timeGFX": "0:00", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + print(data) + logging.debug(data) + parse(data) + + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + # main() + read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_NPORT_Deepron.py b/timer_NPORT_Deepron.py new file mode 100644 index 0000000..d1ffd54 --- /dev/null +++ b/timer_NPORT_Deepron.py @@ -0,0 +1,153 @@ +import sys +from socket import * +from datetime import datetime +import logging +import os +import time +import requests + + +SETTING = "9600,RS-232" +HOST = "192.168.127.254" +PORT = 1993 +URL = "http://127.0.0.1:8088/API/" +INPUT = ["ТАЙМЕР МУЖЧИНЫ", "ТАЙМЕР ЖЕНЩИНЫ"] + + +def send_data(data, name): + for i in INPUT: + params = { + "Function": "SetText", + "Input": i, + "SelectedName": f"{name}.Text", + "Value": data, + } + requests.get(URL, params=params) + + +def win(name): + params = { + "Function": "SetTextColour", + "Input": INPUT, + "SelectedName": f"{name}.Text", + "Value": "Green", + } + requests.get(URL, params=params) + + +def reset(name): + params = { + "Function": "SetTextColour", + "Input": INPUT, + "SelectedName": f"{name}.Text", + "Value": "white", + } + requests.get(URL, params=params) + + +def func_new(i, name, tag): + data = ( + i.split(f"{tag}<")[1] + .replace("0'0", "") + .replace("0'", "") + .replace("10>", "") + .split()[0] + ) + if "FALSE START" in i: + send_data("FS", name) + elif "OK NO FS" in i: + pass + else: + send_data(data, name) + # if "WIN" in i: + # win(name) + + +def parse(line): + decode_line = line.decode("utf-8") + print(decode_line) + temp_list = decode_line.split("") + name1, name2, name3, name4 = "Time1", "Time2", "Reaction1", "Reaction2" + for i in temp_list: + if i != "": + if "READY" in i: + send_data('0"000', name1) + send_data('0"000', name2) + send_data("", name3) + send_data("", name4) + # reset(name1) + # reset(name2) + + if not any(char in i[7] for char in ["R", "G", "B", "C", "Y", "M", "A"]): + if "" in i and not any(char in i for char in ["$", "@", "%"]): + func_new(i, name1, "") + elif "" in i and not any(char in i for char in ["$", "@", "%"]): + func_new(i, name2, "") + elif "" in i: + func_new(i, name3, "") + elif "" in i: + func_new(i, name4, "") + + +def read_logs(): + with open("C:\Code\LOGS\\timer_NPORT_tcp_2024-03-29_13-24-22.log", "r") as file: + timestamp_temp = "" + diff_time = 0 + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0] + if timestamp_temp == "": + timestamp_temp = timestamp + else: + time_format = "%Y-%m-%d %H:%M:%S,%f" + timestamp_datetime = datetime.strptime(timestamp, time_format) + timestamp_temp_datetime = datetime.strptime( + timestamp_temp, time_format + ) + delta = timestamp_datetime - timestamp_temp_datetime + seconds = delta.total_seconds() # Convert timedelta to seconds + timestamp_temp = timestamp + time.sleep(abs(seconds - diff_time)) + data = eval(parts[1]) + start_time = time.time() + parse(data) + end_time = time.time() + diff_time = end_time - start_time + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_NPORT_tcp_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + logging.debug(data) + parse(data) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # while True: + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_NPORT_коньки.py b/timer_NPORT_коньки.py new file mode 100644 index 0000000..590ce42 --- /dev/null +++ b/timer_NPORT_коньки.py @@ -0,0 +1,128 @@ +import sys +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii +import requests + + +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def parse(line): + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + + if len(edata.split()) == 33: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + minutes = temp_new[6] + seconds = temp_new[7] + milliseconds = temp_new[8] + timer_str = ( + f"{minutes}:{seconds:02d}" + if minutes != 0 + else f"{seconds:02d}.{milliseconds}" + ) + active_temp = temp_new[ + 9 + ] # 133 - таймер идёт | 132 - таймер стоит | 128 - не игровое время стоит | 129 - не игровое время идёт + + if temp_new[-2] != 0: + time_attack = ( + temp_new[-4] if temp_new[-4] > 4 else f"{temp_new[-4]}.{temp_new[-3]}" + ) + else: + time_attack = "" # temp_new[-2] == 1 - таймер идёт | 2 - таймер стоит | 0 - таймер не отображён + + # print(f"{str(temp_new):<120}__{timer_str:<7}__{time_attack:<3}__") + else: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + + # time.sleep(0.1) + + +def read_logs(): + with open("timer_NN_2023-12-20_18-17-29.log", "r") as file: + # with open("timer_NN_test.log", "r") as file: + temp_line = "" + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + parse(data) + time.sllep(0.1) + + # if len(eval(data)) > 30 and eval(data)[-7] == "00": + # time.sleep(.1) + # else: + # time.sleep(1) + + +def parse_2(data): + data = data.decode() + print(data) + if "S04" in data: + temp = data.split("S04")[1] + print(f"{data:<50}", temp) + elif "S09" in data: #White + temp = data + elif "S00" in data: #Red + temp = data + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_NPORT_zzz_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + temp = b"" + line_new = b"" + while True: + data = tcp_socket.recv(1024) + logging.debug(data) + print(data) + if b"\x03" in data: + temp += data + line_new = temp + temp = b"" + else: + temp += data + + parse_2(line_new) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_app.py b/timer_app.py new file mode 100644 index 0000000..34644d7 --- /dev/null +++ b/timer_app.py @@ -0,0 +1,92 @@ +import socket +import tkinter as tk +import threading +import re + + +def on_validate(P): + # Проверка на соответствие шаблону IP-адреса (допускаются промежуточные неполные значения) + pattern = ( + r"^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){0,3}" + r"(25[0-5]|2[0-4]\d|[01]?\d\d?)?$" + ) + return re.match(pattern, P) is not None + + +class ServerConnectionApp: + def __init__(self, root): + self.root = root + self.root.title("Server Connection App") + + # GUI setup + self.setup_gui() + + # Server connection + self.client_socket = None + + def setup_gui(self): + self.ip_label = tk.Label(self.root, text="IP Address:") + self.ip_label.grid(row=0, column=0) + + self.ip_entry = tk.Entry(self.root) + self.ip_entry.grid(row=0, column=1) + self.ip_entry.insert(0, "127.0.0.1") # Default IP address (localhost) + + self.port_label = tk.Label(self.root, text="Port:") + self.port_label.grid(row=1, column=0) + + self.port_entry = tk.Entry(self.root) + self.port_entry.grid(row=1, column=1) + self.port_entry.insert(0, "12345") # Default port + + self.connect_button = tk.Button(self.root, text="Connect", command=self.initiate_connection) + self.connect_button.grid(row=2, column=0, columnspan=2) + + self.status_label = tk.Label(self.root, text="") + self.status_label.grid(row=3, column=0, columnspan=2) + + def initiate_connection(self): + ip = self.ip_entry.get() + port = int(self.port_entry.get()) + + # Create a thread to avoid blocking the GUI + connection_thread = threading.Thread(target=self.connect_to_server, args=(ip, port)) + connection_thread.daemon = True + connection_thread.start() + + def connect_to_server(self, ip, port): + try: + self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.client_socket.connect((ip, port)) + self.status_label.config(text="Connected successfully.") + + # Consume the data and print it to the console + self.listen_to_server() + + except Exception as e: + self.status_label.config(text=f"Connection failed: {e}") + + def listen_to_server(self): + try: + while True: + data = self.client_socket.recv(1024) + if data: + print("Received from server:", data.decode()) + else: + # Connection is closed + print("Server has closed the connection.") + self.client_socket.close() + break + except Exception as e: + print(f"Error while listening to the server: {e}") + if self.client_socket: + self.client_socket.close() + +# Create the Tkinter window +root = tk.Tk() + +# Create an instance of the app +app = ServerConnectionApp(root) + +# Start the Tkinter main event loop +root.mainloop() \ No newline at end of file diff --git a/timer_app2.py b/timer_app2.py new file mode 100644 index 0000000..f1d31da --- /dev/null +++ b/timer_app2.py @@ -0,0 +1,326 @@ +import tkinter as tk +from tkinter import filedialog, messagebox, ttk +import threading +import socket +import time +import binascii + +def hexspace(data, n): + return " ".join([data[i:i + n] for i in range(0, len(data), n)]) + +def send_data(key, value): + print(f"Sending {key}: {value}") + + +class DataReceiver: + def __init__(self): + self.running = False + self.file_mode = False + self.file_path = None + + def start_tcp(self, host, port, callback): + self.running = True + def run(): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind((host, port)) + s.listen(1) + conn, addr = s.accept() + with conn: + while self.running: + data = conn.recv(1024) + if data: + callback(data.decode('utf-8')) + threading.Thread(target=run, daemon=True).start() + + def start_file(self, callback): + self.running = True + def run(): + if not self.file_path: + return + with open(self.file_path, 'r') as f: + while self.running: + line = f.readline() + if line: + callback(line.strip()) + else: + time.sleep(0.5) + threading.Thread(target=run, daemon=True).start() + + def stop(self): + self.running = False + +class DataSender: + def __init__(self): + self.targets = [] + + def add_target(self, host, port): + self.targets.append((host, port)) + + + # def send(self, data): + # for host, port in self.targets: + # try: + # with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + # s.connect((host, port)) + # s.sendall(data.encode('utf-8')) + # except Exception as e: + # print(f"Error sending data to {host}:{port}: {e}") + +class DataProcessor: + def process_protocol_a(self, data): + return data.upper() + + def process_protocol_b(self, data): + return data[::-1] + + def process_protocol_saratov(self, data): + if data == "\xff": + return + + cdata = binascii.hexlify(data.encode("utf-8")) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + results = [] + for i in temp: + try: + minutes = int(i.split()[5], 16) + seconds = int(i.split()[6], 16) + timer_str = f"{minutes}:{seconds:02d}" if seconds < 60 else f"{minutes}.{seconds-128}" + + seconds_24 = int(i.split()[7], 16) + timer_attack = "" + timer_pic = "D:\\Graphics\\Basketball\\24Sec_Orange.png" + if seconds_24 != 255: + if seconds_24 > 127: + seconds_24 -= 128 + timer_attack = f"{seconds_24//10}.{seconds_24%10}" + timer_pic = "D:\\Graphics\\Basketball\\24Sec_Red.png" + else: + timer_attack = seconds_24 + + quarter = int(i.split()[14][1], 16) + timeout1 = int(i.split()[10], 16) + timeout2 = int(i.split()[11], 16) + score1 = int(i.split()[8], 16) + score2 = int(i.split()[9], 16) + foul1 = int(i.split()[12], 16) + foul2 = int(i.split()[13], 16) + + data = { + "TIMER.Text": timer_str, + "ATTACK.Text": timer_attack, + "Score_Home.Text": score1, + "Score_Away.Text": score2, + "fouls1.Source": f"D:\\Graphics\\Basketball\\Home_{foul1}.png", + "fouls2.Source": f"D:\\Graphics\\Basketball\\Away_{foul2}.png", + "24SECBACKGROUND.Source": timer_pic, + } + for key, value in data.items(): + send_data(key, value) + + results.append(data) + except (IndexError, ValueError): + continue + + return results + + +class App: + def __init__(self, root): + self.receiver = DataReceiver() + self.sender = DataSender() + self.processor = DataProcessor() + + self.protocol_var = tk.StringVar(value="Protocol A") + self.mode_var = tk.StringVar(value="Log File") + + self.create_ui(root) + + def display_data(self, data): + protocol = self.protocol_var.get() + if protocol == "Protocol A": + processed_data = self.processor.process_protocol_a(data) + elif protocol == "Protocol B": + processed_data = self.processor.process_protocol_b(data) + elif protocol == "Saratov": + processed_data = self.processor.process_protocol_saratov(data) + else: + processed_data = data + + if processed_data: + self.update_send_status(True) + self.sender.send(str(processed_data)) + self.update_send_status(False) + + def create_ui(self, root): + root.title("Data Processing Application") + + self.notebook = tk.ttk.Notebook(root) + self.notebook.pack(fill="both", expand=True) + + self.settings_frame = tk.Frame(self.notebook) + self.game_frame = tk.Frame(self.notebook) + + self.notebook.add(self.settings_frame, text="Settings") + self.notebook.add(self.game_frame, text="Game") + + self.create_settings_ui(self.settings_frame) + self.create_game_ui(self.game_frame) + + def create_settings_ui(self, frame): + # Frame for receiving data + frame_receive = tk.LabelFrame(frame, text="Receive Data") + frame_receive.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_receive, text="Select Mode:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(frame_receive, self.mode_var, "Log File", "TCP Connection", command=self.update_mode).pack(side="left", padx=5, pady=5) + + self.file_button = tk.Button(frame_receive, text="Select Log File", command=self.select_file) + + self.tcp_frame = tk.Frame(frame_receive) + tk.Label(self.tcp_frame, text="IP:").pack(side="left") + self.tcp_ip_entry = tk.Entry(self.tcp_frame) + self.tcp_ip_entry.pack(side="left", padx=5) + tk.Label(self.tcp_frame, text="Port:").pack(side="left") + self.tcp_port_entry = tk.Entry(self.tcp_frame) + self.tcp_port_entry.pack(side="left", padx=5) + + self.start_button = tk.Button(frame_receive, text="Start", command=self.start_receiving) + self.start_button.pack(side="left", padx=5, pady=5) + tk.Button(frame_receive, text="Stop", command=self.stop_receiving).pack(side="left", padx=5, pady=5) + + # Frame for processing data + frame_process = tk.LabelFrame(frame, text="Process Data") + frame_process.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_process, text="Select Protocol:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(frame_process, self.protocol_var, "Protocol A", "Protocol B", "Saratov").pack(side="left", padx=5, pady=5) + + # Frame for sending data + frame_send = tk.LabelFrame(frame, text="Send Data") + frame_send.pack(fill="x", padx=5, pady=5) + + self.target_count_var = tk.IntVar(value=1) + tk.Label(frame_send, text="Number of Targets:").pack(side="left", padx=5, pady=5) + tk.Spinbox(frame_send, from_=1, to=10, textvariable=self.target_count_var, command=self.update_targets).pack(side="left", padx=5, pady=5) + + self.targets_frame = tk.Frame(frame_send) + self.targets_frame.pack(fill="x", padx=5, pady=5) + self.target_entries = [] + self.update_targets() + + tk.Button(frame_send, text="Send Data", command=self.send_data).pack(side="left", padx=5, pady=5) + + self.update_mode(self.mode_var.get()) + + def create_game_ui(self, frame): + frame_status = tk.LabelFrame(frame, text="Status") + frame_status.pack(fill="x", padx=5, pady=5) + + self.data_receive_status = tk.Label(frame_status, text="Receiving Data: Not Active", fg="red") + self.data_receive_status.pack(pady=5) + + self.data_send_status = tk.Label(frame_status, text="Sending Data: Not Active", fg="red") + self.data_send_status.pack(pady=5) + + def update_mode(self, mode): + if mode == "Log File": + self.file_button.pack(side="left", padx=5, pady=5) + self.tcp_frame.pack_forget() + self.start_button.config(state="normal") + else: + self.file_button.pack_forget() + self.tcp_frame.pack(side="left", padx=5, pady=5) + self.start_button.config(state="normal") + + def select_file(self): + self.receiver.file_path = filedialog.askopenfilename() + + def start_receiving(self): + self.start_button.config(state="disabled") + mode = self.mode_var.get() + if mode == "Log File": + if self.receiver.file_path: + self.receiver.start_file(self.display_data) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "No file selected.") + elif mode == "TCP Connection": + host = self.tcp_ip_entry.get() + port = self.tcp_port_entry.get() + if host and port.isdigit(): + self.receiver.start_tcp(host, int(port), self.display_data) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "Invalid IP or port.") + self.start_button.config(state="normal") + + def stop_receiving(self): + self.receiver.stop() + self.start_button.config(state="normal") + self.update_receive_status(False) + + def display_data(self, data): + protocol = self.protocol_var.get() + if protocol == "Protocol A": + processed_data = self.processor.process_protocol_a(data) + else: + processed_data = self.processor.process_protocol_b(data) + + self.update_send_status(True) + self.sender.send(processed_data) + self.update_send_status(False) + + def update_receive_status(self, active): + if active: + self.data_receive_status.config(text="Receiving Data: Active", fg="green") + else: + self.data_receive_status.config(text="Receiving Data: Not Active", fg="red") + + def update_send_status(self, active): + if active: + self.data_send_status.config(text="Sending Data: Active", fg="green") + else: + self.data_send_status.config(text="Sending Data: Not Active", fg="red") + + def update_targets(self): + for widget in self.targets_frame.winfo_children(): + widget.destroy() + + self.target_entries = [] + for i in range(self.target_count_var.get()): + target_frame = tk.Frame(self.targets_frame) + target_frame.pack(fill="x", pady=2) + + tk.Label(target_frame, text=f"Target {i+1} Host:").pack(side="left") + host_entry = tk.Entry(target_frame) + host_entry.pack(side="left", padx=5) + + tk.Label(target_frame, text="Port:").pack(side="left") + port_entry = tk.Entry(target_frame) + port_entry.pack(side="left", padx=5) + + self.target_entries.append((host_entry, port_entry)) + + def send_data(self): + data = "Sample data to send" + if not data: + messagebox.showerror("No Data", "No data to send.") + return + + self.sender.targets = [] + for host_entry, port_entry in self.target_entries: + host = host_entry.get() + port = port_entry.get() + if host and port.isdigit(): + self.sender.add_target(host, int(port)) + + self.update_send_status(True) + self.sender.send(data) + self.update_send_status(False) + +if __name__ == "__main__": + root = tk.Tk() + app = App(root) + root.mainloop() diff --git a/timer_app2_temp.py b/timer_app2_temp.py new file mode 100644 index 0000000..842ae14 --- /dev/null +++ b/timer_app2_temp.py @@ -0,0 +1,369 @@ +import tkinter as tk +from tkinter import filedialog, messagebox, ttk +import threading +import socket +import time +import binascii +import requests +import json # To handle structured data better + +def hexspace(data, n): + return " ".join([data[i:i + n] for i in range(0, len(data), n)]) + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + +class DataReceiver: + def __init__(self): + self.running = False + self.file_mode = False + self.file_path = None + self.manual_mode = False + + def start_tcp(self, host, port, callback): + self.running = True + def run(): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind((host, port)) + s.listen(1) + conn, addr = s.accept() + with conn: + while self.running: + data = conn.recv(1024) + if data: + callback(data.decode('utf-8')) + threading.Thread(target=run, daemon=True).start() + + def start_file(self, callback, timeout): + self.running = True + def run(): + if not self.file_path: + return + with open(self.file_path, 'r') as f: + while self.running: + if self.manual_mode: + continue + line = f.readline() + if line: + try: + # Safely parse the data, assuming the data format is correct + callback(json.loads(line.strip().split(" DEBUG ")[1])) + except Exception as e: + print(f"Error parsing line: {e}") + time.sleep(timeout) + threading.Thread(target=run, daemon=True).start() + + def read_next_line(self, callback): + if not self.file_path: + return + with open(self.file_path, 'r') as f: + line = f.readline() + if line: + try: + callback(json.loads(line.strip().split(" DEBUG ")[1])) + except Exception as e: + print(f"Error parsing line: {e}") + + def stop(self): + self.running = False + +class DataSender: + def __init__(self): + self.targets = [] + + def add_target(self, host, port): + self.targets.append((host, port)) + + def send(self, data): + for host, port in self.targets: + try: + url = f"http://{host}:{port}/API/" + for k, v in data.items(): + par = "SetText" if k.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": 23, + "SelectedName": k, + "Value": v, + } + session.get(url, params=params) + except Exception as e: + print(f"Error sending data to {host}:{port}: {e}") + +class DataProcessor: + def process_protocol_a(self, data): + return data.upper() + + def process_protocol_b(self, data): + return data[::-1] + + def process_protocol_saratov(self, data): + if data == "\xff": + return None + + cdata = binascii.hexlify(data.encode()) # Ensure data is properly encoded to bytes + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + processed_data = [] + for i in temp: + try: + parts = i.split() + minutes = int(parts[5], 16) + seconds = int(parts[6], 16) + timer_str = f"{minutes}:{seconds:02d}" if seconds < 60 else f"{minutes}.{seconds - 128}" + + seconds_24 = int(parts[7], 16) + timer_attack = "" + timer_pic = "D:/Графика/БАСКЕТБОЛ/ЕДИНАЯ ЛИГА ВТБ 2022-2023/Scorebug Indicators/24Sec_Orange.png" + if seconds_24 != 255: + if seconds_24 > 127: + seconds_24 -= 128 + timer_attack = f"{seconds_24 // 10}.{seconds_24 % 10}" + timer_pic = "D:/Графика/БАСКЕТБОЛ/ЕДИНАЯ ЛИГА ВТБ 2022-2023/Scorebug Indicators/24Sec_Red.png" + else: + timer_attack = seconds_24 + + quarter = int(parts[14][1], 16) + timeout1 = int(parts[10], 16) + timeout2 = int(parts[11], 16) + score1 = int(parts[8], 16) + score2 = int(parts[9], 16) + foul1 = int(parts[12], 16) + foul2 = int(parts[13], 16) + + data_dict = { + "TIMER.Text": timer_str, + "ATTACK.Text": timer_attack, + "Score_Home.Text": score1, + "Score_Away.Text": score2, + "fouls1.Source": f"D:/Графика/БАСКЕТБОЛ/ЕДИНАЯ ЛИГА ВТБ 2022-2023/Scorebug Indicators/Home_{foul1}.png", + "fouls2.Source": f"D:/Графика/БАСКЕТБОЛ/ЕДИНАЯ ЛИГА ВТБ 2022-2023/Scorebug Indicators/Away_{foul2}.png", + "24SECBACKGROUND.Source": timer_pic, + } + + processed_data.append(data_dict) + except (IndexError, ValueError) as e: + print(f"Error processing data: {e}") + continue + + return processed_data + +class App: + def __init__(self, root): + self.receiver = DataReceiver() + self.sender = DataSender() + self.processor = DataProcessor() + + self.protocol_var = tk.StringVar(value="Protocol A") + self.mode_var = tk.StringVar(value="Log File") + self.read_mode_var = tk.StringVar(value="Automatic") + self.timeout_var = tk.DoubleVar(value=0.5) + + self.create_ui(root) + + def display_data(self, data): + protocol = self.protocol_var.get() + if protocol == "Protocol A": + processed_data = self.processor.process_protocol_a(data) + elif protocol == "Protocol B": + processed_data = self.processor.process_protocol_b(data) + elif protocol == "Saratov": + processed_data = self.processor.process_protocol_saratov(data) + else: + processed_data = data + + if processed_data: + self.update_send_status(True) + self.sender.send(processed_data) + self.update_send_status(False) + + self.log_text.insert(tk.END, f"{data}\n") + self.log_text.see(tk.END) + + self.processed_data_text.insert(tk.END, f"{processed_data}\n") + self.processed_data_text.see(tk.END) + + def create_ui(self, root): + root.title("Data Processing Application") + + self.notebook = ttk.Notebook(root) + self.notebook.pack(fill="both", expand=True) + + self.settings_frame = tk.Frame(self.notebook) + self.game_frame = tk.Frame(self.notebook) + + self.notebook.add(self.settings_frame, text="Settings") + self.notebook.add(self.game_frame, text="Game") + + self.create_settings_ui(self.settings_frame) + self.create_game_ui(self.game_frame) + + def create_settings_ui(self, frame): + frame_receive = tk.LabelFrame(frame, text="Receive Data") + frame_receive.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_receive, text="Select Mode:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(frame_receive, self.mode_var, "Log File", "TCP Connection", command=self.update_mode).pack(side="left", padx=5, pady=5) + + self.file_button = tk.Button(frame_receive, text="Select Log File", command=self.select_file) + + self.tcp_frame = tk.Frame(frame_receive) + tk.Label(self.tcp_frame, text="IP:").pack(side="left") + self.tcp_ip_entry = tk.Entry(self.tcp_frame) + self.tcp_ip_entry.pack(side="left", padx=5) + self.tcp_ip_entry.insert(0, "192.168.127.254") # Example default IP address + tk.Label(self.tcp_frame, text="Port:").pack(side="left") + self.tcp_port_entry = tk.Entry(self.tcp_frame) + self.tcp_port_entry.pack(side="left", padx=5) + self.tcp_port_entry.insert(0, 1993) # Example default port + + self.read_mode_frame = tk.Frame(frame_receive) + tk.Label(self.read_mode_frame, text="Read Mode:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(self.read_mode_frame, self.read_mode_var, "Automatic", "Manual", command=self.update_read_mode).pack(side="left", padx=5, pady=5) + tk.Label(self.read_mode_frame, text="Timeout (s):").pack(side="left", padx=5, pady=5) + self.timeout_entry = tk.Entry(self.read_mode_frame, textvariable=self.timeout_var) + self.timeout_entry.pack(side="left", padx=5) + self.manual_read_button = tk.Button(self.read_mode_frame, text="Read Next Line", command=self.read_next_line) + + self.start_button = tk.Button(frame_receive, text="Start", command=self.start_receiving) + self.start_button.pack(side="left", padx=5, pady=5) + tk.Button(frame_receive, text="Stop", command=self.stop_receiving).pack(side="left", padx=5, pady=5) + + frame_process = tk.LabelFrame(frame, text="Process Data") + frame_process.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_process, text="Select Protocol:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(frame_process, self.protocol_var, "Protocol A", "Protocol B", "Saratov").pack(side="left", padx=5, pady=5) + + frame_send = tk.LabelFrame(frame, text="Send Data") + frame_send.pack(fill="x", padx=5, pady=5) + + self.target_count_var = tk.IntVar(value=1) + tk.Label(frame_send, text="Number of Targets:").pack(side="left", padx=5, pady=5) + tk.Spinbox(frame_send, from_=1, to=10, textvariable=self.target_count_var, command=self.update_targets).pack(side="left", padx=5, pady=5) + + self.targets_frame = tk.Frame(frame_send) + self.targets_frame.pack(fill="x", padx=5, pady=5) + self.target_entries = [] + self.update_targets() + + tk.Button(frame_send, text="Send Data", command=self.send_data).pack(side="left", padx=5, pady=5) + + self.update_mode(self.mode_var.get()) + + def create_game_ui(self, frame): + frame_status = tk.LabelFrame(frame, text="Status") + frame_status.pack(fill="x", padx=5, pady=5) + + self.data_receive_status = tk.Label(frame_status, text="Receiving Data: Not Active", fg="red") + self.data_receive_status.pack(pady=5) + + self.data_send_status = tk.Label(frame_status, text="Sending Data: Not Active", fg="red") + self.data_send_status.pack(pady=5) + + frame_log = tk.LabelFrame(frame, text="Log") + frame_log.pack(fill="both", expand=True, padx=5, pady=5) + + self.log_text = tk.Text(frame_log, height=10, state="normal") + self.log_text.pack(fill="both", expand=True, padx=5, pady=5) + + frame_processed = tk.LabelFrame(frame, text="Processed Data") + frame_processed.pack(fill="both", expand=True, padx=5, pady=5) + + self.processed_data_text = tk.Text(frame_processed, height=10, state="normal") + self.processed_data_text.pack(fill="both", expand=True, padx=5, pady=5) + + def update_mode(self, mode): + if mode == "Log File": + self.file_button.pack(side="left", padx=5, pady=5) + self.tcp_frame.pack_forget() + self.read_mode_frame.pack(fill="x", padx=5, pady=5) + self.start_button.config(state="normal") + else: + self.file_button.pack_forget() + self.read_mode_frame.pack_forget() + self.tcp_frame.pack(side="left", padx=5, pady=5) + self.start_button.config(state="normal") + + def update_read_mode(self, mode): + if mode == "Automatic": + self.timeout_entry.config(state="normal") + self.manual_read_button.pack_forget() + self.receiver.manual_mode = False + else: + self.timeout_entry.config(state="disabled") + self.manual_read_button.pack(side="left", padx=5, pady=5) + self.receiver.manual_mode = True + + def select_file(self): + self.receiver.file_path = filedialog.askopenfilename() + + def start_receiving(self): + self.start_button.config(state="disabled") + mode = self.mode_var.get() + if mode == "Log File": + if self.receiver.file_path: + timeout = self.timeout_var.get() if self.read_mode_var.get() == "Automatic" else 0 + self.receiver.start_file(self.display_data, timeout) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "No file selected.") + elif mode == "TCP Connection": + host = self.tcp_ip_entry.get() + port = self.tcp_port_entry.get() + if host and port.isdigit(): + self.receiver.start_tcp(host, int(port), self.display_data) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "Invalid IP or port.") + self.start_button.config(state="normal") + + def stop_receiving(self): + self.receiver.stop() + self.start_button.config(state="normal") + self.update_receive_status(False) + + def read_next_line(self): + self.receiver.read_next_line(self.display_data) + + def update_receive_status(self, active): + if active: + self.data_receive_status.config(text="Receiving Data: Active", fg="green") + else: + self.data_receive_status.config(text="Receiving Data: Not Active", fg="red") + + def update_send_status(self, active): + if active: + self.data_send_status.config(text="Sending Data: Active", fg="green") + else: + self.data_send_status.config(text="Sending Data: Not Active", fg="red") + + def update_targets(self): + for widget in self.targets_frame.winfo_children(): + widget.destroy() + + self.target_entries = [] + for i in range(self.target_count_var.get()): + target_frame = tk.Frame(self.targets_frame) + target_frame.pack(fill="x", pady=2) + + tk.Label(target_frame, text=f"Target {i+1}:").pack(side="left", padx=5, pady=5) + host_entry = tk.Entry(target_frame) + host_entry.pack(side="left", padx=5) + host_entry.insert(0, f"192.168.1.{i+1}") + self.target_entries.append(host_entry) + + def send_data(self): + if not self.target_entries: + messagebox.showerror("Error", "No targets defined.") + return + + targets = [(entry.get(), 8080) for entry in self.target_entries] + self.sender.targets = targets + self.sender.send({"data": "sample"}) + +if __name__ == "__main__": + root = tk.Tk() + app = App(root) + root.mainloop() diff --git a/timer_app3.py b/timer_app3.py new file mode 100644 index 0000000..161111c --- /dev/null +++ b/timer_app3.py @@ -0,0 +1,415 @@ +import tkinter as tk +from tkinter import filedialog, messagebox, ttk +import threading +import socket +import time +import binascii +import requests +from concurrent.futures import ThreadPoolExecutor + +def hexspace(data, n): + return " ".join([data[i:i + n] for i in range(0, len(data), n)]) + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + +class DataReceiver: + def __init__(self): + self.running = False + self.file_mode = False + self.file_path = None + self.manual_mode = False + + def start_tcp(self, host, port, callback): + self.running = True + def run(): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind((host, port)) + s.listen(1) + conn, addr = s.accept() + with conn: + while self.running: + data = conn.recv(1024) + if data: + callback(data.decode('utf-8')) + threading.Thread(target=run, daemon=True).start() + + def start_file(self, callback, timeout): + self.running = True + def run(): + if not self.file_path: + return + with open(self.file_path, 'r') as f: + while self.running: + if self.manual_mode: + continue + line = f.readline() + if line: + callback(eval(line.strip().split(" DEBUG ")[1])) + time.sleep(timeout) + threading.Thread(target=run, daemon=True).start() + + def read_next_line(self, callback): + if not self.file_path: + return + with open(self.file_path, 'r') as f: + line = f.readline() + if line: + callback(eval(line.strip().split(" DEBUG ")[1])) + + def stop(self): + self.running = False + +class DataSender: + def __init__(self): + self.targets = [] + self.session = requests.Session() + self.session.headers.update({"Connection": "keep-alive"}) + + def add_target(self, host, port): + self.targets.append((host, port)) + + + def send(self, data): + """Многопоточная отправка данных на все указанные цели.""" + if not self.targets: + print("No targets available to send data.") + return + + def send_to_target(target): + host, port = target + url = f"http://{host}:{port}/API/" + try: + for k, v in data.items(): + par = "SetText" if k.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": 51, + "SelectedName": k, + "Value": v, + } + response = self.session.get(url, params=params, timeout=5) + response.raise_for_status() # Проверяет, есть ли ошибки HTTP + except requests.exceptions.RequestException as e: + print(f"Error sending data to {host}:{port}: {e}") + + # Используем ThreadPoolExecutor для многопоточной отправки + with ThreadPoolExecutor(max_workers=5) as executor: # max_workers можно настроить + executor.map(send_to_target, self.targets) + + + # def send(self, data): + # for host, port in self.targets: + # try: + # url = f"http://{host}:{port}/API/" + # print(data) + # for k,v in data.items(): + # par = "SetText" if k.split(".")[1] == "Text" else "SetImage" + # params = { + # "Function": par, + # "Input": 51, + # "SelectedName": k, + # "Value": v, + # } + # session.get(url, params=params) + # except Exception as e: + # print(f"Error sending data to {host}:{port}: {e}") + + # def send(self, data): + # for host, port in self.targets: + # try: + # with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + # s.connect((host, port)) + # s.sendall(data.encode('utf-8')) + # except Exception as e: + # print(f"Error sending data to {host}:{port}: {e}") + +class DataProcessor: + def process_protocol_a(self, data): + return data.upper() + + def process_protocol_b(self, data): + return data[::-1] + + def process_protocol_saratov(self, data): + if data == "\xff": + return + + cdata = binascii.hexlify(data) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + # results = [] + for i in temp: + try: + minutes = int(i.split()[5], 16) + seconds = int(i.split()[6], 16) + timer_str = f"{minutes}:{seconds:02d}" if seconds < 60 else f"{minutes}.{seconds-128}" + + seconds_24 = int(i.split()[7], 16) + timer_attack = "" + timer_pic = "D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\\24Sec_Orange.png" + if seconds_24 != 255: + if seconds_24 > 127: + seconds_24 -= 128 + timer_attack = f"{seconds_24//10}.{seconds_24%10}" + timer_pic = "D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\\24Sec_Red.png" + else: + timer_attack = seconds_24 + + quarter = int(i.split()[14][1], 16) + timeout1 = int(i.split()[10], 16) + timeout2 = int(i.split()[11], 16) + score1 = int(i.split()[8], 16) + score2 = int(i.split()[9], 16) + foul1 = int(i.split()[12], 16) + foul2 = int(i.split()[13], 16) + + data = { + "TIMER.Text": timer_str, + "ATTACK.Text": timer_attack, + "Score_Home.Text": score1, + "Score_Away.Text": score2, + "fouls1.Source": f"D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\Home_{foul1}.png", + "fouls2.Source": f"D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\Away_{foul2}.png", + "24SECBACKGROUND.Source": timer_pic, + } + + # results.append(data) + except (IndexError, ValueError): + continue + + return data + +class App: + def __init__(self, root): + self.receiver = DataReceiver() + self.sender = DataSender() + self.processor = DataProcessor() + + self.protocol_var = tk.StringVar(value="Protocol A") + self.mode_var = tk.StringVar(value="Log File") + self.read_mode_var = tk.StringVar(value="Automatic") + self.timeout_var = tk.DoubleVar(value=0.5) + + self.create_ui(root) + + def display_data(self, data): + protocol = self.protocol_var.get() + if protocol == "Protocol A": + processed_data = self.processor.process_protocol_a(data) + elif protocol == "Protocol B": + processed_data = self.processor.process_protocol_b(data) + elif protocol == "Saratov": + processed_data = self.processor.process_protocol_saratov(data) + else: + processed_data = data + + if processed_data: + self.update_send_status(True) + self.sender.send(processed_data) + self.update_send_status(False) + + self.log_text.insert(tk.END, f"{data}\n") + self.log_text.see(tk.END) + + self.processed_data_text.insert(tk.END, f"{processed_data}\n") + self.processed_data_text.see(tk.END) + + def create_ui(self, root): + root.title("Data Processing Application") + + self.notebook = ttk.Notebook(root) + self.notebook.pack(fill="both", expand=True) + + self.settings_frame = tk.Frame(self.notebook) + self.game_frame = tk.Frame(self.notebook) + + self.notebook.add(self.settings_frame, text="Settings") + self.notebook.add(self.game_frame, text="Game") + + self.create_settings_ui(self.settings_frame) + self.create_game_ui(self.game_frame) + + def create_settings_ui(self, frame): + frame_receive = tk.LabelFrame(frame, text="Receive Data") + frame_receive.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_receive, text="Select Mode:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(frame_receive, self.mode_var, "Log File", "TCP Connection", command=self.update_mode).pack(side="left", padx=5, pady=5) + + self.file_button = tk.Button(frame_receive, text="Select Log File", command=self.select_file) + + self.tcp_frame = tk.Frame(frame_receive) + tk.Label(self.tcp_frame, text="IP:").pack(side="left") + self.tcp_ip_entry = tk.Entry(self.tcp_frame) + self.tcp_ip_entry.pack(side="left", padx=5) + self.tcp_ip_entry.insert(0, "192.168.127.254") # например, default IP адрес + tk.Label(self.tcp_frame, text="Port:").pack(side="left") + self.tcp_port_entry = tk.Entry(self.tcp_frame) + self.tcp_port_entry.pack(side="left", padx=5) + self.tcp_port_entry.insert(0, 1993) # например, default порт + + self.read_mode_frame = tk.Frame(frame_receive) + tk.Label(self.read_mode_frame, text="Read Mode:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(self.read_mode_frame, self.read_mode_var, "Automatic", "Manual", command=self.update_read_mode).pack(side="left", padx=5, pady=5) + tk.Label(self.read_mode_frame, text="Timeout (s):").pack(side="left", padx=5, pady=5) + self.timeout_entry = tk.Entry(self.read_mode_frame, textvariable=self.timeout_var) + self.timeout_entry.pack(side="left", padx=5) + self.manual_read_button = tk.Button(self.read_mode_frame, text="Read Next Line", command=self.read_next_line) + + self.start_button = tk.Button(frame_receive, text="Start", command=self.start_receiving) + self.start_button.pack(side="left", padx=5, pady=5) + tk.Button(frame_receive, text="Stop", command=self.stop_receiving).pack(side="left", padx=5, pady=5) + + frame_process = tk.LabelFrame(frame, text="Process Data") + frame_process.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_process, text="Select Protocol:").pack(side="left", padx=5, pady=5) + tk.OptionMenu(frame_process, self.protocol_var, "Protocol A", "Protocol B", "Saratov").pack(side="left", padx=5, pady=5) + + frame_send = tk.LabelFrame(frame, text="Send Data") + frame_send.pack(fill="x", padx=5, pady=5) + + self.target_count_var = tk.IntVar(value=1) + tk.Label(frame_send, text="Number of Targets:").pack(side="left", padx=5, pady=5) + tk.Spinbox(frame_send, from_=1, to=10, textvariable=self.target_count_var, command=self.update_targets).pack(side="left", padx=5, pady=5) + + self.targets_frame = tk.Frame(frame_send) + self.targets_frame.pack(fill="x", padx=5, pady=5) + self.target_entries = [] + self.update_targets() + + tk.Button(frame_send, text="Send Data", command=self.send_data).pack(side="left", padx=5, pady=5) + + self.update_mode(self.mode_var.get()) + + def create_game_ui(self, frame): + frame_status = tk.LabelFrame(frame, text="Status") + frame_status.pack(fill="x", padx=5, pady=5) + + self.data_receive_status = tk.Label(frame_status, text="Receiving Data: Not Active", fg="red") + self.data_receive_status.pack(pady=5) + + self.data_send_status = tk.Label(frame_status, text="Sending Data: Not Active", fg="red") + self.data_send_status.pack(pady=5) + + frame_log = tk.LabelFrame(frame, text="Log") + frame_log.pack(fill="both", expand=True, padx=5, pady=5) + + self.log_text = tk.Text(frame_log, height=10, state="normal") + self.log_text.pack(fill="both", expand=True, padx=5, pady=5) + + frame_processed = tk.LabelFrame(frame, text="Processed Data") + frame_processed.pack(fill="both", expand=True, padx=5, pady=5) + + self.processed_data_text = tk.Text(frame_processed, height=10, state="normal") + self.processed_data_text.pack(fill="both", expand=True, padx=5, pady=5) + + def update_mode(self, mode): + if mode == "Log File": + self.file_button.pack(side="left", padx=5, pady=5) + self.tcp_frame.pack_forget() + self.read_mode_frame.pack(fill="x", padx=5, pady=5) + self.start_button.config(state="normal") + else: + self.file_button.pack_forget() + self.read_mode_frame.pack_forget() + self.tcp_frame.pack(side="left", padx=5, pady=5) + self.start_button.config(state="normal") + + def update_read_mode(self, mode): + if mode == "Automatic": + self.timeout_entry.config(state="normal") + self.manual_read_button.pack_forget() + self.receiver.manual_mode = False + else: + self.timeout_entry.config(state="disabled") + self.manual_read_button.pack(side="left", padx=5, pady=5) + self.receiver.manual_mode = True + + def select_file(self): + self.receiver.file_path = filedialog.askopenfilename() + + def start_receiving(self): + self.start_button.config(state="disabled") + mode = self.mode_var.get() + if mode == "Log File": + if self.receiver.file_path: + timeout = self.timeout_var.get() if self.read_mode_var.get() == "Automatic" else 0 + self.receiver.start_file(self.display_data, timeout) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "No file selected.") + elif mode == "TCP Connection": + host = self.tcp_ip_entry.get() + port = self.tcp_port_entry.get() + if host and port.isdigit(): + self.receiver.start_tcp(host, int(port), self.display_data) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "Invalid IP or port.") + self.start_button.config(state="normal") + + def stop_receiving(self): + self.receiver.stop() + self.start_button.config(state="normal") + self.update_receive_status(False) + + def read_next_line(self): + self.receiver.read_next_line(self.display_data) + + def update_receive_status(self, active): + if active: + self.data_receive_status.config(text="Receiving Data: Active", fg="green") + else: + self.data_receive_status.config(text="Receiving Data: Not Active", fg="red") + + def update_send_status(self, active): + if active: + self.data_send_status.config(text="Sending Data: Active", fg="green") + else: + self.data_send_status.config(text="Sending Data: Not Active", fg="red") + + def update_targets(self): + for widget in self.targets_frame.winfo_children(): + widget.destroy() + + self.target_entries = [] + for i in range(self.target_count_var.get()): + target_frame = tk.Frame(self.targets_frame) + target_frame.pack(fill="x", pady=2) + + tk.Label(target_frame, text=f"Target {i+1} Host:").pack(side="left") + host_entry = tk.Entry(target_frame) + host_entry.pack(side="left", padx=5) + host_entry.insert(0, "127.0.0.1") + + tk.Label(target_frame, text="Port:").pack(side="left") + port_entry = tk.Entry(target_frame) + port_entry.pack(side="left", padx=5) + port_entry.insert(0, 8088) + + self.target_entries.append((host_entry, port_entry)) + + def send_data(self): + data = "Sample data to send" + if not data: + messagebox.showerror("No Data", "No data to send.") + return + + self.sender.targets = [] + for host_entry, port_entry in self.target_entries: + host = host_entry.get() + port = port_entry.get() + if host and port.isdigit(): + self.sender.add_target(host, int(port)) + + self.update_send_status(True) + self.sender.send(data) + self.update_send_status(False) + +if __name__ == "__main__": + root = tk.Tk() + app = App(root) + root.mainloop() diff --git a/timer_app4.py b/timer_app4.py new file mode 100644 index 0000000..046ca46 --- /dev/null +++ b/timer_app4.py @@ -0,0 +1,620 @@ +import tkinter as tk +from tkinter import filedialog, messagebox, ttk +import threading +import socket +import time +import binascii +import requests +from concurrent.futures import ThreadPoolExecutor + + +def hexspace(data, n): + return " ".join([data[i : i + n] for i in range(0, len(data), n)]) + + +class DataReceiver: + def __init__(self): + self.running = False + self.file_mode = False + self.file_path = None + self.manual_mode = False + + def start_tcp(self, host, port, callback): + self.running = True + + def run(): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + try: + # Подключаемся к серверу + s.connect((host, port)) + + # Отправляем строку "hello" в виде байтов + s.sendall("hello".encode("utf-8")) + + # Основной цикл для получения данных + while self.running: + try: + # Получаем данные от сервера (максимум 1024 байта) + data = s.recv(1024) + + if data: + try: + # Преобразуем байты в строку UTF-8 + decoded_data = data + # Вызываем callback с декодированными данными + callback(decoded_data) + except UnicodeDecodeError: + print(f"Ошибка декодирования данных: {data}") + callback(data.decode("latin1", errors="replace")) + else: + # Если data пустое, соединение закрылось + print("Сервер закрыл соединение.") + break + except (socket.error, OSError) as e: + print(f"Ошибка приёма данных: {e}") + break + except Exception as e: + print(f"Ошибка подключения: {e}") + finally: + print("Соединение закрыто.") + self.running = False + + threading.Thread(target=run, daemon=True).start() + + def start_file(self, callback, timeout): + self.running = True + + def run(): + if not self.file_path: + return + with open(self.file_path, "r") as f: + while self.running: + if self.manual_mode: + continue + line = f.readline() + if line: + callback(eval(line.strip().split(" DEBUG ")[1])) + time.sleep(timeout) + + threading.Thread(target=run, daemon=True).start() + + def read_next_line(self, callback): + if not self.file_path: + return + with open(self.file_path, "r") as f: + line = f.readline() + if line: + callback(eval(line.strip().split(" DEBUG ")[1])) + + def stop(self): + self.running = False + + +class DataSender: + def __init__(self): + self.targets = [] + self.session = requests.Session() + self.session.headers.update({"Connection": "keep-alive"}) + + def add_target(self, host, port): + self.targets.append((host, port)) + + def send(self, data): + """Многопоточная отправка данных на все указанные цели.""" + if not self.targets: + print("No targets available to send data.") + return + + def send_to_target(target): + host, port = target + url = f"http://{host}:{port}/API/" + # url = f"http://{host}:{port}/" + try: + for k, v in data.items(): + par = "SetText" if k.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": 51, + "SelectedName": k, + "Value": v, + } + + # params = { + # "action": "set_text", + # "layer": f"SCORE STRIPE FLAGS INTRO\Data\{k}", + # "value": str(v), + # "channel": "live1", + # } + + # params = { + # "action": "set_data_source_query_parameter", + # "data_source": "timer_data", + # "parameter": k, + # "value": v, + # } + # params = { "action" : "set_data_source_query_parameter", "data_source" : "XML/JSON Source 11", "parameter" : "TIMER", "value" : "London" } + # print(url, params) + response = self.session.get(url, params=params, timeout=5) + # response = self.session.post(url, params=params) + # print(response.headers) + response.raise_for_status() # Проверяет, есть ли ошибки HTTP + except requests.exceptions.RequestException as e: + print(f"Error sending data to {host}:{port}: {e}") + + # Используем ThreadPoolExecutor для многопоточной отправки + with ThreadPoolExecutor( + max_workers=5 + ) as executor: # max_workers можно настроить + executor.map(send_to_target, self.targets) + + def check_vmix_connections(self): + """Проверяем соединения для всех целей и обновляем индикаторы.""" + for index, (host_entry, port_entry) in enumerate(self.target_entries): + host = host_entry.get() + port = port_entry.get() + + if not port.isdigit(): + continue # Пропускаем некорректные порты + + connected = self.sender.check_vmix_connection(host, int(port)) + self.update_connection_indicator(index, connected) + + def update_connection_indicator(self, index, connected): + """Обновляем цвет индикатора для определенной цели.""" + color = "green" if connected else "red" + self.connection_indicators[index].itemconfig("indicator", fill=color) + + def check_vmix_connection(self, host, port): + url = f"http://{host}:{port}/API/" + # url = f"http://{host}:{port}" + try: + response = self.session.get(url, timeout=2) # Таймаут в секундах + return response.status_code == 200 + except requests.exceptions.RequestException: + return False + + +class DataProcessor: + def process_protocol_a(self, data): + return data.upper() + + def process_protocol_b(self, data): + return data[::-1] + + def process_chine(self, data): + cdata = binascii.hexlify(data) + ddata = cdata.decode("utf-8", errors="replace").upper() + edata = hexspace(ddata, 2) + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + # print(temp_new) + timer = f"{temp_new[3]}:{temp_new[2]}" + seconds = temp_new[5] + milliseconds = str(temp_new[4])[0] + if int(seconds) > 4: + temp = float(f"{seconds}.{milliseconds}") + if int(milliseconds) >= 5: + seconds = int(seconds) + 1 + else: + seconds = seconds + timer_attack = seconds + timer_color = "#59358A" + else: + timer_attack = f"{seconds}.{milliseconds}" + timer_color = "#FF6A13" + if temp_new[0] in [16, 24]: + timer_attack = "" + timer_color = "#000000" + data = { + "12sec.Text": timer_attack, + "12SecBackground.Fill.Color": timer_color, + } + return data + + def process_protocol_saratov(self, data): + if data == "\xff": + return + + cdata = binascii.hexlify(data) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + for i in temp: + try: + minutes = int(i.split()[5], 16) + seconds = int(i.split()[6], 16) + timer_str = ( + f"{minutes}:{seconds:02d}" + if seconds < 60 + else f"{minutes}.{seconds-128}" + ) + + seconds_24 = int(i.split()[7], 16) + timer_attack = "" + timer_pic = "D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\\24Sec_Orange.png" + if seconds_24 != 255: + if seconds_24 > 127: + seconds_24 -= 128 + timer_attack = f"{seconds_24//10}.{seconds_24%10}" + timer_pic = "D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\\24Sec_Red.png" + else: + timer_attack = seconds_24 + + quarter = int(i.split()[14][1], 16) + timeout1 = int(i.split()[10], 16) + timeout2 = int(i.split()[11], 16) + score1 = int(i.split()[8], 16) + score2 = int(i.split()[9], 16) + foul1 = int(i.split()[12], 16) + foul2 = int(i.split()[13], 16) + + data = { + "TIMER.Text": timer_str, + "ATTACK.Text": timer_attack, + "Score_Home.Text": score1, + "Score_Away.Text": score2, + "fouls1.Source": f"D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\Home_{foul1}.png", + "fouls2.Source": f"D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\Away_{foul2}.png", + "24SECBACKGROUND.Source": timer_pic, + } + # data = { + # "Timer": timer_str, + # # "Attack": timer_attack, + # # "Score1": score1, + # # "Score2": score2, + # # "fouls1.Source": f"D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\Home_{foul1}.png", + # # "fouls2.Source": f"D:\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\Away_{foul2}.png", + # # "24SECBACKGROUND.Source": timer_pic, + # } + + except (IndexError, ValueError): + continue + + return data + + +class App: + def __init__(self, root): + self.receiver = DataReceiver() + self.sender = DataSender() + self.processor = DataProcessor() + + self.protocol_var = tk.StringVar(value="Protocol A") + self.mode_var = tk.StringVar(value="Log File") + self.read_mode_var = tk.StringVar(value="Automatic") + self.timeout_var = tk.DoubleVar(value=0.5) + + self.create_ui(root) + self.start_vmix_connection_check() + + def display_data(self, data): + protocol = self.protocol_var.get() + if protocol == "Protocol A": + processed_data = self.processor.process_protocol_a(data) + elif protocol == "Protocol B": + processed_data = self.processor.process_protocol_b(data) + elif protocol == "Saratov": + processed_data = self.processor.process_protocol_saratov(data) + elif protocol == "Chine": + processed_data = self.processor.process_chine(data) + else: + processed_data = data + + if processed_data: + self.update_send_status(True) + self.sender.send(processed_data) + self.update_send_status(False) + + self.log_text.insert(tk.END, f"{data}\n") + self.log_text.see(tk.END) + + self.processed_data_text.insert(tk.END, f"{processed_data}\n") + self.processed_data_text.see(tk.END) + + def create_ui(self, root): + root.title("Data Processing Application") + + self.notebook = ttk.Notebook(root) + self.notebook.pack(fill="both", expand=True) + + self.settings_frame = tk.Frame(self.notebook) + self.game_frame = tk.Frame(self.notebook) + + self.notebook.add(self.settings_frame, text="Settings") + self.notebook.add(self.game_frame, text="Game") + + self.create_settings_ui(self.settings_frame) + self.create_game_ui(self.game_frame) + + def create_settings_ui(self, frame): + frame_receive = tk.LabelFrame(frame, text="Receive Data") + frame_receive.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_receive, text="Select Mode:").pack(side="left", padx=5, pady=5) + tk.OptionMenu( + frame_receive, + self.mode_var, + "Log File", + "TCP Connection", + command=self.update_mode, + ).pack(side="left", padx=5, pady=5) + + self.file_button = tk.Button( + frame_receive, text="Select Log File", command=self.select_file + ) + + self.tcp_frame = tk.Frame(frame_receive) + tk.Label(self.tcp_frame, text="IP:").pack(side="left") + self.tcp_ip_entry = tk.Entry(self.tcp_frame) + self.tcp_ip_entry.pack(side="left", padx=5) + self.tcp_ip_entry.insert(0, "192.168.127.254") # например, default IP адрес + tk.Label(self.tcp_frame, text="Port:").pack(side="left") + self.tcp_port_entry = tk.Entry(self.tcp_frame) + self.tcp_port_entry.pack(side="left", padx=5) + self.tcp_port_entry.insert(0, 1993) # например, default порт + + self.read_mode_frame = tk.Frame(frame_receive) + tk.Label(self.read_mode_frame, text="Read Mode:").pack( + side="left", padx=5, pady=5 + ) + tk.OptionMenu( + self.read_mode_frame, + self.read_mode_var, + "Automatic", + "Manual", + command=self.update_read_mode, + ).pack(side="left", padx=5, pady=5) + tk.Label(self.read_mode_frame, text="Timeout (s):").pack( + side="left", padx=5, pady=5 + ) + self.timeout_entry = tk.Entry( + self.read_mode_frame, textvariable=self.timeout_var + ) + self.timeout_entry.pack(side="left", padx=5) + self.manual_read_button = tk.Button( + self.read_mode_frame, text="Read Next Line", command=self.read_next_line + ) + + self.start_button = tk.Button( + frame_receive, text="Start", command=self.start_receiving + ) + self.start_button.pack(side="left", padx=5, pady=5) + tk.Button(frame_receive, text="Stop", command=self.stop_receiving).pack( + side="left", padx=5, pady=5 + ) + + frame_process = tk.LabelFrame(frame, text="Process Data") + frame_process.pack(fill="x", padx=5, pady=5) + + tk.Label(frame_process, text="Select Protocol:").pack( + side="left", padx=5, pady=5 + ) + tk.OptionMenu( + frame_process, + self.protocol_var, + "Protocol A", + "Protocol B", + "Saratov", + "Chine", + ).pack(side="left", padx=5, pady=5) + + frame_send = tk.LabelFrame(frame, text="Send Data") + frame_send.pack(fill="x", padx=5, pady=5) + + self.target_count_var = tk.IntVar(value=1) + tk.Label(frame_send, text="Number of Targets:").pack( + side="left", padx=5, pady=5 + ) + tk.Spinbox( + frame_send, + from_=1, + to=10, + textvariable=self.target_count_var, + command=self.update_targets, + ).pack(side="left", padx=5, pady=5) + + self.targets_frame = tk.Frame(frame_send) + self.targets_frame.pack(fill="x", padx=5, pady=5) + self.target_entries = [] + self.update_targets() + + tk.Button(frame_send, text="Send Data", command=self.send_data).pack( + side="left", padx=5, pady=5 + ) + + self.update_mode(self.mode_var.get()) + + def create_game_ui(self, frame): + frame_status = tk.LabelFrame(frame, text="Status") + frame_status.pack(fill="x", padx=5, pady=5) + + # Canvas indicators + self.receive_status_canvas = tk.Canvas(frame_status, width=20, height=20) + self.receive_status_canvas.create_oval( + 2, 2, 18, 18, fill="red", tags="indicator" + ) + self.receive_status_canvas.pack(side="left", padx=10, pady=5) + tk.Label(frame_status, text="Receiving Data").pack(side="left") + + self.send_status_canvas = tk.Canvas(frame_status, width=20, height=20) + self.send_status_canvas.create_oval(2, 2, 18, 18, fill="red", tags="indicator") + self.send_status_canvas.pack(side="left", padx=10, pady=5) + tk.Label(frame_status, text="Sending Data").pack(side="left") + + frame_log = tk.LabelFrame(frame, text="Log") + frame_log.pack(fill="both", expand=True, padx=5, pady=5) + + self.log_text = tk.Text(frame_log, height=10, state="normal") + self.log_text.pack(fill="both", expand=True, padx=5, pady=5) + + frame_processed = tk.LabelFrame(frame, text="Processed Data") + frame_processed.pack(fill="both", expand=True, padx=5, pady=5) + + self.processed_data_text = tk.Text(frame_processed, height=10, state="normal") + self.processed_data_text.pack(fill="both", expand=True, padx=5, pady=5) + + # self.vmix_status_indicator = tk.Canvas(frame_status, width=20, height=20) + # self.vmix_status_indicator.pack(side="left", padx=5, pady=5) + # self.update_vmix_indicator(False) + + # tk.Label(frame_status, text="vMix Connection").pack(side="left", padx=5, pady=5) + + # def update_vmix_indicator(self, connected): + # self.vmix_status_indicator.delete("all") + # color = "green" if connected else "red" + # self.vmix_status_indicator.create_oval(2, 2, 18, 18, fill=color) + + # def check_vmix_connection(self): + # if not self.target_entries: + # return False + + # host_entry, port_entry = self.target_entries[0] # Проверяем первую цель + # host = host_entry.get() + # port = port_entry.get() + # if not port.isdigit(): + # return False + + # connected = self.sender.check_vmix_connection(host, int(port)) + # self.update_vmix_indicator(connected) + # return connected + + def check_vmix_connections(self): + for index, (host_entry, port_entry) in enumerate(self.target_entries): + host = host_entry.get() + port = port_entry.get() + + if not port.isdigit(): + continue # Пропускаем некорректные порты + + connected = self.sender.check_vmix_connection(host, int(port)) + self.update_connection_indicator(index, connected) + + def update_connection_indicator(self, index, connected): + color = "green" if connected else "red" + self.connection_indicators[index].itemconfig("indicator", fill=color) + + def start_vmix_connection_check(self): + """Периодически проверяем соединения.""" + + def check_loop(): + while True: + self.check_vmix_connections() + time.sleep(1) + + threading.Thread(target=check_loop, daemon=True).start() + + def update_mode(self, mode): + if mode == "Log File": + self.file_button.pack(side="left", padx=5, pady=5) + self.tcp_frame.pack_forget() + self.read_mode_frame.pack(fill="x", padx=5, pady=5) + self.start_button.config(state="normal") + else: + self.file_button.pack_forget() + self.read_mode_frame.pack_forget() + self.tcp_frame.pack(side="left", padx=5, pady=5) + self.start_button.config(state="normal") + + def update_read_mode(self, mode): + if mode == "Automatic": + self.timeout_entry.config(state="normal") + self.manual_read_button.pack_forget() + self.receiver.manual_mode = False + else: + self.timeout_entry.config(state="disabled") + self.manual_read_button.pack(side="left", padx=5, pady=5) + self.receiver.manual_mode = True + + def select_file(self): + self.receiver.file_path = filedialog.askopenfilename() + + def start_receiving(self): + self.start_button.config(state="disabled") + mode = self.mode_var.get() + if mode == "Log File": + if self.receiver.file_path: + timeout = ( + self.timeout_var.get() + if self.read_mode_var.get() == "Automatic" + else 0 + ) + self.receiver.start_file(self.display_data, timeout) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "No file selected.") + elif mode == "TCP Connection": + host = self.tcp_ip_entry.get() + port = self.tcp_port_entry.get() + if host and port.isdigit(): + self.receiver.start_tcp(host, int(port), self.display_data) + self.update_receive_status(True) + else: + messagebox.showerror("Error", "Invalid IP or port.") + self.start_button.config(state="normal") + + def stop_receiving(self): + self.receiver.stop() + self.start_button.config(state="normal") + self.update_receive_status(False) + + def read_next_line(self): + self.receiver.read_next_line(self.display_data) + + def update_receive_status(self, active): + color = "green" if active else "red" + self.receive_status_canvas.itemconfig("indicator", fill=color) + + def update_send_status(self, active): + color = "green" if active else "red" + self.send_status_canvas.itemconfig("indicator", fill=color) + + def update_targets(self): + for widget in self.targets_frame.winfo_children(): + widget.destroy() + + self.target_entries = [] + self.connection_indicators = [] # Храним индикаторы состояния + + for i in range(self.target_count_var.get()): + target_frame = tk.Frame(self.targets_frame) + target_frame.pack(fill="x", pady=2) + + tk.Label(target_frame, text=f"Target {i+1} Host:").pack(side="left") + host_entry = tk.Entry(target_frame) + host_entry.pack(side="left", padx=5) + host_entry.insert(0, "127.0.0.1") + + tk.Label(target_frame, text="Port:").pack(side="left") + port_entry = tk.Entry(target_frame) + port_entry.pack(side="left", padx=5) + port_entry.insert(0, 8088) + + indicator = tk.Canvas(target_frame, width=20, height=20) + indicator.create_oval(2, 2, 18, 18, fill="red", tags="indicator") + indicator.pack(side="left", padx=5) + + self.target_entries.append((host_entry, port_entry)) + self.connection_indicators.append(indicator) + + def send_data(self): + data = "Sample data to send" + if not data: + messagebox.showerror("No Data", "No data to send.") + return + + self.sender.targets = [] + for host_entry, port_entry in self.target_entries: + host = host_entry.get() + port = port_entry.get() + if host and port.isdigit(): + self.sender.add_target(host, int(port)) + + # self.update_send_status(True) + self.sender.send(data) + # self.update_send_status(False) + + +if __name__ == "__main__": + root = tk.Tk() + app = App(root) + root.mainloop() diff --git a/timer_china_tcp.py b/timer_china_tcp.py new file mode 100644 index 0000000..67611dd --- /dev/null +++ b/timer_china_tcp.py @@ -0,0 +1,155 @@ +import sys +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii +import requests + + +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def parse(line): + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + + if len(edata.split()) == 33: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + minutes = temp_new[6] + seconds = temp_new[7] + milliseconds = temp_new[8] + timer_str = ( + f"{minutes}:{seconds:02d}" + if minutes != 0 + else f"{seconds:02d}.{milliseconds}" + ) + active_temp = temp_new[ + 9 + ] # 133 - таймер идёт | 132 - таймер стоит | 128 - не игровое время стоит | 129 - не игровое время идёт + + if temp_new[-2] != 0: + time_attack = ( + temp_new[-4] if temp_new[-4] > 4 else f"{temp_new[-4]}.{temp_new[-3]}" + ) + else: + time_attack = "" # temp_new[-2] == 1 - таймер идёт | 2 - таймер стоит | 0 - таймер не отображён + + # print(f"{str(temp_new):<120}__{timer_str:<7}__{time_attack:<3}__") + else: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + + # time.sleep(0.1) + + +def read_logs(): + with open("timer_NN_2023-12-20_18-17-29.log", "r") as file: + # with open("timer_NN_test.log", "r") as file: + temp_line = "" + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + parse(data) + time.sllep(0.1) + + # if len(eval(data)) > 30 and eval(data)[-7] == "00": + # time.sleep(.1) + # else: + # time.sleep(1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_Chine_tcp_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + logging.debug(data) + cdata = binascii.hexlify(data) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + timer = f"{temp_new[3]}:{temp_new[2]}" + seconds = temp_new[5] + milliseconds = str(temp_new[4])[0] + if int(seconds) > 4: + temp = float(f"{seconds}.{milliseconds}") + if int(milliseconds) >= 5: + seconds = int(seconds) + 1 + else: + seconds = seconds + timer_attack = seconds + timer_color = "#FF6EAB" + else: + timer_attack = f"{seconds}.{milliseconds}" + timer_color = "#561D93" + if temp_new[0] in [16, 24]: + timer_attack = "" + timer_color = "#000000" + url = "http://127.0.0.1:8088/API/" + params = { + "Function": "SetText", + "Input": 151, + "SelectedName": "12sec.Text", + "Value": timer_attack, + } + params1 = { + "Function": "SetColor", + "Input": 150, + "SelectedName": "12SecBackground.Fill.Color", + "Value": timer_color, + } + requests.get(url, params=params) + requests.get(url, params=params1) + print( + f"data: {edata}", + temp_new, + timer, + f"{seconds}.{milliseconds}, attack: {timer_attack}", + ) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + except Exception: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) + except Exception as ex: + print(ex) diff --git a/timer_chine.py b/timer_chine.py new file mode 100644 index 0000000..12e1c32 --- /dev/null +++ b/timer_chine.py @@ -0,0 +1,119 @@ +import serial +from serial import SerialException +import datetime +import binascii +import logging +import time +import json + +import re + +# Configuration Data (later to be put in Panel2Net.conf) +# SerialPort: Name of RPi serial port receiving the panel data +# SerialPort = "COM1" +SerialPort = "COM1" +# BaudRate: Serial port speed (Baud, Default will be adjusted later) +BaudRate = 19200 +# PackageByTime: Time Duration until a package is closed +# and sent off (seconds) +PackageByTime = 0.1 +# PackageByLength* Length (in bytes) of data input +# until a package is closed and sent off +PackageByLength = 128 +# PackageByLength = 256 #попробовать нужно !!!!!!!!!!!!!!!!!!!! +# PackageByLength = 256 + +# MaxBuffer before flushing (in order to avoid buffer overflow) +BufferMax = 2000 + + +# LogFileName: Name of LogFile +current_time = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") +LogFileName = f"timer_megasport5_{current_time}.log" +# LogFileSize Maximum Size of LogFile (in Mbytes) +LogFileSize = 10 +# LogLevel Minimum Severity Level to be logged (see severity in Logs) +LogLevel = "E" + +logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", +) + +def hexspace(string, length): + return ' '.join(string[i:i+length] for i in range(0,len(string),length)) + +ser = serial.Serial() +ser.port = SerialPort +ser.baudrate = BaudRate +ser.bytesize = serial.EIGHTBITS # number of bits per bytes +ser.parity = serial.PARITY_NONE # PARITY_NONE # set parity check: no parity +ser.stopbits = serial.STOPBITS_ONE # number of stop bits +ser.timeout = PackageByTime # non-block read +ser.xonxoff = False # disable software flow control +ser.rtscts = False # disable hardware (RTS/CTS) flow control +ser.dsrdtr = False # disable hardware (DSR/DTR) flow control +ser.writeTimeout = 0 # timeout for write + +while True: + try: + print("Initializing") + ser.close() + ser.open() + if ser.is_open: + try: + ser.reset_input_buffer() + # flush input buffer, discarding all its contents + ser.reset_output_buffer() + # flush output buffer, aborting current output + # and discard all that is in buffer + RequestCount = 0 + print("Port Opening") + # Initialise RetryCounter + RetryCount = 0 + # Initialise Variable to take remainder string + remainder_hex = b"" + + while True: + # Read from Serial Interface + response = ser.read(PackageByLength) + # print(response) + if len(response) > 0: + # In case there is something coming down the serial path + logging.debug(response) + + if response != b"": + cdata = binascii.hexlify(response) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + timer = f"{temp_new[3]}:{temp_new[2]}" + seconds = temp_new[5] + # milliseconds = str(temp_new[6])[0] + print(len(temp_new), edata, temp_new, timer, seconds) + + + else: + # In case nothing is coming down the serial interface + print( + "\rWaiting for serial input...", + end=" ", + flush=True, + ) + + # in case that the Serial Read or HTTP request fails + except Exception as e1: + print("error communicating...: " + str(e1)) + logging.error("error communicating...: " + str(e1)) + + else: + print("Port Opening Failed... trying again in 5 seconds") + time.sleep(0.1) + ser.close() + + except SerialException: + print("No port connected... trying again in 5 seconds") + time.sleep(0.1) diff --git a/timer_chine_tcp.py b/timer_chine_tcp.py new file mode 100644 index 0000000..669caaf --- /dev/null +++ b/timer_chine_tcp.py @@ -0,0 +1,165 @@ +import sys +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii +import requests + + +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def parse(line): + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + + if len(edata.split()) == 33: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + minutes = temp_new[6] + seconds = temp_new[7] + milliseconds = temp_new[8] + timer_str = ( + f"{minutes}:{seconds:02d}" + if minutes != 0 + else f"{seconds:02d}.{milliseconds}" + ) + active_temp = temp_new[ + 9 + ] # 133 - таймер идёт | 132 - таймер стоит | 128 - не игровое время стоит | 129 - не игровое время идёт + + if temp_new[-2] != 0: + time_attack = ( + temp_new[-4] if temp_new[-4] > 4 else f"{temp_new[-4]}.{temp_new[-3]}" + ) + else: + time_attack = "" # temp_new[-2] == 1 - таймер идёт | 2 - таймер стоит | 0 - таймер не отображён + + # print(f"{str(temp_new):<120}__{timer_str:<7}__{time_attack:<3}__") + else: + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + + # time.sleep(0.1) + + +def read_logs(): + with open("timer_NN_2023-12-20_18-17-29.log", "r") as file: + # with open("timer_NN_test.log", "r") as file: + temp_line = "" + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + parse(data) + time.sllep(0.1) + + # if len(eval(data)) > 30 and eval(data)[-7] == "00": + # time.sleep(.1) + # else: + # time.sleep(1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_Chine_tcp_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + # new_data = { + # "timeGFX": "0:00", + # "time_attackGFX": "", + # "quarter": "0", + # "points1": "0", + # "points2": "0", + # "foul1": "0", + # "foul2": "0", + # "foul_pic1": "", + # "foul_pic2": "", + # "time_attac_pic": "", + # } + # with open(PATH, "w", encoding="utf-8") as file: + # json.dump([new_data], file, ensure_ascii=False, indent=4) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + logging.debug(data) + cdata = binascii.hexlify(data) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp_data = edata.split() + temp_new = [int(t, 16) for t in temp_data] + # print(temp_new) + timer = f"{temp_new[3]}:{temp_new[2]}" + seconds = temp_new[5] + milliseconds = str(temp_new[4])[0] + if int(seconds) > 4: + temp = float(f"{seconds}.{milliseconds}") + if int(milliseconds) >= 5: + seconds = int(seconds) + 1 + else: + seconds = seconds + timer_attack = seconds + timer_color = "#59358A" + else: + timer_attack = f"{seconds}.{milliseconds}" + timer_color = "#FF6A13" + if temp_new[0] in [16, 24]: + timer_attack = "" + timer_color = "#000000" + url = "http://127.0.0.1:8088/API/" + params = { + "Function": "SetText", + "Input": 221, + "SelectedName": "12sec.Text", + "Value": timer_attack, + } + params1 = { + "Function": "SetColor", + "Input": 221, + "SelectedName": "12SecBackground.Fill.Color", + "Value": timer_color, + } + requests.get(url, params=params) + requests.get(url, params=params1) + print( + f"data: {edata}", + temp_new, + timer, + f"{seconds}.{milliseconds}, attack: {timer_attack}", + ) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_exe.py b/timer_exe.py new file mode 100644 index 0000000..16c4d73 --- /dev/null +++ b/timer_exe.py @@ -0,0 +1,169 @@ +import tkinter as tk +from tkinter import filedialog, ttk, messagebox +import threading +import serial +import socket +import json +import os +import time +from data_sender import send_data_to_ips + + +class ConnectionApp: + def __init__(self, root): + self.root = root + self.root.title("Connection and Parser Application") + + # Variables + self.connection_type = tk.StringVar(value="IP") + self.log_file_path = tk.StringVar(value="No file selected") + self.parser_type = tk.StringVar(value="Parser 1") + self.ip_address = tk.StringVar(value="127.0.0.1") + self.port = tk.IntVar(value=8080) + self.com_port = tk.StringVar(value="COM1") + self.baud_rate = tk.IntVar(value=9600) + self.data = "" + self.http_destinations = [] + + # Thread control + self.connection_thread = None + self.is_running = False + + # UI + self.create_widgets() + + def create_widgets(self): + # Connection Type Selection + tk.Label(self.root, text="Connection Type:").grid(row=0, column=0, pady=5, sticky="e") + connection_menu = ttk.Combobox( + self.root, textvariable=self.connection_type, values=["IP", "Log File", "COM"], state="readonly" + ) + connection_menu.grid(row=0, column=1, pady=5, sticky="w") + + # IP Settings + tk.Label(self.root, text="IP Address:").grid(row=1, column=0, pady=5, sticky="e") + tk.Entry(self.root, textvariable=self.ip_address).grid(row=1, column=1, pady=5, sticky="w") + + tk.Label(self.root, text="Port:").grid(row=2, column=0, pady=5, sticky="e") + tk.Entry(self.root, textvariable=self.port).grid(row=2, column=1, pady=5, sticky="w") + + # Log File Selection + tk.Label(self.root, text="Log File:").grid(row=3, column=0, pady=5, sticky="e") + tk.Button(self.root, text="Select File", command=self.select_log_file).grid(row=3, column=1, pady=5, sticky="w") + tk.Label(self.root, textvariable=self.log_file_path).grid(row=4, column=0, columnspan=2, sticky="w") + + # COM Port Settings + tk.Label(self.root, text="COM Port:").grid(row=5, column=0, pady=5, sticky="e") + tk.Entry(self.root, textvariable=self.com_port).grid(row=5, column=1, pady=5, sticky="w") + + tk.Label(self.root, text="Baud Rate:").grid(row=6, column=0, pady=5, sticky="e") + tk.Entry(self.root, textvariable=self.baud_rate).grid(row=6, column=1, pady=5, sticky="w") + + # Parser Selection + tk.Label(self.root, text="Parser:").grid(row=7, column=0, pady=5, sticky="e") + parser_menu = ttk.Combobox( + self.root, textvariable=self.parser_type, values=["Parser 1", "Parser 2", "Parser 3"], state="readonly" + ) + parser_menu.grid(row=7, column=1, pady=5, sticky="w") + + # Control Buttons + tk.Button(self.root, text="Start", command=self.start_connection).grid(row=8, column=0, pady=10) + tk.Button(self.root, text="Stop", command=self.stop_connection).grid(row=8, column=1, pady=10) + + # Destination Management + tk.Button(self.root, text="Add HTTP Destination", command=self.add_http_destination).grid(row=9, column=0, pady=10) + tk.Button(self.root, text="Show Destinations", command=self.show_destinations).grid(row=9, column=1, pady=10) + + def select_log_file(self): + file_path = filedialog.askopenfilename( + title="Select Log File", filetypes=[("Log files", "*.log"), ("All files", "*.*")] + ) + if file_path: + self.log_file_path.set(file_path) + + def start_connection(self): + if self.connection_thread and self.connection_thread.is_alive(): + messagebox.showinfo("Info", "Connection is already running.") + return + + self.is_running = True + connection_type = self.connection_type.get() + + if connection_type == "IP": + self.connection_thread = threading.Thread(target=self.connect_via_ip, daemon=True) + elif connection_type == "Log File": + self.connection_thread = threading.Thread(target=self.read_log_file, daemon=True) + elif connection_type == "COM": + self.connection_thread = threading.Thread(target=self.connect_via_com, daemon=True) + else: + messagebox.showerror("Error", "Unknown connection type.") + return + + self.connection_thread.start() + + def stop_connection(self): + self.is_running = False + if self.connection_thread and self.connection_thread.is_alive(): + self.connection_thread.join() + messagebox.showinfo("Info", "Connection stopped.") + + def connect_via_ip(self): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((self.ip_address.get(), self.port.get())) + while self.is_running: + data = s.recv(1024).decode() + self.process_data(data) + except Exception as e: + messagebox.showerror("Error", f"IP connection error: {e}") + + def read_log_file(self): + try: + with open(self.log_file_path.get(), "r") as file: + while self.is_running: + line = file.readline() + if not line: + time.sleep(0.1) + continue + self.process_data(line) + except Exception as e: + messagebox.showerror("Error", f"Log file error: {e}") + + def connect_via_com(self): + try: + with serial.Serial(self.com_port.get(), self.baud_rate.get(), timeout=1) as ser: + while self.is_running: + data = ser.readline().decode() + self.process_data(data) + except Exception as e: + messagebox.showerror("Error", f"COM port error: {e}") + + def process_data(self, data): + parser = self.get_parser(self.parser_type.get()) + parsed_data = parser(data) + self.data = parsed_data + send_data_to_ips(parsed_data, self.http_destinations) + + def get_parser(self, parser_name): + if parser_name == "Parser 1": + return lambda x: {"parsed": f"Parser 1 processed {x}"} + elif parser_name == "Parser 2": + return lambda x: {"parsed": f"Parser 2 processed {x}"} + elif parser_name == "Parser 3": + return lambda x: {"parsed": f"Parser 3 processed {x}"} + else: + return lambda x: {"error": "No valid parser selected"} + + def add_http_destination(self): + ip = tk.simpledialog.askstring("Add HTTP Destination", "Enter IP (http://:port):") + if ip: + self.http_destinations.append(ip) + + def show_destinations(self): + messagebox.showinfo("HTTP Destinations", "\n".join(self.http_destinations)) + + +if __name__ == "__main__": + root = tk.Tk() + app = ConnectionApp(root) + root.mainloop() diff --git a/timer_hockey_balashikha.py b/timer_hockey_balashikha.py new file mode 100644 index 0000000..05bc766 --- /dev/null +++ b/timer_hockey_balashikha.py @@ -0,0 +1,107 @@ +import socket +from datetime import datetime +import json + +HOST = "10.1.68.38" # local +PORT = 40001 +PATH = "D:\\timer.json" + + +def connect(): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((HOST, PORT)) + s.sendall(b"Hello, world") + data = s.recv(1024) + return data + + +def save_log(name, data): + current_time = datetime.now().strftime("%d-%m-%Y %H:%M:%S.%f") + message_with_time = f"[{current_time}] {data}" + with open(name, "a") as file: + file.write(message_with_time + "\n") + + +def formatted_data(data): + save_log("logs_balashikha.txt", data) + + data_converted = list(data) + data_formatted = [ + str(hex_value // 16) + str(hex_value % 16) for hex_value in data_converted + ] + save_log("logs_balashikha_formatted.txt", data_formatted) + + +def parse(data_formatted): + # print(len(data_formatted)) + # print(data_formatted) + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + new_data = new_data[0] + + if len(data_formatted) > 30: + if data_formatted[17] == "010": + if data_formatted[-8] in ["01", "05"]: + timer_str = ( + f"{int(data_formatted[-7])}:{data_formatted[-6]}" + if int(data_formatted[-7]) != 0 + else f"{int(data_formatted[-6])}.{int(data_formatted[-5])}" + ) + new_data["timeGFX"] = timer_str + new_data["minutesGFX"] = int( + data_formatted[-7] + ) # [25] #data_formatted[17] = 010 - таймер data_formatted[-8] = 05 - овертайм, 06 - перерыв между основным временем и овертаймом, 01 - игровое время, 02 - перерыв между периодами + new_data["secondsGFX"] = data_formatted[-6] # [26] + else: + timer_str = f"{int(data_formatted[-7])}:{data_formatted[-6]}" + new_data["timeNotGame"] = timer_str + + if len(data_formatted) == 58: + new_data[ + "timeDel1" + ] = f"{int(data_formatted[26])}:{data_formatted[27]}" # data_formatted[17] = 24 - удаление + new_data["timeDel2"] = f"{int(data_formatted[41])}:{data_formatted[42]}" + + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + print(new_data) + except Exception: + pass + + +def main(): + while True: + data = connect() + data_new = formatted_data(data) + parse(data_new) + + +def read_logs(): + import time + with open("test_logs_balashikha_new.txt", "r") as file: + for line in file: + parts = line.strip().split("] ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = parts[1] + parse(eval(data)) + if len(eval(data)) > 30 and eval(data)[-7] == "00": + time.sleep(.1) + else: + time.sleep(1) + + +if __name__ == "__main__": + new_data = { + "timeGFX": "0:00", + "minutesGFX": "0", + "secondsGFX": "0", + "timeDel1": "0:00", + "timeDel2": "0:00", + "timeNotGame": "0:00", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + # main() + read_logs() diff --git a/timer_jet.py b/timer_jet.py new file mode 100644 index 0000000..07c5697 --- /dev/null +++ b/timer_jet.py @@ -0,0 +1,203 @@ +import sys +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii +import requests + + +HOST = "127.0.0.1" +PORT = 50000 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + +import socket + +sock = socket.socket() +sock.bind(('', PORT)) +sock.listen(1) +conn, addr = sock.accept() +print ('connected:', addr) + +def send_data_CW(name, value): + try: + with socket.socket(AF_INET, SOCK_STREAM) as tcp_socket: + tcp_socket.connect(('192.168.1.170', 5115)) + data = f"{name}={value}\n".encode() + # print(f"Sending: {data}") # Отладка + tcp_socket.sendall(data) + # print("Data sent!") # Подтверждение отправки + except Exception as e: + print(f"Error sending TCP data: {e}") + +def send_vmix(params): + try: + url = "http://192.168.1.240:8088/API/" + requests.get(url, params=params) + except Exception as ex: + print(ex) + +def parse(line, score1, score2): + temp = line.split('#') + diff1, diff2 = None, None + t = temp[0] + # for t in temp: + if t not in [" ", ""]: + a = t.split('/') + print(a) + timer_str = f"{a[4]}:{a[5] if len(a[5]) != 1 else f'0{a[5]}'}" if a[4] != "0" else f"{a[5]}.{a[6]}" + timer_attack_str = a[2] + points1 = a[7] + points2 = a[8] + quarter = a[13] + if score1 != points1: + diff1 = int(points1) - int(score1) + score1 = points1 + if score2 != points2: + score2 = points2 + diff2 = int(points2) - int(score2) + + fouls1 = a[9] + fouls2 = a[10] + path = r"D:\Графика\БАСКЕТБОЛ\FIBA" + if int(fouls1) > 4: + foul_pic1 = path + "\HOME-FOUL4.png" + else: + foul_pic1 = path + f"\HOME-FOUL{fouls1}.png" + if int(fouls2) > 4: + foul_pic2 = path + "\AWAY-FOUL4.png" + else: + foul_pic2 = path + f"\AWAY-FOUL{fouls2}.png" + + data = { + "TIMER": timer_str, + "ATTACK": timer_attack_str, + "Score_Home": score1, + "Score_Away": score2, + "fouls1": fouls1, + "fouls2": fouls2, + "quarter": quarter, + } + + send_data_CW("TIMER", data["TIMER"]) + send_data_CW("ATTACK", data["ATTACK"]) + send_data_CW("Score_Home", data["Score_Home"]) + send_data_CW("Score_Away", data["Score_Away"]) + send_data_CW("fouls1", data["fouls1"]) + send_data_CW("fouls2", data["fouls2"]) + send_data_CW("quarter", data["quarter"]) + + params = { + "Function": "SetText", + "Input": 2, + "SelectedName": "ATTACK.Text", + "Value": data["ATTACK"], + # "SelectedName": "TIME.Text", + # "Value": timer_str, + } + send_vmix(params) + params = { + "Function": "SetText", + "Input": 2, + "SelectedName": "TIME.Text", + "Value": data["TIMER"], + } + send_vmix(params) + params = { + "Function": "SetText", + "Input": 2, + "SelectedName": "SCORE1.Text", + "Value": data["Score_Home"], + } + send_vmix(params) + params = { + "Function": "SetText", + "Input": 2, + "SelectedName": "SCORE2.Text", + "Value": data["Score_Away"], + } + send_vmix(params) + # params = { + # "Function": "SetText", + # "Input": 20, + # "SelectedName": "SCOREDIFF1.Text", + # "Value": f"+{diff1}", + # } + # requests.get(url, params=params) + # params = { + # "Function": "SetText", + # "Input": 20, + # "SelectedName": "SCOREDIFF2.Text", + # "Value": f"+{diff2}", + # } + # requests.get(url, params=params) + + params = { + "Function": "SetImage", + "Input": 2, + "SelectedName": "FOULS_HOME.Source", + "Value": foul_pic1, + } + send_vmix(params) + params = { + "Function": "SetImage", + "Input": 2, + "SelectedName": "FOULS_AWAY.Source", + "Value": foul_pic2, + } + send_vmix(params) + print(timer_str, timer_attack_str, points1, points2,fouls1, fouls2, diff1, diff2, a) + return score1, score2 + + +score1, score2 = 0, 0 +while True: + data = conn.recv(1024) + line = data.decode("utf-8") + print(line) + if not data: + break + score1, score2 = parse(line, score1, score2) + +conn.close() + + + + + + + +# def main(): +# try: +# tcp_socket = socket(AF_INET, SOCK_STREAM) +# tcp_socket.connect((HOST, PORT)) +# data = str.encode("hello") +# tcp_socket.send(data) +# data = bytes.decode(data) +# while True: +# data = tcp_socket.recv(1024) +# print(data) +# # url = "http://127.0.0.1:8088/API/" +# # params = { +# # "Function": "SetText", +# # "Input": 221, +# # "SelectedName": "12sec.Text", +# # "Value": timer_attack, +# # } +# # params1 = { +# # "Function": "SetColor", +# # "Input": 221, +# # "SelectedName": "12SecBackground.Fill.Color", +# # "Value": timer_color, +# # } +# # requests.get(url, params=params) +# except KeyboardInterrupt: +# tcp_socket.close() +# sys.exit(1) + + +# if __name__ == "__main__": +# main() diff --git a/timer_nata_test (2).py b/timer_nata_test (2).py new file mode 100644 index 0000000..9199402 --- /dev/null +++ b/timer_nata_test (2).py @@ -0,0 +1,189 @@ +import sys +import json +from socket import * +from datetime import datetime +import logging +import os +import time +import binascii +import requests + + +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +def send_data(name, value): + url = "http://127.0.0.1:8088/API/" + par = "SetText" if name.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": 51, + "SelectedName": name, + "Value": value, + } + session.get(url, params=params) + +def parse_new(line): + try: + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + except json.decoder.JSONDecodeError: + new_data = [ + { + "timeGFX": "0:00", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + "timeout1": "0", + "timeout2": "0", + } + ] + + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + print(line) + for i in temp: + if "7D 4A C0 0A" in i: #основной таймер + minutes = int(i.split()[-5], ) + seconds = int(i.split()[-4], ) + milliseconds = int(i.split()[-3], ) + timer_str = ( + f"{minutes}:{seconds:02d}" if minutes != 0 else f"{seconds}.{milliseconds}" + ) + send_data("TIMER.Text", timer_str) + + # print(i.split()[-7], i) + # if i.split()[-7] == "13" or i.split()[-7] == "10": + # new_data[0]["timeGFX"] = timer_str + elif "7D 4A C0 07" in i: #Счет + if i.split()[-7] == "06": #Счет первой команды + score1 = int(i.split()[-4], 16) + # new_data[0]["points1"] = score1 + send_data("Score_Home.Text", score1) + elif i.split()[-7] == "07": #Счет второй команды + score2 = int(i.split()[-4], 16) + send_data("Score_Away.Text", score2) + # new_data[0]["points2"] = score2 + else: + print("[СЧЁТ] == НЕПОНЯТНО") + elif "7D 4A C0 06" in i: #Информация + if i.split()[-6] == "09": #фолы первой команды + foul1 = int(i.split()[-3], 16) + # new_data[0]["foul1"] = foul1 + send_data("fouls1.Source", f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Home_{foul1}.png") + elif i.split()[-6] == "0A": #фолы второй команды + foul2 = int(i.split()[-3], 16) + send_data("fouls2.Source", f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Away_{foul2}.png") + # new_data[0]["foul2"] = foul2 + elif i.split()[-6] == "0E": #тайм-аут первой команды + time_out1 = int(i.split()[-3], 16) + # new_data[0]["timeout1"] = time_out1 + elif i.split()[-6] == "0F": #тайм-аут второй команды + time_out2 = int(i.split()[-3], 16) + # new_data[0]["timeout2"] = time_out2 + elif i.split()[-6] == "08": #четверть + quarter = int(i.split()[-3], 16) + # new_data[0]["quarter"] = quarter + + elif "79 84 C0 0A" in i: #24 секунды + # print(i) + seconds = int(i.split()[-4]) + milliseconds = int(i.split()[-3]) + if seconds < int(5): + time_attack = f"{seconds}.{milliseconds}" + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Red.png" + else: + time_attack = seconds + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Empty.png" + if time_attack == "0.0": + time_attack = "" + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Empty.png" + send_data("ATTACK.Text", time_attack) + send_data("24SECBACKGROUND.Source", timer_pic) + + # print(time_attack) + elif "89 4E C8 05" in i: + if i.split()[-3] == "05": #таймер 24 секунд выключен + time_attack = "" + timer_pic = "D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Empty.png" + send_data("ATTACK.Text", time_attack) + send_data("24SECBACKGROUND.Source", timer_pic) + # data = { + # "TIMER.Text": timer_str, + # "ATTACK.Text": time_attack, + # "Score_Home.Text": score1, + # "Score_Away.Text": score2, + # "fouls1.Source": f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Home_{foul1}.png", + # "fouls2.Source": f"D:\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\Away_{foul2}.png", + # "24SECBACKGROUND.Source": timer_pic, + # } + +# def read_logs(): +# with open( +# r"C:\Users\soule\Downloads\Telegram Desktop\timer_Megasport_Nport_2024-03-05_20-00-17.log", +# "r", +# ) as file: +# for line in file: +# parts = line.strip().split(" DEBUG ") +# if len(parts) == 2: +# timestamp = parts[0][1:] +# data = eval(parts[1]) +# if b"\xf83" in data or b"\xf88" in data or b"\xf87" in data: +# parse(data) +# time.sleep(0.1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_Nata_Nport_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + logging.debug(data) + parse_new(data) + + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_playground copy.py b/timer_playground copy.py new file mode 100644 index 0000000..8f56ed6 --- /dev/null +++ b/timer_playground copy.py @@ -0,0 +1,78 @@ +import requests +import time +import json + + +URL = "http://192.168.88.247:4700/TabloData/GetTabloData" + + +def main(): + req = requests.get(URL) + new_json = { + "QUARTER": "", + "TIMER": "", + "TIMER_24": "", + "TEAM1": "", + "TEAM2": "", + "SCORE1": "", + "SCORE2": "", + "FOUL1": "", + "FOUL2": "", + } + + temp = req.json() + path_to_foul = "E:\TABLO\public_html obs — LETO 22 (09.10)" + if len(temp) > 3: + for i in temp: + if i["ID"] == "43": + new_json["TEAM1"] = i["VAL"] + elif i["ID"] == "44": + new_json["TEAM2"] = i["VAL"] + elif i["ID"] == "TIMER": + new_json["TIMER"] = i["VAL"].split(".")[0] + elif i["ID"] == "21": + new_json["SCORE1"] = i["VAL"] + elif i["ID"] == "22": + new_json["SCORE2"] = i["VAL"] + elif i["ID"] == "23": + foul1 = i["VAL"] + if int(foul1) > 5: + new_json["FOUL1"] = path_to_foul + "\\left" + "\\5.png" + else: + new_json["FOUL1"] = path_to_foul + "\\left" + f"\{i['VAL']}.png" + elif i["ID"] == "24": + foul2 = i["VAL"] + if int(foul2) > 5: + new_json["FOUL2"] = path_to_foul + "\\right" + "\\5.png" + else: + new_json["FOUL2"] = path_to_foul + "\\right" + f"\{i['VAL']}.png" + elif i["ID"] == "5": + val = "" + if i["VAL"] == "1": + val = "1ST" + elif i["VAL"] == "2": + val = "2ND" + elif i["VAL"] == "3": + val = "3RD" + elif i["VAL"] == "4": + val = "4TH" + else: + val = "OT" + str(int(i["VAL"]) - 4) + new_json["QUARTER"] = val + elif i["ID"] == "4": + new_json["TIMER_24"] = i["VAL"] + with open("E:\\TABLO\\timer_basketball.json", "w", encoding="utf-8") as file: + json.dump([new_json], file, ensure_ascii=False, indent=4) + print(new_json) + + +if __name__ == "__main__": + try: + while True: + try: + main() + time.sleep(0.1) + except Exception as ex: + print(ex) + except KeyboardInterrupt: + exit(1) diff --git a/timer_playground.py b/timer_playground.py new file mode 100644 index 0000000..d295d1b --- /dev/null +++ b/timer_playground.py @@ -0,0 +1,87 @@ +import requests +import time +import json + + +URL = "http://192.168.1.80:4700/TabloData/GetTabloData" +# URL = "http://192.168.88.247:4700/TabloData/GetTabloData" + + +def main(): + req = requests.get(URL) + new_json = { + "QUARTER": "", + "TIMER": "", + "TIMER_24": "", + "TEAM1": "", + "TEAM2": "", + "SCORE1": "", + "SCORE2": "", + "FOUL1": "", + "FOUL2": "", + } + + if req.status_code == 200: + temp = req.json() + path_to_foul = "E:\TABLO\public_html obs — LETO 22 (09.10)" + if len(temp) > 3: + for i in temp: + if i["ID"] == "43": + new_json["TEAM1"] = i["VAL"] + elif i["ID"] == "44": + new_json["TEAM2"] = i["VAL"] + elif i["ID"] == "TIMER": + new_json["TIMER"] = i["VAL"].split(".")[0] + elif i["ID"] == "21": + new_json["SCORE1"] = i["VAL"] + elif i["ID"] == "22": + new_json["SCORE2"] = i["VAL"] + elif i["ID"] == "23": + foul1 = i["VAL"] + if int(foul1) > 5: + new_json["FOUL1"] = path_to_foul + "\\left" + "\\5.png" + else: + new_json["FOUL1"] = path_to_foul + "\\left" + f"\{i['VAL']}.png" + elif i["ID"] == "24": + foul2 = i["VAL"] + if int(foul2) > 5: + new_json["FOUL2"] = path_to_foul + "\\right" + "\\5.png" + else: + new_json["FOUL2"] = ( + path_to_foul + "\\right" + f"\{i['VAL']}.png" + ) + elif i["ID"] == "5": + val = "" + if i["VAL"] == "1": + val = "1ST" + elif i["VAL"] == "2": + val = "2ND" + elif i["VAL"] == "3": + val = "3RD" + elif i["VAL"] == "4": + val = "4TH" + else: + val = "OT" + str(int(i["VAL"]) - 4) + new_json["QUARTER"] = val + elif i["ID"] == "4": + new_json["TIMER_24"] = i["VAL"] + with open( + "E:\\TABLO\\timer_basketball.json", "w", encoding="utf-8" + ) as file: + json.dump([new_json], file, ensure_ascii=False, indent=4) + print(new_json) + else: + print(f"!!!!!Error!!!!!") + + +if __name__ == "__main__": + try: + while True: + try: + main() + time.sleep(0.1) + except Exception as ex: + print(ex) + except KeyboardInterrupt: + exit(1) + diff --git a/timer_saratov.py b/timer_saratov.py new file mode 100644 index 0000000..0e96c60 --- /dev/null +++ b/timer_saratov.py @@ -0,0 +1,141 @@ +import sys +import json +from socket import * +import logging +import os +import time +import binascii +import requests + + +SETTING = "19200,None,8,1,None,Enable,RS-485(2 wire)" +HOST = "192.168.127.254" +PORT = 1993 + + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + + +def send_data(name, value): + url = "http://127.0.0.1:8088/API/" + par = "SetText" if name.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": "SCOREBUG", + "SelectedName": name, + "Value": value, + } + session.get(url, params=params) + + +def parse_new(line): + if line == b"\xff": + return + + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + for i in temp: + minutes = int(i.split()[5], 16) + seconds = int(i.split()[6], 16) + if seconds < 60: + timer_str = f"{minutes}:{seconds:02d}" + else: + timer_str = f"{minutes}.{seconds-128}" + seconds_24 = int(i.split()[7], 16) + timer_attack = "" + timer_pic = "D:\\YandexDisk\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Orange.png" + if seconds_24 == 255: + timer_attack = "" + else: + if seconds_24 > 127: + seconds_24 = seconds_24 - 128 + timer_attack = f"{seconds_24//10}.{seconds_24%10}" + timer_pic = "D:\\YandexDisk\\Графика\\БАСКЕТБОЛ\\ЕДИНАЯ ЛИГА ВТБ 2022-2023\\Scorebug Indicators\\24Sec_Red.png" + else: + timer_attack = seconds_24 + + quarter = int(i.split()[14][1], 16) + timeout1 = int(i.split()[10], 16) + timeout2 = int(i.split()[11], 16) + score1 = int(i.split()[8], 16) + score2 = int(i.split()[9], 16) + foul1 = int(i.split()[12], 16) + foul2 = int(i.split()[13], 16) + data = { + "TIMER.Text": timer_str, + "24sec.Text": timer_attack, + "SCORE1.Text": score1, + "SCORE2.Text": score2, + } + send_data("TIMER.Text", data["TIMER.Text"]) + send_data("24sec.Text", data["24sec.Text"]) + send_data("SCORE1.Text", data["SCORE1.Text"]) + send_data("SCORE2.Text", data["SCORE2.Text"]) + # send_data("fouls1.Source", data["fouls1.Source"]) + # send_data("fouls2.Source", data["fouls2.Source"]) + # send_data("24SECBACKGROUND.Source", data["24SECBACKGROUND.Source"]) + x = [int(x, 16) for x in i.split()] + print(f"{i}, timer: {timer_str}, attack: {timer_attack}, Q: {quarter}, {x}") + + +def read_logs(): + with open( + r"C:\Code\timer\LOGS\timer_SARATOV_full.log", + "r", + ) as file: + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0] + data = eval(parts[1]) + parse_new(data) + time.sleep(0.1) + + +def main(): + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_SARATOV.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + print(data) + logging.debug(data) + try: + parse_new(data) + except Exception as ex: + print(f"\n{ex}\n") + except Exception as ex: + pass + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_saratovCW.py b/timer_saratovCW.py new file mode 100644 index 0000000..096706c --- /dev/null +++ b/timer_saratovCW.py @@ -0,0 +1,160 @@ +import sys +import json +from socket import * +import logging +import os +import time +import binascii +import requests + + +HOST = "192.168.127.254" +PORT = 1993 + +def hexspace(string, length): + return " ".join(string[i : i + length] for i in range(0, len(string), length)) + + +session = requests.Session() +session.headers.update({"Connection": "keep-alive"}) + + +def send_data(name, value): + url = "http://127.0.0.1:8088/API/" + par = "SetText" if name.split(".")[1] == "Text" else "SetImage" + params = { + "Function": par, + "Input": 51, + "SelectedName": name, + "Value": value, + } + session.get(url, params=params) + + +def send_data_CW(name, value): + try: + with socket(AF_INET, SOCK_STREAM) as tcp_socket: + tcp_socket.connect(('localhost', 5115)) + data = f"{name}={value}\n".encode() + # print(f"Sending: {data}") # Отладка + tcp_socket.sendall(data) + # print("Data sent!") # Подтверждение отправки + except Exception as e: + print(f"Error sending TCP data: {e}") + + + + +def parse_new(line): + if line == b"\xff": + return + + cdata = binascii.hexlify(line) + ddata = cdata.decode("utf-8").upper() + edata = hexspace(ddata, 2) + temp = edata.split("FF 52") + for i in temp: + minutes = int(i.split()[5], 16) + seconds = int(i.split()[6], 16) + if seconds < 60: + timer_str = f"{minutes}:{seconds:02d}" + else: + timer_str = f"{minutes}.{seconds-128}" + seconds_24 = int(i.split()[7], 16) + timer_attack = "" + timer_pic = "D:\YandexDisk\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\\24Sec_Orange.png" + if seconds_24 == 255: + timer_attack = "" + else: + if seconds_24 > 127: + seconds_24 = seconds_24 - 128 + timer_attack = f"{seconds_24//10}.{seconds_24%10}" + timer_pic = "D:\YandexDisk\Графика\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators\\24Sec_Red.png" + else: + timer_attack = seconds_24 + + quarter = int(i.split()[14][1], 16) + timeout1 = int(i.split()[10], 16) + timeout2 = int(i.split()[11], 16) + score1 = int(i.split()[8], 16) + score2 = int(i.split()[9], 16) + foul1 = int(i.split()[12], 16) + foul2 = int(i.split()[13], 16) + data = { + "TIMER": timer_str, + "ATTACK": timer_attack, + "Score_Home": score1, + "Score_Away": score2, + "fouls1": foul1, + "fouls2": foul2, + "quarter": quarter, + } + # with open("D:\FIBA CW\\timer.json", "w", encoding="utf-8") as file: + # json.dump([data], file, ensure_ascii=False, indent=4) + send_data_CW("TIMER", data["TIMER"]) + send_data_CW("ATTACK", data["ATTACK"]) + send_data_CW("Score_Home", data["Score_Home"]) + send_data_CW("Score_Away", data["Score_Away"]) + send_data_CW("fouls1", data["fouls1"]) + send_data_CW("fouls2", data["fouls2"]) + send_data_CW("quarter", data["quarter"]) + # send_data("Score_Home", data["Score_Home"]) + # send_data("Score_Away", data["Score_Away"]) + # send_data("fouls1", data["fouls1"]) + # send_data("fouls2", data["fouls2"]) + # send_data("24SECBACKGROUND.Source", data["24SECBACKGROUND.Source"]) + # x = [int(x, 16) for x in i.split()] + print(f"{i}, {data}") + + +def read_logs(): + with open( + r"C:\Code\timer\LOGS\timer_SARATOV copy 2.log", + "r", + ) as file: + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0] + data = eval(parts[1]) + parse_new(data) + time.sleep(0.1) + + +def main(): + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_SARATOV copy.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + print(data) + logging.debug(data) + try: + parse_new(data) + except Exception as ex: + print(f"\n{ex}\n") + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + # main() + read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_stramatel copy.py b/timer_stramatel copy.py new file mode 100644 index 0000000..a995dd2 --- /dev/null +++ b/timer_stramatel copy.py @@ -0,0 +1,161 @@ +import sys +import json +from socket import * +from datetime import datetime +import logging +import os +import time + +SETTING = "19200,RS-485" +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def parse(line): + + # if len(line) > 6: + try: + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + timer_bool = 0 + if b"\xf87" in line: + temp_new = str(line.split(b"\xf87")[1]) + elif b"\xf88" in line: + temp_new = str(line.split(b"\xf88")[1]) + elif b"\xf83" in line: + temp_new = str(line.split(b"\xf83")[1]) + timer_bool = 1 + print(line) + timer_temp = temp_new[4:8] + # print(str(timer_temp) == '\\xf2') + if timer_temp != "\\xf2": + if timer_temp[-1] != " ": + minutes = int(timer_temp[:2]) + seconds = timer_temp[2:] + timer_str = f"{minutes}:{seconds}" + else: + seconds = int(timer_temp[0:2]) + milliseconds = int(timer_temp[2:]) + timer_str = f"{seconds}.{milliseconds}" + if timer_bool == 1: + quarter = temp_new[14] + points1 = (temp_new[8:11]).strip() + points2 = (temp_new[11:14]).strip() + fouls1 = temp_new[15] + fouls2 = temp_new[16] + new_data[0]["points1"] = points1 + new_data[0]["points2"] = points2 + new_data[0]["foul1"] = fouls1 + new_data[0]["foul2"] = fouls2 + new_data[0]["quarter"] = quarter + + path_pic = r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + attack_display = temp_new[51:53] + if attack_display == "30": + time_attack = "" + path_pic = path_pic + "\\24Sec_empty.png" + else: + word_to_int = "ABCDEFGHI@" + time_attack_temp = temp_new[48:50] + # print(time_attack_temp) + # print(word_to_int.index(time_attack_temp[1])+1 if time_attack_temp[1] != '@' else '0') + if time_attack_temp[1] in word_to_int: + time_attack = f"{time_attack_temp[0]}.{word_to_int.index(time_attack_temp[1])+1 if time_attack_temp[1] != '@' else '0'}" + path_pic = path_pic + "\\24Sec_Red.png" + else: + time_attack = ( + int(time_attack_temp) + if time_attack_temp != " " + else time_attack_temp + ) + path_pic = path_pic + "\\24Sec_Orange.png" + if time_attack == "0.0": + time_attack = "" + path_pic = path_pic + "\\24Sec_empty.png" + if timer_str == "0:00": + timer_str = "0.0" + + new_data[0]["timeGFX"] = timer_str + new_data[0]["time_attackGFX"] = time_attack + new_data[0]["time_attac_pic"] = path_pic + + print(new_data[0]["timeGFX"], new_data[0]["time_attackGFX"]) + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump(new_data, file, ensure_ascii=False, indent=4) + except Exception: + print(Exception) + pass + # logging.debug(new_data) + except Exception as ex: + print(ex) + pass + + +def read_logs(): + with open( + r"C:\Users\soule\Downloads\Telegram Desktop\timer_Megasport_Nport_2024-03-05_20-00-17.log", + "r", + ) as file: + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + if b"\xf83" in data or b"\xf88" in data or b"\xf87" in data: + parse(data) + time.sleep(0.1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_Megasport_Nport_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + new_data = { + "timeGFX": "0.0", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + logging.debug(data) + # if b"\xf83" in data or b"\xf88" in data or b"\xf87" in data: + parse(data) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1) diff --git a/timer_stramatel.py b/timer_stramatel.py new file mode 100644 index 0000000..0bc3237 --- /dev/null +++ b/timer_stramatel.py @@ -0,0 +1,160 @@ +import sys +import json +from socket import * +from datetime import datetime +import logging +import os +import time + +SETTING = "19200,RS-485" +HOST = "192.168.127.254" +PORT = 1993 +PATH = ( + r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\python\JSON\timer_basketball.json" +) + + +def parse(line): + if len(line) > 6: + try: + with open(PATH, "r", encoding="utf-8") as f: + new_data = json.load(f) + timer_bool = 0 + if b"\xf87" in line: + temp_new = str(line.split(b"\xf87")[1]) + elif b"\xf88" in line: + temp_new = str(line.split(b"\xf88")[1]) + elif b"\xf83" in line: + temp_new = str(line.split(b"\xf83")[1]) + timer_bool = 1 + print(line) + timer_temp = temp_new[4:8] + # print(str(timer_temp) == '\\xf2') + if timer_temp != "\\xf2": + if timer_temp[-1] != " ": + minutes = int(timer_temp[:2]) + seconds = timer_temp[2:] + timer_str = f"{minutes}:{seconds}" + else: + seconds = int(timer_temp[0:2]) + milliseconds = int(timer_temp[2:]) + timer_str = f"{seconds}.{milliseconds}" + if timer_bool == 1: + quarter = temp_new[14] + points1 = (temp_new[8:11]).strip() + points2 = (temp_new[11:14]).strip() + fouls1 = temp_new[15] + fouls2 = temp_new[16] + new_data[0]["points1"] = points1 + new_data[0]["points2"] = points2 + new_data[0]["foul1"] = fouls1 + new_data[0]["foul2"] = fouls2 + new_data[0]["quarter"] = quarter + + path_pic = r"D:\ГРАФИКА\БАСКЕТБОЛ\ЕДИНАЯ ЛИГА ВТБ 2022-2023\Scorebug Indicators" + attack_display = temp_new[51:53] + if attack_display == "30": + time_attack = "" + path_pic = path_pic + "\\24Sec_empty.png" + else: + word_to_int = "ABCDEFGHI@" + time_attack_temp = temp_new[48:50] + # print(time_attack_temp) + # print(word_to_int.index(time_attack_temp[1])+1 if time_attack_temp[1] != '@' else '0') + if time_attack_temp[1] in word_to_int: + time_attack = f"{time_attack_temp[0]}.{word_to_int.index(time_attack_temp[1])+1 if time_attack_temp[1] != '@' else '0'}" + path_pic = path_pic + "\\24Sec_Red.png" + else: + time_attack = ( + int(time_attack_temp) + if time_attack_temp != " " + else time_attack_temp + ) + path_pic = path_pic + "\\24Sec_Orange.png" + if time_attack == "0.0": + time_attack = "" + path_pic = path_pic + "\\24Sec_empty.png" + if timer_str == "0:00": + timer_str = "0.0" + + new_data[0]["timeGFX"] = timer_str + new_data[0]["time_attackGFX"] = time_attack + new_data[0]["time_attac_pic"] = path_pic + + print(new_data[0]["timeGFX"], new_data[0]["time_attackGFX"]) + try: + with open(PATH, "w", encoding="utf-8") as file: + json.dump(new_data, file, ensure_ascii=False, indent=4) + except Exception: + print(Exception) + pass + # logging.debug(new_data) + except Exception as ex: + print(ex) + pass + + +def read_logs(): + with open( + r"C:\Users\soule\Downloads\Telegram Desktop\timer_Megasport_Nport_2024-03-05_20-00-17.log", + "r", + ) as file: + for line in file: + parts = line.strip().split(" DEBUG ") + if len(parts) == 2: + timestamp = parts[0][1:] + data = eval(parts[1]) + if b"\xf83" in data or b"\xf88" in data or b"\xf87" in data: + parse(data) + time.sleep(0.1) + + +def main(): + current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + if not os.path.isdir("LOGS"): + os.mkdir("LOGS") + + LogFileName = f"LOGS/timer_Megasport_Nport_{current_time}.log" + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + filename=LogFileName, + filemode="w", + ) + new_data = { + "timeGFX": "0.0", + "time_attackGFX": "", + "quarter": "0", + "points1": "0", + "points2": "0", + "foul1": "0", + "foul2": "0", + "foul_pic1": "", + "foul_pic2": "", + "time_attac_pic": "", + } + with open(PATH, "w", encoding="utf-8") as file: + json.dump([new_data], file, ensure_ascii=False, indent=4) + + try: + tcp_socket = socket(AF_INET, SOCK_STREAM) + tcp_socket.connect((HOST, PORT)) + data = str.encode("hello") + tcp_socket.send(data) + data = bytes.decode(data) + while True: + data = tcp_socket.recv(1024) + logging.debug(data) + if b"\xf83" in data or b"\xf88" in data or b"\xf87" in data: + parse(data) + except KeyboardInterrupt: + tcp_socket.close() + sys.exit(1) + + +if __name__ == "__main__": + try: + main() + # read_logs() + except KeyboardInterrupt: + sys.exit(1)