From 626490133e30977130007f7c9e60a9222194abdd Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Sun, 2 Aug 2020 16:17:43 +0200 Subject: [PATCH] init the mystrom exporter for usage + temperature --- .gitignore | 1 + mystrom_exporter.py | 68 +++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 2 ++ 3 files changed, 71 insertions(+) create mode 100644 .gitignore create mode 100644 mystrom_exporter.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f7275bb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv/ diff --git a/mystrom_exporter.py b/mystrom_exporter.py new file mode 100644 index 0000000..82ac631 --- /dev/null +++ b/mystrom_exporter.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +import aiohttp +from aiohttp import web +import asyncio +import argparse +from prometheus_client import Gauge +from prometheus_client.exposition import generate_latest +import json +import re + +async def fetch(session, url): + url_report = f"{url}/report" + device_name = re.sub('[/:.-]', '_', re.sub('(http|https)://','',url)) + + async with session.get(url_report) as response: + response = json.loads(await response.text()) + + return (device_name, response['power'], response['temperature']) + +async def main(devices): + async with aiohttp.ClientSession() as session: + tasks = [] + + for device in devices: + tasks.append(fetch(session, device)) + + results = await asyncio.gather(*tasks) + +class MyStrom(object): + def __init__(self, devices): + self.devices = devices + self.usage = Gauge('mystrom_usage_watts', 'Electricity usage of the device', ['device']) + self.temperature = Gauge('mystrom_temperature_celsius', 'Temperature', ['device']) + + async def fetch(self, session, url): + url_report = f"{url}/report" + device_name = re.sub('[/:.-]', '_', re.sub('(http|https)://','',url)) + + async with session.get(url_report) as response: + response = json.loads(await response.text()) + return (device_name, response['power'], response['temperature']) + + async def get(self, request): + tasks = [] + + async with aiohttp.ClientSession() as session: + for device in self.devices: + tasks.append(self.fetch(session, device)) + + results = await asyncio.gather(*tasks) + + for res in results: + self.usage.labels(device=res[0]).set(res[1]) + self.temperature.labels(device=res[0]).set(res[2]) + + return web.Response(text=generate_latest().decode('utf-8')) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Export usage data from mystrom devices via prometheus') + parser.add_argument('device', nargs='+', help="URL to your mystrom device(s)") + args = parser.parse_args() + + mystrom = MyStrom(args.device) + app = web.Application() + app.add_routes([web.get('/metrics', mystrom.get)]) + web.run_app(app) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8882968 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +aiohttp +prometheus-client