annotate convert.py @ 10:2a507e679d0d default tip

add zigbee covnerters
author drewp@bigasterisk.com
date Mon, 12 Aug 2024 13:15:07 -0700
parents bc2a93b306e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4
cd1b8d7bda78 get metrics writing to victoriametrics
drewp@bigasterisk.com
parents: 2
diff changeset
1 '''
cd1b8d7bda78 get metrics writing to victoriametrics
drewp@bigasterisk.com
parents: 2
diff changeset
2 Note that these functions need to parse the message['payload'] into a float
cd1b8d7bda78 get metrics writing to victoriametrics
drewp@bigasterisk.com
parents: 2
diff changeset
3 '''
6
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
4 import json
10
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
5 import logging
6
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
6
10
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
7 log = logging.getLogger('conv')
2
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
8 converters = []
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
9
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
10
5
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
11 def f_from_c(c):
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
12 return (c * 9 / 5) + 32
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
13
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
14
2
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
15 def topic(topic_pattern: str):
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
16
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
17 def decorator(func):
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
18 func.topic_pattern = topic_pattern
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
19 converters.append(func)
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
20 return func
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
21
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
22 return decorator
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
23
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
24
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
25 @topic(r'([^-]+)-air-quality/sensor/particulate_matter__10_0__m_concentration/state')
5
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
26 def pm(message, topicGroups: tuple[str]) -> list[dict]:
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
27 return [{
2
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
28 'name': 'air_quality_pm',
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
29 'labels': [{
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
30 'labelName': 'location',
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
31 'labelValue': topicGroups[0],
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
32 }, {
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
33 'labelName': 'size',
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
34 'labelValue': '10',
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
35 }],
4
cd1b8d7bda78 get metrics writing to victoriametrics
drewp@bigasterisk.com
parents: 2
diff changeset
36 'value': float(message['payload']),
5
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
37 }]
2
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
38
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
39
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
40 @topic(r'([^-]+)-air-quality/sensor/air_temperature_c/state')
5
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
41 def air_temp(message, topicGroups: tuple[str]) -> list[dict]:
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
42 return [{
2
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
43 'name': 'air_temperature_f',
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
44 'labels': [{
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
45 'labelName': 'location',
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
46 'labelValue': topicGroups[0],
579df3a4e62d rewrite converters as register'able functions
drewp@bigasterisk.com
parents:
diff changeset
47 }],
5
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
48 'value': f_from_c(float(message['payload'])),
8390d5d0d512 one mqtt message can convert to multiple measurements
drewp@bigasterisk.com
parents: 4
diff changeset
49 }]
6
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
50
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
51
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
52 @topic(r'(tele/st-wall-power/SENSOR|tele/ki-fridge/SENSOR|tt-console-power/SENSOR)')
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
53 def poorly_named_sonoff_powermeter(message, topicGroups: tuple[str]) -> list[dict]:
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
54 energy = json.loads(message['payload'])['ENERGY']
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
55 sensor = {
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
56 'tele/st-wall-power/SENSOR': 'st_wall',
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
57 'tele/ki-fridge/SENSOR': 'ki_fridge',
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
58 'tt-console-power/SENSOR': 'tt_console',
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
59 }[topicGroups[0]]
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
60 return [{ 'name': 'powermeter_w', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': energy['Power'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
61 { 'name': 'powermeter_apparent_power_va', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': energy['ApparentPower'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
62 { 'name': 'powermeter_reactive_power_var', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': energy['ReactivePower'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
63 { 'name': 'powermeter_factor', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': energy['Factor'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
64 { 'name': 'powermeter_voltage_v', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': energy['Voltage'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
65 { 'name': 'powermeter_current_a', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': energy['Current'] } ] # yapf: disable
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
66
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
67 @topic(r'(.*)-power/status/switch:0')
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
68 def shelly_powermeter(message, topicGroups: tuple[str]) -> list[dict]:
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
69 sensor = topicGroups[0].replace('-', '_')
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
70 msg = json.loads(message['payload'])
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
71 return [
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
72 { 'name': 'powermeter_w', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': msg['apower'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
73 { 'name': 'powermeter_voltage_v', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': msg['voltage'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
74 { 'name': 'powermeter_current_a', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': msg['current'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
75 { 'name': 'powermeter_apparent_power_va', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': msg['apower'] },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
76 { 'name': 'powermeter_temp_f', 'labels': [{'labelName': 'sensor', 'labelValue': sensor}], 'value': f_from_c(msg['temperature']['tC']) },
bc2a93b306e9 port over the powermeter measurements
drewp@bigasterisk.com
parents: 5
diff changeset
77 ] # yapf: disable
10
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
78
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
79 @topic(r'^zigbee/([^/]+)$')
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
80 def zigbee(message, topicGroups: tuple[str]) -> list[dict]:
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
81 dev = topicGroups[0]
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
82 body = json.loads(message['payload'])
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
83 ret = []
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
84 for v in ['update_available', 'link_quality', 'battery', 'occupancy', 'brightness', 'contact']:
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
85 body_key = 'linkquality' if v == 'link_quality' else v
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
86 if body_key not in body:
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
87 continue
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
88 value = body[body_key]
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
89 if v in ['update_available', 'contact', 'occupancy']:
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
90 value = int(bool(value))
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
91 if v == 'brightness' and body.get('state', None) != 'ON':
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
92 value = 0
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
93 if v == 'link_quality' and value is None:
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
94 value = -1
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
95 if value is None:
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
96 logging.warning(f'zigbee {v=} {value=}')
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
97 continue
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
98 ret.append({'name': 'zigbee_' + v, 'labels': [{'labelName': 'dev', 'labelValue': dev}], 'value': value})
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
99 return ret
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
100
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
101
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
102 @topic(r'^zigbee/([^/]+)/availability$')
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
103 def zigbee_availability(message, topicGroups: tuple[str]) -> list[dict]:
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
104 dev = topicGroups[0]
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
105 online = message['payload'] == "online"
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
106 ret = [{'name': 'zigbee_online', 'labels': [{'labelName': 'dev', 'labelValue': dev}], 'value': int(online)}]
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
107 if online and dev.startswith('0x'):
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
108 ret.append({'name': 'zigbee_unnamed_dev', 'labels': [{'labelName': 'dev', 'labelValue': dev}], 'value': 1})
2a507e679d0d add zigbee covnerters
drewp@bigasterisk.com
parents: 6
diff changeset
109 return ret