diff --git a/.gitignore b/.gitignore
index 19eddcf..63a433d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,8 @@
 *.py[ocd]
 
+.mypy_cache/
+__pycache__/
+
 *.log
 *.zip
 
diff --git a/consumers/mqtt.py b/consumers/mqtt.py
index f7fa483..38f54b6 100644
--- a/consumers/mqtt.py
+++ b/consumers/mqtt.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+import json
 from typing import Any, Dict, List, Optional
 from uuid import uuid4
 
@@ -34,11 +35,13 @@ MAP_VALUES: Dict[str, Dict[str, Any]] = {
         "unit": "Wh",
         "type": "energy",
         "state_class": "total_increasing",
+        "expiry": 180,
     },
     "total_consumption_power": {
         "unit": "Wh",
         "type": "energy",
         "state_class": "total_increasing",
+        "expiry": 180,
     },
     #
     "battery_charge": {"unit": "%", "type": "battery", "state_class": "measurement"},
@@ -128,6 +131,7 @@ class MqttConsumer(BaseConsumer):
                 # TODO: Get charger serial and use for identifier instead
                 # See: https://www.home-assistant.io/integrations/sensor.mqtt/#device
                 # "via_device": self.settings["device_id"],
+                "suggested_area": "Solar panel",
             },
             "force_update": True,
             "expire_after": expiry,
@@ -140,6 +144,8 @@ class MqttConsumer(BaseConsumer):
         if state_class:
             res["state_class"] = state_class
 
+        return res
+
     # The callback for when the client receives a CONNACK response from the server.
     @staticmethod
     def on_connect(client: mqtt.Client, userdata: "MqttConsumer", flags, rc):
@@ -162,15 +168,17 @@ class MqttConsumer(BaseConsumer):
         return super().poll()
 
     def write(self, data: Dict[str, Any]):
-        self.client.publish(f"{self.topic_prefix}/raw", payload=data)
+        self.client.publish(f"{self.topic_prefix}/raw", payload=json.dumps(data))
 
         for k, v in data.items():
             if k in MAP_VALUES:
                 if k not in self.initialized:
                     pretty_name = k.replace("_", " ").capitalize()
                     self.client.publish(
-                        f"{self.settings['discovery_prefix']}/sensor/{self.settings['device_id']}/config",  # noqa: E501
-                        self.get_ha_config(k, pretty_name, **MAP_VALUES[k]),
+                        f"{self.settings['discovery_prefix']}/sensor/{self.settings['device_id']}_{k}/config",  # noqa: E501
+                        payload=json.dumps(
+                            self.get_ha_config(k, pretty_name, **MAP_VALUES[k])
+                        ),
                         retain=True,
                     )
                     self.initialized.append(k)
diff --git a/solar_ble.py b/solar_ble.py
index 138225a..0ff0c0f 100755
--- a/solar_ble.py
+++ b/solar_ble.py
@@ -12,6 +12,7 @@ from bluepy import btle
 from libscrc import modbus
 
 from feasycom_ble import BTLEUart
+from test_config import get_config, get_consumers
 
 MAC = "DC:0D:30:9C:61:BA"
 
@@ -366,68 +367,92 @@ class Periodical:
 
 
 if __name__ == "__main__":
+    conf = get_config()
+    consumers = get_consumers(conf)
 
     per_voltages = Periodical(interval=15)
     per_current_hist = Periodical(interval=60)
 
-    while True:
-        try:
-            log("Connecting...")
-            with BTLEUart(MAC, timeout=10) as dev:
-                log("Connected.")
+    try:
+        while True:
+            try:
+                log("Connecting...")
+                with BTLEUart(MAC, timeout=10) as dev:
+                    log("Connected.")
 
-                # write(dev, construct_request(0, 32))
+                    # write(dev, construct_request(0, 32))
 
-                # Memory dump
-                # for address in range(0, 0x10000, 16):
-                #    log(f"Reading 0x{address:04X}...")
-                #    write(wd, construct_request(address, 16))
-                days = 7
-                res = readMemory(dev, 0x010B, 21)
-                if res:
-                    d = parse_historical_entry(res)
-                    log(d)
-                    days = cast(int, d.get("run_days", 7))
-
-                for i in range(days):
-                    res = readMemory(dev, 0xF000 + i, 10)
+                    # Memory dump
+                    # for address in range(0, 0x10000, 16):
+                    #    log(f"Reading 0x{address:04X}...")
+                    #    write(wd, construct_request(address, 16))
+                    days = 7
+                    res = readMemory(dev, 0x010B, 21)
                     if res:
                         d = parse_historical_entry(res)
-                        log({i: d})
+                        log(d)
+                        for consumer in consumers:
+                            consumer.write(d)
+                        days = cast(int, d.get("run_days", 7))
 
-                while True:
-                    now = time.time()
-                    if per_voltages(now):
-                        # CMD_GET_BATTERY_STATE + CMD_GET_PANEL_STATUS
-                        res = readMemory(dev, 0x0100, 11)
+                    for i in range(days):
+                        res = readMemory(dev, 0xF000 + i, 10)
                         if res:
