add MQTT page

This commit is contained in:
Stefan Allius
2025-05-03 16:27:59 +02:00
parent f799bf9a17
commit d1b21abc4d
5 changed files with 154 additions and 13 deletions

View File

@@ -7,13 +7,18 @@ from modbus import Modbus
from messages import Message from messages import Message
from cnf.config import Config from cnf.config import Config
from singleton import Singleton from singleton import Singleton
from datetime import datetime
logger_mqtt = logging.getLogger('mqtt') logger_mqtt = logging.getLogger('mqtt')
class Mqtt(metaclass=Singleton): class Mqtt(metaclass=Singleton):
__client = None __client: aiomqtt.Client = None
__cb_mqtt_is_up = None __cb_mqtt_is_up = None
ctime = None
published: int = 0
received: int = 0
def __init__(self, cb_mqtt_is_up): def __init__(self, cb_mqtt_is_up):
logger_mqtt.debug('MQTT: __init__') logger_mqtt.debug('MQTT: __init__')
@@ -52,6 +57,7 @@ class Mqtt(metaclass=Singleton):
| int | float | None = None) -> None: | int | float | None = None) -> None:
if self.__client: if self.__client:
await self.__client.publish(topic, payload) await self.__client.publish(topic, payload)
self.published += 1
async def __loop(self) -> None: async def __loop(self) -> None:
mqtt = Config.get('mqtt') mqtt = Config.get('mqtt')
@@ -69,6 +75,9 @@ class Mqtt(metaclass=Singleton):
try: try:
async with self.__client: async with self.__client:
logger_mqtt.info('MQTT broker connection established') logger_mqtt.info('MQTT broker connection established')
self.ctime = datetime.now()
self.published = 0
self.received = 0
if self.__cb_mqtt_is_up: if self.__cb_mqtt_is_up:
await 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: async for message in self.__client.messages:
await self.dispatch_msg(message) await self.dispatch_msg(message)
self.received += 1
except aiomqtt.MqttError: except aiomqtt.MqttError:
self.ctime = None
if Config.is_default('mqtt'): if Config.is_default('mqtt'):
logger_mqtt.info( logger_mqtt.info(
"MQTT is unconfigured; Check your config.toml!") "MQTT is unconfigured; Check your config.toml!")
@@ -101,6 +113,7 @@ class Mqtt(metaclass=Singleton):
return return
except Exception: except Exception:
# self.inc_counter('SW_Exception') # fixme # self.inc_counter('SW_Exception') # fixme
self.ctime = None
logger_mqtt.error( logger_mqtt.error(
f"Exception:\n" f"Exception:\n"
f"{traceback.format_exc()}") f"{traceback.format_exc()}")

83
app/src/web/mqtt_table.py Normal file
View File

@@ -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'<i class="fa {icon1}"></i> {ip1}:{port1}')
row.append(f'<i class="fa {icon1}"></i> {ip1}')
row.append(inv_serial)
row.append(f'<i class="fa {icon2}"></i> {ip2}:{port2}')
row.append(f'<i class="fa {icon2}"></i> {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"<h3>{ctime}</h3>",
"mqtt-tx": f"<h3>{mqtt.published}</h3>",
"mqtt-rx": f"<h3>{mqtt.received}</h3>",
}
# data["conn-table"] = await render_template('templ_conn_table.html.j2',
# table=get_table_data())
return data

View File

@@ -11,9 +11,11 @@ async def index():
fetch_url=url_for('.data_fetch')) fetch_url=url_for('.data_fetch'))
@web.route('/page') @web.route('/mqtt')
async def empty(): async def mqtt():
return await render_template('empty.html.j2') return await render_template(
'page_mqtt.html.j2',
fetch_url=url_for('.mqtt_fetch'))
@web.route('/logging') @web.route('/logging')

View File

@@ -1,9 +0,0 @@
{% extends 'base.html.j2' %}
{% block title %} TSUN Proxy - View {% endblock title%}
{% block menu2_class %}w3-blue{% endblock %}
{% block content %}
{% endblock content%}
{% block footer %}{% endblock footer %}

View File

@@ -0,0 +1,52 @@
{% extends 'base.html.j2' %}
{% block title %} TSUN Proxy - MQTT Status {% endblock title%}
{% block menu2_class %}w3-blue{% endblock %}
{% block headline %}<i class="fa fa-database"></i>  {{_('MQTT Overview')}}{% endblock headline %}
{% block content %}
<div class="w3-row-padding w3-margin-bottom">
<div class="w3-third">
<div class="w3-card-4">
<div class="w3-container w3-indigo w3-padding-16">
<div class="w3-left"><i class="fa fa-link w3-xxxlarge"></i></div>
<div id = "mqtt-ctime" class="w3-right">
<h3>-</h3>
</div>
<div class="w3-clear"></div>
<h4>{{_('MQTT Connect Time')}}</h4>
<div class="w3-hide-small w3-hide-medium" style="min-height:50px">{{_('Forwarding data to cloud')}}</div>
</div>
</div>
</div>
<div class="w3-third">
<div class="w3-card-4">
<div class="w3-container w3-purple w3-padding-16">
<div class="w3-left"><i class="fa fa-server w3-xxxlarge"></i></div>
<div id = "mqtt-tx" class="w3-right">
<h3>-</h3>
</div>
<div class="w3-clear"></div>
<h4>{{_('MQTT Published Topics')}}</h4>
<div class="w3-hide-small w3-hide-medium" style="min-height:50px">{{_('Established from device to proxy')}}</div>
</div>
</div>
</div>
<div class="w3-third">
<div class="w3-card-4">
<div class="w3-container w3-orange w3-text-white w3-padding-16">
<div class="w3-left"><i class="fa fa-user w3-xxxlarge"></i></div>
<div id = "mqtt-rx" class="w3-right">
<h3>-</h3>
</div>
<div class="w3-clear"></div>
<h4>{{_('MQTT Received Topics')}}</h4>
<div class="w3-hide-small w3-hide-medium" style="min-height:50px">{{_('Established from proxy to device')}}</div>
</div>
</div>
</div>
</div>
{% endblock content%}
{% block footer %}{% endblock footer %}