diff --git a/code/espurna/analog.ino b/code/espurna/analog.ino deleted file mode 100644 index 56f60990..00000000 --- a/code/espurna/analog.ino +++ /dev/null @@ -1,81 +0,0 @@ -/* - -ANALOG MODULE - -Copyright (C) 2016-2017 by Xose Pérez - -*/ - -#if ANALOG_SUPPORT - -// ----------------------------------------------------------------------------- -// ANALOG -// ----------------------------------------------------------------------------- - -void _analogWebSocketOnSend(JsonObject& root) { - root["analogVisible"] = 1; - root["analogValue"] = getAnalog(); -} - -// ----------------------------------------------------------------------------- - -unsigned int getAnalog() { - return analogRead(ANALOG_PIN); -} - -void analogSetup() { - - pinMode(ANALOG_PIN, INPUT); - - #if WEB_SUPPORT - - // Websocket register - wsOnSendRegister(_analogWebSocketOnSend); - - // API register - apiRegister(ANALOG_TOPIC, ANALOG_TOPIC, [](char * buffer, size_t len) { - snprintf_P(buffer, len, PSTR("%d"), getAnalog()); - }); - - #endif - - DEBUG_MSG_P(PSTR("[ANALOG] Monitoring analog values\n")); - -} - -void analogLoop() { - - // Check if we should read new data - static unsigned long last_update = 0; - if ((millis() - last_update > ANALOG_UPDATE_INTERVAL) || (last_update == 0)) { - - last_update = millis(); - - unsigned int analog = getAnalog(); - DEBUG_MSG_P(PSTR("[ANALOG] Value: %d\n"), analog); - - // Send MQTT messages - #if MQTT_SUPPORT - mqttSend(getSetting("analogTopic", ANALOG_TOPIC).c_str(), String(analog).c_str()); - #endif - - // Send to Domoticz - #if DOMOTICZ_SUPPORT - domoticzSend("dczAnaIdx", 0, String(analog).c_str()); - #endif - - // Send to InfluxDB - #if INFLUXDB_SUPPORT - idbSend(MQTT_TOPIC_ANALOG, analog); - #endif - - // Update websocket clients - #if WEB_SUPPORT - wsSend(_analogWebSocketOnSend); - #endif - - } - -} - -#endif diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 3f6dbc55..3c6fee20 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -755,12 +755,14 @@ PROGMEM const char* const custom_reset_string[] = { #define SENSOR_USE_INDEX 0 // Use the index in topic (i.e. temperature/0) // even if just one sensor (0 for backwards compatibility) -#define SENSOR_TEMPERATURE_DECIMALS 2 +#define SENSOR_TEMPERATURE_DECIMALS 1 #define SENSOR_HUMIDITY_DECIMALS 0 +#define SENSOR_ANALOG_DECIMALS 0 #define SENSOR_UNKNOWN_TOPIC "unknown" #define SENSOR_TEMPERATURE_TOPIC "temperature" #define SENSOR_HUMIDITY_TOPIC "humidity" +#define SENSOR_ANALOG_TOPIC "analog" #define SENSOR_TEMPERATURE_UNITS TMP_CELSIUS // Temperature units (TMP_CELSIUS | TMP_FAHRENHEIT) #define SENSOR_TEMPERATURE_CORRECTION 0.0 // Offset correction diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index 74aaa43c..a1eb1665 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -74,7 +74,7 @@ template bool idbSend(const char * topic, unsigned char id, T payloa // ----------------------------------------------------------------------------- // Sensors // ----------------------------------------------------------------------------- -#include "sensors/SensorBase.h" +#include "sensors/BaseSensor.h" // ----------------------------------------------------------------------------- // Utils diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index bad927b8..3b93a8e9 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -68,7 +68,7 @@ //-------------------------------------------------------------------------------- #ifndef ANALOG_SUPPORT -#define ANALOG_SUPPORT 0 +#define ANALOG_SUPPORT 1 #endif #ifndef ANALOG_PIN diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index 20e1d038..421e079b 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -317,16 +317,9 @@ void setup() { #if DS18B20_SUPPORT dsSetup(); #endif - #if ANALOG_SUPPORT - analogSetup(); - #endif #if COUNTER_SUPPORT counterSetup(); #endif - #if DHT_SUPPORT - //dhtSetup(); - sensorSetup(); - #endif #if RF_SUPPORT rfSetup(); #endif @@ -340,6 +333,8 @@ void setup() { haSetup(); #endif + sensorSetup(); + // Prepare configuration for version 2.0 hwUpwardsCompatibility(); @@ -388,16 +383,9 @@ void loop() { #if DS18B20_SUPPORT dsLoop(); #endif - #if ANALOG_SUPPORT - analogLoop(); - #endif #if COUNTER_SUPPORT counterLoop(); #endif - #if DHT_SUPPORT - //dhtLoop(); - sensorLoop(); - #endif #if RF_SUPPORT rfLoop(); #endif @@ -405,6 +393,8 @@ void loop() { irLoop(); #endif + sensorLoop(); + // Power saving delay delay(_loopDelay); diff --git a/code/espurna/libs/AggregatorBase.h b/code/espurna/filters/BaseFilter.h similarity index 92% rename from code/espurna/libs/AggregatorBase.h rename to code/espurna/filters/BaseFilter.h index 2a0c3286..e86dac37 100644 --- a/code/espurna/libs/AggregatorBase.h +++ b/code/espurna/filters/BaseFilter.h @@ -6,15 +6,15 @@ #include -class AggregatorBase { +class BaseFilter { public: - AggregatorBase() { + BaseFilter() { _data = new std::vector(); } - ~AggregatorBase() { + ~BaseFilter() { if (_data) delete _data; } diff --git a/code/espurna/libs/AggregatorMedian.h b/code/espurna/filters/MedianFilter.h similarity index 93% rename from code/espurna/libs/AggregatorMedian.h rename to code/espurna/filters/MedianFilter.h index 26d48a17..298de511 100644 --- a/code/espurna/libs/AggregatorMedian.h +++ b/code/espurna/filters/MedianFilter.h @@ -4,9 +4,9 @@ #pragma once -#include "AggregatorBase.h" +#include "BaseFilter.h" -class AggregatorMedian : public AggregatorBase { +class MedianFilter : public BaseFilter { public: diff --git a/code/espurna/libs/AggregatorMovingAverage.h b/code/espurna/filters/MovingAverageFilter.h similarity index 85% rename from code/espurna/libs/AggregatorMovingAverage.h rename to code/espurna/filters/MovingAverageFilter.h index 4c7a812c..a5614164 100644 --- a/code/espurna/libs/AggregatorMovingAverage.h +++ b/code/espurna/filters/MovingAverageFilter.h @@ -5,13 +5,13 @@ #pragma once #include -#include "AggregatorBase.h" +#include "BaseFilter.h" -class AggregatorMovingAverage : public AggregatorBase { +class MovingAverageFilter : public BaseFilter { public: - AggregatorMovingAverage(unsigned char size) { + MovingAverageFilter(unsigned char size) { _size = size; for (unsigned char i=0; ipush_back(0); diff --git a/code/espurna/power.ino b/code/espurna/power.ino index 745304be..1dba6829 100644 --- a/code/espurna/power.ino +++ b/code/espurna/power.ino @@ -12,7 +12,7 @@ Copyright (C) 2016-2017 by Xose Pérez // MODULE GLOBALS AND CACHE // ----------------------------------------------------------------------------- -#include "libs/AggregatorMedian.h" +#include "filters/MedianFilter.h" #include #include @@ -27,15 +27,15 @@ double _power_current = 0; double _power_voltage = 0; double _power_apparent = 0; double _power_energy = 0; -AggregatorMedian _filter_current = AggregatorMedian(); +MedianFilter _filter_current = MedianFilter(); #if POWER_HAS_ACTIVE double _power_active = 0; double _power_reactive = 0; double _power_factor = 0; - AggregatorMedian _filter_voltage = AggregatorMedian(); - AggregatorMedian _filter_active = AggregatorMedian(); - AggregatorMedian _filter_apparent = AggregatorMedian(); + MedianFilter _filter_voltage = MedianFilter(); + MedianFilter _filter_active = MedianFilter(); + MedianFilter _filter_apparent = MedianFilter(); #endif #if POWER_HAS_ENERGY diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 10e51291..52e6406f 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -7,21 +7,21 @@ Copyright (C) 2016-2017 by Xose Pérez */ #include -#include "libs/AggregatorMedian.h" -#include "libs/AggregatorMovingAverage.h" -#include "sensors/SensorBase.h" +#include "filters/MedianFilter.h" +#include "filters/MovingAverageFilter.h" +#include "sensors/BaseSensor.h" typedef struct { - SensorBase * sensor; + BaseSensor * sensor; unsigned char local; // Local index in its provider magnitude_t type; // Type of measurement unsigned char global; // Global index in its type double current; // Current (last) value, unfiltered double filtered; // Filtered (averaged) value - AggregatorBase * filter; // Filter object + BaseFilter * filter; // Filter object } sensor_magnitude_t; -std::vector _sensors; +std::vector _sensors; std::vector _magnitudes; unsigned char _counts[MAGNITUDE_MAX]; @@ -29,10 +29,6 @@ bool _sensor_realtime = API_REAL_TIME_VALUES; unsigned char _sensor_temperature_units = SENSOR_TEMPERATURE_UNITS; double _sensor_temperature_correction = SENSOR_TEMPERATURE_CORRECTION; -#if DHT_SUPPORT - #include "sensors/SensorDHT.h" -#endif - // ----------------------------------------------------------------------------- // Private // ----------------------------------------------------------------------------- @@ -42,6 +38,8 @@ String _sensorTopic(magnitude_t type) { return String(SENSOR_TEMPERATURE_TOPIC); } else if (type == MAGNITUDE_HUMIDITY) { return String(SENSOR_HUMIDITY_TOPIC); + } else if (type == MAGNITUDE_ANALOG) { + return String(SENSOR_ANALOG_TOPIC); } return String(SENSOR_UNKNOWN_TOPIC); } @@ -51,6 +49,8 @@ unsigned char _sensorDecimals(magnitude_t type) { return SENSOR_TEMPERATURE_DECIMALS; } else if (type == MAGNITUDE_HUMIDITY) { return SENSOR_HUMIDITY_DECIMALS; + } else if (type == MAGNITUDE_ANALOG) { + return SENSOR_ANALOG_DECIMALS; } return 0; } @@ -86,15 +86,19 @@ void _sensorConfigure() { void _sensorWebSocketOnSend(JsonObject& root) { + char buffer[10]; bool hasTemperature = false; JsonArray& sensors = root.createNestedArray("sensors"); for (unsigned char i=0; i<_magnitudes.size(); i++) { sensor_magnitude_t magnitude = _magnitudes[i]; + unsigned char decimals = _sensorDecimals(magnitude.type); + dtostrf(magnitude.current, 1-sizeof(buffer), decimals, buffer); + JsonObject& sensor = sensors.createNestedObject(); sensor["type"] = int(magnitude.type); - sensor["value"] = magnitude.current; + sensor["value"] = String(buffer); sensor["units"] = _sensorUnits(magnitude.type); sensor["description"] = magnitude.sensor->slot(magnitude.local); @@ -138,18 +142,21 @@ void sensorSetup() { // Load sensors #if DHT_SUPPORT - { - _sensors.push_back(new SensorDHT(DHT_PIN, DHT_TYPE)); + #include "sensors/DHTSensor.h" + _sensors.push_back(new DHTSensor(DHT_PIN, DHT_TYPE)); #if DHT_PULLUP pinMode(DHT_PIN, INPUT_PULLUP); #endif - } + #endif + #if ANALOG_SUPPORT + #include "sensors/AnalogSensor.h" + _sensors.push_back(new AnalogSensor(ANALOG_PIN)); #endif // Read magnitudes for (unsigned char i=0; i<_sensors.size(); i++) { - SensorBase * sensor = _sensors[i]; + BaseSensor * sensor = _sensors[i]; DEBUG_MSG("[SENSOR] %s\n", sensor->name().c_str()); for (unsigned char k=0; kcount(); k++) { @@ -164,9 +171,9 @@ void sensorSetup() { new_magnitude.current = 0; new_magnitude.filtered = 0; if (type == MAGNITUDE_EVENTS) { - new_magnitude.filter = new AggregatorMovingAverage(SENSOR_REPORT_EVERY); + new_magnitude.filter = new MovingAverageFilter(SENSOR_REPORT_EVERY); } else { - new_magnitude.filter = new AggregatorMedian(); + new_magnitude.filter = new MedianFilter(); } _magnitudes.push_back(new_magnitude); diff --git a/code/espurna/sensors/AnalogSensor.h b/code/espurna/sensors/AnalogSensor.h new file mode 100644 index 00000000..59502f5a --- /dev/null +++ b/code/espurna/sensors/AnalogSensor.h @@ -0,0 +1,68 @@ +// ----------------------------------------------------------------------------- +// DHT Sensor +// ----------------------------------------------------------------------------- + +#pragma once + +#include "Arduino.h" +#include "BaseSensor.h" + +class AnalogSensor : public BaseSensor { + + public: + + AnalogSensor(unsigned char gpio): BaseSensor() { + _gpio = gpio; + } + + // Pre-read hook (usually to populate registers with up-to-date data) + void pre() {} + + // Post-read hook (usually to reset things) + void post() {} + + // Return sensor status (true for ready) + bool status() { + return true; + } + + // Return sensor last internal error + int error() { + return 0; + } + + // Number of available slots + unsigned char count() { + return 1; + } + + // Descriptive name of the sensor + String name() { + char buffer[20]; + snprintf(buffer, sizeof(buffer), "ANALOG @ GPIO%d", _gpio); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return name(); + } + + // Type for slot # index + magnitude_t type(unsigned char index) { + if (index == 0) return MAGNITUDE_ANALOG; + return MAGNITUDE_NONE; + } + + // Current value for slot # index + double value(unsigned char index) { + if (index == 0) return analogRead(_gpio); + return 0; + } + + + private: + + unsigned char _gpio; + +}; diff --git a/code/espurna/sensors/SensorBase.h b/code/espurna/sensors/BaseSensor.h similarity index 95% rename from code/espurna/sensors/SensorBase.h rename to code/espurna/sensors/BaseSensor.h index c8792ff7..da700088 100644 --- a/code/espurna/sensors/SensorBase.h +++ b/code/espurna/sensors/BaseSensor.h @@ -27,14 +27,14 @@ typedef enum magnitude_t { } magnitude_t; -class SensorBase { +class BaseSensor { public: - SensorBase() { + BaseSensor() { } - ~SensorBase() { + ~BaseSensor() { } // Pre-read hook (usually to populate registers with up-to-date data) diff --git a/code/espurna/sensors/SensorDHT.h b/code/espurna/sensors/DHTSensor.h similarity index 97% rename from code/espurna/sensors/SensorDHT.h rename to code/espurna/sensors/DHTSensor.h index 6bb92d10..b531a394 100644 --- a/code/espurna/sensors/SensorDHT.h +++ b/code/espurna/sensors/DHTSensor.h @@ -5,7 +5,7 @@ #pragma once #include "Arduino.h" -#include "SensorBase.h" +#include "BaseSensor.h" #define DHT_MAX_DATA 5 #define DHT_MAX_ERRORS 5 @@ -19,11 +19,11 @@ #define DHT21 21 #define AM2301 21 -class SensorDHT : public SensorBase { +class DHTSensor : public BaseSensor { public: - SensorDHT(unsigned char gpio, unsigned char type): SensorBase() { + DHTSensor(unsigned char gpio, unsigned char type): BaseSensor() { _gpio = gpio; _type = type; } diff --git a/code/html/custom.js b/code/html/custom.js index fe36c6ac..8146ff5b 100644 --- a/code/html/custom.js +++ b/code/html/custom.js @@ -30,6 +30,7 @@ function initMessages() { function sensorType(type) { if (type == 1) return "Temperature"; if (type == 2) return "Humidity"; + if (type == 11) return "Analog"; return null; }