-                            try:
-                                d = parse_battery_state(res)
-                                log(d)
-                            except struct.error as e:
-                                log(e)
-                                log("0x0100 Unpack error:", len(res), res)
-                                log("Flushed from read buffer; ", dev.read(timeout=0.5))
-                    if per_current_hist(now):
-                        res = readMemory(dev, 0x010B, 21)
-                        if res:
-                            try:
-                                d = parse_historical_entry(res)
-                                log(d)
-                            except struct.error as e:
-                                log(e)
-                                log("0x010B Unpack error:", len(res), res)
-                                log("Flushed from read buffer; ", dev.read(timeout=0.5))
-                    # print(".")
-                    time.sleep(1)
+                            d = parse_historical_entry(res)
+                            log({i: d})
+                            for consumer in consumers:
+                                consumer.write({str(i): d})
 
-                # if STATUS.get('load_enabled'):
-                #    write(wd, CMD_DISABLE_LOAD)
-                # else:
-                #    write(wd, CMD_ENABLE_LOAD)
+                    while True:
+                        now = time.time()
+                        if per_voltages(now):
+                            # CMD_GET_BATTERY_STATE + CMD_GET_PANEL_STATUS
+                            res = readMemory(dev, 0x0100, 11)
+                            if res:
+                                try:
+                                    d = parse_battery_state(res)
+                                    log(d)
+                                    for consumer in consumers:
+                                        consumer.write(d)
+                                except struct.error as e:
+                                    log(e)
+                                    log("0x0100 Unpack error:", len(res), res)
+                                    log(
+                                        "Flushed from read buffer; ",
+                                        dev.read(timeout=0.5),
+                                    )
+                        if per_current_hist(now):
+                            res = readMemory(dev, 0x010B, 21)
+                            if res:
+                                try:
+                                    d = parse_historical_entry(res)
+                                    log(d)
+                                    for consumer in consumers:
+                                        consumer.write(d)
+                                except struct.error as e:
+                                    log(e)
+                                    log("0x010B Unpack error:", len(res), res)
+                                    log(
+                                        "Flushed from read buffer; ",
+                                        dev.read(timeout=0.5),
+                                    )
+                        # print(".")
+                        for consumer in consumers:
+                            consumer.poll()
+                        time.sleep(max(0, 1 - time.time() - now))
 
-        except btle.BTLEDisconnectError:
-            log("ERROR: Disconnected")
-            time.sleep(1)
-        except KeyboardInterrupt:
-            break
+                    # if STATUS.get('load_enabled'):
+                    #    write(wd, CMD_DISABLE_LOAD)
+                    # else:
+                    #    write(wd, CMD_ENABLE_LOAD)
+
+            except btle.BTLEDisconnectError:
+                log("ERROR: Disconnected")
+                time.sleep(1)
+
+    except (KeyboardInterrupt, SystemExit, Exception) as e:
+        for consumer in consumers:
+            consumer.exit()
+
+        if type(e) is not KeyboardInterrupt:
+            raise
diff --git a/test_config.py b/test_config.py
index a0f9e3f..e555bb7 100644
--- a/test_config.py
+++ b/test_config.py
@@ -2,7 +2,7 @@
 import importlib
 import os
 from time import sleep
-from typing import Any, Dict, Optional, Type
+from typing import Any, Dict, List, Optional, Type
 
 import yaml
 
@@ -14,8 +14,8 @@ def get_consumer(name: str) -> Optional[Type[BaseConsumer]]:
 
     mod = importlib.import_module(f"consumers.{mod_name}")
 
-    print(mod)
-    print(dir(mod))
+    # print(mod)
+    # print(dir(mod))
     res = getattr(mod, cls_name)
     assert issubclass(res, BaseConsumer)
 
@@ -36,29 +36,37 @@ def write_config(conf: Dict[str, Any]):
     os.rename(".config.yaml~writing", "config.yaml")
 
 
-conf = get_config()
+def get_consumers(conf: Optional[Dict[str, Any]] = None) -> List[BaseConsumer]:
+    if conf is None:
+        conf = get_config()
 
-consumers = []
-for name, consumer_config in conf["consumers"].items():
-    print(name, consumer_config)
-    mod = get_consumer(name)
-    if mod:
-        print(mod)
-        consumers.append(mod(consumer_config))
-
-write_config(conf)
-
-
-try:
-    while True:
-        for consumer in consumers:
-            consumer.poll()
-            sleep(1)
-except (KeyboardInterrupt, SystemExit, Exception) as e:
-    for consumer in consumers:
-        consumer.exit()
-
-    if type(e) is not KeyboardInterrupt:
-        raise
+    consumers = []
+    for name, consumer_config in conf["consumers"].items():
+        # print(name, consumer_config)
+        mod = get_consumer(name)
+        if mod:
+            # print(mod)
+            consumers.append(mod(consumer_config))
 
     write_config(conf)
+    return consumers
+
+
+if __name__ == "__main__":
+    conf = get_config()
+
+    consumers = get_consumers(conf)
+
+    try:
+        while True:
+            for consumer in consumers:
+                consumer.poll()
+                sleep(1)
+    except (KeyboardInterrupt, SystemExit, Exception) as e:
+        for consumer in consumers:
+            consumer.exit()
+
+        if type(e) is not KeyboardInterrupt:
+            raise
+
+        write_config(conf)