diff --git a/README.md b/README.md index e21ed7f..87e8032 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,99 @@ Receives gas and electric meter data from https://glowmarkt.com/ and exposes it to Prometheus. +``` +usage: glowprom [-h] [--mqtt [MQTT]] [--port [PORT]] [--user [USER]] [--passwd [PASSWD]] [--topic [TOPIC]] [--bind [BIND]] + +Listens to meter reports from Glow (glowmarkt.com) MQTT and exposes them as prometheus metrics + +optional arguments: + -h, --help show this help message and exit + --mqtt [MQTT] the mqtt server to connect to. leave unset for the Glow cloud MQTT. (can also be set with $GLOWPROM_MQTT) + --port [PORT] the mqtt port to connect to. (can also be set with $GLOWPROM_MQTT_PORT) + --user [USER] the user name to use (can also be set with $GLOWPROM_USER) + --passwd [PASSWD] the password to use (can also be set with $GLOWPROM_PASSWD) + --topic [TOPIC] the topic to listen on for cloud MQTT (can also be set with $GLOWPROM_TOPIC) + --bind [BIND] the ip address and port to bind to +``` + +The Glow IHD can be used to connect a cloud MQTT server provided by Glow, or to your own local MQTT. These methods send different +messages, so different prometheus metrics are exposed depending on what you use. + +# Cloud MQTT + +``` +# HELP consumption The consumption over the given period. +# TYPE consumption counter +glowprom_consumption{type="electricity",period="daily"} 4.761 +glowprom_consumption{type="electricity",period="weekly"} 4.761 +glowprom_consumption{type="electricity",period="monthly"} 61.483 +glowprom_consumption{type="gas",period="daily"} 17.326 +glowprom_consumption{type="gas",period="weekly"} 17.326 +glowprom_consumption{type="gas",period="monthly"} 383.157 +# HELP meter The meter reading. +# TYPE meter counter +glowprom_meter{type="electricity"} 15255.87 +glowprom_meter{type="gas"} 5995.276 +``` + +# Local MQTT +``` +# HELP glowprom_timestamp The time the last update was received. +# TYPE glowprom_timestamp counter +glowprom_timestamp{type="electric", mpan="your_mpan"} 1667818379.0 +glowprom_timestamp{type="gas", mprn="your_mprn"} 1667818361.0 + +# HELP glowprom_export_cumulative_Wh The total amount of energy exported. +# TYPE glowprom_export_cumulative_Wh counter +glowprom_export_cumulative_Wh{type="electric", mpan="your_mpan"} 0.0 + +# HELP glowprom_import_cumulative_Wh The total amount of energy imported. +# TYPE glowprom_import_cumulative_Wh counter +glowprom_import_cumulative_Wh{type="electric", mpan="your_mpan"} 15255822.0 +glowprom_import_cumulative_Wh{type="gas", mprn="your_mprn"} 66589570.00000001 + +# HELP glowprom_import_day_Wh The amount of energy imported today. +# TYPE glowprom_import_day_Wh gauge +glowprom_import_day_Wh{type="electric", mpan="your_mpan"} 4714.0 +glowprom_import_day_Wh{type="gas", mprn="your_mprn"} 17326.0 + +# HELP glowprom_import_week_Wh The amount of energy imported this week. +# TYPE glowprom_import_week_Wh gauge +glowprom_import_week_Wh{type="electric", mpan="your_mpan"} 4714.0 +glowprom_import_week_Wh{type="gas", mprn="your_mprn"} 17326.0 + +# HELP glowprom_import_month_Wh The amount of energy imported this month. +# TYPE glowprom_import_month_Wh gauge +glowprom_import_month_Wh{type="electric", mpan="your_mpan"} 61436.0 +glowprom_import_month_Wh{type="gas", mprn="your_mprn"} 383157.0 + +# HELP glowprom_import_price The current unit price for energy. +# TYPE glowprom_import_price gauge +glowprom_import_price{type="electric", mpan="your_mpan"} 0.16401 +glowprom_import_price{type="gas", mprn="your_mprn"} 0.03623 + +# HELP glowprom_import_standing The standing charge for energy. +# TYPE glowprom_import_standing gauge +glowprom_import_standing{type="electric", mpan="your_mpan"} 0.19383 +glowprom_import_standing{type="gas", mprn="your_mprn"} 0.168 + +# HELP glowprom_power_W The current amount of power being used. +# TYPE glowprom_power_W gauge +glowprom_power_W{type="electric", mpan="your_mpan"} 489.0 + +# HELP glowprom_import_cumulativevol_m3 The total volume of gas imported. +# TYPE glowprom_import_cumulativevol_m3 counter +glowprom_import_cumulativevol_m3{type="gas", mprn="your_mprn"} 5995.276 + +# HELP glowprom_import_dayvol_Wh The volume of gas imported today. +# TYPE glowprom_import_dayvol_Wh counter +glowprom_import_dayvol_Wh{type="gas", mprn="your_mprn"} 17326.0 + +# HELP glowprom_import_weekvol_Wh The volume of gas imported this week. +# TYPE glowprom_import_weekvol_Wh counter +glowprom_import_weekvol_Wh{type="gas", mprn="your_mprn"} 17326.0 + +# HELP glowprom_import_monthvol_Wh The volume of gas imported this month. +# TYPE glowprom_import_monthvol_Wh counter +glowprom_import_monthvol_Wh{type="gas", mprn="your_mprn"} 383157.0 +``` \ No newline at end of file diff --git a/bin/glowprom b/bin/glowprom index 31ba329..268e0d1 100644 --- a/bin/glowprom +++ b/bin/glowprom @@ -24,7 +24,7 @@ def main(): args = get_arguments(sys.argv[1:]) threading.Thread(target=connect, - args=(args, update_stats), + args=(args, update_stats(args.cloud)), daemon=True).start() serve(args) diff --git a/glowprom/__init__.py b/glowprom/__init__.py index 4cafc67..e17de62 100644 --- a/glowprom/__init__.py +++ b/glowprom/__init__.py @@ -17,7 +17,6 @@ from .arguments import get_arguments from .exceptions import InvalidArguments from .mqtt import connect -from .prometheus import prometheus from .server import serve, update_stats __version__ = "0.2.6" diff --git a/glowprom/arguments.py b/glowprom/arguments.py index 4dadeca..425d7f9 100644 --- a/glowprom/arguments.py +++ b/glowprom/arguments.py @@ -19,9 +19,17 @@ from .exceptions import InvalidArguments +DEFAULT_MQTT = "glowmqtt.energyhive.com" + parser = argparse.ArgumentParser( description='Listens to meter reports from Glow (glowmarkt.com) MQTT and' + ' exposes them as prometheus metrics') +parser.add_argument('--mqtt', type=str, nargs='?', default=DEFAULT_MQTT, + help='the mqtt server to connect to. leave unset for the ' + + 'Glow cloud MQTT. (can also be set with $GLOWPROM_MQTT)') +parser.add_argument('--port', type=int, nargs='?', default=1883, + help='the mqtt port to connect to. (can also be set with ' + + '$GLOWPROM_MQTT_PORT)') parser.add_argument('--user', type=str, nargs='?', help='the user name to use (can also be set with ' + '$GLOWPROM_USER)') @@ -29,14 +37,18 @@ help='the password to use (can also be set with ' + '$GLOWPROM_PASSWD)') parser.add_argument('--topic', type=str, nargs='?', - help='the topic to listen on (can also be set with ' - + '$GLOWPROM_TOPIC)') + help='the topic to listen on for cloud MQTT' + + ' (can also be set with $GLOWPROM_TOPIC)') parser.add_argument('--bind', type=str, nargs='?', default="0.0.0.0:9100", help='the ip address and port to bind to') def get_arguments(args): args = parser.parse_args(args) + if "GLOWPROM_MQTT" in os.environ: + args.mqtt = os.environ["GLOWPROM_MQTT"] + if "GLOWPROM_MQTT_PORT" in os.environ: + args.port = os.environ["GLOWPROM_MQTT_PORT"] if "GLOWPROM_USER" in os.environ: args.user = os.environ["GLOWPROM_USER"] if "GLOWPROM_PASSWD" in os.environ: @@ -44,15 +56,20 @@ def get_arguments(args): if "GLOWPROM_TOPIC" in os.environ: args.topic = os.environ["GLOWPROM_TOPIC"] - if args.user is None: + args.cloud = args.mqtt == DEFAULT_MQTT + + if args.cloud and args.user is None: raise InvalidArguments("No username supplied. Either use --user " + "or set $GLOWPROM_USER") - if args.passwd is None: + if args.cloud and args.passwd is None: raise InvalidArguments("No password supplied. Either use --passwd " + "or set $GLOWPROM_PASSWD") - if args.topic is None: + if args.cloud and args.topic is None: raise InvalidArguments("No topic supplied. Either use --topic " + "or set $GLOWPROM_TOPIC") + if not args.cloud and args.topic is not None: + raise InvalidArguments( + "A topic should only be supplied when using cloud MQTT.") if ":" not in args.bind: args.bind = (args.bind, 9100) diff --git a/glowprom/prometheus.py b/glowprom/cloud_message.py similarity index 93% rename from glowprom/prometheus.py rename to glowprom/cloud_message.py index fdf5ecf..e327aa4 100644 --- a/glowprom/prometheus.py +++ b/glowprom/cloud_message.py @@ -59,17 +59,18 @@ # - 01: ProviderName (string) -METRIC = "consumption{{type=\"{type}\",period=\"{period}\"}} {value}" -METER = "meter{{type=\"{type}\"}} {value}" +METRIC = "glowprom_consumption{{type=\"{type}\",period=\"{period}\"}} {value}" +METER = "glowprom_meter{{type=\"{type}\"}} {value}" -METRIC_HELP = "# HELP consumption The consumption over the given period." -METRIC_TYPE = "# TYPE consumption counter" +METRIC_HELP = "# HELP glowprom_consumption" \ + + " The consumption over the given period." +METRIC_TYPE = "# TYPE glowprom_consumption counter" -METER_HELP = "# HELP meter The meter reading." -METER_TYPE = "# TYPE meter counter" +METER_HELP = "# HELP glowprom_meter The meter reading." +METER_TYPE = "# TYPE glowprom_meter counter" -def prometheus(msg): +def cloud_message(msg): # Code adapted from # https://gist.github.com/ndfred/b373eeafc4f5b0870c1b8857041289a9 payload = json.loads(msg.payload) diff --git a/glowprom/local_message.py b/glowprom/local_message.py new file mode 100644 index 0000000..30b4e12 --- /dev/null +++ b/glowprom/local_message.py @@ -0,0 +1,215 @@ +# glowprom +# Copyright (C) 2020 Andrew Wilkinson +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import datetime +import json + +# {'electricitymeter': {'timestamp': '2022-11-07T09:20:08Z', +# 'energy': {'export': {'cumulative': 0.0, 'units': 'kWh'}, +# 'import': {'cumulative': 15254.827, 'day': 3.717, +# 'week': 3.717, 'month': 60.439, 'units': 'kWh', +# 'mpan': 'abcd', 'supplier': 'Octopus Energy', +# 'price': {'unitrate': 0.16401, +# 'standingcharge': 0.19383}}}, +# 'power': {'value': 0.425, 'units': 'kW'}}} + +# {'gasmeter': {'timestamp': '2022-11-07T09:35:38Z', +# 'energy': {'import': {'cumulative': 66589.57, 'day': 17.326, +# 'week': 17.326, 'month': 383.157, 'units': 'kWh', +# 'cumulativevol': 5995.276, +# 'cumulativevolunits': 'm3', +# 'dayvol': 17.326, 'weekvol': 17.326, +# 'monthvol': 383.157, +# 'dayweekmonthvolunits': 'kWh', +# 'mprn': 'wxyz', +# 'supplier': '---', +# 'price': {'unitrate': 0.03623, +# 'standingcharge': 0.168}}}}} +METRIC = "glowprom_{metric}" +METRIC_KEYS = "{{type=\"{type}\", {idname}=\"{idvalue}\"}}" + +METRIC_METADATA = { + "timestamp": ("The time the last update was received.", "counter", False), + "export_cumulative": ("The total amount of energy exported.", + "counter", True), + "import_cumulative": ("The total amount of energy imported.", + "counter", True), + "import_day": ("The amount of energy imported today.", "gauge", True), + "import_week": ("The amount of energy imported this week.", "gauge", True), + "import_month": ("The amount of energy imported this month.", + "gauge", True), + "import_price": ("The current unit price for energy.", "gauge", False), + "import_standing": ("The standing charge for energy.", "gauge", False), + "power": ("The current amount of power being used.", "gauge", True), + "import_cumulativevol": ("The total volume of gas imported.", + "counter", True), + "import_dayvol": ("The volume of gas imported today.", "counter", True), + "import_weekvol": ("The volume of gas imported this week.", + "counter", True), + "import_monthvol": ("The volume of gas imported this month.", + "counter", True) +} + +METRIC_HELP = "# HELP {metric} {help}" +METRIC_TYPE = "# TYPE {metric} {type}" + +ELECTRIC_DATA = {} +GAS_DATA = {} + + +def local_message(msg): + # # Code adapted from + # # https://gist.github.com/ndfred/b373eeafc4f5b0870c1b8857041289a9 + payload = json.loads(msg.payload) + + key = list(payload.keys())[0] + energy = payload[key]["energy"] + + timestamp = datetime.datetime.strptime(payload[key]["timestamp"], + r"%Y-%m-%dT%H:%M:%SZ").timestamp() + + if key == "electricitymeter": + mpan = energy["import"]["mpan"] + if mpan not in ELECTRIC_DATA: + ELECTRIC_DATA[mpan] = {} + ELECTRIC_DATA[mpan]["timestamp"] = timestamp + ELECTRIC_DATA[mpan]["export_cumulative"] = \ + convert_units(energy["export"]["cumulative"], + energy["export"]["units"]) + ELECTRIC_DATA[mpan]["import_cumulative"] = \ + convert_units(energy["import"]["cumulative"], + energy["import"]["units"]) + ELECTRIC_DATA[mpan]["import_day"] = \ + convert_units(energy["import"]["day"], + energy["import"]["units"]) + ELECTRIC_DATA[mpan]["import_week"] = \ + convert_units(energy["import"]["week"], + energy["import"]["units"]) + ELECTRIC_DATA[mpan]["import_month"] = \ + convert_units(energy["import"]["month"], + energy["import"]["units"]) + ELECTRIC_DATA[mpan]["import_price"] = \ + energy["import"]["price"]["unitrate"] + ELECTRIC_DATA[mpan]["import_standing"] = \ + energy["import"]["price"]["standingcharge"] + ELECTRIC_DATA[mpan]["power"] = \ + convert_units(payload[key]["power"]["value"], + payload[key]["power"]["units"]) + + elif key == "gasmeter": + mprn = energy["import"]["mprn"] + if mprn not in GAS_DATA: + GAS_DATA[mprn] = {} + GAS_DATA[mprn]["timestamp"] = timestamp + GAS_DATA[mprn]["import_cumulative"] = \ + convert_units(energy["import"]["cumulative"], + energy["import"]["units"]) + GAS_DATA[mprn]["import_day"] = \ + convert_units(energy["import"]["day"], energy["import"]["units"]) + GAS_DATA[mprn]["import_week"] = \ + convert_units(energy["import"]["week"], energy["import"]["units"]) + GAS_DATA[mprn]["import_month"] = \ + convert_units(energy["import"]["month"], energy["import"]["units"]) + GAS_DATA[mprn]["import_cumulativevol"] = \ + convert_units(energy["import"]["cumulativevol"], + energy["import"]["cumulativevolunits"]) + GAS_DATA[mprn]["import_dayvol"] = \ + convert_units(energy["import"]["dayvol"], + energy["import"]["dayweekmonthvolunits"]) + GAS_DATA[mprn]["import_weekvol"] = \ + convert_units(energy["import"]["weekvol"], + energy["import"]["dayweekmonthvolunits"]) + GAS_DATA[mprn]["import_monthvol"] = \ + convert_units(energy["import"]["monthvol"], + energy["import"]["dayweekmonthvolunits"]) + GAS_DATA[mprn]["import_price"] = energy["import"]["price"]["unitrate"] + GAS_DATA[mprn]["import_standing"] = \ + energy["import"]["price"]["standingcharge"] + else: + print(f"Unknown payload type {key}") + + print(ELECTRIC_DATA) + print(GAS_DATA) + + lines = [] + for metric in METRIC_METADATA.keys(): + help, metric_type, has_units = METRIC_METADATA[metric] + + if has_units: + for unit in get_units_for_metric(metric): + metric_name = METRIC.format(metric=metric) + "_" + unit + lines.append(METRIC_HELP.format(metric=metric_name, + help=help)) + lines.append(METRIC_TYPE.format(metric=metric_name, + type=metric_type)) + else: + metric_name = METRIC.format(metric=metric) + lines.append(METRIC_HELP.format(metric=metric_name, + help=help)) + lines.append(METRIC_TYPE.format(metric=metric_name, + type=metric_type)) + + for mpan in ELECTRIC_DATA: + if metric in ELECTRIC_DATA[mpan]: + if has_units: + value = ELECTRIC_DATA[mpan][metric][0] + metric_name = \ + METRIC.format(metric=metric) + "_" \ + + ELECTRIC_DATA[mpan][metric][1] + else: + value = ELECTRIC_DATA[mpan][metric] + metric_name = METRIC.format(metric=metric) + + keys = METRIC_KEYS.format(type="electric", idname="mpan", + idvalue=mpan) + lines.append(f"{metric_name}{keys} {value}") + + for mprn in GAS_DATA: + if metric in GAS_DATA[mprn]: + if has_units: + value = GAS_DATA[mprn][metric][0] + metric_name = METRIC.format(metric=metric) + "_" \ + + GAS_DATA[mprn][metric][1] + else: + value = GAS_DATA[mprn][metric] + metric_name = METRIC.format(metric=metric) + + keys = METRIC_KEYS.format(type="gas", idname="mprn", + idvalue=mprn) + lines.append(f"{metric_name}{keys} {value}") + + lines.append("") + + return "\n".join(lines) + + +def get_units_for_metric(metric): + units = set() + for mpan in ELECTRIC_DATA.keys(): + if metric in ELECTRIC_DATA[mpan]: + units.add(ELECTRIC_DATA[mpan][metric][1]) + for mprn in GAS_DATA.keys(): + if metric in GAS_DATA[mprn]: + units.add(GAS_DATA[mprn][metric][1]) + return units + + +def convert_units(value, units): + if units == "kW": + return (value * 1000, "W") + if units == "kWh": + return (value * 1000, "Wh") + return (value, units) diff --git a/glowprom/mqtt.py b/glowprom/mqtt.py index 8220198..cac0191 100644 --- a/glowprom/mqtt.py +++ b/glowprom/mqtt.py @@ -28,7 +28,9 @@ def on_connect(topic, client, userdata, flags, rc): def connect(args, on_message, retry=True): client = mqtt.Client() - client.on_connect = functools.partial(on_connect, args.topic) + client.on_connect = \ + functools.partial(on_connect, + args.topic if args.cloud else "glow/+/+/+") client.on_message = on_message client.username_pw_set(args.user, password=args.passwd) diff --git a/glowprom/server.py b/glowprom/server.py index fd12982..f22e13a 100644 --- a/glowprom/server.py +++ b/glowprom/server.py @@ -17,7 +17,8 @@ from datetime import datetime import http.server -from .prometheus import prometheus +from .cloud_message import cloud_message +from .local_message import local_message STATS = None @@ -59,9 +60,13 @@ def serve(args): # pragma: no cover server.serve_forever() -def update_stats(client, userdata, msg): - global STATS - if msg is None: - STATS = None - else: - STATS = prometheus(msg) +def update_stats(cloud): + prometheus = cloud_message if cloud else local_message + + def update_stats(client, userdata, msg): + global STATS + if msg is None: + STATS = None + else: + STATS = prometheus(msg) + return update_stats diff --git a/tests/__init__.py b/tests/__init__.py index 00b41ee..033142a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -16,5 +16,6 @@ from .test_arguments import TestArguments from .test_mqtt import TestMQTT -from .test_prometheus import TestPrometheus +from .test_cloud_message import TestCloudMessage +from .test_local_message import TestLocalMessage from .test_server import TestServer diff --git a/tests/test_prometheus.py b/tests/test_cloud_message.py similarity index 59% rename from tests/test_prometheus.py rename to tests/test_cloud_message.py index 32b7593..579b5ea 100644 --- a/tests/test_prometheus.py +++ b/tests/test_cloud_message.py @@ -15,10 +15,9 @@ # along with this program. If not, see . import json -import os import unittest -from glowprom import prometheus +from glowprom.cloud_message import cloud_message MESSAGE_TEXT = open("tests/test_message.txt", "rb").read() @@ -29,31 +28,35 @@ def __init__(self, payload): self.payload = payload -class TestPrometheus(unittest.TestCase): - def test_prometheus(self): - prom = prometheus(MockMessage(MESSAGE_TEXT)) +class TestCloudMessage(unittest.TestCase): + def test_cloud_message(self): + prom = cloud_message(MockMessage(MESSAGE_TEXT)) self.assertIn( - "consumption{type=\"electricity\",period=\"daily\"} 7.971", prom) + "glowprom_consumption{type=\"electricity\",period=\"daily\"} " + + "7.971", prom) self.assertIn( - "consumption{type=\"gas\",period=\"daily\"} 39.452", prom) + "glowprom_consumption{type=\"gas\",period=\"daily\"} 39.452", + prom) def test_missing_electricity(self): data = json.loads(MESSAGE_TEXT) del data["elecMtr"]["0702"]["04"] - prom = prometheus(MockMessage(json.dumps(data))) + prom = cloud_message(MockMessage(json.dumps(data))) self.assertNotIn( - "consumption{type=\"electricity\",period=\"daily\"} 7.971", prom) + "glowprom_consumption{type=\"electricity\",period=\"daily\"} " + + "7.971", prom) self.assertIn( - "consumption{type=\"gas\",period=\"daily\"} 39.452", prom) + "glowprom_consumption{type=\"gas\",period=\"daily\"} 39.452", prom) def test_missing_gas(self): data = json.loads(MESSAGE_TEXT) del data["gasMtr"]["0702"]["0C"] - prom = prometheus(MockMessage(json.dumps(data))) + prom = cloud_message(MockMessage(json.dumps(data))) self.assertIn( - "consumption{type=\"electricity\",period=\"daily\"} 7.971", prom) + "glowprom_consumption{type=\"electricity\",period=\"daily\"} " + + "7.971", prom) self.assertNotIn( - "consumption{type=\"gas\",period=\"daily\"} 39.452", prom) + "glowprom_consumption{type=\"gas\",period=\"daily\"} 39.452", prom) diff --git a/tests/test_local_electric_message.txt b/tests/test_local_electric_message.txt new file mode 100644 index 0000000..ccced80 --- /dev/null +++ b/tests/test_local_electric_message.txt @@ -0,0 +1,8 @@ +{"electricitymeter": {"timestamp": "2022-11-07T09:20:08Z", + "energy": {"export": {"cumulative": 0.0, "units": "kWh"}, + "import": {"cumulative": 15254.827, "day": 3.717, + "week": 3.717, "month": 60.439, "units": "kWh", + "mpan": "abcd", "supplier": "Octopus Energy", + "price": {"unitrate": 0.16401, + "standingcharge": 0.19383}}}, + "power": {"value": 0.425, "units": "kW"}}} \ No newline at end of file diff --git a/tests/test_local_gas_message.txt b/tests/test_local_gas_message.txt new file mode 100644 index 0000000..a5c549a --- /dev/null +++ b/tests/test_local_gas_message.txt @@ -0,0 +1,12 @@ +{"gasmeter": {"timestamp": "2022-11-07T09:35:38Z", + "energy": {"import": {"cumulative": 66589.57, "day": 17.326, + "week": 17.326, "month": 383.157, "units": "kWh", + "cumulativevol": 5995.276, + "cumulativevolunits": "m3", + "dayvol": 17.326, "weekvol": 17.326, + "monthvol": 383.157, + "dayweekmonthvolunits": "kWh", + "mprn": "wxyz", + "supplier": "---", + "price": {"unitrate": 0.03623, + "standingcharge": 0.168}}}}} \ No newline at end of file diff --git a/tests/test_local_message.py b/tests/test_local_message.py new file mode 100644 index 0000000..f8736bc --- /dev/null +++ b/tests/test_local_message.py @@ -0,0 +1,46 @@ +# glowprom +# Copyright (C) 2020 Andrew Wilkinson +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import json +import unittest + +from glowprom.local_message import local_message + + +ELECTRIC_MESSAGE_TEXT = open("tests/test_local_electric_message.txt", "rb") \ + .read() +GAS_MESSAGE_TEXT = open("tests/test_local_gas_message.txt", "rb").read() + + +class MockMessage: + def __init__(self, payload): + self.payload = payload + + +class TestLocalMessage(unittest.TestCase): + def test_electric_message(self): + prom = local_message(MockMessage(ELECTRIC_MESSAGE_TEXT)) + + self.assertIn( + "glowprom_import_cumulative_Wh{type=\"electric\", mpan=\"abcd\"}" + + " 15254827.0", prom) + + def test_gas_message(self): + prom = local_message(MockMessage(GAS_MESSAGE_TEXT)) + + self.assertIn( + "glowprom_import_cumulative_Wh{type=\"gas\", mprn=\"wxyz\"}" + + " 66589570.00000001", prom) diff --git a/tests/test_mqtt.py b/tests/test_mqtt.py index 1210c1c..c1d5480 100644 --- a/tests/test_mqtt.py +++ b/tests/test_mqtt.py @@ -21,6 +21,9 @@ class Arguments: + cloud = True + mqtt = "cloudmqtt" + port = 1883 topic = "TestTopic" user = "TestUser" passwd = "TestPasswd" @@ -35,7 +38,7 @@ class TestMQTT(unittest.TestCase): def test_connect(self, client): clientobj = client() - connect(Arguments(), on_message) + connect(Arguments(), on_message, retry=False) self.assertTrue(clientobj.connect.called) diff --git a/tests/test_server.py b/tests/test_server.py index 542673d..15d0e90 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -39,7 +39,7 @@ def __init__(self): class TestServer(unittest.TestCase): def setUp(self): - update_stats(None, None, None) + update_stats(True)(None, None, None) def test_index(self): handler = MockHandler() @@ -58,7 +58,7 @@ def test_error(self): self.assertTrue("404" in handler.wfile.read().decode("utf8")) def test_metrics(self): - update_stats(None, None, MockMessage()) + update_stats(True)(None, None, MockMessage()) handler = MockHandler() handler.path = "/metrics"