def del_driver(self, drv): drvs = self.drivers key = (drv.get_phy_name(), drv.get_port()) if not key in drvs: log('driver key %s not exists' % str(key)) return del drvs[key]
def del_phy(self, phy): phys = self.phys name = phy.get_name() if not name in phys: log('phy %s not exists' % name) return del phys[name]
def run(self): self._exit = False event = self.data_event dataq = self.dataq devices = self.devices self.load_config() self.first_devid = self.config.get_max_devid() log('first devid: %d' % self.first_devid) while not self._exit: while not self._exit and dataq.empty(): ret = event.wait(1) if ret: event.clear() else: self.keepalive() self.check_timers() continue if self._exit: break try: data = dataq.get_nowait() except queue.Empty: log('dataq empty') continue if isinstance(data, hsb_phy_data): if data.direction == 0: key = data.key() drivers = self.drivers if not key in drivers: log('key %s not found in drivers' % str(key)) continue driver = drivers[key] driver.on_data(data) else: phys = self.phys phy_name = data.phy if not phy_name in phys: log('phy %s not found in phys' % phy_name) continue phy = phys[phy_name] phy.write(data) elif isinstance(data, hsb_cmd): self.deal_hsb_cmd(data) elif isinstance(data, hsb_reply): self.network.on_reply(data) elif isinstance(data, hsb_event): self.network.on_event(data) else: log('manager: unknown data')
def add_device(self, dev): devices = self.devices addr = dev.addr if addr in devices: log('dev %s already exists' % addr) return devices[addr] = dev self.manager.add_device(dev)
def del_device(self, dev): devices = self.devices addr = dev.addr if not addr in devices: log('dev %s not exists' % addr) return del devices[addr] self.manager.del_device(dev)
def del_ir_devices(self, ob): for dev in ob: if not 'devid' in dev: log('unknown ir device: %d' % dev) continue devid = dev['devid'] device = self.find_device(devid) if device: self.del_device(device) self.config.del_device(device)
def on_update(self, eps): log('ep event') endpoints = [{'epid': ep.epid, 'val': ep.val} for ep in eps] ob = {'devid': self.devid, 'endpoints': endpoints} obs = {'devices': [ob]} event = hsb_event(hsb_event.DEVS_UPDATED, ob) self.upload(event)
def check_length(data): length = len(data) if length < 8: return False header = data[:8] h = struct.unpack('4H', header) if length != h[1]: log('bad len %d/%d' % (h[1], length)) return False return True
def __init__(self, client, data): self.valid = False self.client = client self.data = data try: self.ob = json.loads(data) except Exception: log('load cmd fail: %s' % data) self.ob = None else: self.valid = True
def work_proc(self): un_sock = un_new_listen(self.un_path) if not un_sock: log('un_sock fail') return if not self.test: uart = serial.Serial(self.uart_interface, self.uart_baudrate) if not uart: log('open uart %s fail' % self.uart_interface) return else: # test test_path = '/tmp/hsb/un_zigbee_test.listen' uart = un_new_listen(test_path) inputs = [un_sock, uart] outputs = [] while not self._exit: readable, writable, exceptional = select.select( inputs, outputs, inputs) for s in readable: if s is un_sock: data, addr = s.recvfrom(1024) if not self.outq.empty(): if not uart in outputs: outputs.append(uart) elif s is uart: if isinstance(s, serial.Serial): n = s.inWaiting() data = s.read(n) else: data, addr = s.recvfrom(1024) # log(data) self.on_data(data) for s in writable: if s is uart: try: data = self.outq.get_nowait() except queue.Empty: outputs.remove(s) else: if isinstance(s, serial.Serial): s.write(data.raw_data) else: path = '/tmp/hsb/un_zigbee_sim-%d:%d.listen' % ( data.addr, data.port) s.sendto(data.raw_data, path)
def set_ob(self, tms): timers = [] for tm in tms: timer = hsb_dev_timer(tm) if not timer.valid: log('timer invalid: %s' % tm) continue timer.update(int(time()), localtime()) timers.append(timer) log('add new timer') self.timers = timers
def check(self, manager): now = int(time()) lt = localtime() for timer in self.timers: if not timer.check(now): continue log('timer expiring...') manager.do_actions([ timer.action ]) if lt.tm_mday != self.mday: self.mday = lt.tm_mday timer.update(now, lt)
def add_driver(self, drv): drvs = self.drivers phy_name = drv.get_phy_name() port = drv.get_port() phys = self.phys if not phy_name in phys: log('driver phy name %s not found' % phy_name) return key = (phy_name, port) if key in drvs: log('driver %s already exists' % str(key)) return drvs[key] = drv drv.set_phy(phys[phy_name])
def transit(self, new_state): old = self.state if old == new_state: return statem = self.statem if not new_state in statem: return state_ob = statem[old] state_ob.exit() state_ob = statem[new_state] state_ob.enter() self.state = new_state log('transit: [%s] to [%s]' % (statem[old].name, statem[new_state].name))
def add_ir_devices(self, ob): for dev in ob: if not 'attrs' in dev: log('unknown ir device: %s' % dev) continue attrs = dev['attrs'] if not 'irtype' in attrs: log('unknown ir device: %s' % dev) continue irtype = attrs['irtype'] device = dev_ir.new_device(irtype) if not device: continue device.set_ob(dev) self.add_device(device)
def parse_header(self, data): length = len(data) if length < 8: return (None, None, None) header = data[:8] h = struct.unpack('4H', header) if h[0] != phy_data_zigbee.MAGIC: log('invalid magic %s' % h[0]) return (None, None, None) if length != h[1]: log('bad len %d/%d' % (h[1], length)) return (None, None, None) addr = h[2] port = h[3] return (addr, port, data[8:])
def run(self): self.listen = un_new_listen('/tmp/hsb/hsb_audio.listen') self._exit = False if not self.listen: return if not self.test: uart = serial.Serial(self.uart_interface, self.uart_baudrate) if not uart: log('open uart %s fail' % self.uart_interface) return else: uart = None # TODO: enter sleep state if not self.test: inputs = [ self.listen, uart ] else: inputs = [ self.listen ] outputs = [] while not self._exit: readable, writable, exceptional = select.select(inputs, outputs, inputs) if self._exit: break for s in readable: if s is self.listen: data, addr = s.recvfrom(1024) data = data.decode() log('get msg: %s' % data) self.on_result(data) elif s is uart: n = s.inWaiting() data = s.read(n) self.on_data(data)
def on_data(self, phy_data): if not isinstance(phy_data, hsb_phy_data): log('drv_orange get unknown data') return addr = phy_data.addr port = phy_data.port buf = phy_data.data #log('addr: %d, port: %d' % (addr, port)) total = len(buf) if total < 4: log('orange packet bad len: %d' % total) return data = struct.unpack('3H', buf[:6]) cmd, length, transid = data # log('cmd: %x, len=%d' % (cmd, length)) if not cmd in self.data_cb: log('unknown cmd 0x%x' % cmd) cb = self.data_cb[cmd] cb(addr, transid, buf[6:])
def load_config(self): config = self.config devs = config.devices for dev in devs.values(): if not ('devtype' in dev and 'devid' in dev): continue devid = dev['devid'] devtype = dev['devtype'] if devtype != hsb_dev_type.IR: continue if not 'attrs' in dev: continue attrs = dev['attrs'] if not 'irtype' in attrs: continue irtype = attrs['irtype'] device = dev_ir.new_device(irtype) if not device: continue device.devid = devid device.set_ob(dev) device.manager = self self.devices[devid] = device device.online() scenes = config.scenes for s in scenes.values(): scene = hsb_scene(self, s) if not scene.valid: log('scene not valid') continue self.add_scene(scene)
def set_ob(self, act): self.valid = False self.condition = None self.delay = act.get('delay', 0) if not 'actions' in act: return acts = act['actions'] dev_acts = [hsb_dev_action(action) for action in acts] self.actions = dev_acts if 'condition' in act: condition = hsb_scene_condition(act['condition']) if condition.valid: self.condition = condition else: log('invalid condition') self.valid = True
def load(self, path): try: cfg = open(path, 'r') except Exception as e: # log(e) return try: data = cfg.read() except Exception: log('read config failed') return None finally: cfg.close() try: ob = json.loads(data) except Exception: log('json parse failed') return None return ob
def check(self, ts): if self.expired: log('expired') return False if ts >= self.ts: log('ts %d > self.ts %d' % (ts, self.ts)) offset = ts - self.ts self.expired = True if offset < 3: return True else: log('ts %d < self.ts %d' % (ts, self.ts)) return False
def on_discover_resp(self, addr, transid, buf): total = len(buf) if total < 12: log('discover resp len error: %d' % total) return data = struct.unpack('i8s', buf[:12]) dev_type, mac = data if total == 12: log('device without any ep') return device = self.find_device(addr) if device: return buf = buf[12:] eps = [] while len(buf) > 2: ep, buf = self.parse_ep(buf) if not ep: return eps.append(ep) device = self.new_device(dev_type, mac, addr, eps) if not device: log('unknown dev_type %d' % dev_type) return self.add_device(device) log('add device %d %s' % (device.devid, device.mac))
def save(self, filename, ob): path = self.workdir + '/' + filename try: cfg = open(path, 'w') except Exception as e: log(e) return try: data = json.dumps(ob, ensure_ascii=False) except Exception as e: log(e) cfg.close() return try: cfg.write(data) except Exception as e: log(e) return finally: cfg.close()
def del_scene(self, name): if not name in self.scenes: log('scene %s not exists' % name) return del self.scenes[name]
def deal_hsb_cmd(self, cmd): devices = self.devices supported_cmds = [ 'get_devices', 'set_devices', 'get_scenes', 'set_scenes', 'del_scenes', 'enter_scene', 'add_devices', 'del_devices', 'get_asrkey' ] command = cmd.get('cmd') if not command in supported_cmds: return if command == 'get_devices': log('%d devices' % len(devices)) obs = [ dev.get_ob() for dev in devices.values() ] ob = { 'devices': obs } reply = hsb_reply(cmd, ob) self.dispatch(reply) elif command == 'set_devices': devs = cmd.get('devices') if not devs: log('devices not found') return for dev in devs: devid = dev.get('devid', -1) if devid < 0: continue device = self.find_device(devid) if not device: continue device.on_cmd(command, dev) elif command == 'get_asrkey': asrkey = self.get_asrkey() log('asrkey: %s' % asrkey) elif command == 'get_scenes': obs = [ s.get_ob() for s in self.scenes.values() ] ob = { 'scenes': obs } reply = hsb_reply(cmd, ob) self.dispatch(reply) elif command == 'set_scenes': scenes = cmd.get('scenes') if not scenes: return for s in scenes: scene = hsb_scene(self, s) if not scene.valid: log('scene not valid') continue self.add_scene(scene) self.config.save_scenes(self.scenes) elif command == 'del_scenes': scenes = cmd.get('scenes') if not scenes: return for s in scenes: if not 'name' in s: continue name = s['name'] self.del_scene(name) self.config.save_scenes(self.scenes) elif command == 'enter_scene': name = cmd.get('name') self.enter_scene(name) elif command == 'add_devices': ob = cmd.get('devices') if not ob: return self.add_ir_devices(ob) elif command == 'del_devices': ob = cmd.get('devices') if not ob: return self.del_ir_devices(ob)
len(raw) + 4) + raw s.send(data) log('send %s to client %s' % (cmd, s.getpeername())) for s in exceptional: cli = clients[s] inputs.remove(s) if s in outputs: outputs.remove(s) log('client %s exception' % s.getpeername()) s.close() del clients[s] cli.valid = False if __name__ == '__main__': network = hsb_network() network.start() from time import sleep while True: try: sleep(10) except KeyboardInterrupt: network.exit() break except Exception as e: log(e)
def on_asr_result(self, result): log('asr result: %s' % result) manager.on_asr_result(result)
def run(self): tcp_serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_serv.setblocking(False) tcp_serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcp_serv_addr = ('', self.tcp_port) try: tcp_serv.bind(tcp_serv_addr) tcp_serv.listen(5) except Exception as e: log(e) sys.exit(0) udp_serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) udp_serv.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) udp_serv_addr = ('', self.udp_port) try: udp_serv.bind(udp_serv_addr) except Exception as e: log(e) sys.exit(0) un_sock = un_new_listen(self.un_path) if not un_sock: sys.exit(0) inputs = [tcp_serv, udp_serv, un_sock] outputs = [] clients = {} while inputs: readable, writable, exceptional = select.select( inputs, outputs, inputs) for s in readable: if s is tcp_serv: # new connection cli, cliaddr = s.accept() cli.setblocking(False) inputs.append(cli) clients[cli] = hsb_client(cli, cliaddr) log('client %s:%d connected' % cli.getpeername()) elif s is udp_serv: data, addr = s.recvfrom(1024) data = data.decode() if data == 'are you hsb?': log('get udp cmd from %s: %s' % (addr, data)) reply = 'i am hsb' s.sendto(reply.encode(), addr) else: log('unknown udp cmd from %s: %s' % (addr, data)) elif s is un_sock: data, addr = s.recvfrom(1024) while not self.outq.empty(): rdata = self.outq.get_nowait() if not rdata: # exit return if isinstance(rdata, hsb_reply): cli = rdata.client if not cli.valid: continue cli.outq.put(rdata) if not cli.sock in outputs: outputs.append(cli.sock) elif isinstance(rdata, hsb_event): clis = list(clients.values()) for cli in clis: if not cli.valid: continue cli.outq.put(rdata) if not cli.sock in outputs: outputs.append(cli.sock) else: # client get data try: data = s.recv(1024) except Exception: data = None cli = clients[s] if data: while len(data) > 4: hdr, length = struct.unpack('=2H', data[:4]) if hdr != hsb_network.magic: log('bad magic message') break if length <= 4 or length > len(data): log('bad length %d' % length) break cmd = data[4:length].decode() log('received %s from %s' % (cmd, s.getpeername())) command = hsb_cmd(cli, cmd) if command.valid: self.deal_cmd(command) data = data[length:] else: if s in outputs: outputs.remove(s) inputs.remove(s) log('client %s:%d disconnected' % cli.address) s.close() del clients[s] cli.valid = False for s in writable: cli = clients[s] try: reply = cli.outq.get_nowait() except queue.Empty: outputs.remove(s) else: cmd = reply.get() raw = cmd.encode() data = struct.pack('=2H', hsb_network.magic, len(raw) + 4) + raw s.send(data) log('send %s to client %s' % (cmd, s.getpeername())) for s in exceptional: cli = clients[s] inputs.remove(s) if s in outputs: outputs.remove(s) log('client %s exception' % s.getpeername()) s.close() del clients[s] cli.valid = False
def on_data(self, data): log('not implemented')