Mercurial > code > home > repos > homeauto
comparison service/rdf_to_mqtt/mqtt_graph_bridge.py @ 1532:7cc7700302c2
more service renaming; start a lot more serv.n3 job files
Ignore-this: 635aaefc7bd2fa5558eefb8b3fc9ec75
darcs-hash:2c8b587cbefa4db427f9a82676abdb47e651187e
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Thu, 06 Feb 2020 16:36:35 -0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1531:a3dc6a31590f | 1532:7cc7700302c2 |
---|---|
1 """ | |
2 We get output statements that are like light9's deviceAttrs (:dev1 :color "#ff0000"), | |
3 convert those to outputAttrs (:dev1 :red 255; :green 0; :blue 0) and post them to mqtt. | |
4 | |
5 This is like light9/bin/collector. | |
6 """ | |
7 import json | |
8 | |
9 from docopt import docopt | |
10 from rdflib import Namespace, Literal | |
11 from twisted.internet import reactor | |
12 import cyclone.web | |
13 | |
14 from mqtt_client import MqttClient | |
15 from patchablegraph import PatchableGraph, CycloneGraphHandler, CycloneGraphEventsHandler | |
16 from standardservice.logsetup import log, verboseLogging | |
17 import rdf_over_http | |
18 | |
19 ROOM = Namespace('http://projects.bigasterisk.com/room/') | |
20 | |
21 devs = { | |
22 ROOM['kitchenLight']: { | |
23 'root': 'h801_skylight', | |
24 'ctx': ROOM['kitchenH801'] | |
25 }, | |
26 ROOM['kitchenCounterLight']: { | |
27 'root': 'h801_counter', | |
28 'ctx': ROOM['kitchenH801'] | |
29 }, | |
30 ROOM['livingLampShelf']: { | |
31 'root': 'sonoff_0/switch/sonoff_basic_relay/command', | |
32 'ctx': ROOM['sonoff_0'], | |
33 'values': 'binary', | |
34 }, | |
35 } | |
36 | |
37 | |
38 class OutputPage(cyclone.web.RequestHandler): | |
39 def put(self): | |
40 for stmt in rdf_over_http.rdfStatementsFromRequest( | |
41 self.request.arguments, | |
42 self.request.body, | |
43 self.request.headers): | |
44 self._onStatement(stmt) | |
45 | |
46 def _onStatement(self, stmt): | |
47 log.info(f'incoming statement: {stmt}') | |
48 ignored = True | |
49 for dev, attrs in devs.items(): | |
50 if stmt[0] == ROOM['frontWindow']: | |
51 ignored = ignored and self._publishFrontScreenText(stmt) | |
52 | |
53 if stmt[0:2] == (dev, ROOM['brightness']): | |
54 log.info(f'brightness request: {stmt}') | |
55 brightness = stmt[2].toPython() | |
56 | |
57 if attrs.get('values', '') == 'binary': | |
58 self._publishOnOff(attrs, brightness) | |
59 else: | |
60 self._publishRgbw(attrs, brightness) | |
61 # try to stop saving this; let the device be the master usually | |
62 self.settings.masterGraph.patchObject( | |
63 attrs['ctx'], | |
64 stmt[0], stmt[1], stmt[2]) | |
65 ignored = False | |
66 if ignored: | |
67 log.warn("ignoring %s", stmt) | |
68 | |
69 def _publishOnOff(self, attrs, brightness): | |
70 msg = 'OFF' | |
71 if brightness > 0: | |
72 msg = 'ON' | |
73 self._publish(topic=attrs['root'], message=msg) | |
74 | |
75 def _publishRgbw(self, attrs, brightness): | |
76 for chan, scale in [('w1', 1), | |
77 ('r', 1), | |
78 ('g', .8), | |
79 ('b', .8)]: | |
80 self._publish( | |
81 topic=f"{attrs['root']}/light/kit_{chan}/command", | |
82 messageJson={ | |
83 'state': 'ON', | |
84 'brightness': int(brightness * 255) | |
85 }) | |
86 | |
87 def _publishFrontScreenText(self, stmt): | |
88 ignored = True | |
89 for line in ['line1', 'line2', 'line3', 'line4']: | |
90 if stmt[1] == ROOM[line]: | |
91 ignored = False | |
92 self.settings.mqtt.publish( | |
93 b'frontwindow/%s' % line.encode('ascii'), | |
94 stmt[2].toPython()) | |
95 return ignored | |
96 | |
97 def _publish(self, topic: str, messageJson: object=None, | |
98 message: str=None): | |
99 if messageJson is not None: | |
100 message = json.dumps(messageJson) | |
101 self.settings.mqtt.publish( | |
102 topic.encode('ascii'), | |
103 message.encode('ascii')) | |
104 | |
105 | |
106 if __name__ == '__main__': | |
107 arg = docopt(""" | |
108 Usage: mqtt_graph_bridge.py [options] | |
109 | |
110 -v Verbose | |
111 """) | |
112 verboseLogging(arg['-v']) | |
113 | |
114 masterGraph = PatchableGraph() | |
115 | |
116 mqtt = MqttClient(clientId='mqtt_graph_bridge', brokerPort=1883) | |
117 | |
118 port = 10008 | |
119 reactor.listenTCP(port, cyclone.web.Application([ | |
120 (r"/()", cyclone.web.StaticFileHandler, | |
121 {"path": ".", "default_filename": "index.html"}), | |
122 (r'/output', OutputPage), | |
123 ], mqtt=mqtt, debug=arg['-v']), interface='::') | |
124 log.warn('serving on %s', port) | |
125 | |
126 for dev, attrs in devs.items(): | |
127 masterGraph.patchObject(attrs['ctx'], | |
128 dev, ROOM['brightness'], Literal(0.0)) | |
129 | |
130 reactor.run() |