comparison service/powerEagle/plugs/powermeter_exporter.py @ 1754:92999dfbf321 default tip

add shelly support
author drewp@bigasterisk.com
date Tue, 04 Jun 2024 13:03:43 -0700
parents add4ce853035
children
comparison
equal deleted inserted replaced
1753:add4ce853035 1754:92999dfbf321
1 import asyncio
1 import json 2 import json
2 import logging 3 import logging
3 4
4 from aiomqtt import Client 5 from aiomqtt import Client
5 from prometheus_client import Counter, Gauge 6 from prometheus_client import Counter, Gauge
8 logging.basicConfig(level=logging.DEBUG) 9 logging.basicConfig(level=logging.DEBUG)
9 log = logging.getLogger() 10 log = logging.getLogger()
10 11
11 powermeter_reports = Counter('powermeter_reports', 'mqtt messages from powermeter', labelnames=['sensor']) 12 powermeter_reports = Counter('powermeter_reports', 'mqtt messages from powermeter', labelnames=['sensor'])
12 metrics = {} 13 metrics = {}
13 for sensor_field, metric_name in [ 14 for metric_name in [
14 ('Power', 'powermeter_w'), 15 ('powermeter_w'),
15 ('ApparentPower', 'powermeter_apparent_power_va'), 16 ('powermeter_apparent_power_va'),
16 ('ReactivePower', 'powermeter_reactive_power_var'), 17 ('powermeter_reactive_power_var'),
17 ('Factor', 'powermeter_factor'), 18 ('powermeter_factor'),
18 ('Voltage', 'powermeter_voltage_v'), 19 ('powermeter_voltage_v'),
19 ('Current', 'powermeter_current_a'), 20 ('powermeter_current_a'),
20 ]: # yapf: disable 21 ('powermeter_temp_c'),
21 metrics[sensor_field] = Gauge(metric_name, documentation='', labelnames=['sensor']) 22 ]:
23 metrics[metric_name] = Gauge(metric_name, documentation='', labelnames=['sensor'])
22 24
23 25
24 async def subscribe_to_sensor(topic, sensor_label): 26 def sonoff(sensor_label, msg):
27 energy = msg['ENERGY']
28 metrics['powermeter_w'].labels(sensor=sensor_label).set(energy['Power'])
29 metrics['powermeter_apparent_power_va'].labels(sensor=sensor_label).set(energy['ApparentPower'])
30 metrics['powermeter_reactive_power_var'].labels(sensor=sensor_label).set(energy['ReactivePower'])
31 metrics['powermeter_factor'].labels(sensor=sensor_label).set(energy['Factor'])
32 metrics['powermeter_voltage_v'].labels(sensor=sensor_label).set(energy['Voltage'])
33 metrics['powermeter_current_a'].labels(sensor=sensor_label).set(energy['Current'])
34
35
36 def shelly(sensor_label, msg):
37 metrics['powermeter_w'].labels(sensor=sensor_label).set(msg['apower'])
38 metrics['powermeter_voltage_v'].labels(sensor=sensor_label).set(msg['voltage'])
39 metrics['powermeter_current_a'].labels(sensor=sensor_label).set(msg['current'])
40 metrics['powermeter_apparent_power_va'].labels(sensor=sensor_label).set(msg['apower'])
41 metrics['powermeter_temp_c'].labels(sensor=sensor_label).set(msg['temperature']['tC'])
42
43
44 async def subscribe_to_sensor(topic, sensor_label, onMsg):
25 async with Client("mqtt2") as client: 45 async with Client("mqtt2") as client:
26 await client.subscribe(topic) 46 await client.subscribe(topic)
27 async for message in client.messages: 47 async for message in client.messages:
28 msg = json.loads(message.payload) 48 try:
29 for sf, m in metrics.items(): 49 msg = json.loads(message.payload)
30 m.labels(sensor=sensor_label).set(msg['ENERGY'][sf]) 50 onMsg(sensor_label, msg)
31 powermeter_reports.labels(sensor=sensor_label).inc() 51 powermeter_reports.labels(sensor=sensor_label).inc()
52 except Exception:
53 log.error(f'{topic=} {sensor_label=}', exc_info=True)
54
55
56 async def request_shelly_statuses(topic, period=10):
57 async with Client("mqtt2") as client:
58 while True:
59 # todo: this adds lag- better to publish upon a /metrics request
60 # then block until all the statuses come in.
61 await client.publish(topic, 'status_update')
62 await asyncio.sleep(period)
32 63
33 64
34 server = StarletteServer() 65 server = StarletteServer()
35 server.serve(startup_tasks=[ 66 server.serve(startup_tasks=[
36 subscribe_to_sensor(topic="tele/st-wall-power/SENSOR", sensor_label='st_wall'), 67 subscribe_to_sensor( topic="tele/st-wall-power/SENSOR", sensor_label='st_wall', onMsg=sonoff),
37 subscribe_to_sensor(topic="tele/ki-fridge/SENSOR", sensor_label='ki_fridge'), 68 subscribe_to_sensor( topic="tele/ki-fridge/SENSOR", sensor_label='ki_fridge', onMsg=sonoff),
38 subscribe_to_sensor(topic="tt-console-power/SENSOR", sensor_label='tt_console'), 69 subscribe_to_sensor( topic="tt-console-power/SENSOR", sensor_label='tt_console', onMsg=sonoff),
39 ]) 70 request_shelly_statuses(topic="ga-washer-power/command/switch:0"),
71 subscribe_to_sensor( topic="ga-washer-power/status/switch:0", sensor_label='ga_washer', onMsg=shelly),
72 request_shelly_statuses(topic="do-r-power/command/switch:0"),
73 subscribe_to_sensor( topic="do-r-power/status/switch:0", sensor_label='do_r', onMsg=shelly),
74 request_shelly_statuses(topic="ws-atx-power/command/switch:0"),
75 subscribe_to_sensor( topic="ws-atx-power/status/switch:0", sensor_label='ws_atx', onMsg=shelly),
76 ]) # yapf: disable