Browse Source

sns: fix implementation method qualifiers

some swserial migrations
also make sure we use pstrs
pull/2516/head
Maxim Prokhorov 2 years ago
parent
commit
f896d9863d
18 changed files with 522 additions and 498 deletions
  1. +43
    -43
      code/espurna/sensors/CSE7766Sensor.h
  2. +36
    -41
      code/espurna/sensors/DHTSensor.h
  3. +16
    -15
      code/espurna/sensors/DigitalSensor.h
  4. +41
    -35
      code/espurna/sensors/DummySensor.h
  5. +28
    -23
      code/espurna/sensors/ECH1560Sensor.h
  6. +10
    -15
      code/espurna/sensors/EmonADC121Sensor.h
  7. +10
    -8
      code/espurna/sensors/EmonADS1X15Sensor.h
  8. +18
    -24
      code/espurna/sensors/GUVAS12SDSensor.h
  9. +21
    -21
      code/espurna/sensors/HLW8012Sensor.h
  10. +17
    -19
      code/espurna/sensors/PM1006Sensor.h
  11. +106
    -78
      code/espurna/sensors/PMSX003Sensor.h
  12. +22
    -14
      code/espurna/sensors/PZEM004TSensor.h
  13. +14
    -13
      code/espurna/sensors/PZEM004TV30Sensor.h
  14. +14
    -20
      code/espurna/sensors/SDS011Sensor.h
  15. +36
    -38
      code/espurna/sensors/SI7021Sensor.h
  16. +29
    -34
      code/espurna/sensors/SM300D2Sensor.h
  17. +34
    -26
      code/espurna/sensors/SonarSensor.h
  18. +27
    -31
      code/espurna/sensors/T6613Sensor.h

+ 43
- 43
code/espurna/sensors/CSE7766Sensor.h View File

