Compare commits

..

6 Commits

Author SHA1 Message Date
Stefan Allius
84b4b4c8be update po file 2025-06-22 22:05:14 +02:00
Stefan Allius
b9d1868e4e Merge branch 'main' of https://github.com/s-allius/tsun-gen3-proxy into s-allius/issue443 2025-06-22 21:50:56 +02:00
Stefan Allius
d50f443e2f remove fetch function from network test 2025-06-21 11:17:48 +02:00
Stefan Allius
d33e6e8bb4 Merge branch 'main' of https://github.com/s-allius/tsun-gen3-proxy into s-allius/issue443 2025-06-20 22:30:15 +02:00
Stefan Allius
0e039c4683 Merge branch 'main' of https://github.com/s-allius/tsun-gen3-proxy into s-allius/issue443 2025-06-15 22:45:25 +02:00
Stefan Allius
2b6c71c0bb add page for network test 2025-06-12 23:19:58 +02:00
14 changed files with 88 additions and 62 deletions

View File

@@ -7,12 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [unreleased]
- Update dependency pytest-asyncio to v1.1.0
- save task references, to avoid a task disappearing mid-execution
- catch socket.gaierror exception and log this with info level
- Update dependency coverage to v7.9.2
- add-on: bump base-image to version 18.0.3
- add-on: remove armhf and armv7 support
- add-on: add links to config and log-file to the web-UI
- fix some SonarQube warnings
- remove unused 32-bit architectures

View File

