flyte / mqtt-io

Expose GPIO modules (Raspberry Pi, Beaglebone, PCF8754, PiFace2 etc.) and digital sensors (LM75 etc.) to an MQTT server for remote control and monitoring.
MIT License
468 stars 158 forks source link

Sensor error recovery #201

Closed r00tat closed 3 years ago

r00tat commented 3 years ago

Is your feature request related to a problem? Please describe. After some time the ds18b module fails to read the sensor data. From that point in time the sensor is gone and only a restart helps.

This is the error:

2021-03-29 01:05:20 mqtt_io.server [ERROR] Exception in task: <Task finished coro=<MqttIo._init_sensor_inputs.<locals>.poll_sensor() done, defined at /home/pi/rainpi/mqtt-io/mqtt-io/mqtt_io/server.py:528> exception=SensorNotReadyError('Sensor 0120327903dd is not yet ready to read temperature')>:
Traceback (most recent call last):
  File "/home/pi/rainpi/mqtt-io/mqtt-io/mqtt_io/server.py", line 1041, in _remove_finished_transient_tasks
    raise exception
  File "/home/pi/rainpi/mqtt-io/mqtt-io/mqtt_io/server.py", line 533, in poll_sensor
    value = await sensor_module.async_get_value(sens_conf)
  File "/home/pi/rainpi/mqtt-io/mqtt-io/mqtt_io/modules/sensor/__init__.py", line 57, in async_get_value
    return await loop.run_in_executor(ThreadPoolExecutor(), self.get_value, sens_conf)
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/pi/rainpi/mqtt-io/mqtt-io/mqtt_io/modules/sensor/ds18b.py", line 41, in get_value
    return cast(float, self.sensor.get_temperature())
  File "/home/pi/.local/lib/python3.7/site-packages/w1thermsensor/core.py", line 267, in get_temperature
    raw_temperature_line = self.get_raw_sensor_strings()[1]
  File "/home/pi/.local/lib/python3.7/site-packages/w1thermsensor/core.py", line 250, in get_raw_sensor_strings
    raise SensorNotReadyError(self)
w1thermsensor.errors.SensorNotReadyError: Sensor 0120327903dd is not yet ready to read temperature

Describe the solution you'd like If a sensor can't be read, there should be an exponential backoff retrying the read on the sensor.

Describe alternatives you've considered I've implemented a simple ds18b replacement based on the w1_therm kernel module and the 1wire sys files:

"""
DS18S20/DS1822/DS18B20/DS1825/DS28EA00/MAX31850K temperature sensors
make sure w1_therm and w1_gpio modules are loaded to use this sensor
"""
import os
import os.path

from ...types import ConfigType, SensorValueType
from . import GenericSensor

REQUIREMENTS = ()
ALLOWED_TYPES = ["DS18S20", "DS1822", "DS18B20", "DS1825", "DS28EA00", "MAX31850K"]
CONFIG_SCHEMA = {
    "file": dict(type="string", required=True, empty=False),
}

class Sensor(GenericSensor):
    """
    Implementation of Sensor class for the one wire temperature sensors. DS18B etc.
    """

    def setup_module(self) -> None:
        self.file_path = f"/sys/bus/w1/devices/{self.config['file']}/temperature"
        if not os.path.isfile(self.file_path):
            raise FileNotFoundError(
                (f"unable to locate 1wire temperature file under {self.file_path}. "
                 f"Make sure the w1_therm and w1_gpio kernel modules are loaded"))

    def get_value(self, sens_conf: ConfigType) -> SensorValueType:
        """
        Get the temperature value from the sensor
        """
        with open(self.file_path, 'r') as raw_file:
            raw_value = raw_file.read()
        return float(raw_value) / 1000

Additional context

This is my config.yaml:

sensor_modules:
  - name: ds18b20
    module: ds18b
    type: DS18B20
    address: 0120327903dd
sensor_inputs:
  - name: rainpi_temp2
    module: ds18b20
    interval: 60
    digits: 2
    ha_discovery:
      name: Rainpi temperature 1wire
      device_class: temperature
      unit_of_measurement: "°C"
flyte commented 3 years ago

Yep, sensor read errors should not cause the sensor read loop to stop.

I've committed a change including a backoff to the develop branch. Would you mind testing it out and seeing if it solves your issue?

r00tat commented 3 years ago

Sure, I'll deploy it in the evening and let you know, if this solves the issue!

Thanks a lot!

r00tat commented 3 years ago

Hi @flyte, it seems like backoff did solve my sensor issue and I do not see any errors in the log any more.

Thanks for your quick response and fix!