Compare commits

...

4 Commits

Author SHA1 Message Date
Stefan Allius
bb39567d05 Version 0.5.2 2023-11-09 20:05:56 +01:00
Stefan Allius
b6431f8448 improve client conn disconection
- check for race cond. on closing and establishing
  client connections
- improve connection trace
2023-11-09 20:03:09 +01:00
Stefan Allius
714dd92f35 allow multiple calls to Message.close() 2023-11-08 18:57:56 +01:00
Stefan Allius
02861f70af - add int64 data type to info parser 2023-11-07 00:19:48 +01:00
5 changed files with 36 additions and 15 deletions

View File

@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.5.2] - 2023-11-09
- add int64 data type to info parser
- allow multiple calls to Message.close()
- check for race cond. on closing and establishing client connections
## [0.5.1] - 2023-11-05
- fixes f-string by limes007

View File

@@ -16,11 +16,15 @@ class AsyncStream(Message):
self.writer = writer
self.remoteStream = remote_stream
self.addr = addr
self.r_addr = ''
self.l_addr = ''
'''
Our puplic methods
'''
async def loop(self) -> None:
async def loop(self):
self.r_addr = self.writer.get_extra_info('peername')
self.l_addr = self.writer.get_extra_info('sockname')
while True:
try:
@@ -35,26 +39,27 @@ class AsyncStream(Message):
ConnectionAbortedError,
BrokenPipeError,
RuntimeError) as error:
logger.warning(f'In loop for {self.addr}: {error}')
logger.warning(f'In loop for l{self.l_addr} | '
f'r{self.r_addr}: {error}')
self.close()
return
return self
except Exception:
logger.error(
f"Exception for {self.addr}:\n"
f"{traceback.format_exc()}")
self.close()
return
return self
def disc(self) -> None:
logger.debug(f'in AsyncStream.disc() {self.addr}')
logger.debug(f'in AsyncStream.disc() l{self.l_addr} | r{self.r_addr}')
self.writer.close()
def close(self):
logger.debug(f'in AsyncStream.close() {self.addr}')
logger.debug(f'in AsyncStream.close() l{self.l_addr} | r{self.r_addr}')
self.writer.close()
super().close() # call close handler in the parent class
# logger.info (f'AsyncStream refs: {gc.get_referrers(self)}')
# logger.info(f'AsyncStream refs: {gc.get_referrers(self)}')
'''
Our private methods
@@ -96,4 +101,4 @@ class AsyncStream(Message):
pass
def __del__(self):
logging.debug(f"AsyncStream.__del__ {self.addr}")
logging.debug(f"AsyncStream.__del__ l{self.l_addr} | r{self.r_addr}")

View File

@@ -341,6 +341,9 @@ class Infos:
elif data_type == 0x46: # 'F' -> float32
result = round(struct.unpack_from('!f', buf, ind)[0], 2)
ind += 4
elif data_type == 0x4c: # 'L' -> int64
result = struct.unpack_from('!q', buf, ind)[0]
ind += 8
else:
self.inc_counter('Invalid_Data_Type')
logging.error(f"Infos.parse: data_type: {data_type}"

View File

@@ -107,7 +107,7 @@ class Inverter(AsyncStream):
self.inc_counter('Inverter_Cnt')
await self.loop()
self.dec_counter('Inverter_Cnt')
logging.info(f'Server loop stopped for {addr}')
logging.info(f'Server loop stopped for r{self.r_addr}')
# if the server connection closes, we also have to disconnect
# the connection to te TSUN cloud
@@ -121,15 +121,22 @@ class Inverter(AsyncStream):
async def client_loop(self, addr):
'''Loop for receiving messages from the TSUN cloud (client-side)'''
await self.remoteStream.loop()
logging.info(f'Client loop stopped for {addr}')
clientStream = await self.remoteStream.loop()
logging.info(f'Client loop stopped for l{clientStream.l_addr}')
# if the client connection closes, we don't touch the server
# connection. Instead we erase the client connection stream,
# thus on the next received packet from the inverter, we can
# establish a new connection to the TSUN cloud
self.remoteStream.remoteStream = None # erase backlink to inverter
self.remoteStream = None # than erase client connection
# erase backlink to inverter
clientStream.remoteStream = None
if self.remoteStream == clientStream:
# logging.debug(f'Client l{clientStream.l_addr} refs:'
# f' {gc.get_referrers(clientStream)}')
# than erase client connection
self.remoteStream = None
async def async_create_remote(self) -> None:
'''Establish a client connection to the TSUN cloud'''
@@ -197,7 +204,7 @@ class Inverter(AsyncStream):
f"/{node_id}{id}/config", data_json)
def close(self) -> None:
logging.debug(f'Inverter.close() {self.addr}')
logging.debug(f'Inverter.close() l{self.l_addr} | r{self.r_addr}')
super().close() # call close handler in the parent class
# logger.debug (f'Inverter refs: {gc.get_referrers(self)}')

View File

@@ -110,7 +110,7 @@ class Message(metaclass=IterRegistry):
# we have refernces to methods of this class in self.switch
# so we have to erase self.switch, otherwise this instance can't be
# deallocated by the garbage collector ==> we get a memory leak
del self.switch
self.switch.clear()
def inc_counter(self, counter: str) -> None:
self.db.inc_counter(counter)