From 7bf8f12b85ccba29637bb48749bf76202c434326 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 7 Jul 2024 17:20:51 +0200 Subject: [PATCH 01/14] SDP: propose resend protocol --- lib/model/sdp/connection.py | 26 ++++++++++ lib/model/sdp/globals.py | 9 +++- lib/model/sdp/protocol.py | 90 +++++++++++++++++++++++++++++++++- lib/model/smartdeviceplugin.py | 13 ++++- 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/lib/model/sdp/connection.py b/lib/model/sdp/connection.py index ab584d3ff..01b615538 100644 --- a/lib/model/sdp/connection.py +++ b/lib/model/sdp/connection.py @@ -209,6 +209,18 @@ def on_disconnect(self, by=None): if self._params[PLUGIN_ATTR_CB_ON_DISCONNECT]: self._params[PLUGIN_ATTR_CB_ON_DISCONNECT](by) + def store_commands(self, resend_info): + """ + storing commands, e.g. for resend feature + """ + return self._store_commands(resend_info) + + def check_commands(self, command, value): + """ + storing commands, e.g. for resend feature + """ + return self._check_commands(command, value) + # # # overwriting needed for at least some of the following methods... @@ -239,6 +251,20 @@ def _send(self, data_dict): self.logger.debug(f'simulating to send data {data_dict}...') return self.dummy + def _store_commands(self, resend_info): + """ + overwrite with storing of data + Return None by default + """ + return False + + def _check_commands(self, command, value): + """ + overwrite with storing of data + Return None by default + """ + return False + def _send_init_on_open(self): """ This class can be overwritten if anything special is needed to make the diff --git a/lib/model/sdp/globals.py b/lib/model/sdp/globals.py index 4247c96a1..f43bb6f48 100644 --- a/lib/model/sdp/globals.py +++ b/lib/model/sdp/globals.py @@ -60,6 +60,9 @@ PLUGIN_ATTR_CONN_RETRY_CYCLE = 'retry_cycle' # if autoreconnect: how many seconds to wait between retry rounds PLUGIN_ATTR_CONN_RETRY_SUSPD = 'retry_suspend' # after this number of failed connect cycles, activate suspend mode (if enabled) +PLUGIN_ATTR_SEND_RETRIES = 'send_retries' # how often should a command be resent (when not receiving expected answer) +PLUGIN_ATTR_SEND_RETRIES_CYCLE= 'send_retries_cycle' # if using resend protocol: how many seconds to wait between resend rounds + # network attributes PLUGIN_ATTR_NET_HOST = 'host' # hostname / IP for network connection PLUGIN_ATTR_NET_PORT = 'port' # port for network connection @@ -88,7 +91,8 @@ PLUGIN_ATTR_CONN_RETRY_CYCLE, PLUGIN_ATTR_CONN_RETRY_SUSPD, PLUGIN_ATTR_NET_HOST, PLUGIN_ATTR_NET_PORT, PLUGIN_ATTR_SERIAL_PORT, PLUGIN_ATTR_SERIAL_BAUD, PLUGIN_ATTR_SERIAL_BSIZE, PLUGIN_ATTR_SERIAL_PARITY, PLUGIN_ATTR_SERIAL_STOP, PLUGIN_ATTR_PROTOCOL, PLUGIN_ATTR_MSG_TIMEOUT, PLUGIN_ATTR_MSG_REPEAT, - PLUGIN_ATTR_CB_ON_CONNECT, PLUGIN_ATTR_CB_ON_DISCONNECT, PLUGIN_ATTR_CB_SUSPEND) + PLUGIN_ATTR_CB_ON_CONNECT, PLUGIN_ATTR_CB_ON_DISCONNECT, PLUGIN_ATTR_CB_SUSPEND, + PLUGIN_ATTR_SEND_RETRIES, PLUGIN_ATTR_SEND_RETRIES_CYCLE) # connection types for PLUGIN_ATTR_CONNECTION CONN_NULL = '' # use base connection class without real connection functionality, for testing @@ -105,8 +109,9 @@ PROTO_NULL = '' # use base protocol class without added functionality (why??) PROTO_JSONRPC = 'jsonrpc' # JSON-RPC 2.0 support with send queue, msgid and resend of unanswered commands PROTO_VIESSMANN = 'viessmann' # Viessmann P300 / KW +PROTO_RESEND = 'resend' -PROTOCOL_TYPES = (PROTO_NULL, PROTO_JSONRPC, PROTO_VIESSMANN) +PROTOCOL_TYPES = (PROTO_NULL, PROTO_JSONRPC, PROTO_VIESSMANN, PROTO_RESEND) # item attribute suffixes (as defined with individual prefix in plugin.yaml) ITEM_ATTR_COMMAND = '_command' # command to issue/read for the item diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 7e6d7d33b..42f88dca8 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -31,7 +31,7 @@ PLUGIN_ATTR_CB_ON_DISCONNECT, PLUGIN_ATTR_CONNECTION, PLUGIN_ATTR_CONN_AUTO_CONN, PLUGIN_ATTR_CONN_CYCLE, PLUGIN_ATTR_CONN_RETRIES, PLUGIN_ATTR_CONN_TIMEOUT, PLUGIN_ATTR_MSG_REPEAT, PLUGIN_ATTR_MSG_TIMEOUT, - PLUGIN_ATTR_NET_HOST, PLUGIN_ATTR_NET_PORT) + PLUGIN_ATTR_NET_HOST, PLUGIN_ATTR_NET_PORT, PLUGIN_ATTR_SEND_RETRIES, PLUGIN_ATTR_SEND_RETRIES_CYCLE) from lib.model.sdp.connection import SDPConnection from collections import OrderedDict @@ -425,3 +425,91 @@ def _send_rpc_message(self, command, ddict=None, message_id=None, repeat=0): response = self._connection.send(ddict) if response: self.on_data_received('request', response) + + +class SDPProtocolResend(SDPProtocol): + """ Protocol providing resend option + + + """ + + def __init__(self, data_received_callback, name=None, **kwargs): + + # init super, get logger + super().__init__(data_received_callback, name, **kwargs) + + self._send_retries = int(self._params.get(PLUGIN_ATTR_SEND_RETRIES) or 0) + self._send_retries_cycle = int(self._params.get(PLUGIN_ATTR_SEND_RETRIES_CYCLE) or 1) + self._sending = {} + self._sending_retries = {} + self._sending_lock = threading.Lock() + + # tell someone about our actual class + self.logger.debug(f'protocol initialized from {self.__class__.__name__}') + + def _open(self): + if self._plugin.scheduler_get('resend'): + self._plugin.scheduler_remove('resend') + if self._send_retries >= 1: + self._plugin.scheduler_add('resend', self._resend, cycle=self._send_retries_cycle) + self.logger.dbghigh( + f"Adding resend scheduler with cycle {self._send_retries_cycle}.") + super()._open() + + def _close(self): + if self._plugin.scheduler_get('resend'): + self._plugin.scheduler_remove('resend') + super()._close() + + def _store_commands(self, resend_info): + """ + overwrite with storing of data + Return None by default + """ + if resend_info is None: + resend_info = {} + if resend_info.get('returnvalue') is not None: + self._sending.update({resend_info.get('command'): resend_info}) + return True + return False + + def _check_commands(self, command, value): + returnvalue = False + if command in self._sending: + self._sending_lock.acquire(True, 2) + retry = self._sending[command].get("retry") or 0 + compare = self._sending[command].get('returnvalue') + if self._sending[command].get('returntype')(value) == compare: + self._sending.pop(command) + self._sending_retries.pop(command) + self.logger.debug(f'Correct answer for {command}, removing from send. Sending {self._sending}') + returnvalue = True + elif retry is not None and retry <= self._send_retries: + self.logger.debug(f'Should send again {self._sending}...') + if self._sending_lock.locked(): + self._sending_lock.release() + return returnvalue + + def _resend(self): + self.logger.info(f"resending queue is {self._sending} retries {self._sending_retries}") + self._sending_lock.acquire(True, 2) + remove_commands = [] + for command in list(self._sending.keys()): + retry = self._sending_retries.get(command, 0) + sent = True + if retry < self._send_retries: + self.logger.debug(f'Re-sending {command}, retry {retry}.') + sent = self._connection.send(self._sending[command].get("data_dict")) + self._sending_retries[command] = retry + 1 + elif retry >= self._send_retries: + sent = False + if sent is False: + remove_commands.append(command) + self.logger.info(f"Giving up re-sending {command} after {retry} retries.") + for command in remove_commands: + self._sending.pop(command) + self._sending_retries.pop(command) + if self._sending_lock.locked(): + self._sending_lock.release() + + diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index efa925f1c..70e0907b1 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -56,7 +56,8 @@ PLUGIN_ATTR_CMD_CLASS, PLUGIN_ATTR_CONNECTION, PLUGIN_ATTR_SUSPEND_ITEM, PLUGIN_ATTR_CONN_AUTO_RECONN, PLUGIN_ATTR_CONN_AUTO_CONN, PLUGIN_ATTR_PROTOCOL, PLUGIN_ATTR_RECURSIVE, PLUGIN_PATH, PLUGIN_ATTR_CYCLE, - PLUGIN_ATTR_CB_SUSPEND, CMD_IATTR_CYCLIC, ITEM_ATTR_READAFTERWRITE, ITEM_ATTR_CYCLIC) + PLUGIN_ATTR_CB_SUSPEND, CMD_IATTR_CYCLIC, ITEM_ATTR_READAFTERWRITE, ITEM_ATTR_CYCLIC, + PROTO_RESEND,PLUGIN_ATTR_SEND_RETRIES, PLUGIN_ATTR_SEND_RETRIES_CYCLE) from lib.model.sdp.commands import SDPCommands from lib.model.sdp.command import SDPCommand @@ -185,6 +186,11 @@ def __init__(self, sh, logger=None, **kwargs): self._shtime = Shtime.get_instance() + #resend + if self._parameters.get(PLUGIN_ATTR_PROTOCOL) == PROTO_RESEND: + self._parameters[PLUGIN_ATTR_SEND_RETRIES] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES) + self._parameters[PLUGIN_ATTR_SEND_RETRIES_CYCLE] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES_CYCLE) + # init parameters in standalone mode if SDP_standalone: self._parameters = kwargs @@ -715,6 +721,10 @@ def send_command(self, command, value=None, return_result=False, **kwargs): self.logger.warning(f'command {command} with value {value} produced error on converting value, aborting. Error was: {e}') return False + stored = self._connection.store_commands({'command': command, 'returntype': type(value), 'returnvalue': value, 'data_dict': data_dict}) + if stored is True: + self.logger.debug(f'Command {command} stored for resend feature') + if data_dict['payload'] is None or data_dict['payload'] == '': self.logger.warning(f'command {command} with value {value} yielded empty command payload, aborting') return False @@ -792,6 +802,7 @@ def on_data_received(self, by, data, command=None): else: if custom: command = command + CUSTOM_SEP + custom + self._connection.check_commands(command, value) self._dispatch_callback(command, value, by) self._process_additional_data(command, data, value, custom, by) From 08ee3d845c4b0418b00931ccaf878ef55b5efed3 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 7 Jul 2024 22:44:00 +0200 Subject: [PATCH 02/14] sdp: update protocol --- lib/model/sdp/protocol.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 42f88dca8..6f0adc2ab 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -101,6 +101,12 @@ def _send(self, data_dict): self.logger.debug(f'{self.__class__.__name__} _send called with {data_dict}') return self._connection.send(data_dict) + def _store_commands(self, resend_info): + return False + + def _check_commands(self, command, value): + return False + def _get_connection(self, use_callbacks=False, name=None): conn_params = self._params.copy() @@ -447,19 +453,23 @@ def __init__(self, data_received_callback, name=None, **kwargs): # tell someone about our actual class self.logger.debug(f'protocol initialized from {self.__class__.__name__}') - def _open(self): + def on_connect(self, by=None): + super().on_connect(by) + self.logger.info(f'connect called, retry_sends {self._sending}') if self._plugin.scheduler_get('resend'): self._plugin.scheduler_remove('resend') + self._sending = {} if self._send_retries >= 1: - self._plugin.scheduler_add('resend', self._resend, cycle=self._send_retries_cycle) + self._plugin.scheduler_add('resend', self.resend, cycle=self._send_retries_cycle) self.logger.dbghigh( f"Adding resend scheduler with cycle {self._send_retries_cycle}.") - super()._open() - def _close(self): + def on_disconnect(self, by=None): if self._plugin.scheduler_get('resend'): self._plugin.scheduler_remove('resend') - super()._close() + self._sending = {} + self.logger.info(f'disconnect called, retry_sends {self._sending}') + super().on_disconnect(by) def _store_commands(self, resend_info): """ @@ -490,7 +500,7 @@ def _check_commands(self, command, value): self._sending_lock.release() return returnvalue - def _resend(self): + def resend(self): self.logger.info(f"resending queue is {self._sending} retries {self._sending_retries}") self._sending_lock.acquire(True, 2) remove_commands = [] From 76513daa968e81724bac65c58caef17774e801f5 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 8 Jul 2024 21:29:23 +0200 Subject: [PATCH 03/14] sdp: move command storing --- lib/model/smartdeviceplugin.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 70e0907b1..935576b27 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -721,10 +721,6 @@ def send_command(self, command, value=None, return_result=False, **kwargs): self.logger.warning(f'command {command} with value {value} produced error on converting value, aborting. Error was: {e}') return False - stored = self._connection.store_commands({'command': command, 'returntype': type(value), 'returnvalue': value, 'data_dict': data_dict}) - if stored is True: - self.logger.debug(f'Command {command} stored for resend feature') - if data_dict['payload'] is None or data_dict['payload'] == '': self.logger.warning(f'command {command} with value {value} yielded empty command payload, aborting') return False @@ -739,7 +735,9 @@ def send_command(self, command, value=None, return_result=False, **kwargs): except (RuntimeError, OSError) as e: # Exception as e: self.logger.debug(f'error on sending command {command}, error was {e}') return False - + stored = self._connection.store_commands({'command': command, 'returntype': type(value), 'returnvalue': value, 'data_dict': data_dict}) + if stored is True: + self.logger.debug(f'Command {command} stored for resend feature') if result: by = kwargs.get('by') self.logger.debug(f'command {command} received result {result} by {by}') From 0c07a34ff11370c62f0da0b38666ddb1002a3343 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 11 Jul 2024 13:33:21 +0200 Subject: [PATCH 04/14] SDP: move "store command for resend feature" to _send method, therefore extend _send with **kwargs. --- lib/model/sdp/connection.py | 40 ++++++++++++--------------------- lib/model/sdp/protocol.py | 41 ++++++++++++++++++++++------------ lib/model/smartdeviceplugin.py | 15 ++++++------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/lib/model/sdp/connection.py b/lib/model/sdp/connection.py index 01b615538..92532d649 100644 --- a/lib/model/sdp/connection.py +++ b/lib/model/sdp/connection.py @@ -146,7 +146,7 @@ def close(self): self._close() self._is_connected = False - def send(self, data_dict): + def send(self, data_dict, **kwargs): """ Send data, possibly return response @@ -174,7 +174,7 @@ def send(self, data_dict): self._send_lock.acquire() if self._send_init_on_send(): - response = self._send(data_dict) + response = self._send(data_dict, **kwargs) except Exception: raise finally: @@ -209,17 +209,11 @@ def on_disconnect(self, by=None): if self._params[PLUGIN_ATTR_CB_ON_DISCONNECT]: self._params[PLUGIN_ATTR_CB_ON_DISCONNECT](by) - def store_commands(self, resend_info): + def check_command(self, command, value): """ - storing commands, e.g. for resend feature + checking commands, e.g. for resend feature """ - return self._store_commands(resend_info) - - def check_commands(self, command, value): - """ - storing commands, e.g. for resend feature - """ - return self._check_commands(command, value) + return self._check_command(command, value) # # @@ -243,7 +237,7 @@ def _close(self): """ self.logger.debug(f'simulating closing connection as {__name__} with params {self._params}') - def _send(self, data_dict): + def _send(self, data_dict, **kwargs): """ overwrite with sending of data and - possibly - returning response data Return None if no response is received or expected. @@ -251,17 +245,10 @@ def _send(self, data_dict): self.logger.debug(f'simulating to send data {data_dict}...') return self.dummy - def _store_commands(self, resend_info): - """ - overwrite with storing of data - Return None by default - """ - return False - - def _check_commands(self, command, value): + def _check_command(self, command, value): """ - overwrite with storing of data - Return None by default + overwrite with checking of data + Return False by default """ return False @@ -453,7 +440,7 @@ def _open(self): def _close(self): self.logger.debug(f'{self.__class__.__name__} closing connection as {__name__} with params {self._params}') - def _send(self, data_dict): + def _send(self, data_dict, **kwargs): url = data_dict.get('payload', None) if not url: self.logger.error(f'can not send without url parameter from data_dict {data_dict}, aborting') @@ -464,7 +451,7 @@ def _send(self, data_dict): # check for additional data par = {} - for arg in (REQUEST_DICT_ARGS): + for arg in REQUEST_DICT_ARGS: par[arg] = data_dict.get(arg, {}) if request_method == 'get': @@ -552,7 +539,7 @@ def _close(self): self.logger.debug(f'{self.__class__.__name__} closing connection') self._tcp.close() - def _send(self, data_dict): + def _send(self, data_dict, **kwargs): self._tcp.send(data_dict['payload']) # we receive only via callback, so we return "no reply". @@ -564,6 +551,7 @@ def _on_abort(self): else: self.logger.warning('suspend callback wanted, but not set by plugin. Check plugin code...') + class UDPServer(socket.socket): """ This class sets up a UDP unicast socket listener on local_port @@ -762,7 +750,7 @@ def _close(self): if self._params[PLUGIN_ATTR_CB_ON_DISCONNECT]: self._params[PLUGIN_ATTR_CB_ON_DISCONNECT](self) - def _send(self, data_dict): + def _send(self, data_dict, **kwargs): """ send data. data_dict needs to contain the following information: diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 6f0adc2ab..46c30c4b9 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -97,14 +97,11 @@ def _close(self): self._connection.close() self._is_connected = False - def _send(self, data_dict): + def _send(self, data_dict, **kwargs): self.logger.debug(f'{self.__class__.__name__} _send called with {data_dict}') - return self._connection.send(data_dict) + return self._connection.send(data_dict, **kwargs) - def _store_commands(self, resend_info): - return False - - def _check_commands(self, command, value): + def _check_command(self, command, value): return False def _get_connection(self, use_callbacks=False, name=None): @@ -341,7 +338,7 @@ def check_chunk(data): else: self.logger.debug(f'Skipping stale check {time() - self._last_stale_check} seconds after last check') - def _send(self, data_dict): + def _send(self, data_dict, **kwargs): """ wrapper to prepare json rpc message to send. extracts command, id, repeat and params (data) from data_dict and call send_rpc_message(command, params, id, repeat) @@ -471,23 +468,40 @@ def on_disconnect(self, by=None): self.logger.info(f'disconnect called, retry_sends {self._sending}') super().on_disconnect(by) - def _store_commands(self, resend_info): + def _send(self, data_dict, **kwargs): + """ + This method acts as a overwritable intermediate between the handling + logic of send_command() and the connection layer. + If you need any special arrangements for or reaction to events on sending, + you can implement this method in your plugin class. + + By default, this just forwards the data_dict to the connection instance + and return the result. + """ + self._store_commands(kwargs.get('resend_info'), data_dict) + self.logger.debug(f'sending {data_dict}, kwargs {kwargs}') + return self._connection.send(data_dict, **kwargs) + + def _store_commands(self, resend_info, data_dict): """ overwrite with storing of data Return None by default """ if resend_info is None: resend_info = {} + else: + resend_info['data_dict'] = data_dict if resend_info.get('returnvalue') is not None: self._sending.update({resend_info.get('command'): resend_info}) + self.logger.debug(f'saving {resend_info}, self._sending {self._sending}') return True return False - def _check_commands(self, command, value): + def _check_command(self, command, value): returnvalue = False if command in self._sending: self._sending_lock.acquire(True, 2) - retry = self._sending[command].get("retry") or 0 + retry = self._sending[command].get("retry") compare = self._sending[command].get('returnvalue') if self._sending[command].get('returntype')(value) == compare: self._sending.pop(command) @@ -501,7 +515,8 @@ def _check_commands(self, command, value): return returnvalue def resend(self): - self.logger.info(f"resending queue is {self._sending} retries {self._sending_retries}") + if self._sending: + self.logger.debug(f"resending queue is {self._sending} retries {self._sending_retries}") self._sending_lock.acquire(True, 2) remove_commands = [] for command in list(self._sending.keys()): @@ -509,7 +524,7 @@ def resend(self): sent = True if retry < self._send_retries: self.logger.debug(f'Re-sending {command}, retry {retry}.') - sent = self._connection.send(self._sending[command].get("data_dict")) + sent = self._send(self._sending[command].get("data_dict")) self._sending_retries[command] = retry + 1 elif retry >= self._send_retries: sent = False @@ -521,5 +536,3 @@ def resend(self): self._sending_retries.pop(command) if self._sending_lock.locked(): self._sending_lock.release() - - diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 935576b27..3f2339fc5 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -730,14 +730,13 @@ def send_command(self, command, value=None, return_result=False, **kwargs): # if an error occurs on sending, an exception is thrown "below" result = None + resend_info = {'command': command, 'returntype': type(value), 'returnvalue': value} + try: - result = self._send(data_dict) + result = self._send(data_dict, resend_info=resend_info) except (RuntimeError, OSError) as e: # Exception as e: self.logger.debug(f'error on sending command {command}, error was {e}') return False - stored = self._connection.store_commands({'command': command, 'returntype': type(value), 'returnvalue': value, 'data_dict': data_dict}) - if stored is True: - self.logger.debug(f'Command {command} stored for resend feature') if result: by = kwargs.get('by') self.logger.debug(f'command {command} received result {result} by {by}') @@ -800,7 +799,7 @@ def on_data_received(self, by, data, command=None): else: if custom: command = command + CUSTOM_SEP + custom - self._connection.check_commands(command, value) + self._connection.check_command(command, value) self._dispatch_callback(command, value, by) self._process_additional_data(command, data, value, custom, by) @@ -962,7 +961,7 @@ def _do_before_send(self, command, value, kwargs): return (True, True) # return (False, True) - def _send(self, data_dict): + def _send(self, data_dict, **kwargs): """ This method acts as a overwritable intermediate between the handling logic of send_command() and the connection layer. @@ -972,8 +971,8 @@ def _send(self, data_dict): By default, this just forwards the data_dict to the connection instance and return the result. """ - self.logger.debug(f'sending {data_dict}') - return self._connection.send(data_dict) + self.logger.debug(f'sending {data_dict}, kwargs {kwargs}') + return self._connection.send(data_dict, **kwargs) def on_connect(self, by=None): """ callback if connection is made. """ From 5dc5309eebe6ba17b004b8f651859325712611d3 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 11 Jul 2024 23:41:34 +0200 Subject: [PATCH 05/14] SDP: set protocol to resend if send_retries > 0 --- lib/model/smartdeviceplugin.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 3f2339fc5..029b302ba 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -187,10 +187,11 @@ def __init__(self, sh, logger=None, **kwargs): self._shtime = Shtime.get_instance() #resend - if self._parameters.get(PLUGIN_ATTR_PROTOCOL) == PROTO_RESEND: - self._parameters[PLUGIN_ATTR_SEND_RETRIES] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES) - self._parameters[PLUGIN_ATTR_SEND_RETRIES_CYCLE] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES_CYCLE) - + self._parameters[PLUGIN_ATTR_SEND_RETRIES] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES) + self._parameters[PLUGIN_ATTR_SEND_RETRIES_CYCLE] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES_CYCLE) + # Set protocol to resend if send_retries is > 0 + if self._parameters.get(PLUGIN_ATTR_SEND_RETRIES, 0) > 0: + self._parameters[PLUGIN_ATTR_PROTOCOL] = 'resend' # init parameters in standalone mode if SDP_standalone: self._parameters = kwargs From 15fab7766f497e09554edf98cda4359d8ba9ac9e Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 11 Jul 2024 23:43:04 +0200 Subject: [PATCH 06/14] SDP: fix resend_info: if no reply_pattern is given for command, never resend. If no expected value is given (no capture group, lookup, etc.), reply_pattern is handled as expected result --- lib/model/smartdeviceplugin.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 029b302ba..60205c158 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -731,7 +731,13 @@ def send_command(self, command, value=None, return_result=False, **kwargs): # if an error occurs on sending, an exception is thrown "below" result = None - resend_info = {'command': command, 'returntype': type(value), 'returnvalue': value} + reply_pattern = self._commands.get_commandlist(command).get('reply_pattern') + if reply_pattern is None: + resend_info = {'command': command, 'returnvalue': None} + elif not any(x in reply_pattern for x in ['(', '{']): + resend_info = {'command': command, 'returnvalue': reply_pattern} + else: + resend_info = {'command': command, 'returnvalue': value} try: result = self._send(data_dict, resend_info=resend_info) From aec420776fe46c6be07c2ad2bf3853d57a8ff132 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 11 Jul 2024 23:43:55 +0200 Subject: [PATCH 07/14] SDP: resend protocol: fix retry saving in sending queue --- lib/model/sdp/protocol.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 46c30c4b9..0d1a291a5 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -493,6 +493,8 @@ def _store_commands(self, resend_info, data_dict): resend_info['data_dict'] = data_dict if resend_info.get('returnvalue') is not None: self._sending.update({resend_info.get('command'): resend_info}) + if resend_info.get('command') not in self._sending_retries: + self._sending_retries.update({resend_info.get('command'): 0}) self.logger.debug(f'saving {resend_info}, self._sending {self._sending}') return True return False From 207c3fe9bd1bfd092e9b7b0c4cc4951e8ad35a05 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 11 Jul 2024 23:44:38 +0200 Subject: [PATCH 08/14] SDP: resend protocol replace lock acquire by with self._sending_lock: --- lib/model/sdp/protocol.py | 59 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 0d1a291a5..79fd55160 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -502,39 +502,36 @@ def _store_commands(self, resend_info, data_dict): def _check_command(self, command, value): returnvalue = False if command in self._sending: - self._sending_lock.acquire(True, 2) - retry = self._sending[command].get("retry") - compare = self._sending[command].get('returnvalue') - if self._sending[command].get('returntype')(value) == compare: - self._sending.pop(command) - self._sending_retries.pop(command) - self.logger.debug(f'Correct answer for {command}, removing from send. Sending {self._sending}') - returnvalue = True - elif retry is not None and retry <= self._send_retries: - self.logger.debug(f'Should send again {self._sending}...') - if self._sending_lock.locked(): - self._sending_lock.release() + with self._sending_lock: + retry = self._sending_retries.get(command) + compare = self._sending[command].get('returnvalue') + if type(compare)(value) == compare: + self._sending.pop(command) + self._sending_retries.pop(command) + self.logger.debug(f'Correct answer for {command}, removing from send. Sending {self._sending}') + returnvalue = True + elif retry is not None and retry <= self._send_retries: + self.logger.debug(f'Should send again {self._sending}...') + return returnvalue def resend(self): if self._sending: self.logger.debug(f"resending queue is {self._sending} retries {self._sending_retries}") - self._sending_lock.acquire(True, 2) - remove_commands = [] - for command in list(self._sending.keys()): - retry = self._sending_retries.get(command, 0) - sent = True - if retry < self._send_retries: - self.logger.debug(f'Re-sending {command}, retry {retry}.') - sent = self._send(self._sending[command].get("data_dict")) - self._sending_retries[command] = retry + 1 - elif retry >= self._send_retries: - sent = False - if sent is False: - remove_commands.append(command) - self.logger.info(f"Giving up re-sending {command} after {retry} retries.") - for command in remove_commands: - self._sending.pop(command) - self._sending_retries.pop(command) - if self._sending_lock.locked(): - self._sending_lock.release() + with self._sending_lock: + remove_commands = [] + for command in list(self._sending.keys()): + retry = self._sending_retries.get(command, 0) + sent = True + if retry < self._send_retries: + self.logger.debug(f'Re-sending {command}, retry {retry}.') + sent = self._send(self._sending[command].get("data_dict")) + self._sending_retries[command] = retry + 1 + elif retry >= self._send_retries: + sent = False + if sent is False: + remove_commands.append(command) + self.logger.info(f"Giving up re-sending {command} after {retry} retries.") + for command in remove_commands: + self._sending.pop(command) + self._sending_retries.pop(command) From 914460d4564066b3051e73b34b5389fb0095cec0 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 12 Jul 2024 00:06:16 +0200 Subject: [PATCH 09/14] SDP: query current value for command that was not successfully sent --- lib/model/sdp/protocol.py | 6 ++++++ lib/model/smartdeviceplugin.py | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 79fd55160..5eaf1b93e 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -532,6 +532,12 @@ def resend(self): if sent is False: remove_commands.append(command) self.logger.info(f"Giving up re-sending {command} after {retry} retries.") + if self._sending[command].get("querycommand") is not None: + self.logger.info(f"Querying current value.") + data_dict = self._sending[command].get("data_dict") + data_dict['payload'] = self._sending[command].get("querycommand") + data_dict['data'] = None + self._send(data_dict) for command in remove_commands: self._sending.pop(command) self._sending_retries.pop(command) diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 60205c158..21184714c 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -732,12 +732,13 @@ def send_command(self, command, value=None, return_result=False, **kwargs): # if an error occurs on sending, an exception is thrown "below" result = None reply_pattern = self._commands.get_commandlist(command).get('reply_pattern') + querycommand = self._commands.get_commandlist(command).get('read_cmd') if reply_pattern is None: - resend_info = {'command': command, 'returnvalue': None} + resend_info = {'command': command, 'returnvalue': None, 'querycommand': querycommand} elif not any(x in reply_pattern for x in ['(', '{']): - resend_info = {'command': command, 'returnvalue': reply_pattern} + resend_info = {'command': command, 'returnvalue': reply_pattern, 'querycommand': querycommand} else: - resend_info = {'command': command, 'returnvalue': value} + resend_info = {'command': command, 'returnvalue': value, 'querycommand': querycommand} try: result = self._send(data_dict, resend_info=resend_info) From c6e26a0ebcbd754fed9cde4b39c75a9c20b6f5c2 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 13 Jul 2024 23:45:00 +0200 Subject: [PATCH 10/14] SDP: fix and improve read command for querying after resend is not successful --- lib/model/sdp/protocol.py | 7 ++----- lib/model/smartdeviceplugin.py | 8 ++++---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 5eaf1b93e..89a4e0c47 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -532,12 +532,9 @@ def resend(self): if sent is False: remove_commands.append(command) self.logger.info(f"Giving up re-sending {command} after {retry} retries.") - if self._sending[command].get("querycommand") is not None: + if self._sending[command].get("read_cmd") is not None: self.logger.info(f"Querying current value.") - data_dict = self._sending[command].get("data_dict") - data_dict['payload'] = self._sending[command].get("querycommand") - data_dict['data'] = None - self._send(data_dict) + self._send(self._sending[command].get("read_cmd")) for command in remove_commands: self._sending.pop(command) self._sending_retries.pop(command) diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 21184714c..049658a67 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -732,13 +732,13 @@ def send_command(self, command, value=None, return_result=False, **kwargs): # if an error occurs on sending, an exception is thrown "below" result = None reply_pattern = self._commands.get_commandlist(command).get('reply_pattern') - querycommand = self._commands.get_commandlist(command).get('read_cmd') + read_cmd = self._transform_send_data(self._commands.get_send_data(command, None)) if reply_pattern is None: - resend_info = {'command': command, 'returnvalue': None, 'querycommand': querycommand} + resend_info = {'command': command, 'returnvalue': None, 'read_cmd': read_cmd} elif not any(x in reply_pattern for x in ['(', '{']): - resend_info = {'command': command, 'returnvalue': reply_pattern, 'querycommand': querycommand} + resend_info = {'command': command, 'returnvalue': reply_pattern, 'read_cmd': read_cmd} else: - resend_info = {'command': command, 'returnvalue': value, 'querycommand': querycommand} + resend_info = {'command': command, 'returnvalue': value, 'read_cmd': read_cmd} try: result = self._send(data_dict, resend_info=resend_info) From d0a947c6ef425ed33509bf71496f3261f9ce7638 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 2 Aug 2024 07:52:02 +0200 Subject: [PATCH 11/14] Update smartdeviceplugin.py and not self._parameters.get[PLUGIN_ATTR_PROTOCOL]: --- lib/model/smartdeviceplugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 049658a67..36991c73b 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -190,7 +190,7 @@ def __init__(self, sh, logger=None, **kwargs): self._parameters[PLUGIN_ATTR_SEND_RETRIES] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES) self._parameters[PLUGIN_ATTR_SEND_RETRIES_CYCLE] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES_CYCLE) # Set protocol to resend if send_retries is > 0 - if self._parameters.get(PLUGIN_ATTR_SEND_RETRIES, 0) > 0: + if self._parameters.get(PLUGIN_ATTR_SEND_RETRIES, 0) > 0 and not self._parameters.get[PLUGIN_ATTR_PROTOCOL]: self._parameters[PLUGIN_ATTR_PROTOCOL] = 'resend' # init parameters in standalone mode if SDP_standalone: From fa946d90e3dbe4b259b79e373ba0328dbf1bf7cc Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 2 Aug 2024 22:27:41 +0200 Subject: [PATCH 12/14] smartdeviceplugin: minor code improvements --- lib/model/smartdeviceplugin.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 36991c73b..faec016c7 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -189,9 +189,17 @@ def __init__(self, sh, logger=None, **kwargs): #resend self._parameters[PLUGIN_ATTR_SEND_RETRIES] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES) self._parameters[PLUGIN_ATTR_SEND_RETRIES_CYCLE] = self.get_parameter_value(PLUGIN_ATTR_SEND_RETRIES_CYCLE) - # Set protocol to resend if send_retries is > 0 - if self._parameters.get(PLUGIN_ATTR_SEND_RETRIES, 0) > 0 and not self._parameters.get[PLUGIN_ATTR_PROTOCOL]: - self._parameters[PLUGIN_ATTR_PROTOCOL] = 'resend' + + resend = self._parameters.get(PLUGIN_ATTR_SEND_RETRIES, 0) or 0 + protocol = self._parameters.get(PLUGIN_ATTR_PROTOCOL) + if resend > 0: + # Set protocol to resend if send_retries is > 0 and protocol is not defined + if not protocol: + self._parameters[PLUGIN_ATTR_PROTOCOL] = 'resend' + # if send_retries is set and protocl is not set to resend, log info that protocol is overruling the parameter + elif protocol != 'resend': + self.logger.info(f'send_retries is set to {resend}, however, protocol is overruled to {protocol}') + # init parameters in standalone mode if SDP_standalone: self._parameters = kwargs @@ -735,7 +743,8 @@ def send_command(self, command, value=None, return_result=False, **kwargs): read_cmd = self._transform_send_data(self._commands.get_send_data(command, None)) if reply_pattern is None: resend_info = {'command': command, 'returnvalue': None, 'read_cmd': read_cmd} - elif not any(x in reply_pattern for x in ['(', '{']): + # if no reply_pattern has lookup or capture group, put it in resend_info + elif '(' not in reply_pattern and '{' not in reply_pattern: resend_info = {'command': command, 'returnvalue': reply_pattern, 'read_cmd': read_cmd} else: resend_info = {'command': command, 'returnvalue': value, 'read_cmd': read_cmd} From 18425883b272e3af269b939a440e4aae5e86277a Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 2 Aug 2024 22:28:00 +0200 Subject: [PATCH 13/14] smartdeviceplugin: inline documentation update --- lib/model/sdp/protocol.py | 71 +++++++++++++++++++++++++--------- lib/model/smartdeviceplugin.py | 10 +++-- 2 files changed, 58 insertions(+), 23 deletions(-) diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 89a4e0c47..34c16abaa 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -195,7 +195,7 @@ def on_data_received(self, connection, response): """ Handle received data - Data is handed over as byte/bytearray and needs to be converted to + Data is handed over as byte/bytearray and needs to be converted to utf8 strings. As packets can be fragmented, all data is written into a buffer and then checked for complete json expressions. Those are separated, converted to dict and processed with respect to saved @@ -431,8 +431,9 @@ def _send_rpc_message(self, command, ddict=None, message_id=None, repeat=0): class SDPProtocolResend(SDPProtocol): - """ Protocol providing resend option + """ Protocol supporting resend of command and checking reply_pattern + This class implements a protocol to resend commands if reply does not align with reply_pattern """ @@ -440,7 +441,7 @@ def __init__(self, data_received_callback, name=None, **kwargs): # init super, get logger super().__init__(data_received_callback, name, **kwargs) - + # get relevant plugin parameters self._send_retries = int(self._params.get(PLUGIN_ATTR_SEND_RETRIES) or 0) self._send_retries_cycle = int(self._params.get(PLUGIN_ATTR_SEND_RETRIES_CYCLE) or 1) self._sending = {} @@ -451,8 +452,11 @@ def __init__(self, data_received_callback, name=None, **kwargs): self.logger.debug(f'protocol initialized from {self.__class__.__name__}') def on_connect(self, by=None): + """ + When connecting, remove resend scheduler first. If send_retries is set > 0, add new scheduler with given cycle + """ super().on_connect(by) - self.logger.info(f'connect called, retry_sends {self._sending}') + self.logger.info(f'connect called, resending queue is {self._sending}') if self._plugin.scheduler_get('resend'): self._plugin.scheduler_remove('resend') self._sending = {} @@ -462,30 +466,39 @@ def on_connect(self, by=None): f"Adding resend scheduler with cycle {self._send_retries_cycle}.") def on_disconnect(self, by=None): + """ + Remove resend scheduler on disconnect + """ if self._plugin.scheduler_get('resend'): self._plugin.scheduler_remove('resend') self._sending = {} - self.logger.info(f'disconnect called, retry_sends {self._sending}') + self.logger.info(f'disconnect called.') super().on_disconnect(by) def _send(self, data_dict, **kwargs): """ - This method acts as a overwritable intermediate between the handling - logic of send_command() and the connection layer. - If you need any special arrangements for or reaction to events on sending, - you can implement this method in your plugin class. + Send data, possibly return response - By default, this just forwards the data_dict to the connection instance - and return the result. + :param data_dict: dict with raw data and possible additional parameters to send + :type data_dict: dict + :param kwargs: additional information needed for checking the reply_pattern + :return: raw response data if applicable, None otherwise. """ self._store_commands(kwargs.get('resend_info'), data_dict) - self.logger.debug(f'sending {data_dict}, kwargs {kwargs}') + self.logger.debug(f'Sending {data_dict}, kwargs {kwargs}') return self._connection.send(data_dict, **kwargs) def _store_commands(self, resend_info, data_dict): """ - overwrite with storing of data - Return None by default + Store the command in _sending dict and the number of retries is _sending_retries dict + + :param resend_info: dict with command, returnvalue and read_command + :type resend_info: dict + :param data_dict: dict with raw data and possible additional parameters to send + :type data_dict: dict + :param kwargs: additional information needed for checking the reply_pattern + :return: False by default, True if returnvalue is given in resend_info + :rtype: bool """ if resend_info is None: resend_info = {} @@ -495,36 +508,56 @@ def _store_commands(self, resend_info, data_dict): self._sending.update({resend_info.get('command'): resend_info}) if resend_info.get('command') not in self._sending_retries: self._sending_retries.update({resend_info.get('command'): 0}) - self.logger.debug(f'saving {resend_info}, self._sending {self._sending}') + self.logger.debug(f'Saving {resend_info}, resending queue is {self._sending}') return True return False def _check_command(self, command, value): + """ + Check if the command is in _sending dict and if response is same as expected or not + + :param command: name of command + :type command: str + :param value: value the command (item) should be set to + :type value: str + :return: False by default, True if received expected response + :rtype: bool + """ returnvalue = False if command in self._sending: with self._sending_lock: + # getting current retries for current command retry = self._sending_retries.get(command) + # compare the expected returnvalue with the received value after aligning the type of both values compare = self._sending[command].get('returnvalue') if type(compare)(value) == compare: + # if received value equals expexted value, remove command from _sending dict self._sending.pop(command) self._sending_retries.pop(command) - self.logger.debug(f'Correct answer for {command}, removing from send. Sending {self._sending}') + self.logger.debug(f'Got correct response for {command}, ' + f'removing from send. Resending queue is {self._sending}') returnvalue = True elif retry is not None and retry <= self._send_retries: + # return False and log info if response is not the same as the expected response self.logger.debug(f'Should send again {self._sending}...') - return returnvalue def resend(self): + """ + Resend function that is scheduled with a given cycle. + Send command again if response is not as expected and retries are < given retry parameter + If expected response is not received after given retries, give up sending and query value by sending read_command + """ if self._sending: - self.logger.debug(f"resending queue is {self._sending} retries {self._sending_retries}") + self.logger.debug(f"Resending queue is {self._sending}, retries {self._sending_retries}") with self._sending_lock: remove_commands = [] + # Iterate through resend queue for command in list(self._sending.keys()): retry = self._sending_retries.get(command, 0) sent = True if retry < self._send_retries: - self.logger.debug(f'Re-sending {command}, retry {retry}.') + self.logger.debug(f'Resending {command}, retries {retry}.') sent = self._send(self._sending[command].get("data_dict")) self._sending_retries[command] = retry + 1 elif retry >= self._send_retries: diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index faec016c7..64ea2a56c 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -737,18 +737,20 @@ def send_command(self, command, value=None, return_result=False, **kwargs): data_dict = self._transform_send_data(data_dict, **kwargs) self.logger.debug(f'command {command} with value {value} yielded send data_dict {data_dict}') - # if an error occurs on sending, an exception is thrown "below" + # creating resend info, necessary for resend protocol result = None reply_pattern = self._commands.get_commandlist(command).get('reply_pattern') read_cmd = self._transform_send_data(self._commands.get_send_data(command, None)) + # if no reply_pattern given, no response is expected if reply_pattern is None: resend_info = {'command': command, 'returnvalue': None, 'read_cmd': read_cmd} # if no reply_pattern has lookup or capture group, put it in resend_info elif '(' not in reply_pattern and '{' not in reply_pattern: resend_info = {'command': command, 'returnvalue': reply_pattern, 'read_cmd': read_cmd} + # if reply pattern does not expect a specific value, use value as expected reply else: resend_info = {'command': command, 'returnvalue': value, 'read_cmd': read_cmd} - + # if an error occurs on sending, an exception is thrown "below" try: result = self._send(data_dict, resend_info=resend_info) except (RuntimeError, OSError) as e: # Exception as e: @@ -816,7 +818,7 @@ def on_data_received(self, by, data, command=None): else: if custom: command = command + CUSTOM_SEP + custom - self._connection.check_command(command, value) + self._connection.check_command(command, value) # needed for resend protocol self._dispatch_callback(command, value, by) self._process_additional_data(command, data, value, custom, by) @@ -1701,7 +1703,7 @@ def create_struct_yaml(self): self.yaml['item_structs'] = OrderedDict() - # this means the commands dict has 'ALL' and model names at the top level + # this means the commands dict has 'ALL' and model names at the top level # otherwise, the top level nodes are commands or sections cmds_has_models = INDEX_GENERIC in top_level_entries From ada53c3a9848bc89c6ad8e1259f920ab6966a092 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 4 Aug 2024 02:04:37 +0200 Subject: [PATCH 14/14] sdp: rename check_command to check_reply as this is more suitable --- lib/model/sdp/connection.py | 8 ++++---- lib/model/sdp/protocol.py | 4 ++-- lib/model/smartdeviceplugin.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/model/sdp/connection.py b/lib/model/sdp/connection.py index 92532d649..53df675a2 100644 --- a/lib/model/sdp/connection.py +++ b/lib/model/sdp/connection.py @@ -209,11 +209,11 @@ def on_disconnect(self, by=None): if self._params[PLUGIN_ATTR_CB_ON_DISCONNECT]: self._params[PLUGIN_ATTR_CB_ON_DISCONNECT](by) - def check_command(self, command, value): + def check_reply(self, command, value): """ - checking commands, e.g. for resend feature + checking reply, e.g. for resend feature """ - return self._check_command(command, value) + return self._check_reply(command, value) # # @@ -245,7 +245,7 @@ def _send(self, data_dict, **kwargs): self.logger.debug(f'simulating to send data {data_dict}...') return self.dummy - def _check_command(self, command, value): + def _check_reply(self, command, value): """ overwrite with checking of data Return False by default diff --git a/lib/model/sdp/protocol.py b/lib/model/sdp/protocol.py index 34c16abaa..325275fb9 100644 --- a/lib/model/sdp/protocol.py +++ b/lib/model/sdp/protocol.py @@ -101,7 +101,7 @@ def _send(self, data_dict, **kwargs): self.logger.debug(f'{self.__class__.__name__} _send called with {data_dict}') return self._connection.send(data_dict, **kwargs) - def _check_command(self, command, value): + def _check_reply(self, command, value): return False def _get_connection(self, use_callbacks=False, name=None): @@ -512,7 +512,7 @@ def _store_commands(self, resend_info, data_dict): return True return False - def _check_command(self, command, value): + def _check_reply(self, command, value): """ Check if the command is in _sending dict and if response is same as expected or not diff --git a/lib/model/smartdeviceplugin.py b/lib/model/smartdeviceplugin.py index 64ea2a56c..72ec187a6 100644 --- a/lib/model/smartdeviceplugin.py +++ b/lib/model/smartdeviceplugin.py @@ -818,7 +818,7 @@ def on_data_received(self, by, data, command=None): else: if custom: command = command + CUSTOM_SEP + custom - self._connection.check_command(command, value) # needed for resend protocol + self._connection.check_reply(command, value) # needed for resend protocol self._dispatch_callback(command, value, by) self._process_additional_data(command, data, value, custom, by)