Läuft die Voice Acoustic VA-Remotecontrol (AllDSP AllControl) nativ unter Linux auf echtem wxGTK 3.0 — ohne Wine und ohne dekompilierten App-Code. Ausgeführt wird das unveränderte Python-2.7-Bytecode aus dem macOS-.app; C-Extensions (wxGTK/numpy/ scipy/PortAudio) kommen nativ aus Debian stretch. Enthält: va/ (Original-.pyc + pure-Python-Libs + Assets + launch.py mit den drei Linux-Fixes), Dockerfile/run.sh/entrypoint.sh, reference/ (dekompilierter Quellcode zum Debuggen) und README/STATUS. img.cache (378 MB, regenerierbar) ist per .gitignore ausgeschlossen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1333 lines
55 KiB
Python
1333 lines
55 KiB
Python
# uncompyle6 version 3.9.3
|
|
# Python bytecode version base 2.6 (62161)
|
|
# Decompiled from: Python 3.9.25 (main, Oct 31 2025, 23:16:49)
|
|
# [GCC 14.2.0]
|
|
# Embedded file name: server.pyc
|
|
# Compiled at: 2024-11-13 12:27:47
|
|
import mytime, d_protocol, socket, collections, threading, copy, struct, types, sys, os.path, traceback, wx, codecs, string, d_ethernet, d_usb, d_bootloader, d_keepalive, one_unit, main, protocol, data_model, future
|
|
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, EPIPE, errorcode
|
|
errorlist = (
|
|
EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET,
|
|
ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, EPIPE)
|
|
mac_names = 'posix'
|
|
if os.name in mac_names:
|
|
newline = '\n'
|
|
else:
|
|
newline = '\r\n'
|
|
Key = collections.namedtuple('Key', 'struct_id, member_id, channel, num')
|
|
help_text = newline + 'Commands: ' + newline + 'telnet: Enter telnet mode.' + newline + 'list: List available units.' + newline + 'quit: Close the software.' + newline + 'get: Read variale value from unit.' + newline + 'set: Set variable value to unit.' + newline + newline + 'Syntax:' + newline + 'get [MAC]/[Structure ID]/[Member ID]/[Channel]/[index]' + newline + 'Example: get AB:CD:EF:12:34:56/0/0/0/0' + newline + 'set [MAC]/[Structure ID]/[Member ID]/[Channel]/[index]=[value]' + newline + 'Example: set AB:CD:EF:12:34:56/0/0/0/0=-13.47'
|
|
password_text = newline + 'Attention: You need to be logged in with the factory password to be able to read or set values. Log in by setting 13/29/0/0=[password].' + newline + newline
|
|
|
|
class RemoteUnits():
|
|
|
|
def __init__(self, parent):
|
|
self.units = {}
|
|
self.clients = {}
|
|
self.parent = parent
|
|
self.lock = threading.Lock()
|
|
self.ignore_list = []
|
|
self.onlineUnits = 0
|
|
return
|
|
|
|
def add(self, unit):
|
|
if not unit:
|
|
return
|
|
else:
|
|
if unit == None:
|
|
return
|
|
if unit.type not in one_unit.app.supported_unit_ids and unit.type not in one_unit.app.short_unit_ids and one_unit.app.testpc == False and one_unit.app.supportAnyUnit == False:
|
|
if unit.MAC not in self.ignore_list:
|
|
self.ignore_list.append(unit.MAC)
|
|
if unit.type.startswith('1_1') == True:
|
|
one_unit.app.ignoredUnits[unit.MAC] = unit
|
|
print mytime.displayTime() + ' s.a.Ignoring unit: ', unit.MAC, unit.type, unit.IP
|
|
return
|
|
if unit.MAC not in self.units:
|
|
self.units[unit.MAC] = unit
|
|
self.units[unit.MAC].discover_time = mytime.clock()
|
|
if unit.pkt != None:
|
|
self.onlineUnits += 1
|
|
else:
|
|
self.units[unit.MAC].IP = unit.IP
|
|
if self.units[unit.MAC].link_status != 'available':
|
|
self.units[unit.MAC].link_status = unit.link_status
|
|
self.units[unit.MAC].type = unit.type
|
|
self.units[unit.MAC].pkt = unit.pkt
|
|
self.units[unit.MAC].link_type = unit.link_type
|
|
self.units[unit.MAC].DSPState = unit.DSPState
|
|
self.units[unit.MAC].Serial = unit.Serial
|
|
self.units[unit.MAC].HWVersion = unit.HWVersion
|
|
self.units[unit.MAC].PICVersion = unit.PICVersion
|
|
self.units[unit.MAC].ProductionDate = unit.ProductionDate
|
|
self.units[unit.MAC].originalSwID = unit.originalSwID
|
|
return
|
|
|
|
def print_units(self):
|
|
if len(self.units) == 0:
|
|
print mytime.displayTime() + ' None'
|
|
for MAC in self.units:
|
|
print mytime.displayTime(), self.units[MAC].MAC, self.units[MAC].IP, self.units[MAC].type, self.units[MAC].name
|
|
|
|
return
|
|
|
|
def delete(self, MAC):
|
|
if MAC in self.units:
|
|
del self.units[MAC]
|
|
return
|
|
|
|
def set_unit_name(self, MAC, val):
|
|
self.units[MAC].name = val
|
|
return
|
|
|
|
def clear_preset_names(self, MAC):
|
|
self.units[MAC].preset_names = {}
|
|
return
|
|
|
|
def set_by_key(self, MAC, key, val):
|
|
try:
|
|
if key.struct_id >= 0 and self.units[MAC].values[key] == val:
|
|
return
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.units[MAC].values[key] = val
|
|
for client in self.clients[MAC].values():
|
|
client.set_direct(key, val)
|
|
|
|
return
|
|
except:
|
|
pass
|
|
|
|
self.units[MAC].values[key] = val
|
|
self.parent.local_listener.priority_level[key] = mytime.clock() + 2
|
|
return
|
|
|
|
def get(self, key, MAC):
|
|
try:
|
|
return self.units[MAC].values[key]
|
|
except:
|
|
return
|
|
|
|
return
|
|
|
|
|
|
class UnitData():
|
|
|
|
def __init__(self):
|
|
self.vu = {}
|
|
self.gr = {}
|
|
return
|
|
|
|
|
|
unit_data = UnitData()
|
|
|
|
class Daemon():
|
|
|
|
def __init__(self):
|
|
self.thread = threading.Thread(name='AllDSP Client Monitor', target=self.process)
|
|
self.thread.daemon = True
|
|
self.last_loopback = None
|
|
self.start()
|
|
self.last_maclist = []
|
|
self.last_threads = []
|
|
self.last_processlist = []
|
|
return
|
|
|
|
def start(self):
|
|
self.thread.start()
|
|
return
|
|
|
|
def process(self):
|
|
self.peers = RemoteUnits(self)
|
|
self.local_listener = TCP_Listener(self)
|
|
while one_unit.app.init_finished == False:
|
|
mytime.sleep(0.01)
|
|
|
|
self.ethernet_listener = d_ethernet.Ethernet(self)
|
|
self.bootloader_listener = d_bootloader.Bootloader(self)
|
|
self.usb_listener = d_usb.USB_updater(self)
|
|
self.ethernet_listener.start()
|
|
self.bootloader_listener.start()
|
|
self.usb_listener.start()
|
|
last_displaylist = {}
|
|
while one_unit.app.application_stopping == False:
|
|
mytime.sleep(0.1)
|
|
active_threads = threading.enumerate()
|
|
MAClist = [_[1] for MAC in self.peers.units.keys()]
|
|
for MAC in MAClist:
|
|
if MAC.startswith('DEMO') == True:
|
|
continue
|
|
found = False
|
|
for thread in active_threads:
|
|
if thread.name.strip() == MAC.strip():
|
|
found = True
|
|
break
|
|
|
|
if found == False and self.peers.units[MAC].process != None:
|
|
self.peers.units[MAC].process = None
|
|
print mytime.displayTime() + ' s.Process reset'
|
|
if found == False and self.peers.units[MAC].IP[:3] != 'DEM' and (self.peers.units[MAC].link_status == 'available' or self.peers.units[MAC].link_status == 'ready'):
|
|
self.peers.units[MAC].process = d_protocol.Remote_Link(self, MAC)
|
|
print mytime.displayTime() + ' s.p.started thread ' + MAC, self.peers.units[MAC].link_status
|
|
|
|
mytime.sleep(0.1)
|
|
self.local_listener.Close()
|
|
mytime.sleep(0.1)
|
|
threadlist = threading.enumerate()
|
|
exit_counter = 0
|
|
while exit_counter < 1000:
|
|
threadlist = threading.enumerate()
|
|
exit_counter += 1
|
|
continue_loop = False
|
|
for thread in threadlist:
|
|
if thread.name in ('MAC', 'AllDSP Server USB Detection', 'AllDSP Server Ethernet Detection'):
|
|
mytime.sleep(0.1)
|
|
continue_loop = True
|
|
break
|
|
|
|
if continue_loop == False:
|
|
break
|
|
|
|
for thread in threadlist:
|
|
if thread.name in ('MAC', 'AllDSP Server USB Detection', 'AllDSP Server Ethernet Detection'):
|
|
print mytime.displayTime() + ' Not all server threads quit in time, exiting anyway.'
|
|
else:
|
|
print mytime.displayTime() + ' All server threads exited normally'
|
|
|
|
print mytime.displayTime() + ' Server terminated'
|
|
return
|
|
|
|
|
|
class TCP_Listener():
|
|
"""Listen to TCP connections from a user, e.g., a GUI."""
|
|
|
|
def __init__(self, parent):
|
|
self.priority_level = {}
|
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
try:
|
|
self.sock.bind(('0.0.0.0', 50684))
|
|
self.sock.listen(1)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
print mytime.displayTime() + ' Local Loopback Server Failed'
|
|
|
|
self.parent = parent
|
|
self.conn = {}
|
|
self.index = 0
|
|
self.group_membership_list = {}
|
|
self.groups = {}
|
|
self.thread = threading.Thread(name='AllDSP Local Loopback', target=self.process)
|
|
self.thread.daemon = True
|
|
self.start()
|
|
return
|
|
|
|
def start(self):
|
|
self.thread.start()
|
|
return
|
|
|
|
def process(self):
|
|
self.sock.settimeout(1)
|
|
while one_unit.app.application_stopping == False:
|
|
try:
|
|
(new_sock, addr) = self.sock.accept()
|
|
self.conn[self.index] = User_command(self, new_sock)
|
|
self.conn[self.index].start()
|
|
self.index += 1
|
|
except:
|
|
pass
|
|
|
|
print mytime.displayTime() + ' Closing Local Loopback'
|
|
try:
|
|
self.sock.close()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def start_direct_link(self, direct):
|
|
client = direct.parent
|
|
mac = client.MAC
|
|
self.conn[self.index] = User_command(self, None, mac, direct)
|
|
try:
|
|
if mac.startswith('GRP_'):
|
|
group = mac[4:]
|
|
unit_mac = one_unit.app.groups[group].keys()[0]
|
|
if unit_mac not in self.parent.peers.clients:
|
|
self.parent.peers.clients[unit_mac] = {}
|
|
self.parent.peers.clients[unit_mac][client.launchKey] = direct.parent.model
|
|
elif mac not in self.parent.peers.clients:
|
|
self.parent.peers.clients[mac] = {}
|
|
self.parent.peers.clients[mac][client.launchKey] = direct.parent.model
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.index += 1
|
|
return self.conn[self.index - 1]
|
|
|
|
def handle_close(self):
|
|
try:
|
|
self.sock.close()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def Close(self):
|
|
try:
|
|
self.conn[self.index].Close()
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.sock.close()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
|
|
class User_command():
|
|
|
|
def __init__(self, parent, new_sock, mac=None, direct=None):
|
|
if new_sock != None:
|
|
self.s = new_sock
|
|
self.s.settimeout(12)
|
|
self.link_mac = 'Unknown'
|
|
self.direct = None
|
|
else:
|
|
self.s = None
|
|
self.link_mac = mac
|
|
self.direct = direct
|
|
self.ibuffer = ''
|
|
self.echo = False
|
|
self.telnet = False
|
|
self.parent = parent
|
|
self.request_MAC_list = {}
|
|
self.last_requested = 0
|
|
self.group_list = {}
|
|
self.make_group_skip_list()
|
|
self.printed_conn = False
|
|
self.start_time = mytime.clock()
|
|
if self.s != None:
|
|
self.thread = threading.Thread(name='AllDSP Local Loopback conn ' + str(self.parent.index), target=self.process)
|
|
self.thread.daemon = True
|
|
return
|
|
|
|
def start(self):
|
|
if self.s != None:
|
|
self.thread.start()
|
|
return
|
|
|
|
def process(self):
|
|
self.ibuffer = ''
|
|
self.s.settimeout(1)
|
|
while one_unit.app.application_stopping == False:
|
|
try:
|
|
data = self.s.recv(1024)
|
|
if data != None and len(data) >= 1:
|
|
self.collect_incoming_data(data)
|
|
else:
|
|
print mytime.displayTime() + ' Server connection with ' + self.link_mac + ' disconnected'
|
|
break
|
|
except socket.timeout:
|
|
if self.direct != None:
|
|
continue
|
|
except:
|
|
print mytime.displayTime() + ' Server connection with ' + self.link_mac + ' failed!'
|
|
traceback.print_exc(file=sys.stdout)
|
|
break
|
|
|
|
self.s.close()
|
|
print mytime.displayTime() + ' Link process ' + self.link_mac + ' exit'
|
|
return
|
|
|
|
def Close(self):
|
|
self.close()
|
|
return
|
|
|
|
def push(self, data):
|
|
if self.direct == None:
|
|
self.s.send(data)
|
|
return
|
|
else:
|
|
self.direct.recv_direct(data)
|
|
return
|
|
|
|
def make_group_skip_list(self):
|
|
self.group_skip_list = []
|
|
self.group_skip_list.append(Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_SHORT_NAME, 0, 0))
|
|
self.group_skip_list.append(Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_IP, 0, 0))
|
|
self.group_skip_list.append(Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_SUBNET_MASK, 0, 0))
|
|
self.group_skip_list.append(Key(protocol.STRUCT_ID_COMMAND, protocol.MEMBER_ID_COMMAND, 0, protocol.cmdLocate))
|
|
self.group_skip_list.append(Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_HARDWARE_STATUS_FLAGS, 0, 0))
|
|
return
|
|
|
|
def collect_incoming_data(self, data):
|
|
self.ibuffer += data
|
|
if self.echo == True:
|
|
self.push(data)
|
|
if self.ibuffer.find('\r') < 0 and len(data) < 4:
|
|
return
|
|
else:
|
|
if self.echo == True:
|
|
self.push(newline)
|
|
if self.ibuffer.startswith('list'):
|
|
self.command_list()
|
|
elif self.ibuffer.startswith('echo'):
|
|
self.echo = True
|
|
elif self.ibuffer.startswith('DDL'):
|
|
self.command_DDL()
|
|
elif self.ibuffer.startswith('vudata'):
|
|
self.send_vu_data()
|
|
elif self.ibuffer.startswith('presets'):
|
|
self.command_presets()
|
|
elif self.ibuffer.startswith('update_groups'):
|
|
self.update_groups()
|
|
elif self.ibuffer.startswith('mute_single_unit'):
|
|
self.mute_single_unit()
|
|
elif self.ibuffer.startswith('mute_group'):
|
|
self.mute_group()
|
|
elif self.ibuffer.startswith('make_image'):
|
|
self.make_image()
|
|
elif self.ibuffer.startswith('update_display'):
|
|
self.update_display()
|
|
elif self.ibuffer.startswith('power_single_unit'):
|
|
self.power_single_unit()
|
|
elif self.ibuffer.startswith('power_group'):
|
|
self.power_group()
|
|
elif self.ibuffer.startswith('locate_unit'):
|
|
self.locate_unit()
|
|
elif self.ibuffer.startswith('clear_data_buffer'):
|
|
self.clear_data_buffer()
|
|
elif self.ibuffer.startswith('start_main_update'):
|
|
mac = self.ibuffer[18:]
|
|
one_unit.app.always_allow_update[mac] = True
|
|
one_unit.app.interfaceUpdate[mac] = False
|
|
one_unit.app.image_filesize[mac] = '0x1000000'
|
|
one_unit.app.image_filename[mac] = None
|
|
self.start_main_update()
|
|
elif self.ibuffer.startswith('quit'):
|
|
one_unit.app.application_stopping = True
|
|
one_unit.app.main_frame.Close()
|
|
elif self.ibuffer.startswith('enable_bootloader'):
|
|
one_unit.app.enable_bootloader = True
|
|
elif self.ibuffer.startswith('disable_bootloader'):
|
|
one_unit.app.enable_bootloader = False
|
|
elif self.ibuffer.startswith('update_progress'):
|
|
mac = self.ibuffer[16:]
|
|
print mytime.displayTime() + ' Progress for', mac, ':', one_unit.app.bootloader_progress[mac]
|
|
self.push(str(one_unit.app.bootloader_progress[mac]))
|
|
elif self.ibuffer.startswith('bl_update_progress'):
|
|
try:
|
|
self.push(str(one_unit.app.bootloader_progress['Bootloader']))
|
|
except:
|
|
self.push('None')
|
|
|
|
elif self.ibuffer.startswith('time'):
|
|
self.push(str(mytime.clock()))
|
|
elif self.ibuffer.startswith('telnet'):
|
|
self.telnet = True
|
|
elif self.ibuffer.strip() in ('?', 'help', 'HELP', 'Help'):
|
|
self.push(help_text)
|
|
self.push(password_text)
|
|
elif self.ibuffer.startswith('get_info'):
|
|
self.sendMyInfo()
|
|
elif self.ibuffer[:3] in ('GET', 'get', 'Get'):
|
|
self.command_get()
|
|
elif self.ibuffer[:3] in ('SET', 'set', 'Set'):
|
|
self.command_set()
|
|
elif self.ibuffer.strip() == 'testResult':
|
|
self.sendTestResult()
|
|
else:
|
|
self.push(newline + 'Unknown command: ' + self.ibuffer)
|
|
if self.telnet == True:
|
|
self.push(newline)
|
|
self.ibuffer = ''
|
|
return
|
|
|
|
def sendTestResult(self):
|
|
self.push('Test result:' + one_unit.app.testResult)
|
|
return
|
|
|
|
def sendMyInfo(self):
|
|
self.push(os.getcwd())
|
|
return
|
|
|
|
def mute_group(self):
|
|
self.ibuffer = self.ibuffer[10:]
|
|
if len(self.ibuffer) < 1:
|
|
print mytime.displayTime() + ' server.mute_group: Packet too short'
|
|
self.push('error')
|
|
return
|
|
tlen = ord(self.ibuffer[0])
|
|
if len(self.ibuffer) < tlen + 1:
|
|
print mytime.displayTime() + ' server.mute_group: Packet too short (2)'
|
|
self.push('error')
|
|
return
|
|
target = self.ibuffer[1:tlen + 1]
|
|
mute = ord(self.ibuffer[tlen + 1])
|
|
if target == 'all_units':
|
|
maclist = [_[1] for k in self.parent.parent.peers.units if self.parent.parent.peers.units[k].link_status == 'available']
|
|
else:
|
|
maclist = one_unit.getMacList(target)
|
|
if len(maclist) == 0:
|
|
print mytime.displayTime() + ' Unknown Group', target, maclist
|
|
return
|
|
if mute == 0:
|
|
print mytime.displayTime(), 's.mg.Unmuting', len(maclist), 'units'
|
|
else:
|
|
print mytime.displayTime(), 's.mg.Muting', len(maclist), 'units'
|
|
i = 0
|
|
for mac in maclist:
|
|
try:
|
|
self.parent.parent.peers.units[mac].process.TempMute(mute)
|
|
i += 1
|
|
except:
|
|
print mytime.displayTime(), i, 's.mg.Exception for unit', mac
|
|
|
|
return
|
|
|
|
def mute_single_unit(self):
|
|
self.ibuffer = self.ibuffer[16:]
|
|
if len(self.ibuffer) < 18:
|
|
print mytime.displayTime() + ' server.mute_single_unit: Packet too short'
|
|
self.push('error')
|
|
return
|
|
target = self.ibuffer[1:len(self.ibuffer) - 1]
|
|
mute = ord(self.ibuffer[len(self.ibuffer) - 1])
|
|
try:
|
|
self.parent.parent.peers.units[target].process.TempMute(mute)
|
|
except:
|
|
print mytime.displayTime() + ' Mute single unit failed for', target
|
|
|
|
return
|
|
|
|
def make_image(self):
|
|
self.ibuffer = self.ibuffer[10:]
|
|
if len(self.ibuffer) < 1:
|
|
print mytime.displayTime() + ' server.make_image: Packet too short'
|
|
self.push('error')
|
|
return
|
|
target = self.ibuffer[1:len(self.ibuffer)]
|
|
try:
|
|
self.parent.parent.peers.units[target].process.MakeImage()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def update_display(self):
|
|
self.ibuffer = self.ibuffer[14:]
|
|
if len(self.ibuffer) < 1:
|
|
print mytime.displayTime() + ' server.update_display: Packet too short'
|
|
self.push('error')
|
|
return
|
|
target = self.ibuffer[1:len(self.ibuffer)]
|
|
print mytime.displayTime(), 's.update_display'
|
|
try:
|
|
self.parent.parent.peers.units[target].process.startUpdateDisplay()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def power_group(self):
|
|
self.ibuffer = self.ibuffer[11:]
|
|
if len(self.ibuffer) < 1:
|
|
print mytime.displayTime() + ' server.power_group: Packet too short'
|
|
self.push('error')
|
|
return
|
|
tlen = ord(self.ibuffer[0])
|
|
if len(self.ibuffer) < tlen + 1:
|
|
print mytime.displayTime() + ' server.power_group: Packet too short (2)'
|
|
self.push('error')
|
|
return
|
|
target = self.ibuffer[1:tlen + 1]
|
|
state = ord(self.ibuffer[tlen + 1])
|
|
if target == 'all_units':
|
|
maclist = self.parent.parent.peers.units.keys()
|
|
else:
|
|
try:
|
|
maclist = one_unit.app.groups[target]
|
|
except:
|
|
print mytime.displayTime() + ' Unknown Group', target
|
|
return
|
|
|
|
threads = {}
|
|
for mac in maclist:
|
|
if mac not in one_unit.app.pin_verified or one_unit.app.pin_verified[mac] == False:
|
|
continue
|
|
if mac not in self.parent.parent.peers.units:
|
|
continue
|
|
try:
|
|
threads[mac] = threading.Thread('power_state_' + mac, target=self.parent.parent.peers.units[mac].process.SetPower(state))
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def power_single_unit(self):
|
|
self.ibuffer = self.ibuffer[17:]
|
|
if len(self.ibuffer) < 18:
|
|
print mytime.displayTime() + ' server.power_single_unit: Packet too short'
|
|
self.push('error')
|
|
return
|
|
target = self.ibuffer[1:len(self.ibuffer) - 1]
|
|
state = ord(self.ibuffer[len(self.ibuffer) - 1])
|
|
try:
|
|
self.parent.parent.peers.units[target].process.SetPower(state)
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def send_vu_data(self):
|
|
data = 'vu_list:'
|
|
try:
|
|
for mac in unit_data.vu.keys():
|
|
data += str(mac) + struct.pack('b', unit_data.vu[mac][0]) + struct.pack('b', unit_data.vu[mac][1])
|
|
|
|
except:
|
|
pass
|
|
|
|
self.push(data)
|
|
return
|
|
|
|
def update_groups(self):
|
|
group_membership_list = {}
|
|
for MAC in self.parent.parent.peers.units.keys():
|
|
group_membership_list[MAC] = []
|
|
for group_id in one_unit.app.groups:
|
|
if MAC in one_unit.app.groups[group_id].keys():
|
|
group_membership_list[MAC].append(group_id)
|
|
|
|
self.parent.group_membership_list[MAC] = group_membership_list[MAC]
|
|
|
|
self.parent.groups = one_unit.app.groups
|
|
return
|
|
|
|
def locate_unit(self):
|
|
self.ibuffer = self.ibuffer[11:]
|
|
if len(self.ibuffer) < 1:
|
|
print mytime.displayTime() + ' server.locate_unit: Packet too short'
|
|
self.push('error')
|
|
return
|
|
tlen = ord(self.ibuffer[0])
|
|
if len(self.ibuffer) < tlen + 1:
|
|
print mytime.displayTime() + ' server.locate_unit: Packet too short (2)'
|
|
self.push('error')
|
|
return
|
|
target = self.ibuffer[1:tlen + 1]
|
|
key = data_model.Key(protocol.STRUCT_ID_COMMAND, protocol.MEMBER_ID_COMMAND, 0, protocol.cmdLocate)
|
|
try:
|
|
if target in self.parent.parent.peers.units.keys():
|
|
self.parent.parent.peers.units[target].process.conn.set_by_key(key, 1)
|
|
try:
|
|
future.Future(3, self.parent.parent.peers.units[target].process.conn.set_by_key, key, 0)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
else:
|
|
print mytime.displayTime() + ' Unknown Unit:', target
|
|
except:
|
|
print mytime.displayTime() + ' s.lu.Unit not connected:', target
|
|
|
|
return
|
|
|
|
def start_main_update(self):
|
|
print mytime.displayTime(), 's.smu.1'
|
|
self.ibuffer = self.ibuffer[17:]
|
|
if len(self.ibuffer) < 1:
|
|
print mytime.displayTime() + ' server.start_main_update: Packet too short'
|
|
self.push('error: packet too short')
|
|
return
|
|
tlen = ord(self.ibuffer[0])
|
|
if len(self.ibuffer) < tlen + 1 and self.telnet == False:
|
|
print mytime.displayTime() + ' server.start_main_update: Packet too short (2)'
|
|
self.push('error: packet too short')
|
|
return
|
|
if self.telnet == True:
|
|
target = self.ibuffer[1:].strip()
|
|
else:
|
|
target = self.ibuffer[1:tlen + 1]
|
|
if self.telnet == False:
|
|
ignore = self.ibuffer[tlen + 1]
|
|
else:
|
|
ignore = 'i'
|
|
print mytime.displayTime(), ' '
|
|
print mytime.displayTime() + ' s.smu.Updating', target, ignore
|
|
try:
|
|
if target in self.parent.parent.peers.units.keys():
|
|
self.parent.parent.peers.units[target].process.StartMainUpdate(ignore)
|
|
if self.telnet == True:
|
|
self.push('Updating ' + target)
|
|
else:
|
|
print mytime.displayTime() + ' Unknown Unit:', target
|
|
self.push('error: unknown target')
|
|
except:
|
|
print mytime.displayTime() + ' s.smu.Unit not connected:', target
|
|
self.push('error: unit not connected')
|
|
|
|
return
|
|
|
|
def clear_data_buffer(self):
|
|
if len(self.ibuffer) > 3:
|
|
MAC = self.ibuffer[17:]
|
|
if MAC.count(':') != 5:
|
|
print mytime.displayTime(), 's.cdb.No valid MAC found, aborting. MAC:', MAC
|
|
self.push('clear_data_buffer_failed')
|
|
return
|
|
try:
|
|
tmp = self.parent.parent.peers.units[MAC].process.conn.MK2
|
|
except:
|
|
self.push('clear_data_buffer_failed')
|
|
mytime.sleep(0.1)
|
|
return
|
|
else:
|
|
try:
|
|
name = self.parent.parent.peers.units[MAC].name
|
|
while 1:
|
|
for testkey in self.parent.parent.peers.units[MAC].process.conn.values.keys():
|
|
if testkey.struct_id != protocol.STRUCT_ID_COMMAND and testkey.member_id not in protocol.unit_global_items:
|
|
if testkey.struct_id == protocol.STRUCT_ID_PRESET_GLOBAL and testkey.member_id == protocol.MEMBER_ID_SHORT_NAME and testkey.channel > 0:
|
|
continue
|
|
del self.parent.parent.peers.units[MAC].process.conn.values[testkey]
|
|
break
|
|
|
|
stop_loop = True
|
|
for testkey in self.parent.parent.peers.units[MAC].process.conn.values.keys():
|
|
if testkey.struct_id != protocol.STRUCT_ID_COMMAND and testkey.member_id not in protocol.unit_global_items:
|
|
if testkey.struct_id == protocol.STRUCT_ID_PRESET_GLOBAL and testkey.member_id == protocol.MEMBER_ID_SHORT_NAME and testkey.channel > 0:
|
|
continue
|
|
stop_loop = False
|
|
break
|
|
|
|
if stop_loop == True:
|
|
break
|
|
|
|
self.parent.parent.peers.units[MAC].process.conn.ResetValues = True
|
|
self.parent.parent.peers.units[MAC].process.conn.correct_vars = 0
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.push('clear_data_buffer_ok')
|
|
print mytime.displayTime() + ' s.cdb.Cleared data buffer for', MAC
|
|
return
|
|
print mytime.displayTime() + ' s.cdb.Clear data buffer failed, invalid command'
|
|
return
|
|
|
|
def command_get(self):
|
|
try:
|
|
MAC = self.ibuffer[self.ibuffer.find(' ') + 1:self.ibuffer.find('/')]
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
struct_id = int(self.ibuffer[:self.ibuffer.find('/')])
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
member_id = int(self.ibuffer[:self.ibuffer.find('/')])
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
channel = int(self.ibuffer[:self.ibuffer.find('/')])
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
num = int(self.ibuffer)
|
|
if member_id in (protocol.MEMBER_ID_SET_PASSWORD, protocol.MEMBER_ID_CHECK_PASSWORD):
|
|
self.push(newline + 'Access Denied')
|
|
return
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_CURRENT_USER, 0, 0)
|
|
try:
|
|
user = int(self.parent.parent.peers.units[MAC].process.conn.values[key].read_val)
|
|
except:
|
|
user = protocol.uLocked
|
|
|
|
if user != protocol.uFactory and member_id != protocol.MEMBER_ID_CURRENT_USER and one_unit.app.testpc == False:
|
|
self.push(newline + 'Access Denied')
|
|
return
|
|
key = data_model.Key(struct_id, member_id, channel, num)
|
|
if key not in one_unit.app.member_scale:
|
|
one_unit.app.member_scale[key] = protocol.get_member_scale(key.member_id)
|
|
one_unit.app.member_offset[key] = 0.0
|
|
try:
|
|
if protocol.get_member_format(member_id)[-1:] == 's':
|
|
val = self.parent.parent.peers.units[MAC].process.conn.values[key].read_val
|
|
else:
|
|
val = self.parent.parent.peers.units[MAC].process.conn.values[key].read_val - one_unit.app.member_offset[key]
|
|
val = val / one_unit.app.member_scale[key]
|
|
self.push(newline + MAC + '/' + str(struct_id) + '/' + str(member_id) + '/' + str(channel) + '/' + str(num) + ': ' + str(val))
|
|
except:
|
|
self.push(newline + MAC + '/' + str(struct_id) + '/' + str(member_id) + '/' + str(channel) + '/' + str(num) + ': None')
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.push(newline + 'Syntax error')
|
|
|
|
return
|
|
|
|
def command_set(self):
|
|
try:
|
|
MAC = self.ibuffer[self.ibuffer.find(' ') + 1:self.ibuffer.find('/')]
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
struct_id = int(self.ibuffer[:self.ibuffer.find('/')])
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
member_id = int(self.ibuffer[:self.ibuffer.find('/')])
|
|
key = data_model.Key(protocol.STRUCT_ID_GLOBAL, protocol.MEMBER_ID_CURRENT_USER, 0, 0)
|
|
try:
|
|
user = int(self.parent.parent.peers.units[MAC].process.conn.values[key].read_val)
|
|
except:
|
|
user = protocol.uLocked
|
|
|
|
if user != protocol.uFactory and member_id != protocol.MEMBER_ID_CHECK_PASSWORD and one_unit.app.testpc == False:
|
|
self.push(newline + 'Access Denied')
|
|
return
|
|
if member_id in (protocol.MEMBER_ID_SET_PASSWORD, protocol.MEMBER_ID_CURRENT_USER):
|
|
self.push(newline + 'Access Denied')
|
|
return
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
channel = int(self.ibuffer[:self.ibuffer.find('/')])
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('/') + 1:]
|
|
num = int(self.ibuffer[:self.ibuffer.find('=')])
|
|
self.ibuffer = self.ibuffer[self.ibuffer.find('=') + 1:]
|
|
val = self.ibuffer.strip()
|
|
valstring = val
|
|
key = data_model.Key(struct_id, member_id, channel, num)
|
|
if key not in one_unit.app.member_scale:
|
|
one_unit.app.member_scale[key] = protocol.get_member_scale(key.member_id)
|
|
one_unit.app.member_offset[key] = 0.0
|
|
try:
|
|
if protocol.get_member_format(member_id)[-1:] != 's':
|
|
val = float(val) * one_unit.app.member_scale[key]
|
|
val = val + one_unit.app.member_offset[key]
|
|
try:
|
|
if member_id in (protocol.MEMBER_ID_CHECK_PASSWORD, protocol.MEMBER_ID_COMMAND):
|
|
self.parent.parent.peers.units[MAC].process.conn.set_by_key(key, val, False)
|
|
else:
|
|
self.parent.parent.peers.units[MAC].process.conn.set_by_key(key, val, True)
|
|
self.parent.parent.peers.set_by_key(MAC, key, val)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.push(newline + 'Connection to target lost')
|
|
|
|
self.push(newline + 'Setting ' + MAC + '/' + str(struct_id) + '/' + str(member_id) + '/' + str(channel) + '/' + str(num) + ': ' + valstring)
|
|
except:
|
|
self.push(newline + 'Unknown error')
|
|
print mytime.displayTime(), 's.cs.Error in telnet process'
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.push(newline + 'Syntax error')
|
|
|
|
return
|
|
|
|
def command_DDL(self):
|
|
if len(self.ibuffer) > 3:
|
|
cmd = self.process_data_pkt(parse_data_pkt(self.ibuffer), True)
|
|
if cmd == None:
|
|
return
|
|
self.push(cmd)
|
|
self.parent.parent.last_loopback = mytime.clock()
|
|
return
|
|
|
|
def command_list(self):
|
|
"""Process a 'list' command from the user."""
|
|
if len(self.parent.parent.peers.units) == 0:
|
|
self.push('unit_list:None' + newline)
|
|
elif self.telnet == True:
|
|
res = ''
|
|
try:
|
|
for MAC in self.parent.parent.peers.units.keys():
|
|
if MAC.startswith('DEMO') == True:
|
|
continue
|
|
res += 'unit:' + newline
|
|
res += 'MAC='
|
|
res += str(MAC) + newline
|
|
res += 'Name='
|
|
res += str(self.parent.parent.peers.units[MAC].name) + newline
|
|
res += 'Type='
|
|
res += str(self.parent.parent.peers.units[MAC].type) + newline
|
|
res += 'Link_type='
|
|
res += str(self.parent.parent.peers.units[MAC].link_type) + newline
|
|
res += 'Link_status='
|
|
res += str(self.parent.parent.peers.units[MAC].link_status) + newline
|
|
res += 'IP='
|
|
res += str(self.parent.parent.peers.units[MAC].IP) + newline
|
|
res += 'Serial_number='
|
|
res += str(self.parent.parent.peers.units[MAC].Serial) + newline
|
|
res += 'Hardware_version='
|
|
res += str(self.parent.parent.peers.units[MAC].HWVersion) + newline
|
|
res += 'Firmware_version='
|
|
res += str(self.parent.parent.peers.units[MAC].FWVersion) + newline
|
|
res += 'Interface_version='
|
|
res += str(self.parent.parent.peers.units[MAC].PICVersion) + newline
|
|
res += 'Type_String_2='
|
|
if self.parent.parent.peers.units[MAC].originalSwID == '':
|
|
self.parent.parent.peers.units[MAC].originalSwID = self.parent.parent.peers.units[MAC].type
|
|
res += str(self.parent.parent.peers.units[MAC].originalSwID) + newline
|
|
res += 'Production_date='
|
|
res += str(self.parent.parent.peers.units[MAC].ProductionDate) + newline
|
|
res += 'Mute_status='
|
|
res += str(self.parent.parent.peers.units[MAC].Muted) + newline
|
|
res += 'Build_Number='
|
|
res += str(self.parent.parent.peers.units[MAC].BuildNumber) + newline
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.push(res)
|
|
return
|
|
res = ''
|
|
res += 'unit_list:'
|
|
try:
|
|
for MAC in self.parent.parent.peers.units.keys():
|
|
if MAC.startswith('DEMO') == True:
|
|
continue
|
|
res += 'unit'
|
|
res += chr(len(MAC))
|
|
res += str(MAC)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].name))
|
|
res += str(self.parent.parent.peers.units[MAC].name)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].type))
|
|
res += str(self.parent.parent.peers.units[MAC].type)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].link_type))
|
|
res += str(self.parent.parent.peers.units[MAC].link_type)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].link_status))
|
|
res += str(self.parent.parent.peers.units[MAC].link_status)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].IP))
|
|
res += str(self.parent.parent.peers.units[MAC].IP)
|
|
res += chr(len(unicode(self.parent.parent.peers.units[MAC].Serial)))
|
|
res += str(self.parent.parent.peers.units[MAC].Serial)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].HWVersion))
|
|
res += str(self.parent.parent.peers.units[MAC].HWVersion)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].FWVersion))
|
|
res += str(self.parent.parent.peers.units[MAC].FWVersion)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].PICVersion))
|
|
res += str(self.parent.parent.peers.units[MAC].PICVersion)
|
|
if self.parent.parent.peers.units[MAC].originalSwID == '':
|
|
self.parent.parent.peers.units[MAC].originalSwID = self.parent.parent.peers.units[MAC].type
|
|
res += chr(len(self.parent.parent.peers.units[MAC].originalSwID))
|
|
res += str(self.parent.parent.peers.units[MAC].originalSwID)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].ProductionDate))
|
|
res += str(self.parent.parent.peers.units[MAC].ProductionDate)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].Muted))
|
|
res += str(self.parent.parent.peers.units[MAC].Muted)
|
|
res += chr(len(str(self.parent.parent.peers.units[MAC].BuildNumber)))
|
|
res += str(self.parent.parent.peers.units[MAC].BuildNumber)
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
res += 'end'
|
|
self.push(res)
|
|
return
|
|
|
|
def command_get_group(self):
|
|
my_group = 'None'
|
|
pos = ord(self.ibuffer[7]) + 6
|
|
MAC = self.ibuffer[6:pos]
|
|
res = 'group:'
|
|
for group in one_unit.app.groups.keys():
|
|
if group == 'all_units':
|
|
continue
|
|
if MAC in one_unit.app.groups[group].keys():
|
|
my_group = group
|
|
|
|
res += chr(len(my_group))
|
|
res += str(my_group)
|
|
self.push(res)
|
|
return
|
|
|
|
def command_presets(self):
|
|
"""Process a 'presets' command from the user."""
|
|
pos = ord(self.ibuffer[7]) + 8
|
|
MAC = self.ibuffer[8:pos]
|
|
if MAC == 'Main':
|
|
self.push('Not supported yet')
|
|
return
|
|
try:
|
|
length = len(self.parent.parent.peers.units[MAC].preset_names)
|
|
except:
|
|
print mytime.displayTime() + ' s.cp.unknown MAC address:', MAC
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.push('Unknown')
|
|
return
|
|
else:
|
|
if length == 0:
|
|
print mytime.displayTime() + ' s.cp.len=0'
|
|
self.push('None')
|
|
return
|
|
res = 'preset_list:'
|
|
for number in self.parent.parent.peers.units[MAC].preset_names.keys():
|
|
res += chr(number)
|
|
res += chr(len(self.parent.parent.peers.units[MAC].preset_names[number]))
|
|
res += str(self.parent.parent.peers.units[MAC].preset_names[number])
|
|
|
|
self.push(res)
|
|
return
|
|
|
|
def build_vars_to_send(self, MAC, limit):
|
|
vars = {}
|
|
no_of_correct_vars = 0
|
|
if MAC in self.parent.parent.peers.units:
|
|
try:
|
|
keys = [_[1] for k in self.parent.parent.peers.units[MAC].values.keys() if k[0] < 0]
|
|
except:
|
|
print mytime.displayTime() + ' server.build_vars_to_send VU list error'
|
|
return
|
|
else:
|
|
nitems = len(keys)
|
|
no_added = 0
|
|
item = 0
|
|
if nitems > 0:
|
|
while item < nitems:
|
|
key = keys[item]
|
|
try:
|
|
result = self.parent.parent.peers.units[MAC].values[key]
|
|
except:
|
|
print mytime.displayTime() + ' server.build_vars_to_send VU key error'
|
|
break
|
|
|
|
var = result
|
|
vars[key] = var
|
|
item += 1
|
|
|
|
try:
|
|
keys = [_[2] for k in self.parent.parent.peers.units[MAC].values.keys() if k[0] >= 0]
|
|
except:
|
|
print mytime.displayTime() + ' server.build_vars_to_send data key list error'
|
|
return
|
|
else:
|
|
nitems = len(keys)
|
|
if self.last_requested > nitems:
|
|
self.last_requested = 0
|
|
starting_point = self.last_requested
|
|
priority = 1
|
|
loopcounter = 0
|
|
added_pri = 0
|
|
now = mytime.clock()
|
|
if nitems > 0:
|
|
while no_added < limit and loopcounter < 10000:
|
|
loopcounter += 1
|
|
if self.last_requested >= nitems:
|
|
self.last_requested = 0
|
|
self.next_requested = (self.last_requested + 1) % nitems
|
|
self.last_requested = self.next_requested
|
|
key = keys[self.next_requested]
|
|
if key in vars.keys():
|
|
continue
|
|
if priority == 1:
|
|
if self.next_requested == starting_point:
|
|
priority = 0
|
|
try:
|
|
if self.parent.priority_level[key] - now < 0:
|
|
continue
|
|
except:
|
|
self.parent.priority_level[key] = 0
|
|
continue
|
|
|
|
elif self.next_requested == starting_point:
|
|
break
|
|
try:
|
|
vars[key] = self.parent.parent.peers.units[MAC].values[key]
|
|
if priority == 1:
|
|
added_pri = 1
|
|
no_added += 1
|
|
except:
|
|
print mytime.displayTime() + ' server.build_vars_to_send data key error'
|
|
break
|
|
|
|
try:
|
|
if MAC[:4] not in ('DEMO', 'GRPdeactivated'):
|
|
no_of_correct_vars = self.parent.parent.peers.units[MAC].process.conn.correct_vars
|
|
synced = self.parent.parent.peers.units[MAC].process.conn.synced
|
|
else:
|
|
no_of_correct_vars = 10000
|
|
synced = True
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
res = build_command(MAC, vars, no_of_correct_vars, synced)
|
|
except:
|
|
res = None
|
|
|
|
return res
|
|
|
|
def set_get_key(self, key, MAC):
|
|
if key.struct_id < 0:
|
|
return
|
|
if key.struct_id in (11, 255):
|
|
return
|
|
if key.member_id in (37, 50):
|
|
return
|
|
maclist = []
|
|
try:
|
|
for group_id in self.parent.group_membership_list[MAC]:
|
|
if one_unit.app.group_enabled[group_id] == False:
|
|
continue
|
|
if group_id == 'all_units':
|
|
continue
|
|
if one_unit.app.group_type[group_id] == 'Mute':
|
|
if key.struct_id == protocol.STRUCT_ID_MUTE and key.channel < 128:
|
|
for target_MAC in one_unit.app.groups[group_id]:
|
|
maclist.append(target_MAC)
|
|
|
|
elif one_unit.app.group_type[group_id] == 'Carbon Copy':
|
|
if key not in one_unit.app.group_exceptions[group_id]:
|
|
for target_MAC in one_unit.app.groups[group_id]:
|
|
maclist.append(target_MAC)
|
|
|
|
elif key in one_unit.app.group_links[group_id]:
|
|
for target_MAC in one_unit.app.groups[group_id]:
|
|
maclist.append(target_MAC)
|
|
|
|
if len(maclist) == 0:
|
|
maclist.append(MAC)
|
|
if key in self.group_skip_list:
|
|
maclist = [
|
|
MAC]
|
|
for SET_MAC in maclist:
|
|
try:
|
|
del self.parent.parent.peers.units[SET_MAC].process.conn.values[key]
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
self.parent.parent.peers.units[SET_MAC].process.conn.get_list.insert(0, key)
|
|
self.parent.parent.peers.units[SET_MAC].process.conn.config_vars.insert(0, key)
|
|
except:
|
|
pass
|
|
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def set_direct_value(self, key, val, MAC, factory, group=None):
|
|
maclist = []
|
|
relative_maclist = []
|
|
if MAC[:4] == 'GRP_':
|
|
print mytime.displayTime(), 's.sdv.GRP_:', MAC
|
|
group = MAC[4:]
|
|
if group != None:
|
|
if group not in one_unit.app.groups:
|
|
print mytime.displayTime(), 's.sdv.invalid group:', group, MAC
|
|
group = None
|
|
else:
|
|
if one_unit.app.group_enabled[group] == False:
|
|
return
|
|
group_type = one_unit.app.group_type[group]
|
|
if group_type == 'Mute':
|
|
if key.struct_id != protocol.STRUCT_ID_MUTE:
|
|
return
|
|
elif group_type == 'Carbon Copy':
|
|
if key in one_unit.app.group_exceptions[group]:
|
|
return
|
|
elif key not in one_unit.app.group_links[group]:
|
|
print key, 'not in group links', group, one_unit.app.group_links
|
|
return
|
|
if one_unit.app.group_type[group] in one_unit.app.group_relative and one_unit.app.group_relative[one_unit.app.group_type[group]] == True:
|
|
if key in one_unit.app.group_links[group]:
|
|
relative_maclist += one_unit.app.groups[group]
|
|
else:
|
|
maclist = one_unit.getMacList(group)
|
|
else:
|
|
for group_id in self.parent.group_membership_list[MAC]:
|
|
if group_id in ('all_units', None):
|
|
continue
|
|
if one_unit.app.group_enabled[group_id] == False:
|
|
continue
|
|
group_type = one_unit.app.group_type[group_id]
|
|
print mytime.displayTime(), 's.sdv.unit:', MAC, group_type
|
|
if group_type == 'Mute':
|
|
maclist = [
|
|
MAC]
|
|
elif one_unit.app.group_type[group_id] == 'Carbon Copy':
|
|
if key not in one_unit.app.group_exceptions[group_id]:
|
|
maclist += one_unit.app.groups[group_id]
|
|
elif one_unit.app.group_type[group_id] in one_unit.app.group_relative and one_unit.app.group_relative[one_unit.app.group_type[group_id]] == True:
|
|
maclist = [
|
|
MAC]
|
|
elif key in one_unit.app.group_links[group_id]:
|
|
maclist += one_unit.app.groups[group_id]
|
|
|
|
if len(maclist) == 0 and len(relative_maclist) == 0:
|
|
if group != None:
|
|
return
|
|
maclist.append(MAC)
|
|
if key in self.group_skip_list:
|
|
maclist = [MAC]
|
|
relative_maclist = []
|
|
if len(relative_maclist) > 0:
|
|
relative_maclist.remove(MAC)
|
|
maclist = [MAC]
|
|
try:
|
|
delta = val - self.parent.parent.peers.get(key, MAC)
|
|
print mytime.displayTime(), 's.Relative change, old:', self.parent.parent.peers.get(key, MAC), 'new:', val, 'delta:', delta, 'source MAC:', MAC
|
|
except:
|
|
print mytime.displayTime(), 's.Trying to get delta failed for key', key
|
|
traceback.print_exc(file=sys.stdout)
|
|
return
|
|
else:
|
|
repeatlist = relative_maclist[:]
|
|
for SET_MAC in repeatlist:
|
|
if SET_MAC not in one_unit.app.pin_verified or one_unit.app.pin_verified[SET_MAC] == False or SET_MAC[:4] in ('DEMO',
|
|
'GRP_',
|
|
'VN::'):
|
|
relative_maclist.remove(SET_MAC)
|
|
|
|
repeat = 50
|
|
while repeat > 0 and len(relative_maclist) > 0:
|
|
repeatlist = relative_maclist[:]
|
|
print mytime.displayTime(), 's.Applying relative change to', len(repeatlist), 'units', repeat
|
|
for SET_MAC in repeatlist:
|
|
try:
|
|
set_val = self.parent.parent.peers.units[SET_MAC].process.conn.add_by_key(key, delta, factory)
|
|
if set_val != None:
|
|
relative_maclist.remove(SET_MAC)
|
|
self.parent.parent.peers.set_by_key(SET_MAC, key, set_val)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
repeat -= 1
|
|
mytime.sleep(0.1)
|
|
|
|
for SET_MAC in maclist:
|
|
if SET_MAC not in one_unit.app.pin_verified or one_unit.app.pin_verified[SET_MAC] == False or SET_MAC[:4] in ('DEMO',
|
|
'GRP_',
|
|
'VN::'):
|
|
continue
|
|
try:
|
|
self.parent.parent.peers.units[SET_MAC].process.conn.set_by_key(key, val, factory)
|
|
self.parent.parent.peers.set_by_key(SET_MAC, key, val)
|
|
except:
|
|
print mytime.displayTime() + ' s.sd: Connection to', SET_MAC, 'lost'
|
|
|
|
return
|
|
|
|
def process_data_pkt(self, pkt, reply):
|
|
if pkt == None:
|
|
return
|
|
else:
|
|
MAC = None
|
|
priority_time = mytime.clock() + 2
|
|
for (opcode, fragment, MAC) in pkt.fragments:
|
|
if opcode == 234:
|
|
factory = True
|
|
else:
|
|
factory = False
|
|
if self.printed_conn == False:
|
|
print mytime.displayTime() + ' Accepting Connection from', MAC
|
|
self.printed_conn = True
|
|
if self.s != None:
|
|
self.link_mac = MAC
|
|
if len(fragment) == 0:
|
|
continue
|
|
if len(fragment) < 5:
|
|
print mytime.displayTime() + ' server.process.too small fragment! len=', len(fragment), ', packet discarded'
|
|
break
|
|
if MAC not in self.parent.parent.peers.units:
|
|
return
|
|
struct_id = struct.unpack('B', fragment[0])[0]
|
|
member_id = struct.unpack('B', fragment[1])[0]
|
|
channel = struct.unpack('B', fragment[2])[0]
|
|
index = struct.unpack('B', fragment[3])[0]
|
|
key = Key(struct_id, member_id, channel, index)
|
|
val = ''
|
|
try:
|
|
val = struct.unpack(protocol.get_member_format(member_id), fragment[4:])[0]
|
|
except:
|
|
continue
|
|
|
|
self.set_direct_value(key, val, MAC, factory)
|
|
|
|
self.invalid_packet_counter = 0
|
|
if reply == True and MAC != None:
|
|
return self.build_vars_to_send(MAC, 10)
|
|
return
|
|
return
|
|
|
|
|
|
class Data_packet():
|
|
"""The announcement broadcast by hardware units over USB"""
|
|
|
|
def __init__(self):
|
|
"""Constructor"""
|
|
self.fragments = []
|
|
self.PC_PacketId = None
|
|
self.HW_PacketId = None
|
|
self.invalid_packet_counter = 0
|
|
return
|
|
|
|
def __str__(self):
|
|
return 'Data_packet(opcode=%s, id=%s)' % (self.opcode,
|
|
self.HW_PacketId)
|
|
|
|
|
|
def parse_data_pkt(data):
|
|
res = Data_packet()
|
|
if len(data) < 5:
|
|
print mytime.displayTime() + ' server.invalid data (1)! length: ', len(data), ', packet discarded'
|
|
res.fragments = []
|
|
return res
|
|
else:
|
|
DDL = data[:3]
|
|
if DDL != 'DDL' and DDL != 'DDG':
|
|
print mytime.displayTime() + ' server.invalid data (2)! code: ', DDL, ', packet discarded'
|
|
res.fragments = []
|
|
res.invalid_packet_counter = res.invalid_packet_counter + 1
|
|
return res
|
|
pos = ord(data[3]) + 4
|
|
if len(data) < pos - 1:
|
|
print mytime.displayTime() + ' server.invalid data (3)! length: ', len(data), ', packet discarded'
|
|
res.fragments = []
|
|
return res
|
|
MAC = data[4:pos]
|
|
no_of_fragments = 0
|
|
if len(data) <= pos:
|
|
res.fragments.append((0, '', MAC))
|
|
return res
|
|
while pos + 6 < len(data):
|
|
opcode = ord(data[pos])
|
|
if opcode != 187 and opcode != 234:
|
|
return None
|
|
pos += 1
|
|
size = ord(data[pos])
|
|
pos += 1
|
|
size -= 2
|
|
if size < 2:
|
|
print mytime.displayTime() + ' server.too small fragment! opcode: ', opcode, ' size:', size + 2, ', packet discarded'
|
|
return None
|
|
if pos + size > len(data):
|
|
print mytime.displayTime() + ' server.fragment exceeds packet boundary! opcode: ', opcode, ', packet discarded'
|
|
return None
|
|
res.fragments.append((opcode, data[pos:pos + size], MAC))
|
|
pos += size
|
|
no_of_fragments += 1
|
|
|
|
return res
|
|
|
|
|
|
def build_command(MAC, vars={}, correct_vars=0, synced=False):
|
|
no_of_fragments = 0
|
|
if synced == False:
|
|
synced = chr(0)
|
|
else:
|
|
synced = chr(1)
|
|
cmd = 'DDR' + chr(len(MAC)) + MAC + struct.pack('I', correct_vars) + synced
|
|
for (k, v) in vars.items():
|
|
opcode = 123
|
|
(struct_id, member_id, channel, index) = k
|
|
new_val = struct.pack(protocol.get_member_format(member_id), v)
|
|
struct_id = struct.pack('b', struct_id)
|
|
member_id = struct.pack('B', member_id)
|
|
channel = struct.pack('B', channel)
|
|
index = struct.pack('B', index)
|
|
cmd += chr(opcode) + chr(6 + len(new_val)) + struct_id + member_id + channel + index + new_val
|
|
no_of_fragments += 1
|
|
|
|
return cmd
|
|
|
|
|
|
if __name__ == '__main__':
|
|
print 'Server start'
|
|
daemon = Daemon()
|
|
|
|
# okay decompiling pycode/server.pyc
|