Overview
SensorModuleV2 is the modern container class that manages multiple BaseSensV2 sensors. It provides type-safe access, real-time filtering, threshold alerts, and advanced debugging capabilities.
Header: lib/sensors/SensorModuleV2/SensorModule/SensorModuleV2.h
Class Definition
class SensorModuleV2 {
public:
SensorModuleV2 ();
~SensorModuleV2 ();
// Lifecycle
void init ();
void update ();
// Sensor management
void addSensor ( const char * name , BaseSensV2 * sensor );
void addSensor ( const char * name , SensorCreateCallback callbackSensModule );
// Access
BaseSensV2 * getSensor ( uint8_t index ) const ;
BaseSensV2 * getSensorByName ( const char * name ) const ;
template < typename T >
T getValue ( const char * sensorName , const char * valueKey ) const ;
// Filtering system
bool attachFilter ( const char * sensorName , const char * valueKey ,
FilterType type , FilterParams params );
float getFilteredValue ( const char * sensorName , const char * valueKey );
// Alert system
bool setThreshold ( const char * sensorName , const char * valueKey ,
float lowThreshold , float highThreshold ,
AlertType type = ALERT_OUTSIDE);
void setGlobalAlertCallback ( AlertCallback callback );
// Debug
void debugAll ( bool showHeapMemory = false );
void debugPretty ( uint32_t time = 1000 );
};
Lifecycle Methods
init()
Initializes all registered sensors.
Behavior:
Creates shared JSON document
Calls init() on each sensor
Prints initialization status to Serial
Stores initialization status for each sensor
Example:
SensorModuleV2 sensors;
sensors . addSensor ( "temp" , new DHTSensV2 ( 2 , DHT22));
sensors . addSensor ( "gas" , new MQSensV2 (A0, MQ135));
sensors . init ();
Serial Output:
| [NAME]: temp [INFO]: Init Success
| [NAME]: gas [INFO]: Init Success
update()
Updates all sensors and processes filters/alerts.
Behavior:
Calls update() on each initialized sensor
Updates all attached filters with new values
Checks all threshold alerts
Triggers alert callbacks if thresholds are violated
Example:
void loop () {
sensors . update ();
// Access updated values
float temp = sensors . getValue < float > ( "temp" , "temperature" );
Serial . println (temp);
delay ( 1000 );
}
Sensor Management
addSensor()
Adds a sensor to the module.
void addSensor ( const char * name , BaseSensV2 * sensor );
void addSensor ( const char * name , SensorCreateCallback callbackSensModule );
Unique identifier for the sensor
Pointer to the sensor instance
Factory function: BaseSensV2* (*)()
Example:
// Direct addition
sensors . addSensor ( "temp" , new DHTSensV2 ( 2 , DHT22));
// Using factory function
BaseSensV2 * createGasSensor () {
return new MQSensV2 (A0, MQ135);
}
sensors . addSensor ( "gas" , createGasSensor);
Call addSensor() before init(). Sensors added after initialization will not be properly configured.
getSensor()
Retrieves a sensor by index or name.
BaseSensV2 * getSensor ( uint8_t index ) const ;
BaseSensV2 * getSensorByName ( const char * name ) const ;
const char * getSensorName ( uint8_t index ) const ;
uint8_t getSensorCount () const ;
Example:
BaseSensV2 * sensor = sensors . getSensorByName ( "temp" );
if (sensor) {
float temp = sensor -> getFloatValue ( "temperature" );
}
// Iterate all sensors
for ( uint8_t i = 0 ; i < sensors . getSensorCount (); i ++ ) {
Serial . println ( sensors . getSensorName (i));
}
Type-Safe Value Access
getValue()
Retrieves a typed value from a sensor.
template < typename T >
T getValue ( const char * sensorName , const char * valueKey ) const ;
Value type (float, int, bool, const char*, etc.)
Value key within the sensor
The requested value with type safety
Example:
float temperature = sensors . getValue < float > ( "temp" , "temperature" );
int humidity = sensors . getValue < int > ( "temp" , "humidity" );
bool status = sensors . getValue < bool > ( "temp" , "valid" );
isUpdated()
Checks if a sensor was updated in the last cycle.
bool isUpdated ( const char * sensorName ) const ;
Example:
sensors . update ();
if ( sensors . isUpdated ( "temp" )) {
float temp = sensors . getValue < float > ( "temp" , "temperature" );
Serial . println (temp);
}
Filtering System
attachFilter()
Attaches a real-time filter to a sensor value.
bool attachFilter ( const char * sensorName , const char * valueKey ,
FilterType type , FilterParams params );
Filter configuration parameters
true if filter was attached successfully
FilterType Enum:
enum FilterType {
FILTER_NONE ,
FILTER_MOVING_AVERAGE ,
FILTER_MEDIAN ,
FILTER_KALMAN ,
FILTER_EXPONENTIAL
};
FilterParams Structure:
struct FilterParams {
union {
struct { uint8_t windowSize; } movingAverage;
struct { uint8_t windowSize; } median;
struct {
float processNoise;
float measurementNoise;
float estimateError;
} kalman;
struct { float alpha; } exponential;
};
};
Example:
// Moving average filter (window size 10)
FilterParams maParams;
maParams . movingAverage . windowSize = 10 ;
sensors . attachFilter ( "temp" , "temperature" , FILTER_MOVING_AVERAGE, maParams);
// Kalman filter
FilterParams kalmanParams;
kalmanParams . kalman . processNoise = 0.01 f ;
kalmanParams . kalman . measurementNoise = 0.1 f ;
kalmanParams . kalman . estimateError = 1.0 f ;
sensors . attachFilter ( "accel" , "x" , FILTER_KALMAN, kalmanParams);
// Exponential filter (alpha = 0.2)
FilterParams expParams;
expParams . exponential . alpha = 0.2 f ;
sensors . attachFilter ( "sensor" , "value" , FILTER_EXPONENTIAL, expParams);
getFilteredValue()
Retrieves the filtered value.
float getFilteredValue ( const char * sensorName , const char * valueKey );
float getLastFilteredValue ( const char * sensorName , const char * valueKey );
Example:
sensors . update ();
float rawTemp = sensors . getValue < float > ( "temp" , "temperature" );
float filteredTemp = sensors . getFilteredValue ( "temp" , "temperature" );
Serial . printf ( "Raw: %.2f , Filtered: %.2f \n " , rawTemp, filteredTemp);
Filter Management
bool updateFilter ( const char * sensorName , const char * valueKey ,
FilterType type , FilterParams params );
bool detachFilter ( const char * sensorName , const char * valueKey );
void detachAllFilters ();
void resetFilter ( const char * sensorName , const char * valueKey );
void resetAllFilters ();
bool hasFilter ( const char * sensorName , const char * valueKey );
FilterType getFilterType ( const char * sensorName , const char * valueKey );
Example:
// Check if filter exists
if ( sensors . hasFilter ( "temp" , "temperature" )) {
FilterType type = sensors . getFilterType ( "temp" , "temperature" );
}
// Reset filter state
sensors . resetFilter ( "temp" , "temperature" );
// Remove filter
sensors . detachFilter ( "temp" , "temperature" );
Alert System
setThreshold()
Configures a threshold alert for a sensor value.
bool setThreshold ( const char * sensorName , const char * valueKey ,
float lowThreshold , float highThreshold ,
AlertType type = ALERT_OUTSIDE);
type
AlertType
default: "ALERT_OUTSIDE"
Alert trigger condition
AlertType Enum:
enum AlertType {
ALERT_ABOVE , // Trigger when value > highThreshold
ALERT_BELOW , // Trigger when value < lowThreshold
ALERT_BETWEEN , // Trigger when lowThreshold < value < highThreshold
ALERT_OUTSIDE // Trigger when value < lowThreshold OR value > highThreshold
};
Example:
// Alert if temperature outside 20-30°C range
sensors . setThreshold ( "temp" , "temperature" , 20.0 f , 30.0 f , ALERT_OUTSIDE);
// Alert if humidity below 40%
sensors . setThreshold ( "temp" , "humidity" , 40.0 f , 100.0 f , ALERT_BELOW);
// Alert if CO2 above 1000 ppm
sensors . setThreshold ( "air" , "co2" , 0.0 f , 1000.0 f , ALERT_ABOVE);
setGlobalAlertCallback()
Sets a callback for all alert events.
void setGlobalAlertCallback ( AlertCallback callback );
bool setSensorAlertCallback ( const char * sensorName , AlertCallback callback );
void clearAlertCallbacks ();
AlertCallback Type:
typedef void (* AlertCallback )( AlertInfo alertInfo );
struct AlertInfo {
char * sensorName;
char * valueKey;
float currentValue;
float lowThreshold;
float highThreshold;
AlertType type;
AlertState state;
uint32_t timeTriggered;
uint8_t repeatCount;
};
AlertState Enum:
enum AlertState {
ALERT_INACTIVE , // No alert condition
ALERT_ACTIVE , // Alert triggered
ALERT_ACKNOWLEDGED // Alert acknowledged by user
};
Example:
void onAlert ( AlertInfo info ) {
Serial . printf ( "ALERT! %s / %s = %.2f (threshold: %.2f - %.2f ) \n " ,
info . sensorName , info . valueKey , info . currentValue ,
info . lowThreshold , info . highThreshold );
if ( info . state == ALERT_ACTIVE) {
// Trigger alarm, send notification, etc.
digitalWrite (ALARM_PIN, HIGH);
}
}
sensors . setGlobalAlertCallback (onAlert);
// Sensor-specific callback
sensors . setSensorAlertCallback ( "temp" , []( AlertInfo info ) {
Serial . println ( "Temperature alert!" );
});
Alert Management
AlertState getAlertState ( const char * sensorName , const char * valueKey );
bool isAlertActive ( const char * sensorName , const char * valueKey );
void acknowledgeAlert ( const char * sensorName , const char * valueKey );
void acknowledgeAllAlerts ();
void resetAlert ( const char * sensorName , const char * valueKey );
void resetAllAlerts ();
bool removeThreshold ( const char * sensorName , const char * valueKey );
void removeAllThresholds ();
Example:
if ( sensors . isAlertActive ( "temp" , "temperature" )) {
AlertState state = sensors . getAlertState ( "temp" , "temperature" );
if (state == ALERT_ACTIVE) {
// User acknowledged the alert
sensors . acknowledgeAlert ( "temp" , "temperature" );
}
}
Alert Configuration
bool setThresholdParams ( const char * sensorName , const char * valueKey ,
uint32_t hysteresis , uint32_t debounceTime );
void setDefaultHysteresis ( uint32_t hysteresis );
void setDefaultDebounceTime ( uint32_t debounceTime );
Hysteresis value to prevent rapid toggling (in same units as threshold)
Minimum time in milliseconds before triggering alert
Example:
// Set defaults for all new thresholds
sensors . setDefaultHysteresis ( 2 ); // 2 units
sensors . setDefaultDebounceTime ( 5000 ); // 5 seconds
// Override for specific threshold
sensors . setThreshold ( "temp" , "temperature" , 20.0 f , 30.0 f );
sensors . setThresholdParams ( "temp" , "temperature" , 1 , 3000 );
Debug Methods
debugAll()
Prints all sensor values to Serial.
void debugAll ( bool showHeapMemory = false );
void debugHorizontal ( bool showHeapMemory = false );
void debugHorizontalWithTime ( uint32_t time , bool showHeapMemory = false );
Include free heap memory in output
Debug interval in milliseconds (for timed variants)
Example:
// Print all values
sensors . debugAll ();
// Horizontal format with memory
sensors . debugHorizontal ( true );
// Periodic debug (in loop)
sensors . debugHorizontalWithTime ( 1000 , true );
debugPretty()
Prints formatted JSON output.
void debugPretty ( uint32_t time = 1000 );
Output interval in milliseconds
Example:
void loop () {
sensors . update ();
sensors . debugPretty ( 2000 ); // Print every 2 seconds
}
Output:
{
"temp" : {
"temperature" : 25.5 ,
"humidity" : 65.2
},
"gas" : {
"ppm" : 450.3
}
}
debug()
Debug specific sensor/value.
void debug ( const char * sensorName , const char * valueKey , bool showHeapMemory = false );
Example:
sensors . debug ( "temp" , "temperature" , true );
System Control
enableAlertSystem() / enableFilterSystem()
Enables or disables subsystems.
void enableAlertSystem ( bool enable = true );
bool hasAlertSystem () const ;
void enableFilterSystem ( bool enable = true );
bool hasFilterSystem () const ;
Example:
// Disable alerts temporarily
sensors . enableAlertSystem ( false );
// Re-enable
sensors . enableAlertSystem ( true );
if ( sensors . hasAlertSystem ()) {
Serial . println ( "Alerts active" );
}
Complete Usage Example
#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_DHT_V2
#define ENABLE_SENSOR_MQ_V2
#include "Kinematrix.h"
SensorModuleV2 sensors;
void onTemperatureAlert ( AlertInfo info ) {
Serial . printf ( "⚠️ Temperature alert: %.1f °C \n " , info . currentValue );
digitalWrite (LED_PIN, HIGH);
}
void setup () {
Serial . begin ( 115200 );
pinMode (LED_PIN, OUTPUT);
// Add sensors
sensors . addSensor ( "climate" , new DHTSensV2 ( 2 , DHT22));
sensors . addSensor ( "airquality" , new MQSensV2 (A0, MQ135));
// Initialize
sensors . init ();
// Configure moving average filter for temperature
FilterParams maParams;
maParams . movingAverage . windowSize = 10 ;
sensors . attachFilter ( "climate" , "temperature" , FILTER_MOVING_AVERAGE, maParams);
// Configure Kalman filter for gas sensor
FilterParams kalmanParams;
kalmanParams . kalman . processNoise = 0.01 f ;
kalmanParams . kalman . measurementNoise = 0.5 f ;
kalmanParams . kalman . estimateError = 1.0 f ;
sensors . attachFilter ( "airquality" , "ppm" , FILTER_KALMAN, kalmanParams);
// Set temperature alert (20-30°C safe range)
sensors . setThreshold ( "climate" , "temperature" , 20.0 f , 30.0 f , ALERT_OUTSIDE);
sensors . setSensorAlertCallback ( "climate" , onTemperatureAlert);
// Set air quality alert (CO2 > 1000 ppm)
sensors . setThreshold ( "airquality" , "ppm" , 0.0 f , 1000.0 f , ALERT_ABOVE);
Serial . println ( "System ready!" );
}
void loop () {
// Update all sensors (also updates filters and checks alerts)
sensors . update ();
// Get raw and filtered values
float rawTemp = sensors . getValue < float > ( "climate" , "temperature" );
float filteredTemp = sensors . getFilteredValue ( "climate" , "temperature" );
Serial . printf ( "Temp: %.1f °C (filtered: %.1f °C) \n " , rawTemp, filteredTemp);
// Check if updated
if ( sensors . isUpdated ( "climate" )) {
int humidity = sensors . getValue < int > ( "climate" , "humidity" );
Serial . printf ( "Humidity: %d%% \n " , humidity);
}
// Pretty debug every 5 seconds
sensors . debugPretty ( 5000 );
delay ( 2000 );
}
Key Features
Type Safety Template-based getValue() with compile-time type checking
Real-Time Filtering Moving Average, Median, Kalman, and Exponential filters
Threshold Alerts Configurable alerts with callbacks and hysteresis
Metadata Labels, units, precision for each sensor value
See Also