@@ -29,17 +29,17 @@ target "_common" {
"type =sbom,generator=docker/scout-sbom-indexer:latest"
]
annotations = [
"index,manifest-descriptor:org.opencontainers.image.title=TSUN-Proxy",
"index,manifest-descriptor:org.opencontainers.image.authors=Stefan Allius",
"index,manifest-descriptor:org.opencontainers.image.created=${BUILD_DATE}",
"index,manifest-descriptor:org.opencontainers.image.version=${VERSION}",
"index,manifest-descriptor:org.opencontainers.image.revision=${BRANCH}",
"index,manifest-descriptor:org.opencontainers.image.description=${DESCRIPTION}",
"index:org.opencontainers.image.title=TSUN Gen3 Proxy",
"index:org.opencontainers.image.authors=Stefan Allius",
"index:org.opencontainers.image.created=${BUILD_DATE}",
"index:org.opencontainers.image.version=${VERSION}",
"index:org.opencontainers.image.revision=${BRANCH}",
"index:org.opencontainers.image.description=${DESCRIPTION}",
"index:org.opencontainers.image.licenses=BSD-3-Clause",
"index:org.opencontainers.image.source=https://github.com/s-allius/tsun-gen3-proxy"
]
labels = {
"org.opencontainers.image.title" = "TSUN-Proxy"
"org.opencontainers.image.title" = "TSUN Gen3 Proxy"
"org.opencontainers.image.authors" = "Stefan Allius"
"org.opencontainers.image.created" = "${BUILD_DATE}"
"org.opencontainers.image.version" = "${VERSION}"

View File

@@ -1,8 +1,8 @@
flake8==7.3.0
pytest==8.4.1
pytest-asyncio==1.1.0
pytest-cov==6.3.0
python-dotenv==1.1.1
pytest-asyncio==1.0.0
pytest-cov==6.2.1
python-dotenv==1.1.0
mock==5.2.0
coverage==7.9.2
coverage==7.9.1
jinja2-cli==0.8.2

View File

@@ -327,7 +327,6 @@ class SolarmanV5(SolarmanBase):
self.sensor_list = 0
self.mb_regs = [{'addr': 0x3000, 'len': 48},
{'addr': 0x2000, 'len': 96}]
self.background_tasks = set()
'''
Our puplic methods
@@ -340,7 +339,6 @@ class SolarmanV5(SolarmanBase):
self.inverter = None
self.switch.clear()
self.log_lvl.clear()
self.background_tasks.clear()
super().close()
def send_start_cmd(self, snr: int, host: str,
@@ -692,10 +690,8 @@ class SolarmanV5(SolarmanBase):
self.__forward_msg()
def publish_mqtt(self, key, data): # pragma: no cover
task = asyncio.ensure_future(
asyncio.ensure_future(
Proxy.mqtt.publish(key, data))
self.background_tasks.add(task)
task.add_done_callback(self.background_tasks.discard)
def get_cmd_rsp_log_lvl(self) -> int:
ftype = self.ifc.rx_peek()[self.header_len]

View File

@@ -4,7 +4,6 @@ import logging
import traceback
import json
import gc
import socket
from aiomqtt import MqttCodeError
from asyncio import StreamReader, StreamWriter
from ipaddress import ip_address
@@ -39,7 +38,6 @@ class InverterBase(InverterIfc, Proxy):
self.use_emulation = False
self.__ha_restarts = -1
self.remote = StreamPtr(None)
self.background_tasks = set()
ifc = AsyncStreamServer(reader, writer,
self.async_publ_mqtt,
self.create_remote,
@@ -74,7 +72,6 @@ class InverterBase(InverterIfc, Proxy):
if self.remote.ifc:
self.remote.ifc.close()
self.remote.ifc = None
self.background_tasks.clear()
async def disc(self, shutdown_started=False) -> None:
if self.remote.stream:
@@ -139,14 +136,9 @@ class InverterBase(InverterIfc, Proxy):
logging.info(f'[{self.remote.stream.node_id}:'
f'{self.remote.stream.conn_no}] '
f'Connected to {addr}')
task = asyncio.create_task(
self.remote.ifc.client_loop(addr))
self.background_tasks.add(task)
task.add_done_callback(self.background_tasks.discard)
asyncio.create_task(self.remote.ifc.client_loop(addr))
except (ConnectionRefusedError,
TimeoutError,
socket.gaierror) as error:
except (ConnectionRefusedError, TimeoutError) as error:
logging.info(f'{error}')
except Exception:
Infos.inc_counter('SW_Exception')

View File

@@ -43,7 +43,6 @@ class ModbusTcp():
def __init__(self, loop, tim_restart=10) -> None:
self.tim_restart = tim_restart
self.background_tasks = set()
inverters = Config.get('inverters')
batteries = Config.get('batteries')
@@ -55,13 +54,10 @@ class ModbusTcp():
and 'client_mode' in inv):
client = inv['client_mode']
logger.info(f"'client_mode' for Monitoring-SN: {inv['monitor_sn']} host: {client['host']}:{client['port']}, forward: {client['forward']}") # noqa: E501
task = loop.create_task(
self.modbus_loop(client['host'],
client['port'],
inv['monitor_sn'],
client['forward']))
self.background_tasks.add(task)
task.add_done_callback(self.background_tasks.discard)
loop.create_task(self.modbus_loop(client['host'],
client['port'],
inv['monitor_sn'],
client['forward']))
async def modbus_loop(self, host, port,
snr: int, forward: bool) -> None:

View File

@@ -218,7 +218,6 @@ app = Quart(__name__,
static_folder='web/static')
app.secret_key = 'JKLdks.dajlKKKdladkflKwolafallsdfl'
app.jinja_env.globals.update(url_for=url_for)
app.background_tasks = set()
server = Server(app, __name__ == "__main__")
Web(app, server.trans_path, server.rel_urls)
@@ -269,13 +268,9 @@ async def startup_app(): # pragma: no cover
for inv_class, port in [(InverterG3, 5005), (InverterG3P, 10000)]:
logging.info(f'listen on port: {port} for inverters')
task = loop.create_task(
asyncio.start_server(lambda r, w, i=inv_class:
handle_client(r, w, i),
'0.0.0.0', port))
app.background_tasks.add(task)
task.add_done_callback(app.background_tasks.discard)
loop.create_task(asyncio.start_server(lambda r, w, i=inv_class:
handle_client(r, w, i),
'0.0.0.0', port))
ProxyState.set_up(True)
@@ -299,7 +294,6 @@ async def handle_shutdown(): # pragma: no cover
await inverter.disc(True)
logging.info('Proxy disconnecting done')
app.background_tasks.clear()
await Proxy.class_close(loop)

View File

@@ -30,3 +30,9 @@ async def logging():
return await render_template(
'page_logging.html.j2',
fetch_url=url_for('.file_fetch'))
@web.route('/network_tests')
async def network_tests():
return await render_template(
'page_network_tests.html.j2')

View File

@@ -59,6 +59,7 @@
<a href="{{ url_for('.mqtt')}}" class="w3-bar-item w3-button w3-padding {% block menu2_class %}{% endblock %}"><i class="fa fa-database fa-fw"></i>  MQTT</a>
<a href="{{ url_for('.notes')}}" class="w3-bar-item w3-button w3-padding {% block menu3_class %}{% endblock %}"><i class="fa fa-info fa-fw"></i>  {{_('Important Messages')}}</a>
<a href="{{ url_for('.logging')}}" class="w3-bar-item w3-button w3-padding {% block menu4_class %}{% endblock %}"><i class="fa fa-file-export fa-fw"></i>  {{_('Log Files')}}</a>
<a href="{{ url_for('.network_tests')}}" class="w3-bar-item w3-button w3-padding {% block menu5_class %}{% endblock %}"><i class="fa fa-file-export fa-fw"></i>  {{_('Network Tests')}}</a>
{% if hassio is defined %}
<br>
<a href="/hassio/addon/{{addonname}}/config" target="_top" class="w3-bar-item w3-button w3-padding"><i class="fa fa-gear fa-fw"></i>  {{_('Add-on Config')}}</a>

View File

@@ -0,0 +1,31 @@
{% extends 'base.html.j2' %}
{% block title %}{{_("TSUN Proxy - Network Tests")}}{% endblock title %}
{% block menu5_class %}w3-blue{% endblock %}
{% block headline %}<i class="fa fa-file-export fa-fw"></i>  {{_('Network Tests')}}{% endblock headline %}
{% block content %}
<script>
url = "http://127.0.0.1:10000"
const req = new XMLHttpRequest();
req.open("POST", url, true);
//req.setRequestHeader("RESOLVE", "bla.com")
req.onload = (event) => {
// Uploaded
};
const blob = new Blob(["abc123"], { type: "text/plain" });
req.send(blob);
ws = new WebSocket("ws://127.0.0.1:10000");
// ws.open()
ws.onopen = () => {
console.log("Connection opened")
ws.send("Hi server, please send me the score of yesterday's game")
}
</script>
{% endblock content%}
{% block footer %}{% endblock footer %}

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: tsun-gen3-proxy 0.14.0\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2025-05-13 22:34+0200\n"
"POT-Creation-Date: 2025-06-21 10:54+0200\n"
"PO-Revision-Date: 2025-04-18 16:24+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
@@ -75,11 +75,16 @@ msgstr "Wichtige Hinweise"
msgid "Log Files"
msgstr "Log Dateien"
#: src/web/templates/base.html.j2:64
#: src/web/templates/base.html.j2:62
#: src/web/templates/page_network_tests.html.j2:5
msgid "Network Tests"
msgstr ""
#: src/web/templates/base.html.j2:65
msgid "Add-on Config"
msgstr "Add-on Konfiguration"
#: src/web/templates/base.html.j2:65
#: src/web/templates/base.html.j2:66
msgid "Add-on Log"
msgstr "Add-on Protokoll"
@@ -172,6 +177,11 @@ msgstr "Empfangene Topics"
msgid "Number of topics received"
msgstr "Anzahl der empfangenen Topics"
#: src/web/templates/page_network_tests.html.j2:3
#, fuzzy
msgid "TSUN Proxy - Network Tests"
msgstr "TSUN Proxy - Verbindungen"
#: src/web/templates/page_notes.html.j2:3
msgid "TSUN Proxy - Important Messages"
msgstr "TSUN Proxy - Wichtige Hinweise"

View File

@@ -29,23 +29,27 @@ target "_common" {
"type =sbom,generator=docker/scout-sbom-indexer:latest"
]
annotations = [
"index:io.hass.version=${VERSION}",
"index:io.hass.type=addon",
"index:io.hass.arch=aarch64|amd64",
"index,manifest-descriptor:org.opencontainers.image.title=TSUN-Proxy",
"index,manifest-descriptor:org.opencontainers.image.authors=Stefan Allius",
"index,manifest-descriptor:org.opencontainers.image.created=${BUILD_DATE}",
"index,manifest-descriptor:org.opencontainers.image.version=${VERSION}",
"index,manifest-descriptor:org.opencontainers.image.description=${DESCRIPTION}",
"index:io.hass.arch=armhf|aarch64|i386|amd64",
"index:org.opencontainers.image.title=TSUN-Proxy",
"index:org.opencontainers.image.authors=Stefan Allius",
"index:org.opencontainers.image.created=${BUILD_DATE}",
"index:org.opencontainers.image.version=${VERSION}",
"index:org.opencontainers.image.revision=${BRANCH}",
"index:org.opencontainers.image.description=${DESCRIPTION}",
"index:org.opencontainers.image.licenses=BSD-3-Clause",
"index:org.opencontainers.image.source=https://github.com/s-allius/tsun-gen3-proxy/ha_addons/ha_addon",
"index:org.opencontainers.image.source=https://github.com/s-allius/tsun-gen3-proxy/ha_addons/ha_addon"
]
labels = {
"io.hass.version" = "${VERSION}"
"io.hass.type" = "addon"
"io.hass.arch" = "aarch64|amd64"
"io.hass.arch" = "armhf|aarch64|i386|amd64"
"org.opencontainers.image.title" = "TSUN-Proxy"
"org.opencontainers.image.authors" = "Stefan Allius"
"org.opencontainers.image.created" = "${BUILD_DATE}"
"org.opencontainers.image.version" = "${VERSION}"
"org.opencontainers.image.revision" = "${BRANCH}"
"org.opencontainers.image.description" = "${DESCRIPTION}"
"org.opencontainers.image.licenses" = "BSD-3-Clause"
"org.opencontainers.image.source" = "https://github.com/s-allius/tsun-gen3-proxy/ha_addonsha_addon"

View File

@@ -13,12 +13,12 @@
# 1 Build Base Image #
######################
ARG BUILD_FROM="ghcr.io/hassio-addons/base:18.0.3"
ARG BUILD_FROM="ghcr.io/hassio-addons/base:17.2.5"
# hadolint ignore=DL3006
FROM $BUILD_FROM AS base
# Installiere Python, pip und virtuelle Umgebungstools
RUN apk add --no-cache python3=3.12.11-r0 py3-pip=25.1.1-r0 && \
RUN apk add --no-cache python3=3.12.10-r1 py3-pip=24.3.1-r0 && \
python -m venv /opt/venv && \
. /opt/venv/bin/activate

View File

@@ -10,6 +10,8 @@ init: false
arch:
- aarch64
- amd64
- armhf
- armv7
startup: services
homeassistant_api: true
map: