Skip to main content

Overview

SensorModule is the container class that manages multiple BaseSens sensors in the V1 framework. It handles initialization, updates, data access, and debugging for all registered sensors. Header: lib/sensors/SensorModuleV1/base/sensor-module.h

Class Definition

class SensorModule {
public:
    SensorModule();
    ~SensorModule();
    
    // Lifecycle methods
    virtual void init(void (*initializeCallback)() = nullptr);
    virtual void update(void (*updateCallback)() = nullptr);
    virtual void update(const char *searchName);
    virtual bool isReady(void (*readyCallback)() = nullptr);
    
    // Module management
    void addModule(BaseSens *sensModule);
    void addModule(const char *newName, BaseSens *sensModule);
    void addModule(const char *newName, BaseSens *(*callbackSensModule)());
    void removeModule(uint8_t index);
    void clearModules();
    
    // Access methods
    BaseSens &getModule(uint8_t index);
    BaseSens *getModulePtr(uint8_t index) const;
    BaseSens &getModuleByName(const char *searchName);
    BaseSens *getModuleByNamePtr(const char *searchName);
    
    template<typename T>
    T *getModule(const char *searchName, void (*getModuleCb)(T *) = nullptr);
    
    // Operators
    JsonVariant operator[](const char *searchName);
    JsonDocument operator()(const char *searchName);
    
    // Debug methods
    virtual void debug(const char *searchName, bool showHeapMemory = false, bool endl = true);
    virtual void debug(bool showHeapMemory = false);
    virtual void debug(uint32_t time, bool showHeapMemory = false, void (*debugCallback)() = nullptr);
    virtual void debugPretty(uint32_t time = 1000);
    
    // Utility
    void enable();
    void disable();
    bool isEnable() const;
    uint8_t getModuleCount() const;
};

Lifecycle Methods

init()

Initializes all registered sensors.
virtual void init(void (*initializeCallback)() = nullptr);
initializeCallback
void (*)()
default:"nullptr"
Optional callback function called after initialization completes
Behavior:
  • Calls init() on each registered sensor
  • Prints initialization status to Serial for each sensor
  • Automatically enables the sensor module
  • Executes callback if provided
Example:
SensorModule sensors;
sensors.addModule("DHT", new DHTSens(2, DHT22));
sensors.addModule("BME280", new BME280Sens());

void onSensorsReady() {
    Serial.println("All sensors initialized!");
}

sensors.init(onSensorsReady);
Serial Output:
| [NAME]: DHT [INFO]: Init Success
| [NAME]: BME280 [INFO]: Init Success

update()

Updates all sensors or a specific sensor.
virtual void update(void (*updateCallback)() = nullptr);
virtual void update(const char *searchName);
updateCallback
void (*)()
default:"nullptr"
Optional callback executed after updates (only when module is ready)
searchName
const char*
Name of specific sensor to update (overload)
Example:
// Update all sensors
sensors.update();

// Update specific sensor
sensors.update("DHT");

// Update with callback
sensors.update([]() {
    Serial.println("Sensors updated");
});

isReady()

Checks if the sensor module is ready for use.
virtual bool isReady(void (*readyCallback)() = nullptr);
readyCallback
void (*)()
default:"nullptr"
Optional callback executed when checking ready state
return
bool
true if module is initialized and ready

enable() / disable()

Enables or disables sensor updates.
void enable();
void disable();
bool isEnable() const;
Example:
sensors.disable();  // Pause sensor updates
// ... do something ...
sensors.enable();   // Resume updates

Module Management

addModule()

Adds a sensor to the module.
void addModule(BaseSens *sensModule);
void addModule(const char *newName, BaseSens *sensModule);
void addModule(const char *newName, BaseSens *(*callbackSensModule)());
newName
const char*
Unique identifier for the sensor
sensModule
BaseSens*
required
Pointer to the sensor instance
callbackSensModule
BaseSens* (*)()
Factory function that creates and returns a sensor instance
Example:
// Direct addition
sensors.addModule("DHT", new DHTSens(2, DHT22));

// Using factory function
BaseSens* createBME() {
    return new BME280Sens(0x76);
}
sensors.addModule("BME280", createBME);

// Without name (uses default indexing)
sensors.addModule(new AnalogSens(A0));

removeModule()

Removes a sensor by index.
void removeModule(uint8_t index);
index
uint8_t
required
Index of the sensor to remove (0-based)
This deletes the sensor object and shifts remaining sensors down.

clearModules()

Removes all sensors and frees memory.
void clearModules();
Example:
sensors.clearModules();  // Clean slate

Access Methods

getModule()

Retrieves a sensor by index or name.
BaseSens &getModule(uint8_t index);
BaseSens *getModulePtr(uint8_t index) const;
BaseSens &getModuleByName(const char *searchName);
BaseSens *getModuleByNamePtr(const char *searchName);
index
uint8_t
Zero-based sensor index
searchName
const char*
Sensor name identifier
Example:
// Access by index
BaseSens& sensor = sensors.getModule(0);

// Access by name
BaseSens* dht = sensors.getModuleByNamePtr("DHT");
if (dht) {
    dht->update();
}

getModule() (Template)

