comparison service/rdf_to_mqtt/rdf_to_mqtt.py @ 739:03bad43bbcb3

more renaming, build updates Ignore-this: 94a0df55a1d8a74d90ec84bb7351d3ef
author drewp@bigasterisk.com
date Mon, 10 Feb 2020 23:56:42 -0800
parents service/rdf_to_mqtt/mqtt_graph_bridge.py@fdddbdaf07b5
children 1f8abec7f687
comparison
equal deleted inserted replaced
738:4167101b816f 739:03bad43bbcb3
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()