import json import time import paho.mqtt.client as mqtt from prometheus_client import start_http_server, Gauge CONFIG = json.load(open("/etc/mqtt2prometheus.json", mode="r", encoding="utf-8")) people_now_present = Gauge( "people_now_present", "People currently present in the space" ) space_state = Gauge("space_state", "The current space state") space_lastchange = Gauge( "space_lastchange", "The lastchange timestamp of the current space state" ) member_count = Gauge( "member_count", "The current count of members", labelnames=["name"] ) availability = Gauge( "availability", "The availability status of different MQTT clients", labelnames=["clientname"], ) temperature = Gauge( "temperature_celsius", "The current temperature", labelnames=["location"] ) humidity = Gauge("humidity_percent", "The current humidity", labelnames=["location"]) barometer = Gauge( "barometer_hectopascal", "The current air pressure", labelnames=["location"] ) power_consumption = Gauge( "power_consumption_watt", "The current power used", labelnames=["location"] ) co2_emission = Gauge( "co2_emission_kilogramm", "The CO2 emission in kilogramm", labelnames=["location"] ) energy_consumption = Gauge( "energy_consumption_kilowatthour", "The energy consumption in kilowatthour", labelnames=["location"], ) TOPIC_TO_HANDLER = { "availability/#": handle_availability, "space/status": handle_space_status, "space/member_count": handle_member_count, "sensors/people_now_present": handle_people_now_present, "sensors/temperature/#": handle_temperature, "sensors/humidity/#": handle_humidity, "sensors/barometer/#": handle_barometer, "sensors/power_consumption/#": handle_power_consumption, "sensors/co2_emission/#": handle_co2_emission, "sensors/energy_consumption/#": handle_energy_consumption, } def on_connect(client, userdata, flags, rc): client.publish("availability/mqtt2prometheus", "online", 2, True) for topic, handler in TOPIC_TO_HANDLER: client.message_callback_add(topic, handler) for topic in ["availability/#", "space/status", "space/member_count", "sensors/#"]: client.subscribe(topic) def handle_people_now_present(client, userdata, msg): people_now_present.set(json.loads(msg.payload)) def handle_space_status(client, userdata, msg): state = json.loads(msg.payload) space_state.set(int(state["open"])) space_lastchange.set(state["lastchange"]) def handle_member_count(client, userdata, msg): count = json.loads(msg.payload) member_count.labels(count["name"]).set(count["value"]) def handle_availability(client, userdata, msg): t = msg.topic.split("/") if len(t) == 2: c = t[-1] else: c = "_".join(t[1:]) v = 1 if msg.payload == b"online" else 0 availability.labels(c).set(v) def handle_temperature(client, userdata, msg): t = msg.topic.split("/") location = "-".join(t[2:]) try: temperature.labels(location).set(float(msg.payload)) except: pass def handle_humidity(client, userdata, msg): t = msg.topic.split("/") location = "-".join(t[2:]) try: humidity.labels(location).set(float(msg.payload)) except: pass def handle_barometer(client, userdata, msg): t = msg.topic.split("/") location = "-".join(t[2:]) try: barometer.labels(location).set(float(msg.payload)) except: pass def handle_power_consumption(client, userdata, msg): t = msg.topic.split("/") location = "-".join(t[2:]) try: power_consumption.labels(location).set(float(msg.payload)) except: pass def handle_co2_emission(client, userdata, msg): t = msg.topic.split("/") location = "-".join(t[2:]) try: co2_emission.labels(location).set(float(msg.payload)) except: pass def handle_energy_consumption(client, userdata, msg): t = msg.topic.split("/") location = "-".join(t[2:]) try: energy_consumption.labels(location).set(float(msg.payload)) except: pass def main(): client = mqtt.Client("mqtt2prometheus") client.on_connect = on_connect client.username_pw_set(CONFIG["mqtt"]["username"], CONFIG["mqtt"]["password"]) client.will_set("availability/mqtt2prometheus", "offline", 2, True) client.connect(CONFIG["mqtt"]["host"]) client.loop_start() start_http_server(CONFIG["prometheus"]["port"]) while True: time.sleep(1) if __name__ == "__main__": main()