Retrieves a sensor with type casting.
template<typename T>
T *getModule(const char *searchName, void (*getModuleCb)(T *) = nullptr);
T
template
Specific sensor type (e.g., DHTSens)
searchName
const char*
required
Sensor name identifier
getModuleCb
void (*)(T*)
default:"nullptr"
Optional callback receiving the typed sensor pointer
return
T*
Pointer to the sensor cast to the specified type
Example:
DHTSens* dht = sensors.getModule<DHTSens>("DHT");
float temp = dht->getTemperature();
float humidity = dht->getHumidity();

// With callback
sensors.getModule<DHTSens>("DHT", [](DHTSens* dht) {
    Serial.print("Temp: ");
    Serial.println(dht->getTemperature());
});

getName()

Retrieves sensor names.
char *getName(uint8_t index) const;
char **getNames();
Example:
for (uint8_t i = 0; i < sensors.getModuleCount(); i++) {
    Serial.println(sensors.getName(i));
}

getModuleCount()

Returns the number of registered sensors.
uint8_t getModuleCount() const;

Operators

operator[]

Accesses sensor data as JSON variant.
JsonVariant operator[](const char *searchName);
searchName
const char*
required
Sensor name identifier
Example:
float temp = sensors["DHT"].as<float>();
JsonObject climate = sensors["BME280"].as<JsonObject>();
Serial.println(climate["temperature"].as<float>());

operator()

Retrieves the full JSON document for a sensor.
JsonDocument operator()(const char *searchName);
Example:
JsonDocument doc = sensors("DHT");
serializeJson(doc, Serial);

Debug Methods

debug()

Prints sensor values to Serial.
virtual void debug(const char *searchName, bool showHeapMemory = false, bool endl = true);
virtual void debug(bool showHeapMemory = false);
virtual void debug(uint32_t time, bool showHeapMemory = false, void (*debugCallback)() = nullptr);
searchName
const char*
Specific sensor to debug (omit for all)
showHeapMemory
bool
default:"false"
Include free heap memory in output
endl
bool
default:"true"
Print newline after output
time
uint32_t
Debug interval in milliseconds
debugCallback
void (*)()
default:"nullptr"
Callback executed before debug output
Example:
// Debug single sensor
sensors.debug("DHT", true);
// Output: | DHT: 25.5 | mem: 45632

// Debug all sensors
sensors.debug(true);
// Output: | DHT: 25.5 | BME280: [temperature] 24.8 [humidity] 65.2 | mem: 45632

// Periodic debug (in loop)
sensors.debug(1000, true);  // Print every 1 second

debugPretty()

Prints formatted JSON output.
virtual void debugPretty(uint32_t time = 1000);
time
uint32_t
default:"1000"
Output interval in milliseconds
Example:
// In loop()
sensors.debugPretty(2000);
Output:
{
  "DHT": 25.5,
  "BME280": {
    "temperature": 24.8,
    "humidity": 65.2,
    "pressure": 1013.25
  }
}

Utility Methods

setModule()

Replaces a sensor at a specific index.
void setModule(uint8_t index, BaseSens *sensModule);

swapModules()

Swaps two sensors by index.
void swapModules(uint8_t index1, uint8_t index2);

isModulePresent()

Checks if a sensor is registered.
bool isModulePresent(BaseSens *sensModule);
bool isModulePresent(uint8_t index);

Static Utility

static void print(const char *format, ...);
static void wait(uint32_t time);
Example:
SensorModule::print("Temperature: %.2f°C", temp);
SensorModule::wait(1000);  // delay(1000)

Complete Usage Example

#define ENABLE_SENSOR_MODULE_V1
#define ENABLE_SENSOR_DHT_V1
#define ENABLE_SENSOR_BME280_V1
#define ENABLE_SENSOR_ANALOG_V1
#include "Kinematrix.h"

SensorModule sensors;

void setup() {
    Serial.begin(115200);
    
    // Add sensors
    sensors.addModule("DHT", new DHTSens(2, DHT22));
    sensors.addModule("BME280", new BME280Sens());
    sensors.addModule("Soil", new AnalogSens(A0));
    
    // Initialize all
    sensors.init([]() {
        Serial.println("\n=== Sensors Ready ===");
    });
}

void loop() {
    // Update all sensors
    sensors.update();
    
    // Access by operator
    float dhtTemp = sensors["DHT"].as<float>();
    
    // Access specific sensor type
    DHTSens* dht = sensors.getModule<DHTSens>("DHT");
    if (dht) {
        float temp = dht->getTemperature();
        float humidity = dht->getHumidity();
        Serial.printf("DHT - Temp: %.1f°C, Humidity: %.1f%%\n", temp, humidity);
    }
    
    // Debug all sensors
    sensors.debug(true);
    
    // Pretty print every 5 seconds
    sensors.debugPretty(5000);
    
    delay(2000);
}

Memory Management

The SensorModule owns all added sensors and will delete them in its destructor or when calling clearModules(). Do not manually delete sensors after adding them.
Safe:
sensors.addModule("DHT", new DHTSens(2, DHT22));
// SensorModule will handle cleanup
Unsafe:
DHTSens* dht = new DHTSens(2, DHT22);
sensors.addModule("DHT", dht);
delete dht;  // DON'T DO THIS!

See Also

Build docs developers (and LLMs) love