diff --git a/CHANGELOG.md b/CHANGELOG.md index fb3d0ea..4aa1173 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +- 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 diff --git a/app/src/gen3plus/solarman_v5.py b/app/src/gen3plus/solarman_v5.py index 76d9297..8a82bb2 100755 --- a/app/src/gen3plus/solarman_v5.py +++ b/app/src/gen3plus/solarman_v5.py @@ -327,6 +327,7 @@ 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 @@ -339,6 +340,7 @@ 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, @@ -690,8 +692,10 @@ class SolarmanV5(SolarmanBase): self.__forward_msg() def publish_mqtt(self, key, data): # pragma: no cover - asyncio.ensure_future( + task = 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] diff --git a/app/src/inverter_base.py b/app/src/inverter_base.py index d35ddcd..9166100 100644 --- a/app/src/inverter_base.py +++ b/app/src/inverter_base.py @@ -39,6 +39,7 @@ 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, @@ -73,6 +74,7 @@ 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: @@ -137,7 +139,10 @@ class InverterBase(InverterIfc, Proxy): logging.info(f'[{self.remote.stream.node_id}:' f'{self.remote.stream.conn_no}] ' f'Connected to {addr}') - asyncio.create_task(self.remote.ifc.client_loop(addr)) + task = asyncio.create_task( + self.remote.ifc.client_loop(addr)) + self.background_tasks.add(task) + task.add_done_callback(self.background_tasks.discard) except (ConnectionRefusedError, TimeoutError, diff --git a/app/src/modbus_tcp.py b/app/src/modbus_tcp.py index f51eef0..b702801 100644 --- a/app/src/modbus_tcp.py +++ b/app/src/modbus_tcp.py @@ -43,6 +43,7 @@ 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') @@ -54,10 +55,13 @@ 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 - loop.create_task(self.modbus_loop(client['host'], - client['port'], - inv['monitor_sn'], - client['forward'])) + 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) async def modbus_loop(self, host, port, snr: int, forward: bool) -> None: diff --git a/app/src/server.py b/app/src/server.py index fac746b..5eb75dc 100644 --- a/app/src/server.py +++ b/app/src/server.py @@ -218,6 +218,7 @@ 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) @@ -268,9 +269,13 @@ 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') - loop.create_task(asyncio.start_server(lambda r, w, i=inv_class: - handle_client(r, w, i), - '0.0.0.0', port)) + 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) + ProxyState.set_up(True) @@ -294,6 +299,7 @@ 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)