SensorBase.SensorBase

Abstract base class defining the interface for all Oizom sensor wrappers.

This module hosts GenericSensor, the abstract base class (ABC) that every sensor wrapper in OzWrapper (battery, dust, noise, weather, vibration, GPS, MPPT, soil, radiation, and roughly forty more) must inherit from. The ABC pins down a uniform four-method lifecycle so the orchestrator in Sensor.Sensor can drive any sensor type without special-casing hardware specifics. All ~70 hardware drivers in drivers are reached only through wrappers that subclass this class.

Lifecycle protocol (in call order):

  1. initialize() – receive the device configuration the Gateway returned for this wrapper and stash any per-run state (calibration offsets, enable flags, last-known values for continuity across reboots).

  2. initializeSensor() – bring up a single physical sensor entry from the configuration (typically called by initialize() once per "en": 1 entry). Configures I2C/SPI/UART buses, instantiates the underlying driver, and verifies the device responds.

  3. getSensorReading() – perform one measurement cycle, read every initialized hardware sensor, apply averaging/calibration, and return a flat {parameter: value} mapping. Must be non-raising; on hardware error wrappers return zero-filled values so the data pipeline keeps flowing.

  4. putSensorValue() – merge this wrapper’s readings into the outbound payload dictionary that the orchestrator assembles across every active wrapper. Should call getSensorReading() once per invocation.

The non-abstract helper putInitvalues() is an optional hook used by wrappers that need to inject startup defaults or last-known values into the first payload sent after boot.

Example

Minimal subclass implementing every abstract method:

from SensorBase import GenericSensor


class OzTemp(GenericSensor):
    partNumber = "pn"
    parameter = "temp"

    def initialize(self, config, init_value):
        for sensor in config.get("temp", []):
            if sensor.get("en") == 1:
                self.initializeSensor(sensor)

    def initializeSensor(self, sensor):
        # bring up the underlying driver, save handle on self
        ...

    def getSensorReading(self):
        return {"temp": 25.3, "hum": 60.0}

    def putSensorValue(self, value):
        value.update(self.getSensorReading())
        return value

Note

Lifecycle methods run on the firmware’s scheduler thread, not the HTTP/Gateway thread. Implementations must be re-entrant only with respect to themselves: a single wrapper instance will never have two of these methods executing concurrently, but other wrapper instances may be running their own lifecycle methods in parallel on other threads. Blocking I2C/SPI/UART reads inside getSensorReading() will delay the next scheduled iteration, so individual reads should be kept short and any long-running averaging done with bounded in-memory buffers.

Classes

GenericSensor

Abstract base class for all Oizom sensor wrappers.