405 lines
13 KiB
Python
405 lines
13 KiB
Python
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.") |