Mercurial > code > home > repos > homeauto
comparison service/rdf_to_mqtt/rdf_to_mqtt.py @ 778:acf58b83022f
rdf_to_mqtt sylvania bulbs and code cleanup and k8s updates
author | drewp@bigasterisk.com |
---|---|
date | Sat, 08 Aug 2020 13:56:39 -0700 |
parents | df7035db28f1 |
children | e7eb3fc8db54 |
comparison
equal
deleted
inserted
replaced
777:df7035db28f1 | 778:acf58b83022f |
---|---|
28 ) | 28 ) |
29 | 29 |
30 devs = { | 30 devs = { |
31 ROOM['kitchenLight']: { | 31 ROOM['kitchenLight']: { |
32 'root': 'h801_skylight', | 32 'root': 'h801_skylight', |
33 'hasWhite': True, | |
33 }, | 34 }, |
34 ROOM['kitchenCounterLight']: { | 35 ROOM['kitchenCounterLight']: { |
35 'root': 'h801_counter', | 36 'root': 'h801_counter', |
37 'hasWhite': True, | |
36 }, | 38 }, |
37 ROOM['livingLampShelf']: { | 39 ROOM['livingLampShelf']: { |
38 'root': 'sonoff_0/switch/sonoff_basic_relay/command', | 40 'root': 'sonoff_0/switch/sonoff_basic_relay/command', |
39 'values': 'binary', | 41 'values': 'binary', |
40 }, | 42 }, |
58 'root': 'theater_blaster/ir_out', | 60 'root': 'theater_blaster/ir_out', |
59 'values': 'theaterOutputs', | 61 'values': 'theaterOutputs', |
60 }, | 62 }, |
61 ROOM['bedHeadboard']: { | 63 ROOM['bedHeadboard']: { |
62 'root': 'bed/light/headboard/command', | 64 'root': 'bed/light/headboard/command', |
63 }, | 65 'hasWhite': True, |
64 #-t theater_blaster/ir_out -m 'input_game' | 66 }, |
65 #-t theater_blaster/ir_out -m 'input_bd' | 67 # https://github.com/Koenkk/zigbee2mqtt.io/blob/new_api/docs/information/mqtt_topics_and_message_structure.md#general |
66 #-t theater_blaster/ir_out -m 'input_cbl' | 68 ROOM['syl1']: { |
67 #-t theater_blaster/ir_out -m 'input_pc' | 69 'root': 'zigbee2mqtt/syl1/set', |
68 #-t theater_blaster/ir_out/volume_up -m '{"times":1}' | 70 'hasBrightness': True, |
69 #-t theater_blaster/ir_out/volume_down -m '{"times":1}' | 71 'defaults': { |
72 'transition': 0, | |
73 } | |
74 }, | |
75 ROOM['syl2']: { | |
76 'root': 'zigbee2mqtt/syl2/set', | |
77 'hasBrightness': True, | |
78 'defaults': { | |
79 'transition': 0, | |
80 } | |
81 }, | |
82 ROOM['syl3']: { | |
83 'root': 'zigbee2mqtt/syl3/set', | |
84 'hasBrightness': True, | |
85 'defaults': { | |
86 'transition': 0, | |
87 } | |
88 }, | |
89 ROOM['syl4']: { | |
90 'root': 'zigbee2mqtt/syl4/set', | |
91 'hasBrightness': True, | |
92 'defaults': { | |
93 'transition': 0, | |
94 } | |
95 }, | |
70 } | 96 } |
71 | 97 |
72 | 98 |
73 class OutputPage(PrettyErrorHandler, cyclone.web.RequestHandler): | 99 class OutputPage(PrettyErrorHandler, cyclone.web.RequestHandler): |
100 | |
74 @STATS.putRequests.time() | 101 @STATS.putRequests.time() |
75 def put(self): | 102 def put(self): |
76 for stmt in rdf_over_http.rdfStatementsFromRequest( | 103 for stmt in rdf_over_http.rdfStatementsFromRequest(self.request.arguments, self.request.body, self.request.headers): |
77 self.request.arguments, self.request.body, | |
78 self.request.headers): | |
79 self._onStatement(stmt) | 104 self._onStatement(stmt) |
80 | 105 |
81 @STATS.statement.time() | 106 @STATS.statement.time() |
82 def _onStatement(self, stmt): | 107 def _onStatement(self, stmt): |
83 log.info(f'incoming statement: {stmt}') | 108 log.info(f'incoming statement: {stmt}') |
99 self._publish(topic=attrs['root'], message=f'input_{choice}') | 124 self._publish(topic=attrs['root'], message=f'input_{choice}') |
100 ignored = False | 125 ignored = False |
101 if stmt[0:2] == (dev, ROOM['volumeChange']): | 126 if stmt[0:2] == (dev, ROOM['volumeChange']): |
102 delta = int(stmt[2].toPython()) | 127 delta = int(stmt[2].toPython()) |
103 which = 'up' if delta > 0 else 'down' | 128 which = 'up' if delta > 0 else 'down' |
104 self._publish(topic=f'theater_blaster/ir_out/volume_{which}', | 129 self._publish(topic=f'theater_blaster/ir_out/volume_{which}', message=json.dumps({'timed': abs(delta)})) |
105 message=json.dumps({'timed': abs(delta)})) | |
106 ignored = False | 130 ignored = False |
107 if stmt[0:2] == (dev, ROOM['color']): | 131 if stmt[0:2] == (dev, ROOM['color']): |
108 h = stmt[2].toPython() | 132 h = stmt[2].toPython() |
109 r, g, b = int(h[1:3], 16), int(h[3:5], 16), int(h[5:7], 16) | 133 r, g, b = int(h[1:3], 16), int(h[3:5], 16), int(h[5:7], 16) |
110 self._publish(topic=attrs['root'], | 134 msg = { |
111 message=json.dumps({ | 135 'state': 'ON' if r or g or b else 'OFF', |
112 'state': | 136 'color': { |
113 'ON' if r or g or b else 'OFF', | 137 'r': r, |
114 'color': { | 138 'g': g, |
115 'r': r, | 139 'b': b |
116 'g': g, | 140 }, |
117 'b': b | 141 } |
118 }, | 142 if attrs.get('hasBrightness', False): |
119 'white_value': | 143 # todo- still not right for sylvania bulbs; they want color x-y. |
120 max(r, g, b) | 144 # see https://www.zigbee2mqtt.io/information/mqtt_topics_and_message_structure.html#zigbee2mqttfriendly_nameset |
121 })) | 145 msg['brightness'] = max(r, g, b) |
122 ignored = False | 146 if msg['brightness'] != 0: |
147 scl = msg['brightness'] / 255 | |
148 for chan in ['r', 'g', 'b']: | |
149 msg['color'][chan] = int(msg['color'][chan] / 255.0 / scl * 255) | |
150 | |
151 if attrs.get('hasWhite', False): | |
152 msg['white_value'] = max(r, g, b) | |
153 msg.update(attrs.get('defaults', {})) | |
154 self._publish(topic=attrs['root'], message=json.dumps(msg)) | |
155 ignored = False | |
156 | |
123 if ignored: | 157 if ignored: |
124 log.warn("ignoring %s", stmt) | 158 log.warn("ignoring %s", stmt) |
125 | 159 |
126 def _publishOnOff(self, attrs, brightness): | 160 def _publishOnOff(self, attrs, brightness): |
127 msg = 'OFF' | 161 msg = 'OFF' |
140 def _publishFrontScreenText(self, stmt): | 174 def _publishFrontScreenText(self, stmt): |
141 ignored = True | 175 ignored = True |
142 for line in ['line1', 'line2', 'line3', 'line4']: | 176 for line in ['line1', 'line2', 'line3', 'line4']: |
143 if stmt[1] == ROOM[line]: | 177 if stmt[1] == ROOM[line]: |
144 ignored = False | 178 ignored = False |
145 self.settings.mqtt.publish( | 179 self.settings.mqtt.publish(b'frontwindow/%s' % line.encode('ascii'), stmt[2].toPython()) |
146 b'frontwindow/%s' % line.encode('ascii'), | |
147 stmt[2].toPython()) | |
148 return ignored | 180 return ignored |
149 | 181 |
150 @STATS.mqttPublish.time() | 182 @STATS.mqttPublish.time() |
151 def _publish(self, | 183 def _publish(self, topic: str, messageJson: object = None, message: str = None): |
152 topic: str, | |
153 messageJson: object = None, | |
154 message: str = None): | |
155 log.debug(f'mqtt.publish {topic} {message} {messageJson}') | 184 log.debug(f'mqtt.publish {topic} {message} {messageJson}') |
156 if messageJson is not None: | 185 if messageJson is not None: |
157 message = json.dumps(messageJson) | 186 message = json.dumps(messageJson) |
158 self.settings.mqtt.publish(topic.encode('ascii'), | 187 self.settings.mqtt.publish(topic.encode('ascii'), message.encode('ascii')) |
159 message.encode('ascii')) | |
160 | 188 |
161 | 189 |
162 if __name__ == '__main__': | 190 if __name__ == '__main__': |
163 arg = docopt(""" | 191 arg = docopt(""" |
164 Usage: rdf_to_mqtt.py [options] | 192 Usage: rdf_to_mqtt.py [options] |
165 | 193 |
166 -v Verbose | 194 -v Verbose |
167 """) | 195 """) |
168 verboseLogging(arg['-v']) | 196 verboseLogging(arg['-v']) |
169 | 197 |
170 mqtt = MqttClient(clientId='rdf_to_mqtt', | 198 mqtt = MqttClient(clientId='rdf_to_mqtt', brokerHost='mosquitto-ext.default.svc.cluster.local', brokerPort=1883) |
171 brokerHost='mosquitto-ext.default.svc.cluster.local', | |
172 brokerPort=1883) | |
173 | 199 |
174 port = 10008 | 200 port = 10008 |
175 reactor.listenTCP(port, | 201 reactor.listenTCP(port, |
176 cyclone.web.Application([ | 202 cyclone.web.Application([ |
177 (r"/()", cyclone.web.StaticFileHandler, { | 203 (r"/()", cyclone.web.StaticFileHandler, { |