From b755ba46396358cd67b8578d83133a0aeec2d212 Mon Sep 17 00:00:00 2001 From: Dirk Tostmann Date: Wed, 21 Feb 2024 22:52:19 +0100 Subject: [PATCH 1/4] added support for TCP dongle --- enoceanmqtt/communicator.py | 11 +++++- enoceanmqtt/tcpclientcommunicator.py | 53 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 enoceanmqtt/tcpclientcommunicator.py diff --git a/enoceanmqtt/communicator.py b/enoceanmqtt/communicator.py index cdea24c..75ddd5d 100644 --- a/enoceanmqtt/communicator.py +++ b/enoceanmqtt/communicator.py @@ -8,6 +8,7 @@ import platform from enocean.communicators.serialcommunicator import SerialCommunicator +from enoceanmqtt.tcpclientcommunicator import TCPClientCommunicator from enocean.protocol.packet import RadioPacket from enocean.protocol.constants import PACKET, RETURN_CODE, RORG import enocean.utils @@ -65,7 +66,15 @@ def __init__(self, config, sensors): self.mqtt.loop_start() # setup enocean communication - self.enocean = SerialCommunicator(self.conf['enocean_port']) + eport = self.conf['enocean_port'] + seport = eport.split(':') + if seport[0] == "tcp": + logging.info("connecting TCPClient to %s port %d", seport[1],int(seport[2])) + self.enocean = TCPClientCommunicator(seport[1],int(seport[2])) + else: + logging.info("connecting Serial to %s", eport) + self.enocean = SerialCommunicator(eport) + self.enocean.start() # sender will be automatically determined self.enocean_sender = None diff --git a/enoceanmqtt/tcpclientcommunicator.py b/enoceanmqtt/tcpclientcommunicator.py new file mode 100644 index 0000000..ce4095b --- /dev/null +++ b/enoceanmqtt/tcpclientcommunicator.py @@ -0,0 +1,53 @@ +# -*- encoding: utf-8 -*- +from __future__ import print_function, unicode_literals, division, absolute_import +import logging +import socket +import time + + +from enocean.communicators.communicator import Communicator + + +class TCPClientCommunicator(Communicator): + ''' Socket communicator class for EnOcean radio ''' + logger = logging.getLogger('enocean.communicators.TCPClientCommunicator') + + def __init__(self, host='', port=9637): + super(TCPClientCommunicator, self).__init__() + self.host = host + self.port = port + self.sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM) + + def run(self): + self.logger.info('TCPClientCommunicator started') + self.sock.settimeout(0.5) + try: + self.sock.connect(( self.host, self.port)) + except socket.error as e: + self.logger.error('Exception occured while connecting: ' + str(e)) + self.stop() + + while not self._stop_flag.is_set(): + # If there's messages in transmit queue + # send them + while True: + packet = self._get_from_send_queue() + if not packet: + break + try: + self.sock.send(bytearray(packet.build())) + except Exception as e: + self.logger.error('Exception occured while sending: ' + str(e)) + self.stop() + + try: + self._buffer.extend(bytearray(self.sock.recv(16))) + self.parse() + except socket.timeout: + time.sleep(0) + except Exception as e: + self.logger.error('Exception occured while parsing: ' + str(e)) + time.sleep(0) + + self.sock.close() + self.logger.info('TCPClientCommunicator stopped') From a495eba829763e5f2a04abd4220180522a3a7ce3 Mon Sep 17 00:00:00 2001 From: Dirk Tostmann Date: Thu, 22 Feb 2024 01:25:53 +0100 Subject: [PATCH 2/4] added kind of ping to check socket working --- enoceanmqtt/tcpclientcommunicator.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/enoceanmqtt/tcpclientcommunicator.py b/enoceanmqtt/tcpclientcommunicator.py index ce4095b..03cc4b0 100644 --- a/enoceanmqtt/tcpclientcommunicator.py +++ b/enoceanmqtt/tcpclientcommunicator.py @@ -6,6 +6,8 @@ from enocean.communicators.communicator import Communicator +from enocean.protocol.constants import PACKET +from enocean.protocol.packet import Packet class TCPClientCommunicator(Communicator): @@ -21,6 +23,8 @@ def __init__(self, host='', port=9637): def run(self): self.logger.info('TCPClientCommunicator started') self.sock.settimeout(0.5) + pinged = time.time() + try: self.sock.connect(( self.host, self.port)) except socket.error as e: @@ -36,6 +40,7 @@ def run(self): break try: self.sock.send(bytearray(packet.build())) + pinged = time.time() except Exception as e: self.logger.error('Exception occured while sending: ' + str(e)) self.stop() @@ -47,7 +52,11 @@ def run(self): time.sleep(0) except Exception as e: self.logger.error('Exception occured while parsing: ' + str(e)) + time.sleep(0) - + if time.time() > pinged + 60: + self.send(Packet(PACKET.COMMON_COMMAND, data=[0x08])) + pinged = time.time() + self.sock.close() self.logger.info('TCPClientCommunicator stopped') From 8fa852156262dd35c5984d5ebac00ca10b622b4a Mon Sep 17 00:00:00 2001 From: Dirk Tostmann Date: Thu, 22 Feb 2024 09:55:58 +0100 Subject: [PATCH 3/4] re-worked main loop to terminate process properly on connecting issues --- enoceanmqtt/communicator.py | 6 +----- enoceanmqtt/tcpclientcommunicator.py | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/enoceanmqtt/communicator.py b/enoceanmqtt/communicator.py index 75ddd5d..6a10817 100644 --- a/enoceanmqtt/communicator.py +++ b/enoceanmqtt/communicator.py @@ -541,11 +541,7 @@ def run(self): # Loop to empty the queue... try: # get next packet - if platform.system() == 'Windows': - # only timeout on Windows for KeyboardInterrupt checking - packet = self.enocean.receive.get(block=True, timeout=1) - else: - packet = self.enocean.receive.get(block=True) + packet = self.enocean.receive.get(block=True, timeout=1) # check packet type if packet.packet_type == PACKET.RADIO: diff --git a/enoceanmqtt/tcpclientcommunicator.py b/enoceanmqtt/tcpclientcommunicator.py index 03cc4b0..5b767ef 100644 --- a/enoceanmqtt/tcpclientcommunicator.py +++ b/enoceanmqtt/tcpclientcommunicator.py @@ -1,3 +1,4 @@ + # -*- encoding: utf-8 -*- from __future__ import print_function, unicode_literals, division, absolute_import import logging @@ -50,6 +51,9 @@ def run(self): self.parse() except socket.timeout: time.sleep(0) + except ConnectionResetError as e: + self.logger.error('Exception occured while recv: ' + str(e)) + self.stop() except Exception as e: self.logger.error('Exception occured while parsing: ' + str(e)) From 5c0c9ba06f86fb7d919210c570647a27ef452a98 Mon Sep 17 00:00:00 2001 From: Dirk Tostmann Date: Thu, 22 Feb 2024 10:49:01 +0100 Subject: [PATCH 4/4] tuned connection timeouts --- enoceanmqtt/tcpclientcommunicator.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/enoceanmqtt/tcpclientcommunicator.py b/enoceanmqtt/tcpclientcommunicator.py index 5b767ef..69c61e0 100644 --- a/enoceanmqtt/tcpclientcommunicator.py +++ b/enoceanmqtt/tcpclientcommunicator.py @@ -23,15 +23,17 @@ def __init__(self, host='', port=9637): def run(self): self.logger.info('TCPClientCommunicator started') - self.sock.settimeout(0.5) + self.sock.settimeout(3) pinged = time.time() try: self.sock.connect(( self.host, self.port)) - except socket.error as e: + except Exception as e: self.logger.error('Exception occured while connecting: ' + str(e)) self.stop() + self.sock.settimeout(0.5) + while not self._stop_flag.is_set(): # If there's messages in transmit queue # send them @@ -58,7 +60,7 @@ def run(self): self.logger.error('Exception occured while parsing: ' + str(e)) time.sleep(0) - if time.time() > pinged + 60: + if time.time() > pinged + 30: self.send(Packet(PACKET.COMMON_COMMAND, data=[0x08])) pinged = time.time()