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()