-
Notifications
You must be signed in to change notification settings - Fork 0
/
metric.py
104 lines (81 loc) · 3.06 KB
/
metric.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import paho.mqtt.client as mqtt
import logging
import time
import json
import json.decoder
import time
from prometheus_client import start_http_server, Gauge
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-m", "--mqtt_server", dest="mqtt_server",
help="mqtt server ip or host", default="localhost")
(options, args) = parser.parse_args()
logger = logging.getLogger(__name__)
# Start up the server to expose the metrics.
#start_http_server(5055)
start_http_server(5055, 'localhost')
# connect mqtt
c = mqtt.Client('mqtt_to_prometheus_v3')
c.connect(options.mqtt_server)
c.subscribe('inverter/SG12RT/registers')
c.subscribe('inverter/SH10RT/registers')
c.subscribe('tele/+/SENSOR')
def on_log(mqttc, obj, level, string):
print(string)
METRICS = {}
def get_or_create_metric(name, desc):
if name not in METRICS:
METRICS[name] = Gauge(name, desc)
return METRICS[name]
def on_message(client, data, message):
try:
data = json.loads(message.payload.decode('utf8'))
except json.decoder.JSONDecodeError:
print("Error while decoding json:")
print(message.payload)
return
topic = message.topic
if topic.startswith('inverter'):
# solar stuff
device = data.get('device_type_code')
# hack for negative battery power when charging
fac = 1
if data.get('state_battery_charging', 0):
fac = -1
data['battery_power'] = fac * data.get('battery_power', 0)
for key, value in data.items():
if type(value) not in [type(1.0), type(1)]:
print(f'Ignoring {key}: {value}')
continue
# replace '-' because its invalid in metric names
key = key.replace('-','_')
metric_name = f'solar_{device.lower()}_{key}'
metric = get_or_create_metric(metric_name, f'{device} {key}')
metric.set(value)
elif topic.startswith('tele'):
sensor_name = topic[5:topic.rfind('/')]
# tasmota
if 'DS18B20' in data:
temp = data['DS18B20']['Temperature']
id_ = data['DS18B20']['Id']
metric = get_or_create_metric(f'{sensor_name}_ds18b20', f'temp {sensor_name} ({id_})')
metric.set(temp)
if 'BME280' in data:
for key in ('Temperature', 'Humidity', 'DewPoint', 'Pressure'):
val = data['BME280'][key]
if val is not None:
metric = get_or_create_metric(f'{sensor_name}_bme280_{key.lower()}', f'{key.lower()} {sensor_name}')
metric.set(val)
if 'ENERGY' in data:
total = data['ENERGY']['Total']
power = data['ENERGY']['Power']
metric_t = get_or_create_metric(f'{sensor_name}_TotalPower', f'{sensor_name} TotalPower')
metric_p = get_or_create_metric(f'{sensor_name}_Power', f'{sensor_name} Power')
metric_t.set(total)
metric_p.set(power)
c.on_message = on_message
c.on_log = on_log
c.loop_start()
while True:
time.sleep(1)
c.loop_stop()