diff --git a/app/src/mqtt.py b/app/src/mqtt.py index 0d33cac..e106ed2 100644 --- a/app/src/mqtt.py +++ b/app/src/mqtt.py @@ -7,13 +7,18 @@ from modbus import Modbus from messages import Message from cnf.config import Config from singleton import Singleton +from datetime import datetime + logger_mqtt = logging.getLogger('mqtt') class Mqtt(metaclass=Singleton): - __client = None + __client: aiomqtt.Client = None __cb_mqtt_is_up = None + ctime = None + published: int = 0 + received: int = 0 def __init__(self, cb_mqtt_is_up): logger_mqtt.debug('MQTT: __init__') @@ -52,6 +57,7 @@ class Mqtt(metaclass=Singleton): | int | float | None = None) -> None: if self.__client: await self.__client.publish(topic, payload) + self.published += 1 async def __loop(self) -> None: mqtt = Config.get('mqtt') @@ -69,6 +75,9 @@ class Mqtt(metaclass=Singleton): try: async with self.__client: logger_mqtt.info('MQTT broker connection established') + self.ctime = datetime.now() + self.published = 0 + self.received = 0 if self.__cb_mqtt_is_up: await self.__cb_mqtt_is_up() @@ -82,8 +91,11 @@ class Mqtt(metaclass=Singleton): async for message in self.__client.messages: await self.dispatch_msg(message) + self.received += 1 except aiomqtt.MqttError: + self.ctime = None + if Config.is_default('mqtt'): logger_mqtt.info( "MQTT is unconfigured; Check your config.toml!") @@ -101,6 +113,7 @@ class Mqtt(metaclass=Singleton): return except Exception: # self.inc_counter('SW_Exception') # fixme + self.ctime = None logger_mqtt.error( f"Exception:\n" f"{traceback.format_exc()}") diff --git a/app/src/web/mqtt_table.py b/app/src/web/mqtt_table.py new file mode 100644 index 0000000..44ef0bc --- /dev/null +++ b/app/src/web/mqtt_table.py @@ -0,0 +1,83 @@ +from inverter_base import InverterBase +from quart import render_template +from quart_babel import format_datetime, _ +from infos import Infos +from mqtt import Mqtt + +from . import web + + +def _get_device_icon(client_mode: bool): + '''returns the icon for the device conntection''' + if client_mode: + return 'fa-download fa-rotate-180' + + return 'fa-upload fa-rotate-180' + + +def _get_cloud_icon(emu_mode: bool): + '''returns the icon for the cloud conntection''' + if emu_mode: + return 'fa-cloud-arrow-up-alt' + + return 'fa-cloud' + + +def _get_row(inv: InverterBase): + '''build one row for the connection table''' + client_mode = inv.client_mode + inv_serial = inv.local.stream.inv_serial + icon1 = _get_device_icon(client_mode) + ip1, port1 = inv.addr + icon2 = '' + ip2 = '--' + port2 = '--' + + if inv.remote.ifc: + ip2, port2 = inv.remote.ifc.r_addr + icon2 = _get_cloud_icon(client_mode) + + row = [] + row.append(f' {ip1}:{port1}') + row.append(f' {ip1}') + row.append(inv_serial) + row.append(f' {ip2}:{port2}') + row.append(f' {ip2}') + return row + + +def get_table_data(): + '''build the connection table''' + table = { + "col_classes": [ + "w3-hide-small w3-hide-medium", "w3-hide-large", + "", + "w3-hide-small w3-hide-medium", "w3-hide-large", + ], + "thead": [[ + _('Device-IP:Port'), _('Device-IP'), + _("Serial-No"), + _("Cloud-IP:Port"), _("Cloud-IP") + ]], + "tbody": [] + } + for inverter in InverterBase: + table['tbody'].append(_get_row(inverter)) + + return table + + +@web.route('/mqtt-fetch') +async def mqtt_fetch(): + mqtt = Mqtt() + ctime = format_datetime(dt=mqtt.ctime, format='short') + data = { + "update-time": format_datetime(format="medium"), + "mqtt-ctime": f"