#!/usr/bin/env python import json import sys import copy from collections import OrderedDict, deque import tcp_lineserver as lineserver import uuid import traceback class Group(object): def __init__(self, name): self.name = name self.title = name self.components = [] class Component(object): def __init__(self, name, g): self.name = name self.group = g self.value = None self.properties = {} init_values = ['device name', 'device stick_name'] def set_value(c, value): c.value = value print 'set',c.name,c.value,c.group for n in init_values: if c.name == n: init(cindex['device name'].value) break for client in clients.values(): client.send_msg(dict(type='update', updates=[dict(name=c.name, value=c.value)])) def history_add(item): history.append(item) id, is_cmd, line = item for cid, client in console_clients.items(): client.send_msg(dict( type = 'command' if is_cmd else 'reply', origin = 'self' if cid == id else 'other', line = line )) class ClientType: GROUP = 1 CONSOLE = 2 MAINUPDATE = 3 class DummyHandler(lineserver.LineHandler): def __init__(self, *args, **kwargs): lineserver.LineHandler.__init__(self, *args, **kwargs) self.id = None def send_msg(self, msg): print '<', msg self.send_line(json.dumps(msg)) def handle_line(self, line): print '>', line msg = json.loads(line) msgtype = msg['type'] if msgtype == 'init': id = msg.get('id', '0') if self.id != msg['id']: self.id = msg['id'] clients[self.id] = self self.title = "" global main_update main_update.append(self) #self.send_msg({'type': 'accept-mainupdate'}) init(cindex['device name'].value) elif msgtype == 'getblock': path = msg['path'] grp = path.split(",")[-1] g = groups[grp] clist = [] for c in g.components: cdict = copy.deepcopy(c.properties) cdict['name'] = c.name clist.append(cdict) self.send_msg(dict(type='draw', path=path, title=g.title, components=clist)) elif msgtype == 'updateblock': path = msg['path'] grp = path.split(",")[-1] g = groups[grp] clist = [] updates = [] for c in g.components: if c.properties.get('type','') != 'group': updates.append(dict(name=c.name, value=c.value)) self.send_msg(dict(type='accept-block')) self.send_msg(dict(type='update', updates=updates)) elif msgtype == 'console': print '*** make console ',self.id,self self.send_msg(dict(type='accept-console')) console_clients[self.id] = self for item in history: id, is_cmd, line = item self.send_msg(dict( type = 'command' if is_cmd else 'reply', origin = 'self' if self.id == id else 'other', line = line )) elif msgtype == 'sendcommand': cmd = msg['command'].split(' ') history_add((self.id, True, msg['command'])) if len(cmd) == 1: name = cmd[0] c = cindex.get(name, None) val = None else: name = cmd[0] + " " + cmd[1] try: c = cindex[name] except KeyError: try: c = cindex[cmd[0]] except KeyError: c = None else: name = cmd[0] val = " ".join(cmd[1:]) else: if len(cmd) == 2: val = None else: val = " ".join(cmd[2:]) if c == None: history_add((self.id, False, "ERROR: " + name + " not found")) elif val == None: history_add((self.id, False, name + " = " + c.value)) else: set_value(c, val) history_add((self.id, False, "OK: " + name + " = " + c.value)) self.send_msg(dict(type = 'accept-command')) def handle_close(self): try: print 'close client', self del clients[self.id] except KeyError: print 'can not remove client' try: del console_clients[self.id] print '*** removed console client',self.id,self except KeyError: print '*** console client already closed',self.id,self self.close() def init(device): global cindex, groups, actual_device if device != actual_device: print 'INIT', actual_device, device actual_device = device cindex = {} # component index groups = {} groupsfile = device + ".json" with open(groupsfile) as fil: groupdict = json.load(fil) for grp in groupdict: gdict = groupdict[grp] g = find_group(grp) g.title = gdict.get('title', grp) for cdict in gdict['components']: cname = cdict['name'] c = Component(cname, g) g.components.append(c) cindex[cname] = c c.properties = dict((k, v) for k, v in cdict.items() if k != 'name' and k != 'value') c.value = cdict.get('value','') if c.properties.get('type','') == 'group': gg = find_group(cname) if 'title' in cdict: if gg.title == gg.name: gg.title = cdict['title'] else: c.properties['title'] = gg.title devlist = [cindex[n].value for n in init_values] device_title = "DUMMY " + "/".join(devlist) print 'ENDINIT', device_title for m in main_update: if m.title != device_title: m.title=device_title m.send_msg(dict(type='id', id=m.id, title=device_title)) def find_group(grp): if grp in groups: g = groups[grp] else: g = Group(grp) groups[grp] = g return g if __name__ == "__main__": console_clients = {} clients = {} cindex = {} # component index groups = {} history = deque(maxlen=50) console_id = 0 main_update = [] actual_device = '' try: device = sys.argv[2] except IndexError: device = "dummy1" try: port = int(sys.argv[1]) except IndexError: port = 5001 init(device) server = lineserver.LineServer('localhost', port, DummyHandler) server.loop()