def _onStatement(self, stmt): log.info(f'incoming statement: {stmt}') ignored = True for dev, attrs in devs.items(): if stmt[0] == ROOM['frontWindow']: ignored = ignored and self._publishFrontScreenText(stmt) if stmt[0:2] == (dev, ROOM['brightness']): log.info(f'brightness request: {stmt}') brightness = stmt[2].toPython() if attrs.get('values', '') == 'binary': self._publishOnOff(attrs, brightness) else: self._publishRgbw(attrs, brightness) ignored = False if stmt[0:2] == (dev, ROOM['inputSelector']): self._publish(topic=attrs['root'], message='input_' + str(stmt[2].toPython())) ignored = False if stmt[0:2] == (dev, ROOM['volumeChange']): delta = int(stmt[2].toPython()) which = 'up' if delta > 0 else 'down' self._publish(topic=f'theater_blaster/ir_out/volume_{which}', message=json.dumps({'timed': abs(delta)})) ignored = False if ignored: log.warn("ignoring %s", stmt)
def _onStatement(self, stmt): log.info(f'incoming statement: {stmt}') ignored = True for dev, attrs in devs.items(): if stmt[0] == ROOM['frontWindow']: ignored = ignored and self._publishFrontScreenText(stmt) if stmt[0:2] == (dev, ROOM['brightness']): log.info(f'brightness request: {stmt}') brightness = stmt[2].toPython() if attrs.get('values', '') == 'binary': self._publishOnOff(attrs, brightness) else: self._publishRgbw(attrs, brightness) ignored = False if stmt[0:2] == (dev, ROOM['inputSelector']): choice = stmt[2].toPython().decode('utf8') self._publish(topic=attrs['root'], message=f'input_{choice}') ignored = False if stmt[0:2] == (dev, ROOM['volumeChange']): delta = int(stmt[2].toPython()) which = 'up' if delta > 0 else 'down' self._publish(topic=f'theater_blaster/ir_out/volume_{which}', message=json.dumps({'timed': abs(delta)})) ignored = False if stmt[0:2] == (dev, ROOM['color']): h = stmt[2].toPython() msg = {} if h.endswith(b'K'): # accept "0.7*2200K" (brightness 0.7) # see https://www.zigbee2mqtt.io/information/mqtt_topics_and_message_structure.html#zigbee2mqttfriendly_nameset bright, kelvin = map(float, h[:-1].split(b'*')) msg['state'] = 'ON' msg["color_temp"] = round(1000000 / kelvin, 2) msg['brightness'] = int(bright * 255) # 1..20 look about the same else: r, g, b = int(h[1:3], 16), int(h[3:5], 16), int(h[5:7], 16) msg = { 'state': 'ON' if r or g or b else 'OFF', 'color': { 'r': r, 'g': g, 'b': b }, } if attrs.get('hasWhite', False): msg['white_value'] = max(r, g, b) msg.update(attrs.get('defaults', {})) self._publish(topic=attrs['root'], message=json.dumps(msg)) ignored = False if ignored: log.warn("ignoring %s", stmt)
def _onStatement(self, user, stmt): log.info('put statement %r', stmt) if stmt[0:2] == (ROOM['frontDoorLock'], ROOM['state']): if stmt[2] == ROOM['unlocked']: log.info('unlock for %r', user) self.settings.autoLock.onUnlockedStmt() if stmt[2] == ROOM['locked']: self.settings.autoLock.onLockedStmt() self.settings.mqtt.publish(espName + b"/switch/strike/command", mqttMessageFromState(stmt[2])) return log.warn("ignoring %s", stmt)
def reportTimes(self, unlockedFor): g = self.masterGraph lockIn = self.autoLockSec - int(unlockedFor) if lockIn < 0: state = g._graph.value(self.subj, ROOM['state']) log.warn(f"timeUnlocked {self.timeUnlocked}, state {state}, " f"unlockedFor {unlockedFor}, lockIn {lockIn}") lockIn = 0 g.patchObject(ctx, self.subj, ROOM['unlockedForSec'], Literal(int(unlockedFor))) g.patchObject(ctx, self.subj, ROOM['autoLockInSec'], Literal(lockIn))
def put(self): """ request an immediate load of the remote graphs; the thing we do in the background anyway. No payload. Using PUT because this is idempotent and retryable and everything. todo: this should do the right thing when many requests come in very quickly """ log.warn("immediateUpdate from %s %s - ignored", self.request.headers.get('User-Agent', '?'), self.request.headers['Host']) self.set_status(202)
def post(self): try: user = requestUser(self.request) except KeyError: log.warn('request without x-foaf-agent: %s', h) self.set_status(403, 'need x-foaf-agent') return state = self.request.body.strip().decode('ascii') if state == 'unlock': self.settings.autoLock.onUnlockedStmt() self.settings.mqtt.publish(espName + b"/switch/strike/command", b'ON') if state == 'lock': self.settings.autoLock.onLockedStmt() self.settings.mqtt.publish(espName + b"/switch/strike/command", b'OFF')
def runOne(self): if not self.toProcess: print('done') return repo = self.toProcess.pop(0) try: update = {'path': str(repo.path), 'github': repo.github, 'status': (yield repo.getStatus()), 'hgLatest': (yield repo.getLatestHgCommit())} if repo.github: update['githubLatest'] = (yield repo.getLatestGithubCommit()) self.update(str(repo.path), update) except Exception: log.warn(f'not reporting on {repo}') traceback.print_exc() reactor.callLater(0, self.runOne)
def put(self): try: user = requestUser(self.request) except KeyError: log.warn('request without x-foaf-agent: %s', h) self.set_status(403, 'need x-foaf-agent') return arg = self.request.arguments if arg.get('s') and arg.get('p'): subj = URIRef(arg['s'][-1]) pred = URIRef(arg['p'][-1]) obj = URIRef(self.request.body.strip().decode('ascii')) stmt = (subj, pred, obj) else: g = rdfGraphBody(self.request.body, self.request.headers) assert len(g) == 1, len(g) stmt = next(g.triples((None, None, None))) self._onStatement(user, stmt)
def _onStatement(self, stmt): ignored = True for dev, attrs in devs.items(): if stmt[0:2] == (dev, ROOM['brightness']): for chan, scale in [('w1', 1), ('r', 1), ('g', .8), ('b', .8)]: out = stmt[2].toPython() * scale topic = f"{attrs['root']}/light/kit_{chan}/command" self.settings.mqtt.publish( topic.encode('ascii'), json.dumps({ 'state': 'ON', 'brightness': int(out * 255)}).encode('ascii')) self.settings.masterGraph.patchObject( attrs['ctx'], stmt[0], stmt[1], stmt[2]) ignored = False if ignored: log.warn("ignoring %s", stmt)
port = 10018 reactor.listenTCP( port, cyclone.web.Application([ (r"/()", cyclone.web.StaticFileHandler, { "path": ".", "default_filename": "index.html" }), (r"/build/(bundle.js)", cyclone.web.StaticFileHandler, { "path": "build" }), (r"/graph/mqtt", CycloneGraphHandler, { 'masterGraph': masterGraph }), (r"/graph/mqtt/events", CycloneGraphEventsHandler, { 'masterGraph': masterGraph }), (r'/debugPageData', DebugPageData), (r'/metrics', Metrics), ], mqtt=mqtt, internalMqtt=internalMqtt, masterGraph=masterGraph, debugPageData=debugPageData, debug=arg['-v']), interface='::') log.warn('serving on %s', port) reactor.run()
def setEspState(payload): log.info('esp state change %r', payload) masterGraph.patchObject(ctx, ROOM['frontDoorLock'], ROOM['espMqttConnection'], ROOM['mqtt' + payload.decode('ascii').capitalize()]) mqtt.subscribe(espName + b"/status").subscribe(on_next=setEspState) port = 10011 reactor.listenTCP(port, cyclone.web.Application( [ (r"/()", cyclone.web.StaticFileHandler, {"path": ".", "default_filename": "index.html"}), (r"/simple/()", cyclone.web.StaticFileHandler, {"path": ".", "default_filename": "simple.html"}), (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), (r"/graph/events", CycloneGraphEventsHandler, {'masterGraph': masterGraph}), (r'/output', OutputPage), (r'/bluetoothButton', BluetoothButton), (r'/simpleState', SimpleState), ], mqtt=mqtt, masterGraph=masterGraph, autoLock=autoclose, debug=arg['-v']), interface='::') log.warn('serving on %s', port) reactor.run()