From 0d552e3007976689463aa5cbed86822736c93cd3 Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Thu, 2 Feb 2023 14:21:30 +0100 Subject: [PATCH] RPI:error handling while getting corruppted data extended error handling while getting corruppted data on 64 bit operating system (bullseye) lots of currupted data are reseived on Debian 11 OS. So we have to check the data length before using strict.unpack --- tools/rpi/README.md | 13 +++++++------ tools/rpi/hoymiles/__init__.py | 8 ++++---- tools/rpi/hoymiles/__main__.py | 3 ++- tools/rpi/hoymiles/decoders/__init__.py | 18 +++++++++++++----- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/tools/rpi/README.md b/tools/rpi/README.md index 75b5c1e2..36b08f79 100644 --- a/tools/rpi/README.md +++ b/tools/rpi/README.md @@ -78,8 +78,12 @@ cd examples_linux/ python3 getting_started.py # to test and see whether RF24 class can be loaded as module in python correctly ``` +If there are no error messages on the last step, then the NRF24 Wrapper has been installed successfully. + -``` for bullseye - Debian 11 on 64 bit operating system +for Debian 11 (bullseye) 64 bit operating system +------------------------------------------------- +```code [ $(lscpu | grep Architecture | awk '{print $2}') != "aarch64" ]] && echo "Not a 64 bit architecture for this step!" git clone --recurse-submodules https://github.com/nRF24/pyRF24.git @@ -87,15 +91,12 @@ cd pyRF24 python -m pip install . -v # this step takes about 5 minutes! ``` - -If there are no error messages on the last step, then the NRF24 Wrapper has been installed successfully. - Required python modules ----------------------- Some modules are not installed by default on a RaspberryPi, therefore add them manually: -``` +```code pip install crcmod pyyaml paho-mqtt SunTimes ``` @@ -122,7 +123,7 @@ Python parameters The application describes itself -``` +```code python3 -m hoymiles --help usage: hoymiles [-h] -c [CONFIG_FILE] [--log-transactions] [--verbose] diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index eeb7e7de..a754ff6d 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -170,15 +170,15 @@ class ResponseDecoder(ResponseDecoderFactory): model = self.inverter_model command = self.request_command - c_datetime = self.time_rx.strftime("%Y-%m-%d %H:%M:%S.%f") - logging.info(f'{c_datetime} model_decoder: {model}Decode{command.upper()}') + if HOYMILES_DEBUG_LOGGING: + c_datetime = self.time_rx.strftime("%Y-%m-%d %H:%M:%S.%f") + logging.info(f'{c_datetime} model_decoder: {model}Decode{command.upper()}') model_decoders = __import__('hoymiles.decoders') if hasattr(model_decoders, f'{model}Decode{command.upper()}'): device = getattr(model_decoders, f'{model}Decode{command.upper()}') else: - if HOYMILES_DEBUG_LOGGING: - device = getattr(model_decoders, 'DebugDecodeAny') + device = getattr(model_decoders, 'DebugDecodeAny') return device(self.response, time_rx=self.time_rx, diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 97773ed1..35943eb4 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -179,8 +179,8 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): # Handle the response data if any if response: - c_datetime = datetime.now() if hoymiles.HOYMILES_DEBUG_LOGGING: + c_datetime = datetime.now() logging.debug(f'{c_datetime} Payload: ' + hoymiles.hexify_payload(response)) # prepare decoder object @@ -195,6 +195,7 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): # get decoder object result = decoder.decode() if hoymiles.HOYMILES_DEBUG_LOGGING: + c_datetime = datetime.now() logging.info(f'{c_datetime} Decoded: {result.__dict__()}') # check decoder object for output diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index b46dbe48..e27b502d 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -110,6 +110,9 @@ class StatusResponse(Response): :rtype: tuple """ size = struct.calcsize(fmt) + if (len(self.response) < base+size): + logging.error(f'base: {base} size: {size} len: {len(self.response)} fmt: {fmt} rep: {self.response}') + return [0] return struct.unpack(fmt, self.response[base:base+size]) @property @@ -331,10 +334,12 @@ class EventsResponse(UnknownResponse): logging.debug(' '.join([f'{byte:02x}' for byte in chunk]) + ': ') - opcode, a_code, a_count, uptime_sec = struct.unpack('>BBHH', chunk[0:6]) - a_text = self.alarm_codes.get(a_code, 'N/A') - - logging.debug(f' uptime={timedelta(seconds=uptime_sec)} a_count={a_count} opcode={opcode} a_code={a_code} a_text={a_text}') + if (len(chunk[0:6]) == 6): + opcode, a_code, a_count, uptime_sec = struct.unpack('>BBHH', chunk[0:6]) + a_text = self.alarm_codes.get(a_code, 'N/A') + logging.debug(f' uptime={timedelta(seconds=uptime_sec)} a_count={a_count} opcode={opcode} a_code={a_code} a_text={a_text}') + else: + logging.error(f'length of chunk must be greater or equal 6 bytes: {chunk}') dbg = '' for fmt in ['BBHHHHH']: @@ -362,7 +367,10 @@ class HardwareInfoResponse(UnknownResponse): """ Base values, availabe in each __dict__ call """ responce_info = self.response - logging.info(f'HardwareInfoResponse: {struct.unpack(">HHHHHHHH", responce_info)}') + if (len(responce_info) >= 16): + logging.info(f'HardwareInfoResponse: {struct.unpack(">HHHHHHHH", responce_info)}') + else: + logging.error(f'wrong length of HardwareInfoResponse: {responce_info}') fw_version, fw_build_yyyy, fw_build_mmdd, fw_build_hhmm, hw_id = struct.unpack('>HHHHH', self.response[0:10])