@ -31,10 +31,16 @@ class CSE7766Sensor : public BaseEmonSensor {
MAGNITUDE_ENERGY
};
CSE7766Sensor() {
_sensor_id = SENSOR_CSE7766_ID;
_count = std::size(Magnitudes);
findAndAddEnergy(Magnitudes);
CSE7766Sensor() :
BaseEmonSensor(Magnitudes)
{}
unsigned char id() const override {
return SENSOR_CSE7766_ID;
}
unsigned char count() const override {
return std::size(Magnitudes);
}
// ---------------------------------------------------------------------
@ -53,11 +59,11 @@ class CSE7766Sensor : public BaseEmonSensor {
// ---------------------------------------------------------------------
unsigned char getRX() {
unsigned char getRX() const {
return _pin_rx;
}
bool getInverted() {
bool getInverted() const {
return _inverted;
}
@ -97,7 +103,7 @@ class CSE7766Sensor : public BaseEmonSensor {
// ---------------------------------------------------------------------
// Initialization method, must be idempotent
void begin() {
void begin() override {
resetRatios();
@ -125,33 +131,29 @@ class CSE7766Sensor : public BaseEmonSensor {
}
// Descriptive name of the sensor
String description() {
char buffer[28];
String description() const override {
if (_serial_is_hardware()) {
snprintf(buffer, sizeof(buffer), "CSE7766 @ HwSerial");
return F("CSE7766 @ HwSerial");
} else {
snprintf(buffer, sizeof(buffer), "CSE7766 @ SwSerial(%u,NULL)", _pin_rx);
char buffer[28];
snprintf_P(buffer, sizeof(buffer),
PSTR("CSE7766 @ SwSerial(%u,NULL)"), _pin_rx);
return String(buffer);
}
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
return String(_pin_rx);
String address(unsigned char) const override {
return String(_pin_rx, 10);
}
// Loop-like method, call it in your main loop
void tick() {
void tick() override {
_read();
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index < std::size(Magnitudes)) {
return Magnitudes[index].type;
}
@ -160,7 +162,7 @@ class CSE7766Sensor : public BaseEmonSensor {
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _current;
if (index == 1) return _voltage;
if (index == 2) return _active;
@ -184,7 +186,7 @@ class CSE7766Sensor : public BaseEmonSensor {
* "
* @return bool
*/
bool _checksum() {
bool _checksum() const {
unsigned char checksum = 0;
for (unsigned char i = 2; i < 23; i++) {
checksum += _data[i];
@ -198,38 +200,36 @@ class CSE7766Sensor : public BaseEmonSensor {
// 55 5A 02 E9 50 00 03 31 00 3E 9E 00 0D 30 4F 44 F8 00 12 65 F1 81 76 72 (w/ load)
// F2 5A 02 E9 50 00 03 2B 00 3E 9E 02 D7 7C 4F 44 F8 CF A5 5D E1 B3 2A B4 (w/o load)
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] CSE7766: _process: ");
for (byte i=0; i<24; i++) DEBUG_MSG("%02X ", _data[i]);
DEBUG_MSG("\n");
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: _process: %s\n"), hexEncode(_data).c_str());
#endif
// Checksum
if (!_checksum()) {
_error = SENSOR_ERROR_CRC;
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] CSE7766: Checksum error\n");
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Checksum error\n"));
#endif
return;
}
// Calibration
if (0xAA == _data[0]) {
_error = SENSOR_ERROR_CALIBRATION;
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] CSE7766: Chip not calibrated\n");
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Chip not calibrated\n"));
#endif
return;
}
if ((_data[0] & 0xFC) > 0xF0) {
_error = SENSOR_ERROR_OTHER;
#if SENSOR_DEBUG
if (0xF1 == (_data[0] & 0xF1)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Abnormal coefficient storage area\n"));
if (0xF2 == (_data[0] & 0xF2)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Power cycle exceeded range\n"));
if (0xF4 == (_data[0] & 0xF4)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Current cycle exceeded range\n"));
if (0xF8 == (_data[0] & 0xF8)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Voltage cycle exceeded range\n"));
#endif
#if SENSOR_DEBUG
if (0xF1 == (_data[0] & 0xF1)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Abnormal coefficient storage area\n"));
if (0xF2 == (_data[0] & 0xF2)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Power cycle exceeded range\n"));
if (0xF4 == (_data[0] & 0xF4)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Current cycle exceeded range\n"));
if (0xF8 == (_data[0] & 0xF8)) DEBUG_MSG_P(PSTR("[SENSOR] CSE7766: Voltage cycle exceeded range\n"));
#endif
return;
}
@ -348,7 +348,7 @@ class CSE7766Sensor : public BaseEmonSensor {
return (3 == _pin_rx) || (13 == _pin_rx);
}
bool _serial_available() {
bool _serial_available() const {
if (_serial_is_hardware()) {
return Serial.available();
} else {
@ -364,7 +364,7 @@ class CSE7766Sensor : public BaseEmonSensor {
}
}
uint8_t _serial_read() {
uint8_t _serial_read() const {
if (_serial_is_hardware()) {
return Serial.read();
} else {
@ -374,7 +374,7 @@ class CSE7766Sensor : public BaseEmonSensor {
// ---------------------------------------------------------------------
int _pin_rx = CSE7766_RX_PIN;
unsigned char _pin_rx = CSE7766_RX_PIN;
bool _inverted = CSE7766_PIN_INVERSE;
std::unique_ptr<SoftwareSerial> _serial;


+ 36
- 41
code/espurna/sensors/DHTSensor.h View File

@ -12,10 +12,10 @@
#include "../utils.h"
#include "BaseSensor.h"
constexpr const double DHT_DUMMY_VALUE = -255;
constexpr const size_t DHT_MAX_DATA = 5;
constexpr const size_t DHT_MAX_ERRORS = 5;
constexpr const uint32_t DHT_MIN_INTERVAL = 2000;
static constexpr double DHT_DUMMY_VALUE = -255;
static constexpr size_t DHT_MAX_DATA = 5;
static constexpr size_t DHT_MAX_ERRORS = 5;
static constexpr uint32_t DHT_MIN_INTERVAL = 2000;
enum class DHTChipType {
DHT11,
@ -36,19 +36,19 @@ enum class DHTChipType {
int dhtchip_to_number(DHTChipType chip) {
switch (chip) {
case DHTChipType::DHT11:
return 11;
case DHTChipType::DHT12:
return 12;
case DHTChipType::DHT21:
case DHTChipType::AM2301:
return 21;
case DHTChipType::DHT22:
case DHTChipType::SI7021:
return 22;
default:
return -1;
case DHTChipType::DHT11:
return 11;
case DHTChipType::DHT12:
return 12;
case DHTChipType::DHT21:
case DHTChipType::AM2301:
return 21;
case DHTChipType::DHT22:
case DHTChipType::SI7021:
return 22;
}
return -1;
}
class DHTSensor : public BaseSensor {
@ -59,11 +59,6 @@ class DHTSensor : public BaseSensor {
// Public
// ---------------------------------------------------------------------
DHTSensor() {
_count = 2;
_sensor_id = SENSOR_DHTXX_ID;
}
~DHTSensor() {
gpioUnlock(_gpio);
}
@ -80,15 +75,15 @@ class DHTSensor : public BaseSensor {
// ---------------------------------------------------------------------
unsigned char getGPIO() {
unsigned char getGPIO() const {
return _gpio;
}
int getType() {
int getType() const {
return dhtchip_to_number(_type);
}
DHTChipType getChipType() {
DHTChipType getChipType() const {
return _type;
}
@ -96,10 +91,16 @@ class DHTSensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
// Initialization method, must be idempotent
void begin() {
unsigned char id() const override {
return SENSOR_DHTXX_ID;
}
_count = 0;
unsigned char count() const override {
return 2;
}
// Initialization method, must be idempotent
void begin() override {
// Manage GPIO lock (note that this only handles the basic *hw* I/O)
if (_previous != GPIO_NONE) {
@ -115,44 +116,38 @@ class DHTSensor : public BaseSensor {
// Set now to fail the check in _read at least once
_last_ok = millis();
_count = 2;
_ready = true;
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
void pre() override {
_error = SENSOR_ERROR_OK;
_read();
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[20];
snprintf(buffer, sizeof(buffer), "DHT%d @ GPIO%d", dhtchip_to_number(_type), _gpio);
snprintf_P(buffer, sizeof(buffer),
"DHT%d @ GPIO%hhu", dhtchip_to_number(_type), _gpio);
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
return String(_gpio);
String address(unsigned char) const override {
return String(_gpio, 10);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_TEMPERATURE;
if (index == 1) return MAGNITUDE_HUMIDITY;
return MAGNITUDE_NONE;
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _temperature;
if (index == 1) return _humidity;
return 0;


+ 16
- 15
code/espurna/sensors/DigitalSensor.h View File

@ -14,15 +14,6 @@ class DigitalSensor : public BaseSensor {
public:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
DigitalSensor() {
_count = 1;
_sensor_id = SENSOR_DIGITAL_ID;
}
// ---------------------------------------------------------------------
void setGPIO(unsigned char gpio) {
@ -55,38 +46,48 @@ class DigitalSensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_DIGITAL_ID;
}
unsigned char count() const override {
return 1;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
pinMode(_gpio, _mode);
_ready = true;
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[20];
snprintf(buffer, sizeof(buffer), "DIGITAL @ GPIO%d", _gpio);
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
String description(unsigned char) const override {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
String address(unsigned char) const override {
return String(_gpio);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_DIGITAL;
return MAGNITUDE_NONE;
}
// Current value for slot # index
double value(unsigned char index) {
if (index == 0) return (digitalRead(_gpio) == _default) ? 0 : 1;
if (index == 0) {
return (digitalRead(_gpio) == _default) ? 0 : 1;
}
return 0;
}


+ 41
- 35
code/espurna/sensors/DummySensor.h View File

@ -14,13 +14,19 @@ Copyright (C) 2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
struct DummySensor : public BaseSensor {
DummySensor() :
_temperature(25.0),
_humidity(50.0),
_pressure(1000.0),
_lux(0.0)
{
_count = 4;
static constexpr Magnitude Magnitudes[] {
MAGNITUDE_TEMPERATURE,
MAGNITUDE_HUMIDITY,
MAGNITUDE_PRESSURE,
MAGNITUDE_LUX,
};
unsigned char id() const override {
return 0;
}
unsigned char count() const override {
return std::size(Magnitudes);
}
void begin() override {
@ -28,37 +34,36 @@ struct DummySensor : public BaseSensor {
_error = SENSOR_ERROR_OK;
}
String description() override {
static String dummy(F("Dummy"));
return dummy;
}
String description(unsigned char) override {
return description();
String description() const override {
return F("DummySensor");
}
String address(unsigned char) override {
static String dummy(F("/dev/null"));
return dummy;
String address(unsigned char) const override {
return F("/dev/null");
}
unsigned char type(unsigned char index) override {
switch (index) {
case 0: return MAGNITUDE_TEMPERATURE;
case 1: return MAGNITUDE_HUMIDITY;
case 2: return MAGNITUDE_PRESSURE;
case 3: return MAGNITUDE_LUX;
unsigned char type(unsigned char index) const override {
if (index < std::size(Magnitudes)) {
return Magnitudes[index].type;
}
return MAGNITUDE_NONE;
}
double value(unsigned char index) override {
switch (index) {
case 0: return _temperature;
case 1: return _humidity;
case 2: return _pressure;
case 3: return _lux;
if (index < std::size(Magnitudes)) {
switch (Magnitudes[index].type) {
case MAGNITUDE_TEMPERATURE:
return _temperature;
case MAGNITUDE_HUMIDITY:
return _humidity;
case MAGNITUDE_PRESSURE:
return _pressure;
case MAGNITUDE_LUX:
return _lux;
}
}
return 0.0;
}
@ -85,12 +90,13 @@ struct DummySensor : public BaseSensor {
}
}
private:
double _temperature;
double _humidity;
double _pressure;
double _lux;
private:
double _temperature { 25.0 };
double _humidity { 50.0 };
double _pressure { 1000.0 };
double _lux { 0.0 };
};
#if __cplusplus < 201703L
constexpr BaseSensor::Magnitude DummySensor::Magnitudes[];
#endif

+ 28
- 23
code/espurna/sensors/ECH1560Sensor.h View File

@ -25,11 +25,9 @@ class ECH1560Sensor : public BaseEmonSensor {
MAGNITUDE_ENERGY
};
ECH1560Sensor() {
_sensor_id = SENSOR_ECH1560_ID;
_count = std::size(Magnitudes);
findAndAddEnergy(Magnitudes);
}
ECH1560Sensor() :
BaseEmonSensor(Magnitudes)
{}
// ---------------------------------------------------------------------
@ -51,15 +49,15 @@ class ECH1560Sensor : public BaseEmonSensor {
// ---------------------------------------------------------------------
unsigned char getCLK() {
unsigned char getCLK() const {
return _clk.pin();
}
unsigned char getMISO() {
unsigned char getMISO() const {
return _miso;
}
bool getInverted() {
bool getInverted() const {
return _inverted;
}
@ -67,8 +65,16 @@ class ECH1560Sensor : public BaseEmonSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_ECH1560_ID;
}
unsigned char count() const override {
return std::size(Magnitudes);
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) return;
@ -82,31 +88,30 @@ class ECH1560Sensor : public BaseEmonSensor {
}
// Loop-like method, call it in your main loop
void tick() {
if (_dosync) _sync();
void tick() override {
if (_dosync) {
_sync();
}
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[35];
snprintf(buffer, sizeof(buffer), "ECH1560 (CLK,SDO) @ GPIO(%hhu,%hhu)", _clk.pin(), _miso);
snprintf_P(buffer, sizeof(buffer),
PSTR("ECH1560 (CLK,SDO) @ GPIO(%hhu,%hhu)"), _clk.pin(), _miso);
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
char buffer[6];
snprintf(buffer, sizeof(buffer), "%hhu:%hhu", _clk.pin(), _miso);
String address(unsigned char) const override {
char buffer[8];
snprintf_P(buffer, sizeof(buffer),
PSTR("%hhu:%hhu"), _clk.pin(), _miso);
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index < std::size(Magnitudes)) {
return Magnitudes[index].type;
}
@ -115,7 +120,7 @@ class ECH1560Sensor : public BaseEmonSensor {
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _current;
if (index == 1) return _voltage;
if (index == 2) return _apparent;


+ 10
- 15
code/espurna/sensors/EmonADC121Sensor.h View File

@ -36,9 +36,8 @@ private:
{}
bool lock(uint8_t address) {
static uint8_t addresses[] = {0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5A};
return _sensor_address.lock(address) || _sensor_address.findAndLock(sizeof(addresses), addresses);
static constexpr uint8_t addresses[] {0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5A};
return _sensor_address.lock(address) || _sensor_address.findAndLock(addresses);
}
bool lock() {
@ -55,10 +54,6 @@ private:
};
public:
EmonADC121Sensor() {
_sensor_id = SENSOR_EMON_ADC121_ID;
}
void setAddress(uint8_t address) {
if (_address != address) {
_address = address;
@ -67,7 +62,7 @@ public:
}
unsigned int analogRead() override {
constexpr uint16_t Mask { 0x0fff };
static constexpr uint16_t Mask { 0x0fff };
return i2c_read_uint16(_port.address(), ADC121_REG_RESULT) & Mask;
}
@ -75,8 +70,12 @@ public:
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_EMON_ADC121_ID;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) {
return;
}
@ -98,7 +97,7 @@ public:
}
// Descriptive name of the sensor
String description() override {
String description() const override {
char buffer[30];
snprintf_P(buffer, sizeof(buffer),
PSTR("EMON @ ADC121 A0 @ I2C (0x%02X)"),
@ -106,11 +105,7 @@ public:
return String(buffer);
}
String description(unsigned char) override {
return description();
}
String address(unsigned char) override {
String address(unsigned char) const override {
char buffer[10];
snprintf(buffer, sizeof(buffer), "A0 @ 0x%02X", _port.address());
return String(buffer);


+ 10
- 8
code/espurna/sensors/EmonADS1X15Sensor.h View File

@ -113,8 +113,8 @@ public:
{}
bool lock(uint8_t address) {
static uint8_t addresses[] = {0x48, 0x49, 0x4A, 0x4B};
return _sensor_address.lock(address) || _sensor_address.findAndLock(sizeof(addresses), addresses);
static constexpr uint8_t addresses[] {0x48, 0x49, 0x4A, 0x4B};
return _sensor_address.lock(address) || _sensor_address.findAndLock(addresses);
}
bool lock() {
@ -198,9 +198,7 @@ public:
EmonADS1X15Sensor() = delete;
EmonADS1X15Sensor(PortPtr port) :
_port(port)
{
_sensor_id = SENSOR_EMON_ADS1X15_ID;
}
{}
// ---------------------------------------------------------------------
@ -215,6 +213,10 @@ public:
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_EMON_ADS1X15_ID;
}
// Initialization method, must be idempotent
void begin() override {
if (!_dirty) {
@ -235,7 +237,7 @@ public:
}
// Descriptive name of the sensor
String description() override {
String description() const override {
char buffer[30];
snprintf_P(buffer, sizeof(buffer),
PSTR("EMON @ ADS1%c15 @ I2C (0x%02X)"),
@ -245,7 +247,7 @@ public:
}
// Descriptive name of the slot # index
String description(unsigned char) override {
String description(unsigned char) const override {
char buffer[35];
snprintf_P(buffer, sizeof(buffer),
PSTR("EMON @ ADS1%c15 (A%hhu) @ I2C (0x%02X)"),
@ -255,7 +257,7 @@ public:
}
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char) override {
String address(unsigned char) const override {
char buffer[18];
snprintf_P(buffer, sizeof(buffer),
PSTR("A%hhu @ I2C (0x%02X)"),


+ 18
- 24
code/espurna/sensors/GUVAS12SDSensor.h View File

@ -31,15 +31,6 @@ class GUVAS12SDSensor : public BaseSensor {
public:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
GUVAS12SDSensor() {
_count = 1;
_sensor_id = SENSOR_GUVAS12SD_ID;
}
~GUVAS12SDSensor() {
gpioUnlock(_gpio);
}
@ -52,7 +43,7 @@ class GUVAS12SDSensor : public BaseSensor {
// ---------------------------------------------------------------------
unsigned char getGPIO() {
unsigned char getGPIO() const {
return _gpio;
}
@ -60,8 +51,16 @@ class GUVAS12SDSensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_GUVAS12SD_ID;
}
unsigned char count() const override {
return 1;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
// Manage GPIO lock
if (_previous != GPIO_NONE) {
@ -80,41 +79,36 @@ class GUVAS12SDSensor : public BaseSensor {
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
void pre() override {
_error = SENSOR_ERROR_OK;
_read();
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[18];
snprintf(buffer, sizeof(buffer), "GUVAS12SD @ GPIO%hhu", _gpio);
snprintf_P(buffer, sizeof(buffer),
PSTR("GUVAS12SD @ GPIO%hhu"), _gpio);
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
return String(_gpio);
String address(unsigned char) const override {
return String(_gpio, 10);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_UVI;
return MAGNITUDE_NONE;
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _uvindex;
return 0;
}
protected:
// ---------------------------------------------------------------------


+ 21
- 21
code/espurna/sensors/HLW8012Sensor.h View File

@ -98,15 +98,17 @@ class HLW8012Sensor : public BaseEmonSensor {
MAGNITUDE_ENERGY
};
unsigned char count() const override {
return std::size(Magnitudes);
}
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
HLW8012Sensor() {
_sensor_id = SENSOR_HLW8012_ID;
_count = std::size(Magnitudes);
findAndAddEnergy(Magnitudes);
}
HLW8012Sensor()
: BaseEmonSensor(Magnitudes)
{}
~HLW8012Sensor() {
_disableInterrupts();
@ -189,19 +191,19 @@ class HLW8012Sensor : public BaseEmonSensor {
// ---------------------------------------------------------------------
unsigned char getSEL() {
unsigned char getSEL() const {
return _sel;
}
unsigned char getCF() {
unsigned char getCF() const {
return _cf.pin();
}
unsigned char getCF1() {
unsigned char getCF1() const {
return _cf1.pin();
}
unsigned char getSELCurrent() {
unsigned char getSELCurrent() const {
return _sel_current;
}
@ -209,9 +211,12 @@ class HLW8012Sensor : public BaseEmonSensor {
// Sensors API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_HLW8012_ID;
}
// Initialization method, must be idempotent
// Defined outside the class body
void begin() {
void begin() override {
// Initialize HLW8012
// void begin(unsigned char cf_pin, unsigned char cf1_pin, unsigned char sel_pin, unsigned char currentWhen = HIGH, bool use_interrupts = false, unsigned long pulse_timeout = PULSE_TIMEOUT);
@ -237,20 +242,15 @@ class HLW8012Sensor : public BaseEmonSensor {
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[28];
snprintf_P(buffer, sizeof(buffer),
PSTR("HLW8012 @ GPIO(%hhu,%hhu,%hhu)"), _sel, _cf.pin(), _cf1.pin());
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
}
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char) {
String address(unsigned char) const override {
char buffer[12];
snprintf_P(buffer, sizeof(buffer),
PSTR("%hhu:%hhu:%hhu"), _sel, _cf.pin(), _cf1.pin());
@ -258,7 +258,7 @@ class HLW8012Sensor : public BaseEmonSensor {
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index < std::size(Magnitudes)) {
return Magnitudes[index].type;
}
@ -266,7 +266,7 @@ class HLW8012Sensor : public BaseEmonSensor {
return MAGNITUDE_NONE;
}
double getEnergyDelta() {
double getEnergyDelta() const {
return _energy_last;
}
@ -295,7 +295,7 @@ class HLW8012Sensor : public BaseEmonSensor {
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
void pre() override {
if (_hlw8012_use_interrupts() && _hlw8012_wait_for_wifi()) {
if (wifiConnected()) {
_enableInterrupts();


+ 17
- 19
code/espurna/sensors/PM1006Sensor.h View File

@ -21,11 +21,6 @@ class PM1006Sensor : public BaseSensor {
// Public
// ---------------------------------------------------------------------
PM1006Sensor() {
_count = 1;
_sensor_id = SENSOR_PM1006_ID;
}
~PM1006Sensor() {
if (_serial) delete _serial;
}
@ -48,8 +43,16 @@ class PM1006Sensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_PM1006_ID;
}
unsigned char count() const override {
return 1;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) return;
@ -73,7 +76,7 @@ class PM1006Sensor : public BaseSensor {
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[28];
if (_serial_is_hardware()) {
snprintf(buffer, sizeof(buffer), "PM1006 @ HwSerial");
@ -83,32 +86,27 @@ class PM1006Sensor : public BaseSensor {
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char) {
return description();
}
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
String address(unsigned char index) const override {
char buffer[4];
snprintf(buffer, sizeof(buffer), "%hhu", _pin_rx);
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_PM2DOT5;
return MAGNITUDE_NONE;
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _pm25;
return 0;
}
// Process sensor UART
void tick() {
void tick() override {
_read();
}
@ -150,13 +148,13 @@ class PM1006Sensor : public BaseSensor {
void _parse() {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] PM1006: %s\n", hexEncode(_buffer).c_str());
DEBUG_MSG_P(PSTR("[SENSOR] PM1006: %s\n"), hexEncode(_buffer).c_str());
#endif
// check second header byte
if ((_buffer[1] != 0x11) || (_buffer[2] != 0x0B)) {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] PM1006: Wrong header\n");
DEBUG_MSG_P(PSTR("[SENSOR] PM1006: Wrong header\n"));
#endif
return;
}
@ -166,7 +164,7 @@ class PM1006Sensor : public BaseSensor {
for (unsigned char i=0; i<20; i++) crc += _buffer[i];
if (crc != 0) {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] PM1006: Wrong CRC\n");
DEBUG_MSG_P(PSTR("[SENSOR] PM1006: Wrong CRC\n"));
#endif
return;
}


+ 106
- 78
code/espurna/sensors/PMSX003Sensor.h View File

@ -26,23 +26,15 @@
// Sensor type specified data
#define PMS_SLOT_MAX 4
#define PMS_DATA_MAX 17
const static struct {
const char *name;
unsigned char data_count;
unsigned char slot_count;
unsigned char slot_types[PMS_SLOT_MAX];
} pms_specs[] = {
{"PMSX003", 13, 3, {MAGNITUDE_PM1DOT0, MAGNITUDE_PM2DOT5, MAGNITUDE_PM10}},
{"PMSX003_9", 9, 3, {MAGNITUDE_PM1DOT0, MAGNITUDE_PM2DOT5, MAGNITUDE_PM10}},
{"PMS5003T", 13, 3, {MAGNITUDE_PM2DOT5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY}},
{"PMS5003ST", 17, 4, {MAGNITUDE_PM2DOT5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY, MAGNITUDE_HCHO}},
{"PMS5003S", 13, 3, {MAGNITUDE_PM2DOT5, MAGNITUDE_PM10, MAGNITUDE_HCHO}},
};
// [MAGIC][LEN][DATA9|13|17][SUM]
#define PMS_PACKET_SIZE(data_count) ((data_count + 3) * 2)
#define PMS_PAYLOAD_SIZE(data_count) ((data_count + 1) * 2)
inline int PMS_PACKET_SIZE(int size) {
return (size + 3) * 2;
}
inline int PMS_PAYLOAD_SIZE(int size) {
return (size + 1) * 2;
}
// PMS sensor utils
// Command functions copied from: https://github.com/fu-hsi/PMS/blob/master/src/PMS.cpp
@ -50,49 +42,49 @@ const static struct {
class PMSX003 {
protected:
Stream *_serial = NULL; // Should initialized by child class
Stream *_serial = nullptr; // Should initialized by child class
public:
// Standby mode. For low power consumption and prolong the life of the sensor.
inline void sleep() {
uint8_t command[] = { 0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73 };
const uint8_t command[] { 0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73 };
_serial->write(command, sizeof(command));
}
// Operating mode. Stable data should be got at least 30 seconds after the sensor wakeup from the sleep mode because of the fan's performance.
inline void wakeUp() {
uint8_t command[] = { 0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74 };
const uint8_t command[] { 0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74 };
_serial->write(command, sizeof(command));
}
// Active mode. Default mode after power up. In this mode sensor would send serial data to the host automatically.
inline void activeMode() {
uint8_t command[] = { 0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71 };
const uint8_t command[] { 0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71 };
_serial->write(command, sizeof(command));
}
// Passive mode. In this mode, sensor would send serial data to the host only for request.
inline void passiveMode() {
uint8_t command[] = { 0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70 };
const uint8_t command[] { 0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70 };
_serial->write(command, sizeof(command));
}
// Request read, ONLY needed in Passive Mode!!
inline void requestRead() {
uint8_t command[] = { 0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71 };
const uint8_t command[] { 0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71 };
_serial->write(command, sizeof(command));
}
// Read sensor's data
bool readData(uint16_t data[], unsigned char data_count) {
bool readData(uint16_t* data, size_t data_count) {
do {
int avail = _serial->available();
#if SENSOR_DEBUG
//DEBUG_MSG("[SENSOR] PMS: Packet available = %d\n", avail);
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] PMS: Packet available = %d\n"), avail);
#endif
if (avail < PMS_PACKET_SIZE(data_count)) {
break;
}
@ -102,26 +94,27 @@ class PMSX003 {
uint16_t sum = 0x42 + 0x4D;
uint16_t size = read16(sum);
if (size != PMS_PAYLOAD_SIZE(data_count)) {
#if SENSOR_DEBUG
DEBUG_MSG(("[SENSOR] PMS: Payload size: %d != %d.\n"), size, PMS_PAYLOAD_SIZE(data_count));
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] PMS: Payload size: %hu != %zu.\n"),
size, PMS_PAYLOAD_SIZE(data_count));
#endif
break;
}
for (int i = 0; i < data_count; i++) {
for (size_t i = 0; i < data_count; i++) {
data[i] = read16(sum);
#if SENSOR_DEBUG
//DEBUG_MSG(("[SENSOR] PMS: data[%d] = %d\n"), i, data[i]);
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] PMS: data[%zu] = %hu\n"), i, data[i]);
#endif
}
uint16_t checksum = read16();
if (sum == checksum) {
return true;
} else {
#if SENSOR_DEBUG
DEBUG_MSG(("[SENSOR] PMS checksum: %04X != %04X\n"), sum, checksum);
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] PMS checksum: %04X != %04X\n"), sum, checksum);
#endif
}
break;
}
@ -135,7 +128,7 @@ class PMSX003 {
private:
// Read 16-bit
inline uint16_t read16() {
uint16_t read16() {
return ((uint16_t) _serial->read()) << 8 | _serial->read();
}
@ -152,15 +145,24 @@ class PMSX003 {
class PMSX003Sensor : public BaseSensor, PMSX003 {
public:
private:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
PMSX003Sensor() {
_count = pms_specs[_type].slot_count;
_sensor_id = SENSOR_PMSX003_ID;
}
struct Spec {
const char *name;
unsigned char data_count;
unsigned char slot_count;
unsigned char slot_types[PMS_SLOT_MAX];
};
static constexpr Spec Specs[] {
{"PMSX003", 13, 3, {MAGNITUDE_PM1DOT0, MAGNITUDE_PM2DOT5, MAGNITUDE_PM10}},
{"PMSX003_9", 9, 3, {MAGNITUDE_PM1DOT0, MAGNITUDE_PM2DOT5, MAGNITUDE_PM10}},
{"PMS5003T", 13, 3, {MAGNITUDE_PM2DOT5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY}},
{"PMS5003ST", 17, 4, {MAGNITUDE_PM2DOT5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY, MAGNITUDE_HCHO}},
{"PMS5003S", 13, 3, {MAGNITUDE_PM2DOT5, MAGNITUDE_PM10, MAGNITUDE_HCHO}},
};
public:
~PMSX003Sensor() {
removeSerial();
@ -187,7 +189,6 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
// Should call setType after constructor immediately to enable corresponding slot count
void setType(unsigned char type) {
_type = type;
_count = pms_specs[_type].slot_count;
}
// ---------------------------------------------------------------------
@ -208,8 +209,16 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_PMSX003_ID;
}
unsigned char count() const override {
return Specs[_type].slot_count;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) return;
@ -227,61 +236,73 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
passiveMode();
_startTime = millis();
_startTime = TimeSource::now();
_warmedUp = false;
_ready = true;
_dirty = false;
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[28];
if (_soft) {
snprintf(buffer, sizeof(buffer), "%s @ SwSerial(%u,%u)", pms_specs[_type].name, _pin_rx, _pin_tx);
snprintf_P(buffer, sizeof(buffer),
PSTR("%s @ SwSerial(%u,%u)"),
Specs[_type].name, _pin_rx, _pin_tx);
} else {
snprintf(buffer, sizeof(buffer), "%s @ HwSerial", pms_specs[_type].name);
snprintf_P(buffer, sizeof(buffer),
PSTR("%s @ HwSerial"), Specs[_type].name);
}
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
String description(unsigned char index) const override {
char buffer[36] = {0};
if (_soft) {
snprintf(buffer, sizeof(buffer), "%d @ %s @ SwSerial(%u,%u)", int(index + 1), pms_specs[_type].name, _pin_rx, _pin_tx);
snprintf_P(buffer, sizeof(buffer),
PSTR("%d @ %s @ SwSerial(%u,%u)"),
int(index + 1), Specs[_type].name, _pin_rx, _pin_tx);
} else {
snprintf(buffer, sizeof(buffer), "%d @ %s @ HwSerial", int(index + 1), pms_specs[_type].name);
snprintf_P(buffer, sizeof(buffer),
PSTR("%d @ %s @ HwSerial"),
int(index + 1), Specs[_type].name);
}
return String(buffer);
}
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
String address(unsigned char index) const override {
char buffer[6];
snprintf(buffer, sizeof(buffer), "%u:%u", _pin_rx, _pin_tx);
snprintf(buffer, sizeof(buffer), "%hhu:%hhu", _pin_rx, _pin_tx);
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) {
return pms_specs[_type].slot_types[index];
unsigned char type(unsigned char index) const override {
return Specs[_type].slot_types[index];
}
void pre() {
void pre() override {
if (millis() - _startTime < 30000) {
static constexpr auto WarmupDuration = espurna::duration::Seconds(30);
if (!_warmedUp && TimeSource::now() - _startTime < WarmupDuration) {
_error = SENSOR_ERROR_WARM_UP;
return;
}
_warmedUp = true;
#if PMS_SMART_SLEEP
unsigned int readCycle;
if (_readCount++ > 30) {
readCycle = _readCount % 30;
if (readCycle == 0) {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] %s: Wake up: %d\n", pms_specs[_type].name, _readCount);
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] %s: Wake up: %d\n"),
Specs[_type].name, _readCount);
#endif
wakeUp();
return;
} else if (readCycle == 1) {
@ -298,7 +319,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
#endif
uint16_t data[PMS_DATA_MAX];
if (readData(data, pms_specs[_type].data_count)) {
if (readData(data, Specs[_type].data_count)) {
if (_type == PMS_TYPE_5003ST) {
if (data[14] > 10 && data[14] < 1000 && data[13] < 1000) {
_slot_values[0] = data[4];
@ -308,9 +329,10 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
_error = SENSOR_ERROR_OK;
} else {
_error = SENSOR_ERROR_OUT_OF_RANGE;
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] %s: Invalid temperature=%d humidity=%d.\n", pms_specs[_type].name, (int)data[13], (int)data[14]);
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] %s: Invalid temperature=%d humidity=%d.\n"),
Specs[_type].name, (int)data[13], (int)data[14]);
#endif
}
} else if (_type == PMS_TYPE_5003S) {
_slot_values[0] = data[4];
@ -325,9 +347,10 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
_error = SENSOR_ERROR_OK;
} else {
_error = SENSOR_ERROR_OUT_OF_RANGE;
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] %s: Invalid temperature=%d humidity=%d.\n", pms_specs[_type].name, (int)data[10], (int)data[11]);
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] %s: Invalid temperature=%d humidity=%d.\n"),
Specs[_type].name, (int)data[10], (int)data[11]);
#endif
}
} else {
_slot_values[0] = data[3];
@ -340,9 +363,10 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
#if PMS_SMART_SLEEP
if (readCycle == 6) {
sleep();
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] %s: Enter sleep mode: %d\n", pms_specs[_type].name, _readCount);
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] %s: Enter sleep mode: %d\n"),
Specs[_type].name, _readCount);
#endif
return;
}
#endif
@ -352,7 +376,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
return _slot_values[index];
}
@ -365,15 +389,19 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
protected:
bool _soft = true;
unsigned int _pin_rx;
unsigned int _pin_tx;
unsigned long _startTime;
unsigned char _pin_rx;
unsigned char _pin_tx;
using TimeSource = espurna::time::CoreClock;
TimeSource::time_point _startTime;
bool _warmedUp = false;
unsigned char _type = PMS_TYPE_X003;
double _slot_values[PMS_SLOT_MAX] = {0};
#if PMS_SMART_SLEEP
unsigned int _readCount = 0;
#endif
#if PMS_SMART_SLEEP
size_t _readCount = 0;
#endif
};


+ 22
- 14
code/espurna/sensors/PZEM004TSensor.h View File

@ -267,15 +267,22 @@ public:
private:
PZEM004TSensor(PortPtr port, IPAddress address) :
BaseEmonSensor(Magnitudes),
_port(port),
_address(address)
{
_sensor_id = SENSOR_PZEM004T_ID;
_count = std::size(Magnitudes);
findAndAddEnergy(Magnitudes);
}
{}
public:
using BaseEmonSensor::type;
unsigned char id() const override {
return SENSOR_PZEM004T_ID;
}
unsigned char count() const override {
return std::size(Magnitudes);
}
PZEM004TSensor() = delete;
static PZEM004TSensor* make(PortPtr port, IPAddress address) {
@ -351,21 +358,22 @@ public:
// ---------------------------------------------------------------------
// Initialization method, must be idempotent
void begin() {
void begin() override {
_dirty = false;
_ready = static_cast<bool>(_port);
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[32];
snprintf(buffer, sizeof(buffer), "PZEM004T @ %sSerial(%hhu,%hhu)",
snprintf_P(buffer, sizeof(buffer),
PSTR("PZEM004T @ %sSerial(%hhu,%hhu)"),
_port->tag(), _port->rx(), _port->tx());
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
String description(unsigned char) const override {
String out;
out.reserve(48);
@ -377,12 +385,12 @@ public:
}
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char) {
String address(unsigned char) const override {
return _address.toString();
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index < std::size(Magnitudes)) {
return Magnitudes[index].type;
}
@ -391,7 +399,7 @@ public:
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
double response { 0.0 };
if (index < std::size(Magnitudes)) {
@ -419,12 +427,12 @@ public:
}
// Post-read hook (usually to reset things)
void post() {
void post() override {
_error = SENSOR_ERROR_OK;
}
// Loop-like method, call it in your main loop
void tick() {
void tick() override {
static_assert(std::size(Magnitudes) > 0, "");
if (!_head_instance || (_current_instance != this)) {
return;


+ 14
- 13
code/espurna/sensors/PZEM004TV30Sensor.h View File

@ -555,12 +555,20 @@ public:
MAGNITUDE_POWER_FACTOR
};
unsigned char id() const override {
return SENSOR_PZEM004TV30_ID;
}
unsigned char count() const override {
return std::size(Magnitudes);
}
void begin() override {
_last_reading = millis() - _update_interval;
_ready = true;
}
String description() override {
String description() const override {
static const String base(F("PZEM004T V3.0"));
return base + " @ "
+ _port->tag()
@ -568,15 +576,11 @@ public:
+ String(_address, 16);
}
String description(unsigned char) override {
return description();
}
String address(unsigned char) override {
String address(unsigned char) const override {
return String(_address, 16);
}
unsigned char type(unsigned char index) override {
unsigned char type(unsigned char index) const override {
if (index < std::size(Magnitudes)) {
return Magnitudes[index].type;
}
@ -619,12 +623,9 @@ public:
}
private:
PZEM004TV30Sensor() {
_sensor_id = SENSOR_PZEM004TV30_ID;
_error = SENSOR_ERROR_OK;
_count = std::size(Magnitudes);
findAndAddEnergy(Magnitudes);
}
PZEM004TV30Sensor() :
BaseEmonSensor(Magnitudes)
{}
static uint8_t _address;
static unsigned long _read_timeout;


+ 14
- 20
code/espurna/sensors/SDS011Sensor.h View File

@ -19,15 +19,6 @@ class SDS011Sensor : public BaseSensor {
public:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
SDS011Sensor() {
_count = 2;
_sensor_id = SENSOR_SDS011_ID;
}
~SDS011Sensor() {
if (_serial) delete _serial;
}
@ -60,8 +51,16 @@ class SDS011Sensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_SDS011_ID;
}
unsigned char count() const override {
return 2;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) return;
@ -75,37 +74,32 @@ class SDS011Sensor : public BaseSensor {
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[28];
snprintf(buffer, sizeof(buffer), "SDS011 @ SwSerial(%u,%u)", _pin_rx, _pin_tx);
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
String address(unsigned char) const override {
char buffer[6];
snprintf(buffer, sizeof(buffer), "%u:%u", _pin_rx, _pin_tx);
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_PM2DOT5;
if (index == 1) return MAGNITUDE_PM10;
return MAGNITUDE_NONE;
}
void pre() {
void pre() override {
_read();
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _p2dot5;
if (index == 1) return _p10;
return 0;


+ 36
- 38
code/espurna/sensors/SI7021Sensor.h View File

@ -29,26 +29,26 @@ class SI7021Sensor : public I2CSensor<> {
public:
// ---------------------------------------------------------------------
// Public
// Sensor API
// ---------------------------------------------------------------------
SI7021Sensor() {
_sensor_id = SENSOR_SI7021_ID;
unsigned char id() const override {
return SENSOR_SI7021_ID;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
unsigned char count() const override {
return 2;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) return;
_init();
_dirty = !_ready;
}
// Descriptive name of the sensor
String description() {
String description() const override {
char name[10];
strncpy_P(name,
_chip == SI7021_CHIP_SI7021 ?
@ -57,44 +57,49 @@ class SI7021Sensor : public I2CSensor<> {
sizeof(name)
);
char buffer[25];
snprintf(buffer, sizeof(buffer), "%s @ I2C (0x%02X)", name, _address);
snprintf(buffer, sizeof(buffer), "%s @ I2C (0x%02X)", name, getAddress());
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
String description(unsigned char index) const override {
return description();
};
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_TEMPERATURE;
if (index == 1) return MAGNITUDE_HUMIDITY;
return MAGNITUDE_NONE;
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
void pre() override {
_error = SENSOR_ERROR_UNKNOWN_ID;
if (_chip == 0) return;
if (_chip == 0) {
return;
}
_error = SENSOR_ERROR_OK;
double value;
value = _read(SI7021_CMD_TMP_NOHOLD);
const auto address = getAddress();
value = _read(address, SI7021_CMD_TMP_NOHOLD);
if (_error != SENSOR_ERROR_OK) return;
_temperature = (175.72 * value / 65536) - 46.85;
value = _read(SI7021_CMD_HUM_NOHOLD);
value = _read(address, SI7021_CMD_HUM_NOHOLD);
if (_error != SENSOR_ERROR_OK) return;
value = (125.0 * value / 65536) - 6;
_humidity = constrain(value, 0, 100);
_humidity = std::clamp(value, 0.0, 100.0);
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _temperature;
if (index == 1) return _humidity;
return 0;
@ -109,37 +114,30 @@ class SI7021Sensor : public I2CSensor<> {
void _init() {
// I2C auto-discover
unsigned char addresses[] = {0x40};
_address = _begin_i2c(_address, sizeof(addresses), addresses);
if (_address == 0) return;
static constexpr uint8_t addresses[] {0x40};
auto address = findAndLock(addresses);
if (address == 0) {
return;
}
// Check device
i2c_write_uint8(_address, 0xFC, 0xC9);
_chip = i2c_read_uint8(_address);
if ((_chip != SI7021_CHIP_SI7021) & (_chip != SI7021_CHIP_HTU21D)) {
_count = 0;
_sensor_address.unlock();
_error = SENSOR_ERROR_UNKNOWN_ID;
// Setting _address to 0 forces auto-discover
// This might be necessary at this stage if there is a
// different sensor in the hardcoded address
_address = 0;
i2c_write_uint8(address, 0xFC, 0xC9);
_chip = i2c_read_uint8(address);
} else {
_count = 2;
if ((_chip != SI7021_CHIP_SI7021) && (_chip != SI7021_CHIP_HTU21D)) {
_chip = 0;
resetUnknown();
return;
}
_ready = true;
}
unsigned int _read(uint8_t command) {
unsigned int _read(uint8_t address, uint8_t command) {
// Request measurement
i2c_write_uint8(_address, command);
i2c_write_uint8(address, command);
// When not using clock stretching (*_NOHOLD commands) delay here
// is needed to wait for the measurement.
@ -149,7 +147,7 @@ class SI7021Sensor : public I2CSensor<> {
// Clear the last to bits of LSB to 00.
// According to datasheet LSB of RH is always xxxxxx10
unsigned int value = i2c_read_uint16(_address) & 0xFFFC;
unsigned int value = i2c_read_uint16(address) & 0xFFFC;
// We should be checking there are no pending bytes in the buffer
// and raise a CRC error if there are


+ 29
- 34
code/espurna/sensors/SM300D2Sensor.h View File

@ -21,11 +21,6 @@ class SM300D2Sensor : public BaseSensor {
// Public
// ---------------------------------------------------------------------
SM300D2Sensor() {
_count = 7;
_sensor_id = SENSOR_SM300D2_ID;
}
~SM300D2Sensor() {
if (_serial) delete _serial;
}
@ -48,8 +43,16 @@ class SM300D2Sensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_SM300D2_ID;
}
unsigned char count() const override {
return 7;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) return;
@ -73,30 +76,25 @@ class SM300D2Sensor : public BaseSensor {
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[28];
if (_serial_is_hardware()) {
snprintf(buffer, sizeof(buffer), "SM300D2 @ HwSerial");
} else {
snprintf(buffer, sizeof(buffer), "SM300D2 @ SwSerial(%u,NULL)", _pin_rx);
snprintf(buffer, sizeof(buffer), "SM300D2 @ SwSerial(%hhu,NULL)", _pin_rx);
}
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
String address(unsigned char index) const override {
char buffer[6];
snprintf(buffer, sizeof(buffer), "%u", _pin_rx);
snprintf(buffer, sizeof(buffer), "%hhu", _pin_rx);
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_CO2;
if (index == 1) return MAGNITUDE_CH2O;
if (index == 2) return MAGNITUDE_TVOC;
@ -108,7 +106,7 @@ class SM300D2Sensor : public BaseSensor {
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _co2;
if (index == 1) return _ch2o;
if (index == 2) return _tvoc;
@ -120,7 +118,7 @@ class SM300D2Sensor : public BaseSensor {
}
// Process sensor UART
void tick() {
void tick() override {
_read();
}
@ -130,11 +128,11 @@ class SM300D2Sensor : public BaseSensor {
// Protected
// ---------------------------------------------------------------------
bool _serial_is_hardware() {
bool _serial_is_hardware() const {
return (3 == _pin_rx) || (13 == _pin_rx);
}
bool _serial_available() {
bool _serial_available() const {
if (_serial_is_hardware()) {
return Serial.available();
} else {
@ -150,7 +148,7 @@ class SM300D2Sensor : public BaseSensor {
}
}
uint8_t _serial_read() {
uint8_t _serial_read() const {
if (_serial_is_hardware()) {
return Serial.read();
} else {
@ -162,18 +160,15 @@ class SM300D2Sensor : public BaseSensor {
void _parse() {
#if SENSOR_DEBUG
char hex[(sizeof(_buffer)*2)+1] = {0};
if (hexEncode(_buffer, sizeof(_buffer), hex, sizeof(hex))) {
DEBUG_MSG("[SENSOR] SM300D2: %s\n", hex);
}
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] SM300D2: %s\n"), hexEncode(_buffer).c_str());
#endif
// check second header byte
if (_buffer[1] != 0x02) {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] SM300D2: Wrong header\n");
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] SM300D2: Wrong header\n"));
#endif
return;
}
@ -181,9 +176,9 @@ class SM300D2Sensor : public BaseSensor {
uint8_t crc = 0;
for (unsigned char i=0; i<16; i++) crc += _buffer[i];
if (crc != _buffer[16]) {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] SM300D2: Wrong CRC\n");
#endif
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] SM300D2: Wrong CRC\n"));
#endif
return;
}
@ -245,7 +240,7 @@ class SM300D2Sensor : public BaseSensor {
double _temperature = 0;
double _humidity = 0;
unsigned int _pin_rx;
unsigned char _pin_rx = SM300D2_RX_PIN;
SoftwareSerial * _serial = NULL;
};


+ 34
- 26
code/espurna/sensors/SonarSensor.h View File

@ -9,6 +9,7 @@
#pragma once
#include <NewPing.h>
#include <memory>
#include "BaseSensor.h"
@ -16,15 +17,6 @@ class SonarSensor : public BaseSensor {
public:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
SonarSensor() {
_count = 1;
_sensor_id = SENSOR_SONAR_ID;
}
// ---------------------------------------------------------------------
// Echo pin.
@ -70,44 +62,57 @@ class SonarSensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_SONAR_ID;
}
unsigned char count() const override {
return 1;
}
// Initialization method, must be idempotent
void begin() {
_sonar = new NewPing(getTrigger(), getEcho(), getMaxDistance());
void begin() override {
if (_sonar) {
_sonar.reset(nullptr);
}
_sonar = std::make_unique<NewPing>(getTrigger(), getEcho(), getMaxDistance());
_distance = 0.0;
_ready = true;
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[23];
snprintf(buffer, sizeof(buffer), "Sonar @ GPIO(%u, %u)", _trigger, _echo);
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
String address(unsigned char) const override {
return String(_trigger);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_DISTANCE;
return MAGNITUDE_NONE;
}
// Current value for slot # index
double value(unsigned char index) {
if (index != 0) return 0;
if (getIterations() > 0) {
return NewPing::convert_cm(_sonar->ping_median(getIterations())) / 100.0;
// TODO: fix meter <-> cm conversions
void pre() override {
if (getIterations()) {
_distance = NewPing::convert_cm(_sonar->ping_median(getIterations())) / 100.0;
} else {
_distance = _sonar->ping_cm() / 100.0;
}
return _sonar->ping_cm() / 100.0;
}
// Current value for slot # index
double value(unsigned char index) override {
if (index == 0) return _distance;
return 0.0;
}
protected:
@ -117,9 +122,12 @@ class SonarSensor : public BaseSensor {
unsigned char _trigger;
unsigned char _echo;
unsigned int _max_distance;
unsigned int _iterations;
NewPing * _sonar = NULL;
double _distance;
std::unique_ptr<NewPing> _sonar;
};


+ 27
- 31
code/espurna/sensors/T6613Sensor.h View File

@ -27,17 +27,6 @@ class T6613Sensor : public BaseSensor {
// Public
// ---------------------------------------------------------------------
T6613Sensor() {
_count = 1;
_sensor_id = SENSOR_T6613_ID;
}
~T6613Sensor() {
if (_serial) delete _serial;
}
// ---------------------------------------------------------------------
void setRX(unsigned char pin_rx) {
if (_pin_rx == pin_rx) return;
_pin_rx = pin_rx;
@ -52,11 +41,11 @@ class T6613Sensor : public BaseSensor {
// ---------------------------------------------------------------------
unsigned char getRX() {
unsigned char getRX() const {
return _pin_rx;
}
unsigned char getTX() {
unsigned char getTX() const {
return _pin_tx;
}
@ -64,14 +53,24 @@ class T6613Sensor : public BaseSensor {
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_T6613_ID;
}
unsigned char count() const override {
return 1;
}
// Initialization method, must be idempotent
void begin() {
void begin() override {
if (!_dirty) return;
if (_serial) delete _serial;
if (_serial) {
_serial.reset(nullptr);
}
_serial = new SoftwareSerial(_pin_rx, _pin_tx, false);
_serial = std::make_unique<SoftwareSerial>(_pin_rx, _pin_tx, false);
_serial->enableIntTx(false);
_serial->begin(19200);
@ -81,36 +80,33 @@ class T6613Sensor : public BaseSensor {
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[28];
snprintf(buffer, sizeof(buffer), "T6613 @ SwSerial(%u,%u)", _pin_rx, _pin_tx);
snprintf(buffer, sizeof(buffer),
PSTR("T6613 @ SwSerial(%hhu,%hhu)"),
_pin_rx, _pin_tx);
return String(buffer);
}
// Descriptive name of the slot # index
String description(unsigned char index) {
return description();
};
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
String address(unsigned char index) const override {
char buffer[8];
snprintf(buffer, sizeof(buffer), "%u:%u", _pin_rx, _pin_tx);
snprintf(buffer, sizeof(buffer), "%hhu:%hhu", _pin_rx, _pin_tx);
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) {
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_CO2;
return MAGNITUDE_NONE;
}
void pre() {
void pre() override {
_read();
}
// Current value for slot # index
double value(unsigned char index) {
double value(unsigned char index) override {
if (index == 0) return _co2;
return 0;
}
@ -179,9 +175,9 @@ class T6613Sensor : public BaseSensor {
}
double _co2 = 0;
unsigned int _pin_rx;
unsigned int _pin_tx;
SoftwareSerial * _serial = NULL;
unsigned char _pin_rx;
unsigned char _pin_tx;
std::unique_ptr<SoftwareSerial> _serial;
};


Loading…
Cancel
Save