@ -9,6 +9,7 @@ Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com>
# if SENSOR_SUPPORT
# if SENSOR_SUPPORT
# include <vector>
# include <vector>
# include "filters/LastFilter.h"
# include "filters/MaxFilter.h"
# include "filters/MaxFilter.h"
# include "filters/MedianFilter.h"
# include "filters/MedianFilter.h"
# include "filters/MovingAverageFilter.h"
# include "filters/MovingAverageFilter.h"
@ -34,6 +35,7 @@ unsigned char _counts[MAGNITUDE_MAX];
bool _sensor_realtime = API_REAL_TIME_VALUES ;
bool _sensor_realtime = API_REAL_TIME_VALUES ;
unsigned long _sensor_read_interval = 1000 * SENSOR_READ_INTERVAL ;
unsigned long _sensor_read_interval = 1000 * SENSOR_READ_INTERVAL ;
unsigned char _sensor_report_every = SENSOR_REPORT_EVERY ;
unsigned char _sensor_report_every = SENSOR_REPORT_EVERY ;
unsigned char _sensor_save_every = SENSOR_SAVE_EVERY ;
unsigned char _sensor_power_units = SENSOR_POWER_UNITS ;
unsigned char _sensor_power_units = SENSOR_POWER_UNITS ;
unsigned char _sensor_energy_units = SENSOR_ENERGY_UNITS ;
unsigned char _sensor_energy_units = SENSOR_ENERGY_UNITS ;
unsigned char _sensor_temperature_units = SENSOR_TEMPERATURE_UNITS ;
unsigned char _sensor_temperature_units = SENSOR_TEMPERATURE_UNITS ;
@ -100,7 +102,7 @@ bool _sensorWebSocketOnReceive(const char * key, JsonVariant& value) {
if ( strncmp ( key , " sns " , 3 ) = = 0 ) return true ;
if ( strncmp ( key , " sns " , 3 ) = = 0 ) return true ;
if ( strncmp ( key , " tmp " , 3 ) = = 0 ) return true ;
if ( strncmp ( key , " tmp " , 3 ) = = 0 ) return true ;
if ( strncmp ( key , " hum " , 3 ) = = 0 ) return true ;
if ( strncmp ( key , " hum " , 3 ) = = 0 ) return true ;
if ( strncmp ( key , " energy " , 6 ) = = 0 ) return true ;
if ( strncmp ( key , " ene " , 3 ) = = 0 ) return true ;
return false ;
return false ;
}
}
@ -127,8 +129,8 @@ void _sensorWebSocketSendData(JsonObject& root) {
element [ " error " ] = magnitude . sensor - > error ( ) ;
element [ " error " ] = magnitude . sensor - > error ( ) ;
if ( magnitude . type = = MAGNITUDE_ENERGY ) {
if ( magnitude . type = = MAGNITUDE_ENERGY ) {
if ( _sensor_energy_reset_ts . length ( ) = = 0 ) _sensorReset ( ) ;
element [ " description " ] = magnitude . sensor - > slot ( magnitude . local ) + _sensor_energy_reset_ts ;
if ( _sensor_energy_reset_ts . length ( ) = = 0 ) _sensorResetTS ( ) ;
element [ " description " ] = magnitude . sensor - > slot ( magnitude . local ) + String ( " (since " ) + _sensor_energy_reset_ts + String ( " ) " ) ;
} else {
} else {
element [ " description " ] = magnitude . sensor - > slot ( magnitude . local ) ;
element [ " description " ] = magnitude . sensor - > slot ( magnitude . local ) ;
}
}
@ -196,12 +198,13 @@ void _sensorWebSocketStart(JsonObject& root) {
root [ " snsVisible " ] = 1 ;
root [ " snsVisible " ] = 1 ;
//root["apiRealTime"] = _sensor_realtime;
//root["apiRealTime"] = _sensor_realtime;
root [ " pwrUnits " ] = _sensor_power_units ;
root [ " pwrUnits " ] = _sensor_power_units ;
root [ " energy Units " ] = _sensor_energy_units ;
root [ " eneUnits " ] = _sensor_energy_units ;
root [ " tmpUnits " ] = _sensor_temperature_units ;
root [ " tmpUnits " ] = _sensor_temperature_units ;
root [ " tmpCorrection " ] = _sensor_temperature_correction ;
root [ " tmpCorrection " ] = _sensor_temperature_correction ;
root [ " humCorrection " ] = _sensor_humidity_correction ;
root [ " humCorrection " ] = _sensor_humidity_correction ;
root [ " snsRead " ] = _sensor_read_interval / 1000 ;
root [ " snsRead " ] = _sensor_read_interval / 1000 ;
root [ " snsReport " ] = _sensor_report_every ;
root [ " snsReport " ] = _sensor_report_every ;
root [ " snsSave " ] = _sensor_save_every ;
}
}
/*
/*
@ -293,11 +296,18 @@ void _sensorPost() {
}
}
}
}
void _sensorReset ( ) {
void _sensorResetTS ( ) {
# if NTP_SUPPORT
# if NTP_SUPPORT
if ( ntpSynced ( ) ) {
if ( ntpSynced ( ) ) {
_sensor_energy_reset_ts = String ( " (since " ) + ntpDateTime ( ) + String ( " ) " ) ;
if ( _sensor_energy_reset_ts . length ( ) = = 0 ) {
_sensor_energy_reset_ts = ntpDateTime ( now ( ) - millis ( ) / 1000 ) ;
} else {
_sensor_energy_reset_ts = ntpDateTime ( now ( ) ) ;
}
} else {
_sensor_energy_reset_ts = String ( ) ;
}
}
setSetting ( " snsResetTS " , _sensor_energy_reset_ts ) ;
# endif
# endif
}
}
@ -613,6 +623,7 @@ void _sensorCallback(unsigned char i, unsigned char type, double value) {
void _sensorInit ( ) {
void _sensorInit ( ) {
_sensors_ready = true ;
_sensors_ready = true ;
_sensor_save_every = getSetting ( " snsSave " , 0 ) . toInt ( ) ;
for ( unsigned char i = 0 ; i < _sensors . size ( ) ; i + + ) {
for ( unsigned char i = 0 ; i < _sensors . size ( ) ; i + + ) {
@ -642,9 +653,11 @@ void _sensorInit() {
new_magnitude . filtered = 0 ;
new_magnitude . filtered = 0 ;
new_magnitude . reported = 0 ;
new_magnitude . reported = 0 ;
new_magnitude . min_change = 0 ;
new_magnitude . min_change = 0 ;
if ( type = = MAGNITUDE_DIGITAL ) {
if ( MAGNITUDE_ENERGY = = type ) {
new_magnitude . filter = new LastFilter ( ) ;
} else if ( MAGNITUDE_DIGITAL = = type ) {
new_magnitude . filter = new MaxFilter ( ) ;
new_magnitude . filter = new MaxFilter ( ) ;
} else if ( type = = MAGNITUDE_COUNT | | type = = MAGNITUDE_GEIGER_CPM | | type = = MAGNITUDE_GEIGER_SIEVERT ) { // For geiger counting moving average filter is the most appropriate if needed at all.
} else if ( MAGNITUDE_COUNT = = type | | MAGNITUDE_GEIGER_CPM = = type | | MAGNITUDE_GEIGER_SIEVERT = = type ) { // For geiger counting moving average filter is the most appropriate if needed at all.
new_magnitude . filter = new MovingAverageFilter ( ) ;
new_magnitude . filter = new MovingAverageFilter ( ) ;
} else {
} else {
new_magnitude . filter = new MedianFilter ( ) ;
new_magnitude . filter = new MedianFilter ( ) ;
@ -671,6 +684,8 @@ void _sensorInit() {
EmonAnalogSensor * sensor = ( EmonAnalogSensor * ) _sensors [ i ] ;
EmonAnalogSensor * sensor = ( EmonAnalogSensor * ) _sensors [ i ] ;
sensor - > setCurrentRatio ( 0 , getSetting ( " pwrRatioC " , EMON_CURRENT_RATIO ) . toFloat ( ) ) ;
sensor - > setCurrentRatio ( 0 , getSetting ( " pwrRatioC " , EMON_CURRENT_RATIO ) . toFloat ( ) ) ;
sensor - > setVoltage ( getSetting ( " pwrVoltage " , EMON_MAINS_VOLTAGE ) . toInt ( ) ) ;
sensor - > setVoltage ( getSetting ( " pwrVoltage " , EMON_MAINS_VOLTAGE ) . toInt ( ) ) ;
double value = ( _sensor_save_every > 0 ) ? getSetting ( " eneTotal " , 0 ) . toInt ( ) : 0 ;
if ( value > 0 ) sensor - > resetEnergy ( 0 , value ) ;
}
}
# endif // EMON_ANALOG_SUPPORT
# endif // EMON_ANALOG_SUPPORT
@ -692,6 +707,9 @@ void _sensorInit() {
value = getSetting ( " pwrRatioP " , HLW8012_POWER_RATIO ) . toFloat ( ) ;
value = getSetting ( " pwrRatioP " , HLW8012_POWER_RATIO ) . toFloat ( ) ;
if ( value > 0 ) sensor - > setPowerRatio ( value ) ;
if ( value > 0 ) sensor - > setPowerRatio ( value ) ;
value = ( _sensor_save_every > 0 ) ? getSetting ( " eneTotal " , 0 ) . toInt ( ) : 0 ;
if ( value > 0 ) sensor - > resetEnergy ( value ) ;
}
}
# endif // HLW8012_SUPPORT
# endif // HLW8012_SUPPORT
@ -713,6 +731,9 @@ void _sensorInit() {
value = getSetting ( " pwrRatioP " , 0 ) . toFloat ( ) ;
value = getSetting ( " pwrRatioP " , 0 ) . toFloat ( ) ;
if ( value > 0 ) sensor - > setPowerRatio ( value ) ;
if ( value > 0 ) sensor - > setPowerRatio ( value ) ;
value = ( _sensor_save_every > 0 ) ? getSetting ( " eneTotal " , 0 ) . toInt ( ) : 0 ;
if ( value > 0 ) sensor - > resetEnergy ( value ) ;
}
}
# endif // CSE7766_SUPPORT
# endif // CSE7766_SUPPORT
@ -726,12 +747,14 @@ void _sensorConfigure() {
// General sensor settings
// General sensor settings
_sensor_read_interval = 1000 * constrain ( getSetting ( " snsRead " , SENSOR_READ_INTERVAL ) . toInt ( ) , SENSOR_READ_MIN_INTERVAL , SENSOR_READ_MAX_INTERVAL ) ;
_sensor_read_interval = 1000 * constrain ( getSetting ( " snsRead " , SENSOR_READ_INTERVAL ) . toInt ( ) , SENSOR_READ_MIN_INTERVAL , SENSOR_READ_MAX_INTERVAL ) ;
_sensor_report_every = constrain ( getSetting ( " snsReport " , SENSOR_REPORT_EVERY ) . toInt ( ) , SENSOR_REPORT_MIN_EVERY , SENSOR_REPORT_MAX_EVERY ) ;
_sensor_report_every = constrain ( getSetting ( " snsReport " , SENSOR_REPORT_EVERY ) . toInt ( ) , SENSOR_REPORT_MIN_EVERY , SENSOR_REPORT_MAX_EVERY ) ;
_sensor_save_every = getSetting ( " snsSave " , SENSOR_SAVE_EVERY ) . toInt ( ) ;
_sensor_realtime = getSetting ( " apiRealTime " , API_REAL_TIME_VALUES ) . toInt ( ) = = 1 ;
_sensor_realtime = getSetting ( " apiRealTime " , API_REAL_TIME_VALUES ) . toInt ( ) = = 1 ;
_sensor_power_units = getSetting ( " pwrUnits " , SENSOR_POWER_UNITS ) . toInt ( ) ;
_sensor_power_units = getSetting ( " pwrUnits " , SENSOR_POWER_UNITS ) . toInt ( ) ;
_sensor_energy_units = getSetting ( " energy Units " , SENSOR_ENERGY_UNITS ) . toInt ( ) ;
_sensor_energy_units = getSetting ( " eneUnits " , SENSOR_ENERGY_UNITS ) . toInt ( ) ;
_sensor_temperature_units = getSetting ( " tmpUnits " , SENSOR_TEMPERATURE_UNITS ) . toInt ( ) ;
_sensor_temperature_units = getSetting ( " tmpUnits " , SENSOR_TEMPERATURE_UNITS ) . toInt ( ) ;
_sensor_temperature_correction = getSetting ( " tmpCorrection " , SENSOR_TEMPERATURE_CORRECTION ) . toFloat ( ) ;
_sensor_temperature_correction = getSetting ( " tmpCorrection " , SENSOR_TEMPERATURE_CORRECTION ) . toFloat ( ) ;
_sensor_humidity_correction = getSetting ( " humCorrection " , SENSOR_HUMIDITY_CORRECTION ) . toFloat ( ) ;
_sensor_humidity_correction = getSetting ( " humCorrection " , SENSOR_HUMIDITY_CORRECTION ) . toFloat ( ) ;
_sensor_energy_reset_ts = getSetting ( " snsResetTS " , " " ) ;
// Specific sensor settings
// Specific sensor settings
for ( unsigned char i = 0 ; i < _sensors . size ( ) ; i + + ) {
for ( unsigned char i = 0 ; i < _sensors . size ( ) ; i + + ) {
@ -755,7 +778,8 @@ void _sensorConfigure() {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
sensor - > resetEnergy ( ) ;
sensor - > resetEnergy ( ) ;
_sensorReset ( ) ;
delSetting ( " eneTotal " ) ;
_sensorResetTS ( ) ;
}
}
sensor - > setVoltage ( getSetting ( " pwrVoltage " , EMON_MAINS_VOLTAGE ) . toInt ( ) ) ;
sensor - > setVoltage ( getSetting ( " pwrVoltage " , EMON_MAINS_VOLTAGE ) . toInt ( ) ) ;
@ -769,7 +793,8 @@ void _sensorConfigure() {
EmonADC121Sensor * sensor = ( EmonADC121Sensor * ) _sensors [ i ] ;
EmonADC121Sensor * sensor = ( EmonADC121Sensor * ) _sensors [ i ] ;
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
sensor - > resetEnergy ( ) ;
sensor - > resetEnergy ( ) ;
_sensorReset ( ) ;
delSetting ( " eneTotal " ) ;
_sensorResetTS ( ) ;
}
}
}
}
# endif
# endif
@ -779,7 +804,8 @@ void _sensorConfigure() {
EmonADS1X15Sensor * sensor = ( EmonADS1X15Sensor * ) _sensors [ i ] ;
EmonADS1X15Sensor * sensor = ( EmonADS1X15Sensor * ) _sensors [ i ] ;
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
sensor - > resetEnergy ( ) ;
sensor - > resetEnergy ( ) ;
_sensorReset ( ) ;
delSetting ( " eneTotal " ) ;
_sensorResetTS ( ) ;
}
}
}
}
# endif
# endif
@ -809,7 +835,8 @@ void _sensorConfigure() {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
sensor - > resetEnergy ( ) ;
sensor - > resetEnergy ( ) ;
_sensorReset ( ) ;
delSetting ( " eneTotal " ) ;
_sensorResetTS ( ) ;
}
}
if ( getSetting ( " pwrResetCalibration " , 0 ) . toInt ( ) = = 1 ) {
if ( getSetting ( " pwrResetCalibration " , 0 ) . toInt ( ) = = 1 ) {
@ -847,7 +874,8 @@ void _sensorConfigure() {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
if ( getSetting ( " pwrResetE " , 0 ) . toInt ( ) = = 1 ) {
sensor - > resetEnergy ( ) ;
sensor - > resetEnergy ( ) ;
_sensorReset ( ) ;
delSetting ( " eneTotal " ) ;
_sensorResetTS ( ) ;
}
}
if ( getSetting ( " pwrResetCalibration " , 0 ) . toInt ( ) = = 1 ) {
if ( getSetting ( " pwrResetCalibration " , 0 ) . toInt ( ) = = 1 ) {
@ -868,6 +896,11 @@ void _sensorConfigure() {
_magnitudes [ i ] . filter - > resize ( _sensor_report_every ) ;
_magnitudes [ i ] . filter - > resize ( _sensor_report_every ) ;
}
}
// General processing
if ( 0 = = _sensor_save_every ) {
delSetting ( " eneTotal " ) ;
}
// Save settings
// Save settings
delSetting ( " pwrExpectedP " ) ;
delSetting ( " pwrExpectedP " ) ;
delSetting ( " pwrExpectedC " ) ;
delSetting ( " pwrExpectedC " ) ;
@ -1024,6 +1057,7 @@ void sensorSetup() {
// Backwards compatibility
// Backwards compatibility
moveSetting ( " powerUnits " , " pwrUnits " ) ;
moveSetting ( " powerUnits " , " pwrUnits " ) ;
moveSetting ( " energyUnits " , " eneUnits " ) ;
// Load sensors
// Load sensors
_sensorLoad ( ) ;
_sensorLoad ( ) ;
@ -1074,6 +1108,7 @@ void sensorLoop() {
// Check if we should read new data
// Check if we should read new data
static unsigned long last_update = 0 ;
static unsigned long last_update = 0 ;
static unsigned long report_count = 0 ;
static unsigned long report_count = 0 ;
static unsigned long save_count = 0 ;
if ( millis ( ) - last_update > _sensor_read_interval ) {
if ( millis ( ) - last_update > _sensor_read_interval ) {
last_update = millis ( ) ;
last_update = millis ( ) ;
@ -1097,6 +1132,10 @@ void sensorLoop() {
if ( magnitude . sensor - > status ( ) ) {
if ( magnitude . sensor - > status ( ) ) {
// -------------------------------------------------------------
// Instant value
// -------------------------------------------------------------
current = magnitude . sensor - > value ( magnitude . local ) ;
current = magnitude . sensor - > value ( magnitude . local ) ;
// Completely remove spurious values if relay is OFF
// Completely remove spurious values if relay is OFF
@ -1113,17 +1152,26 @@ void sensorLoop() {
}
}
# endif
# endif
// -------------------------------------------------------------
// Processing (filters)
// -------------------------------------------------------------
magnitude . filter - > add ( current ) ;
magnitude . filter - > add ( current ) ;
// Special case
if ( magnitude . type = = MAGNITUDE_COUNT ) {
// Special case for MovingAvergaeFilter
if ( MAGNITUDE_COUNT = = magnitude . type | |
MAGNITUDE_GEIGER_CPM = = magnitude . type | |
MAGNITUDE_GEIGER_SIEVERT = = magnitude . type ) {
current = magnitude . filter - > result ( ) ;
current = magnitude . filter - > result ( ) ;
}
}
current = _magnitudeProcess ( magnitude . type , current ) ;
current = _magnitudeProcess ( magnitude . type , current ) ;
_magnitudes [ i ] . current = current ;
_magnitudes [ i ] . current = current ;
// -------------------------------------------------------------
// Debug
// Debug
// -------------------------------------------------------------
# if SENSOR_DEBUG
# if SENSOR_DEBUG
{
{
char buffer [ 64 ] ;
char buffer [ 64 ] ;
@ -1137,8 +1185,12 @@ void sensorLoop() {
}
}
# endif // SENSOR_DEBUG
# endif // SENSOR_DEBUG
// Time to report (we do it every _sensor_report_every readings)
if ( report_count = = 0 ) {
// -------------------------------------------------------------
// Report
// (we do it every _sensor_report_every readings)
// -------------------------------------------------------------
if ( 0 = = report_count ) {
filtered = magnitude . filter - > result ( ) ;
filtered = magnitude . filter - > result ( ) ;
magnitude . filter - > reset ( ) ;
magnitude . filter - > reset ( ) ;
@ -1147,13 +1199,30 @@ void sensorLoop() {
// Check if there is a minimum change threshold to report
// Check if there is a minimum change threshold to report
if ( fabs ( filtered - magnitude . reported ) > = magnitude . min_change ) {
if ( fabs ( filtered - magnitude . reported ) > = magnitude . min_change ) {
_magnitudes [ i ] . reported = filtered ;
_magnitudes [ i ] . reported = filtered ;
_sensorReport ( i , filtered ) ;
_sensorReport ( i , filtered ) ;
} // if (fabs(filtered - magnitude.reported) >= magnitude.min_change)
} // if (fabs(filtered - magnitude.reported) >= magnitude.min_change)
// -------------------------------------------------------------
// Saving to EEPROM
// (we do it every _sensor_save_every readings)
// -------------------------------------------------------------
if ( _sensor_save_every > 0 ) {
save_count = ( save_count + 1 ) % _sensor_save_every ;
if ( 0 = = save_count ) {
if ( MAGNITUDE_ENERGY = = magnitude . type ) {
setSetting ( " eneTotal " , current ) ;
saveSettings ( ) ;
}
} // if (0 == save_count)
} // if (_sensor_save_every > 0)
} // if (report_count == 0)
} // if (report_count == 0)
} // if (magnitude.sensor->status())
} // if (magnitude.sensor->status())
} // for (unsigned char i=0; i<_magnitudes.size(); i++)
} // for (unsigned char i=0; i<_magnitudes.size(); i++)