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