From 3da00c737e7b3887bf1e55ff5e5d19ce375089f7 Mon Sep 17 00:00:00 2001 From: Jan Mrna Date: Mon, 15 Aug 2022 22:46:48 +0200 Subject: [PATCH] Added configuration detection for IAQ Wired Sensor --- src/veles/device/find.py | 2 +- src/veles/device/generic.py | 17 +++++++++++++++-- src/veles/device/sensor_wired_IAQ.py | 24 +++++++++++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/veles/device/find.py b/src/veles/device/find.py index a115eb4..5041344 100644 --- a/src/veles/device/find.py +++ b/src/veles/device/find.py @@ -6,5 +6,5 @@ from .sensor_wired_RHT import SensorWiredRHT # links device identifiers to its class device_identifiers: Final[Dict[int, Device]] = { SensorWiredIAQ.DEVICE_CODE: SensorWiredIAQ, - SensorWiredRHT.DEVICE_CODE: SensorWiredRHT + SensorWiredRHT.DEVICE_CODE: SensorWiredRHT, } diff --git a/src/veles/device/generic.py b/src/veles/device/generic.py index 99e0e6b..465e85f 100644 --- a/src/veles/device/generic.py +++ b/src/veles/device/generic.py @@ -1,6 +1,6 @@ """Module containing classes for generic wired/wireless devices""" from dataclasses import dataclass -from typing import Dict, Final, Any, Union +from typing import Dict, Final, Any from abc import ABC, abstractmethod import minimalmodbus import serial @@ -27,6 +27,12 @@ class ReadoutErrorCounter: no_response: int = 0 +class NoResponseException(Exception): + """ + Raised when device fails to respond + """ + + class Device(ABC): """ Base class for all devices @@ -92,6 +98,12 @@ class ModbusRTUDevice(Device): self.dev: str = dev self.comm_device: minimalmodbus.Instrument = self.__comm_device_init() self.readout_errors: ReadoutErrorCounter = ReadoutErrorCounter() + # check if device actually exists on the bus (by reading serial number); + # if not, raise NoResponseException + try: + self.read_register(self.input_registers["SERIAL_NUMBER_1"]) + except minimalmodbus.NoResponseError as exc: + raise NoResponseException from exc def read_register( self, register_number: int, signed: bool = False, retries: int = 10 @@ -190,5 +202,6 @@ class ModbusRTUDevice(Device): def get_data(self) -> Dict[str, int]: return { - name: self.read_register(number) for name, number in self.input_registers.items() + name: self.read_register(number) + for name, number in self.input_registers.items() } diff --git a/src/veles/device/sensor_wired_IAQ.py b/src/veles/device/sensor_wired_IAQ.py index a3696a1..6ad0165 100644 --- a/src/veles/device/sensor_wired_IAQ.py +++ b/src/veles/device/sensor_wired_IAQ.py @@ -1,5 +1,6 @@ from time import sleep from typing import Dict, Final +from minimalmodbus import IllegalRequestError from .generic import ModbusRTUDevice @@ -28,7 +29,7 @@ class SensorWiredIAQ(ModbusRTUDevice): "PMC_NUMBER_2_5": 30015, # 1 / m^3 "PMC_NUMBER_4_0": 30016, # 1 / m^3 "PMC_NUMBER_10_0": 30017, # 1 / m^3 - "TYPICAL_PARTICLE_SIZE": 30018, # nm + "PMC_TYPICAL_PARTICLE_SIZE": 30018, # nm "READ_ERR_T": 30019, # temperature sensor error code (0 if no error) "READ_ERR_RH": 30020, # humidity sensor error code (0 if no error) "READ_ERR_CO2": 30021, # CO2 sensor error code (0 if no error) @@ -74,3 +75,24 @@ class SensorWiredIAQ(ModbusRTUDevice): self.write_register(self.holding_registers["LED_BRIGHTNESS"], value) sleep(0.1) self.write_register(self.holding_registers["LED_ON"], 1) + + def __remove_sensor_from_input_registers(self, sensor: str): + """ + Remove all items containing "sensor" str from input_registers + """ + deleted_registers = list(filter(lambda x: sensor in x, self.input_registers)) + _ = list((self.input_registers.pop(x) for x in deleted_registers)) + + def __init__(self, modbus_address, baudrate=19200, dev="/dev/rs485"): + super().__init__(modbus_address, baudrate, dev) + # detect sensor configuration and modify input_registers accordingly + # Check if VOC sensor present + try: + self.read_register(self.input_registers["VOC_INDEX"]) + except IllegalRequestError: + self.__remove_sensor_from_input_registers("VOC") + # Check if PMC sensor present + try: + self.read_register(self.input_registers["PMC_MASS_1_0"]) + except IllegalRequestError: + self.__remove_sensor_from_input_registers("PMC")