first commit
This commit is contained in:
163
RPL/main.py
Normal file
163
RPL/main.py
Normal file
@@ -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()
|
||||
11
data_sender.py
Normal file
11
data_sender.py
Normal file
@@ -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}")
|
||||
405
divs/jsonserver.py
Normal file
405
divs/jsonserver.py
Normal file
@@ -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.")
|
||||
34
divs/tcp_monitor.py
Normal file
34
divs/tcp_monitor.py
Normal file
@@ -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.")
|
||||
123
old/timer_MBA.py
Normal file
123
old/timer_MBA.py
Normal file
@@ -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()
|
||||
143
old/timer_MBA_2.py
Normal file
143
old/timer_MBA_2.py
Normal file
@@ -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)
|
||||
|
||||
141
old/timer_Megasport_test.py
Normal file
141
old/timer_Megasport_test.py
Normal file
@@ -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)
|
||||
82
old/timer_megasport.py
Normal file
82
old/timer_megasport.py
Normal file
@@ -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()
|
||||
70
old/timer_megasport2.py
Normal file
70
old/timer_megasport2.py
Normal file
@@ -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)
|
||||
58
old/timer_megasport3.py
Normal file
58
old/timer_megasport3.py
Normal file
@@ -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)
|
||||
261
old/timer_megasport5.py
Normal file
261
old/timer_megasport5.py
Normal file
@@ -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)
|
||||
25
old/timer_megasport_rider.py
Normal file
25
old/timer_megasport_rider.py
Normal file
@@ -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')
|
||||
363
timer COM copy.py
Normal file
363
timer COM copy.py
Normal file
@@ -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("<EFBFBD>", "")
|
||||
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()
|
||||
345
timer COM.py
Normal file
345
timer COM.py
Normal file
@@ -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] пропуск строки (не формат <20><><EFBFBD><EFBFBD><EFBFBD>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()
|
||||
486
timer COM3.py
Normal file
486
timer COM3.py
Normal file
@@ -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("<EFBFBD>", "")
|
||||
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()
|
||||
117
timer GPT 1.py
Normal file
117
timer GPT 1.py
Normal file
@@ -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()
|
||||
189
timer NATA Kazan.py
Normal file
189
timer NATA Kazan.py
Normal file
@@ -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)
|
||||
162
timer_KAZ.py
Normal file
162
timer_KAZ.py
Normal file
@@ -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)
|
||||
208
timer_MBA.py
Normal file
208
timer_MBA.py
Normal file
@@ -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)
|
||||
171
timer_NN.py
Normal file
171
timer_NN.py
Normal file
@@ -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)
|
||||
159
timer_NN_backup.py
Normal file
159
timer_NN_backup.py
Normal file
@@ -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)
|
||||
153
timer_NPORT_Deepron.py
Normal file
153
timer_NPORT_Deepron.py
Normal file
@@ -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("<E>")
|
||||
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 "<ID01>" in i and not any(char in i for char in ["$", "@", "%"]):
|
||||
func_new(i, name1, "<ID01>")
|
||||
elif "<ID02>" in i and not any(char in i for char in ["$", "@", "%"]):
|
||||
func_new(i, name2, "<ID02>")
|
||||
elif "<ID03>" in i:
|
||||
func_new(i, name3, "<ID03>")
|
||||
elif "<ID04>" in i:
|
||||
func_new(i, name4, "<ID04>")
|
||||
|
||||
|
||||
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)
|
||||
128
timer_NPORT_коньки.py
Normal file
128
timer_NPORT_коньки.py
Normal file
@@ -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)
|
||||
92
timer_app.py
Normal file
92
timer_app.py
Normal file
@@ -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()
|
||||
326
timer_app2.py
Normal file
326
timer_app2.py
Normal file
@@ -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()
|
||||
369
timer_app2_temp.py
Normal file
369
timer_app2_temp.py
Normal file
@@ -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()
|
||||
415
timer_app3.py
Normal file
415
timer_app3.py
Normal file
@@ -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()
|
||||
620
timer_app4.py
Normal file
620
timer_app4.py
Normal file
@@ -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()
|
||||
155
timer_china_tcp.py
Normal file
155
timer_china_tcp.py
Normal file
@@ -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)
|
||||
119
timer_chine.py
Normal file
119
timer_chine.py
Normal file
@@ -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)
|
||||
165
timer_chine_tcp.py
Normal file
165
timer_chine_tcp.py
Normal file
@@ -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)
|
||||
169
timer_exe.py
Normal file
169
timer_exe.py
Normal file
@@ -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://<ip>: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()
|
||||
107
timer_hockey_balashikha.py
Normal file
107
timer_hockey_balashikha.py
Normal file
@@ -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()
|
||||
203
timer_jet.py
Normal file
203
timer_jet.py
Normal file
@@ -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()
|
||||
189
timer_nata_test (2).py
Normal file
189
timer_nata_test (2).py
Normal file
@@ -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)
|
||||
78
timer_playground copy.py
Normal file
78
timer_playground copy.py
Normal file
@@ -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)
|
||||
87
timer_playground.py
Normal file
87
timer_playground.py
Normal file
@@ -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)
|
||||
|
||||
141
timer_saratov.py
Normal file
141
timer_saratov.py
Normal file
@@ -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)
|
||||
160
timer_saratovCW.py
Normal file
160
timer_saratovCW.py
Normal file
@@ -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)
|
||||
161
timer_stramatel copy.py
Normal file
161
timer_stramatel copy.py
Normal file
@@ -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)
|
||||
160
timer_stramatel.py
Normal file
160
timer_stramatel.py
Normal file
@@ -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)
|
||||
Reference in New Issue
Block a user