Browse Source

Merge branch 'dev' into softcfg

v2
Xose Pérez 6 years ago
parent
commit
2ef3a6e154
24 changed files with 6072 additions and 5739 deletions
  1. +1
    -0
      code/espurna/config/all.h
  2. +2
    -0
      code/espurna/config/arduino.h
  3. +0
    -51
      code/espurna/config/dependencies.h
  4. +35
    -1
      code/espurna/config/device.h
  5. +10
    -2
      code/espurna/config/sensors.h
  6. +73
    -0
      code/espurna/config/webui.h
  7. BIN
      code/espurna/data/index.all.html.gz
  8. BIN
      code/espurna/data/index.sensor.html.gz
  9. +18
    -0
      code/espurna/device.ino
  10. +40
    -0
      code/espurna/filters/LastFilter.h
  11. +99
    -23
      code/espurna/sensor.ino
  12. +2
    -2
      code/espurna/sensors/CSE7766Sensor.h
  13. +15
    -0
      code/espurna/sensors/ECH1560Sensor.h
  14. +5
    -0
      code/espurna/sensors/EmonSensor.h
  15. +4
    -2
      code/espurna/sensors/HLW8012Sensor.h
  16. +12
    -1
      code/espurna/sensors/PZEM004TSensor.h
  17. +21
    -6
      code/espurna/sensors/V9261FSensor.h
  18. +3053
    -3047
      code/espurna/static/index.all.html.gz.h
  19. +2604
    -2598
      code/espurna/static/index.sensor.html.gz.h
  20. +6
    -2
      code/espurna/utils.ino
  21. +6
    -0
      code/espurna/wifi.ino
  22. +16
    -4
      code/html/index.html
  23. +50
    -0
      code/platformio.ini
  24. BIN
      images/devices/blitzwolf-bw-shp2.jpg

+ 1
- 0
code/espurna/config/all.h View File

@ -32,6 +32,7 @@
#include "dependencies.h"
#include "prototypes.h"
#include "sensors.h"
#include "webui.h"
#include "progmem.h"
#include "debug.h"


+ 2
- 0
code/espurna/config/arduino.h View File

@ -110,6 +110,8 @@
//#define BH_ONOFRE
//#define ITEAD_SONOFF_IFAN02
//#define GENERIC_AG_L4
//#define ALLTERCO_SHELLY1
//#define LOHAS_9W
//--------------------------------------------------------------------------------
// Features (values below are non-default values)


+ 0
- 51
code/espurna/config/dependencies.h View File

@ -53,54 +53,3 @@
#undef NTP_SUPPORT
#define NTP_SUPPORT 1 // Scheduler needs NTP
#endif
// -----------------------------------------------------------------------------
// WEB UI IMAGE
// -----------------------------------------------------------------------------
#define WEBUI_IMAGE_SMALL 0
#define WEBUI_IMAGE_LIGHT 1
#define WEBUI_IMAGE_SENSOR 2
#define WEBUI_IMAGE_RFBRIDGE 4
#define WEBUI_IMAGE_RFM69 8
#define WEBUI_IMAGE_FULL 15
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
#ifdef WEBUI_IMAGE
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#else
#define WEBUI_IMAGE WEBUI_IMAGE_LIGHT
#endif
#endif
#if SENSOR_SUPPORT == 1
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_SENSOR
#else
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#endif
#endif
#if defined(ITEAD_SONOFF_RFBRIDGE)
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_RFBRIDGE
#else
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#endif
#endif
#if RFM69_SUPPORT == 1
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_RFM69
#else
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#endif
#endif
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_SMALL
#endif

+ 35
- 1
code/espurna/config/device.h View File

@ -96,6 +96,8 @@ enum devices {
DEVICE_ITEAD_SONOFF_IFAN02,
DEVICE_GENERIC_AG_L4,
DEVICE_HOMECUBE_16A,
DEVICE_ALLTERCO_SHELLY1,
DEVICE_LOHAS_9W,
DEVICE_LAST
@ -107,6 +109,7 @@ enum devices {
#if \
defined(ALLNET_4DUINO_IOT_WLAN_RELAIS) || \
defined(ALLTERCO_SHELLY1) || \
defined(ARNIEX_SWIFITCH) || \
defined(BH_ONOFRE) || \
defined(ELECTRODRAGON_WIFI_IOT) || \
@ -220,7 +223,8 @@ enum devices {
#elif \
defined(AITHINKER_AI_LIGHT) || \
defined(ARILUX_E27) || \
defined(ITEAD_SONOFF_B1)
defined(ITEAD_SONOFF_B1) || \
defined(LOHAS_9W)
#undef ESPURNA_IMAGE
#define ESPURNA_IMAGE ESPURNA_MY92XX
@ -513,6 +517,8 @@ enum devices {
#if ESPURNA_IMAGE == ESPURNA_CORE
#define ESPURNA_IMAGE_NAME "CORE"
// Disable non-core modules
#define ALEXA_SUPPORT 0
#define API_SUPPORT 0
@ -539,19 +545,27 @@ enum devices {
#elif ESPURNA_IMAGE == ESPURNA_BASIC
#define ESPURNA_IMAGE_NAME "BASIC"
#elif ESPURNA_IMAGE == ESPURNA_DIMMER
#define ESPURNA_IMAGE_NAME "DIMMER"
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
#elif ESPURNA_IMAGE == ESPURNA_MY92XX
#define ESPURNA_IMAGE_NAME "MY92XX"
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY92XX
#define MY92XX_COMMAND MY92XX_COMMAND_DEFAULT
#elif ESPURNA_IMAGE == ESPURNA_EMON
#define ESPURNA_IMAGE_NAME "EMON"
#ifndef EMON_ANALOG_SUPPORT
#define EMON_ANALOG_SUPPORT 1
#endif
@ -566,18 +580,24 @@ enum devices {
#elif ESPURNA_IMAGE == ESPURNA_HLW8012
#define ESPURNA_IMAGE_NAME "HLW8012"
#ifndef HLW8012_SUPPORT
#define HLW8012_SUPPORT 1
#endif
#elif ESPURNA_IMAGE == ESPURNA_CSE77XX
#define ESPURNA_IMAGE_NAME "CSE77XX"
#ifndef CSE7766_SUPPORT
#define CSE7766_SUPPORT 1
#endif
#elif ESPURNA_IMAGE == ESPURNA_V9261F
#define ESPURNA_IMAGE_NAME "V9261F"
#ifndef V9261F_SUPPORT
#define V9261F_SUPPORT 1
#endif
@ -588,6 +608,8 @@ enum devices {
#elif ESPURNA_IMAGE == ESPURNA_ECH1560
#define ESPURNA_IMAGE_NAME "ECH1560"
#ifndef ECH1560_SUPPORT
#define ECH1560_SUPPORT 1
#endif
@ -598,6 +620,8 @@ enum devices {
#elif ESPURNA_IMAGE == ESPURNA_SENSOR
#define ESPURNA_IMAGE_NAME "SENSOR"
#ifndef ANALOG_SUPPORT
#define ANALOG_SUPPORT 1
#endif
@ -616,12 +640,18 @@ enum devices {
#elif ESPURNA_IMAGE == ESPURNA_SONOFF_DUAL
#define ESPURNA_IMAGE_NAME "SONOFF_DUAL"
#define RELAY_PROVIDER RELAY_PROVIDER_DUAL
#elif ESPURNA_IMAGE == ESPURNA_SONOFF_RFBRIDGE
#define ESPURNA_IMAGE_NAME "SONOFF_RFBRIDGE"
#elif ESPURNA_IMAGE == ESPURNA_RFM69
#define ESPURNA_IMAGE_NAME "RFM69"
// RFM69GW
#define RFM69_SUPPORT 1
@ -636,10 +666,14 @@ enum devices {
#elif ESPURNA_IMAGE == ESPURNA_STM
#define ESPURNA_IMAGE_NAME "STM"
#define RELAY_PROVIDER RELAY_PROVIDER_STM
#elif ESPURNA_IMAGE == ESPURNA_GEIGER
#define ESPURNA_IMAGE_NAME "GEIGER"
// Enable Geiger Counter
#define GEIGER_SUPPORT 1


+ 10
- 2
code/espurna/config/sensors.h View File

@ -36,6 +36,14 @@
#define HUMIDITY_MIN_CHANGE 0 // Minimum humidity change to report
#endif
#ifndef SENSOR_SAVE_EVERY
#define SENSOR_SAVE_EVERY 0 // Save accumulating values to EEPROM (atm only energy)
// A 0 means do not save and it's the default value
// A number different from 0 means it should store the value in EEPROM
// after these many reports
// Warning: this might wear out flash fast!
#endif
#define SENSOR_PUBLISH_ADDRESSES 0 // Publish sensor addresses
#define SENSOR_ADDRESS_TOPIC "address" // Topic to publish sensor addresses
@ -299,7 +307,7 @@
#endif
#ifndef EVENTS_INTERRUPT_MODE
#define EVENTS_INTERRUPT_MODE RISING // RISING, FALLING, BOTH
#define EVENTS_INTERRUPT_MODE RISING // RISING, FALLING, CHANGE
#endif
#define EVENTS_DEBOUNCE 50 // Do not register events within less than 50 millis
@ -322,7 +330,7 @@
#endif
#ifndef GEIGER_INTERRUPT_MODE
#define GEIGER_INTERRUPT_MODE RISING // RISING, FALLING, BOTH
#define GEIGER_INTERRUPT_MODE RISING // RISING, FALLING, CHANGE
#endif
#define GEIGER_DEBOUNCE 25 // Do not register events within less than 25 millis.


+ 73
- 0
code/espurna/config/webui.h View File

@ -0,0 +1,73 @@
// -----------------------------------------------------------------------------
// WEB UI IMAGE
// -----------------------------------------------------------------------------
#define WEBUI_IMAGE_SMALL 0
#define WEBUI_IMAGE_LIGHT 1
#define WEBUI_IMAGE_SENSOR 2
#define WEBUI_IMAGE_RFBRIDGE 4
#define WEBUI_IMAGE_RFM69 8
#define WEBUI_IMAGE_FULL 15
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
#ifdef WEBUI_IMAGE
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#else
#define WEBUI_IMAGE WEBUI_IMAGE_LIGHT
#endif
#endif
#if SENSOR_SUPPORT == 1
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_SENSOR
#else
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#endif
#endif
#if defined(ITEAD_SONOFF_RFBRIDGE)
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_RFBRIDGE
#else
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#endif
#endif
#if RFM69_SUPPORT == 1
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_RFM69
#else
#undef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_FULL
#endif
#endif
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_SMALL
#endif
#include <pgmspace.h>
PROGMEM const char espurna_webui[] =
#if WEBUI_IMAGE == WEBUI_IMAGE_SMALL
"SMALL"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_LIGHT
"LIGHT"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_SENSOR
"SENSOR"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_RFBRIDGE
"RFBRIDGE"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_RFM69
"RFM69"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_FULL
"FULL"
#endif
"";

BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


+ 18
- 0
code/espurna/device.ino View File

@ -1940,6 +1940,24 @@ void _deviceLoad() {
setSetting("litChLogic", 1, 0);
setSetting("litChLogic", 2, 0);
#elif defined(LOHAS_9W)
setSetting("board", DEVICE_LOHAS_9W);
setSetting("device", "LOHAS_9W");
setSetting("fw", ESPURNA_MY92XX);
setSetting("rlyProvider", RELAY_PROVIDER_LIGHT);
setSetting("rlyDummy", 1);
setSetting("litChFactor", 4, 0.1); // White LEDs are way more bright in the B1
setSetting("litChFactor", 5, 0.1); // White LEDs are way more bright in the B1
setSetting("myModel", 1); // 3 channels per chip
setSetting("myChips", 2);
setSetting("myDIGPIO", 13);
setSetting("myDCKIGPIO", 15);
setSetting("myMapping", "01234"); // TODO
#endif
}


+ 40
- 0
code/espurna/filters/LastFilter.h View File

@ -0,0 +1,40 @@
// -----------------------------------------------------------------------------
// Last Filter
// Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com>
// -----------------------------------------------------------------------------
#if SENSOR_SUPPORT
#pragma once
#include "BaseFilter.h"
class LastFilter : public BaseFilter {
public:
void add(double value) {
_value = value;
}
unsigned char count() {
return 1;
}
void reset() {
_value = 0;
}
double result() {
return _value;
}
void resize(unsigned char size) {}
protected:
double _value = 0;
};
#endif // SENSOR_SUPPORT

+ 99
- 23
code/espurna/sensor.ino View File

@ -13,6 +13,7 @@ Sensor-based key previs: air am ana bh bmx cse dht dig ds ech emon evt gei guv h
#if SENSOR_SUPPORT
#include <vector>
#include "filters/LastFilter.h"
#include "filters/MaxFilter.h"
#include "filters/MedianFilter.h"
#include "filters/MovingAverageFilter.h"
@ -38,6 +39,7 @@ unsigned char _counts[MAGNITUDE_MAX];
bool _sensor_realtime = API_REAL_TIME_VALUES;
unsigned long _sensor_read_interval = 1000 * SENSOR_READ_INTERVAL;
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_energy_units = SENSOR_ENERGY_UNITS;
unsigned char _sensor_temperature_units = SENSOR_TEMPERATURE_UNITS;
@ -122,8 +124,8 @@ void _sensorWebSocketSendData(JsonObject& root) {
element["error"] = magnitude.sensor->error();
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 {
element["description"] = magnitude.sensor->slot(magnitude.local);
}
@ -196,6 +198,7 @@ void _sensorWebSocketStart(JsonObject& root) {
root["humOffset"] = _sensor_humidity_correction;
root["snsRead"] = _sensor_read_interval / 1000;
root["snsReport"] = _sensor_report_every;
root["snsSave"] = _sensor_save_every;
}
/*
@ -287,11 +290,18 @@ void _sensorPost() {
}
}
void _sensorReset() {
void _sensorResetTS() {
#if NTP_SUPPORT
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
}
@ -308,6 +318,7 @@ void _sensorLoad() {
unsigned char index = 0;
unsigned char gpio = GPIO_NONE;
_sensor_save_every = getSetting("snsSave", 0).toInt();
#if AM2320_SUPPORT
if (getSetting("amEnabled", 0).toInt() == 1) {
@ -358,6 +369,8 @@ void _sensorLoad() {
if (value > 0) sensor->setVoltageRatio(value);
value = getSetting("pwrRatio", 0).toFloat();
if (value > 0) sensor->setPowerRatio(value);
value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(value);
_sensors.push_back(sensor);
@ -410,6 +423,8 @@ void _sensorLoad() {
sensor->setCLK(getSetting("echCLKGPIO", ECH1560_CLK_PIN).toInt());
sensor->setMISO(getSetting("echMISOGPIO", ECH1560_MISO_PIN).toInt());
sensor->setInverted(getSetting("echLogic", ECH1560_INVERTED).toInt());
double value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(value);
_sensors.push_back(sensor);
}
#endif
@ -425,6 +440,8 @@ void _sensorLoad() {
sensor->setReference(getSetting("emonReference", EMON_REFERENCE_VOLTAGE).toInt());
sensor->setCurrentRatio(0, getSetting("curRatio", EMON_CURRENT_RATIO).toFloat());
sensor->setVoltage(getSetting("volNominal", EMON_MAINS_VOLTAGE).toInt());
double value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(0, value);
_sensors.push_back(sensor);
}
#endif
@ -437,12 +454,14 @@ void _sensorLoad() {
sensor->setMask(getSetting("emonMask", EMON_ADS1X15_MASK).toInt());
sensor->setGain(getSetting("emonGain", EMON_ADS1X15_GAIN).toInt());
sensor->setReference(getSetting("emonReference", EMON_REFERENCE_VOLTAGE).toInt());
double curRatio = getSetting("curRatio", EMON_CURRENT_RATIO).toFloat();
sensor->setCurrentRatio(0, getSetting("curRatio", 0, curRatio).toFloat());
sensor->setCurrentRatio(1, getSetting("curRatio", 1, curRatio).toFloat());
sensor->setCurrentRatio(2, getSetting("curRatio", 2, curRatio).toFloat());
sensor->setCurrentRatio(3, getSetting("curRatio", 3, curRatio).toFloat());
double value = getSetting("curRatio", EMON_CURRENT_RATIO).toFloat();
sensor->setCurrentRatio(0, getSetting("curRatio", 0, value).toFloat());
sensor->setCurrentRatio(1, getSetting("curRatio", 1, value).toFloat());
sensor->setCurrentRatio(2, getSetting("curRatio", 2, value).toFloat());
sensor->setCurrentRatio(3, getSetting("curRatio", 3, value).toFloat());
sensor->setVoltage(getSetting("volNominal", EMON_MAINS_VOLTAGE).toInt());
value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(0, value);
_sensors.push_back(sensor);
}
#endif
@ -453,6 +472,8 @@ void _sensorLoad() {
sensor->setReference(getSetting("emonReference", EMON_REFERENCE_VOLTAGE).toInt());
sensor->setCurrentRatio(0, getSetting("curRatio", EMON_CURRENT_RATIO).toFloat());
sensor->setVoltage(getSetting("volNominal", EMON_MAINS_VOLTAGE).toInt());
double value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(0, value);
_sensors.push_back(sensor);
}
#endif
@ -533,6 +554,8 @@ void _sensorLoad() {
if (value > 0) sensor->setVoltageRatio(value);
value = getSetting("pwrRatio", HLW8012_POWER_RATIO).toFloat();
if (value > 0) sensor->setPowerRatio(value);
value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(value);
_sensors.push_back(sensor);
@ -594,6 +617,8 @@ void _sensorLoad() {
} else {
sensor->setSerial(& PZEM004T_HW_PORT);
}
double value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(value);
_sensors.push_back(sensor);
}
#endif
@ -628,6 +653,8 @@ void _sensorLoad() {
V9261FSensor * sensor = new V9261FSensor();
sensor->setRX(gpio);
sensor->setInverted(getSetting("v92Inverse", V9261F_PIN_INVERSE).toInt());
double value = (_sensor_save_every > 0) ? getSetting("eneTotal", 0).toFloat() : 0;
if (value > 0) sensor->resetEnergy(value);
_sensors.push_back(sensor);
}
}
@ -680,9 +707,11 @@ void _sensorInit() {
new_magnitude.filtered = 0;
new_magnitude.reported = 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();
} 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();
} else {
new_magnitude.filter = new MedianFilter();
@ -710,12 +739,14 @@ void _sensorConfigure() {
// General sensor settings
_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_save_every = getSetting("snsSave", SENSOR_SAVE_EVERY).toInt();
_sensor_realtime = apiRealTime();
_sensor_power_units = getSetting("pwrUnits", SENSOR_POWER_UNITS).toInt();
_sensor_energy_units = getSetting("eneUnits", SENSOR_ENERGY_UNITS).toInt();
_sensor_temperature_units = getSetting("tmpUnits", SENSOR_TEMPERATURE_UNITS).toInt();
_sensor_temperature_correction = getSetting("tmpOffset", SENSOR_TEMPERATURE_CORRECTION).toFloat();
_sensor_humidity_correction = getSetting("humOffset", SENSOR_HUMIDITY_CORRECTION).toFloat();
_sensor_energy_reset_ts = getSetting("snsResetTS", "");
// Specific sensor settings
for (unsigned char i=0; i<_sensors.size(); i++) {
@ -739,7 +770,8 @@ void _sensorConfigure() {
if (getSetting("eneReset", 0).toInt() == 1) {
sensor->resetEnergy();
_sensorReset();
delSetting("eneTotal");
_sensorResetTS();
}
sensor->setVoltage(getSetting("volNominal", EMON_MAINS_VOLTAGE).toInt());
@ -753,7 +785,8 @@ void _sensorConfigure() {
EmonADC121Sensor * sensor = (EmonADC121Sensor *) _sensors[i];
if (getSetting("eneReset", 0).toInt() == 1) {
sensor->resetEnergy();
_sensorReset();
delSetting("eneTotal");
_sensorResetTS();
}
}
#endif
@ -763,7 +796,8 @@ void _sensorConfigure() {
EmonADS1X15Sensor * sensor = (EmonADS1X15Sensor *) _sensors[i];
if (getSetting("eneReset", 0).toInt() == 1) {
sensor->resetEnergy();
_sensorReset();
delSetting("eneTotal");
_sensorResetTS();
}
}
#endif
@ -793,7 +827,8 @@ void _sensorConfigure() {
if (getSetting("eneReset", 0).toInt() == 1) {
sensor->resetEnergy();
_sensorReset();
delSetting("eneTotal");
_sensorResetTS();
}
if (getSetting("snsResetCalibrarion", 0).toInt() == 1) {
@ -831,7 +866,8 @@ void _sensorConfigure() {
if (getSetting("eneReset", 0).toInt() == 1) {
sensor->resetEnergy();
_sensorReset();
delSetting("eneTotal");
_sensorResetTS();
}
if (getSetting("snsResetCalibrarion", 0).toInt() == 1) {
@ -854,6 +890,11 @@ void _sensorConfigure() {
magnitude.min_change = getSetting("tmpDelta", magnitude.type, 0).toFloat();
}
// General processing
if (0 == _sensor_save_every) {
delSetting("eneTotal");
}
// Save settings
delSetting("pwrExpected");
delSetting("curExpected");
@ -1117,6 +1158,7 @@ void sensorLoop() {
// Check if we should read new data
static unsigned long last_update = 0;
static unsigned long report_count = 0;
static unsigned long save_count = 0;
if (millis() - last_update > _sensor_read_interval) {
last_update = millis();
@ -1140,6 +1182,10 @@ void sensorLoop() {
if (magnitude.sensor->status()) {
// -------------------------------------------------------------
// Instant value
// -------------------------------------------------------------
current = magnitude.sensor->value(magnitude.local);
// Completely remove spurious values if relay is OFF
@ -1156,17 +1202,26 @@ void sensorLoop() {
}
#endif
// -------------------------------------------------------------
// Processing (filters)
// -------------------------------------------------------------
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 = _magnitudeProcess(magnitude.type, current);
_magnitudes[i].current = current;
// -------------------------------------------------------------
// Debug
// -------------------------------------------------------------
#if SENSOR_DEBUG
{
char buffer[64];
@ -1180,8 +1235,12 @@ void sensorLoop() {
}
#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();
magnitude.filter->reset();
@ -1190,13 +1249,30 @@ void sensorLoop() {
// Check if there is a minimum change threshold to report
if (fabs(filtered - magnitude.reported) >= magnitude.min_change) {
_magnitudes[i].reported = filtered;
_sensorReport(i, filtered);
} // 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 (magnitude.sensor->status())
} // for (unsigned char i=0; i<_magnitudes.size(); i++)


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

@ -102,8 +102,8 @@ class CSE7766Sensor : public BaseSensor {
_ratioC = _ratioV = _ratioP = 1.0;
}
void resetEnergy() {
_energy = 0;
void resetEnergy(double value = 0) {
_energy = value;
}
// ---------------------------------------------------------------------


+ 15
- 0
code/espurna/sensors/ECH1560Sensor.h View File

@ -59,6 +59,12 @@ class ECH1560Sensor : public BaseSensor {
return _inverted;
}
// ---------------------------------------------------------------------
void resetEnergy(double value = 0) {
_energy = value;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
@ -106,6 +112,7 @@ class ECH1560Sensor : public BaseSensor {
if (index == 0) return MAGNITUDE_CURRENT;
if (index == 1) return MAGNITUDE_VOLTAGE;
if (index == 2) return MAGNITUDE_POWER_APPARENT;
if (index == 3) return MAGNITUDE_ENERGY;
return MAGNITUDE_NONE;
}
@ -114,6 +121,7 @@ class ECH1560Sensor : public BaseSensor {
if (index == 0) return _current;
if (index == 1) return _voltage;
if (index == 2) return _apparent;
if (index == 3) return _energy;
return 0;
}
@ -260,6 +268,12 @@ class ECH1560Sensor : public BaseSensor {
_apparent = ( (float) byte1 * 255 + (float) byte2 + (float) byte3 / 255.0) / 2;
_current = _apparent / _voltage;
static unsigned long last = 0;
if (last > 0) {
_energy += (_apparent * (millis() - last) / 1000);
}
last = millis();
_dosync = false;
}
@ -287,6 +301,7 @@ class ECH1560Sensor : public BaseSensor {
double _apparent = 0;
double _voltage = 0;
double _current = 0;
double _energy = 0;
unsigned char _data[24];


+ 5
- 0
code/espurna/sensors/EmonSensor.h View File

@ -55,6 +55,11 @@ class EmonSensor : public I2CSensor {
}
}
void resetEnergy(unsigned char channel, double value = 0) {
if (channel >= _channels) return;
_energy[channel] = value;
}
// ---------------------------------------------------------------------
void setVoltage(double voltage) {


+ 4
- 2
code/espurna/sensors/HLW8012Sensor.h View File

@ -48,7 +48,8 @@ class HLW8012Sensor : public BaseSensor {
_hlw8012->resetMultipliers();
}
void resetEnergy() {
void resetEnergy(double value = 0) {
_energy_offset = value;
_hlw8012->resetEnergy();
}
@ -216,7 +217,7 @@ class HLW8012Sensor : public BaseSensor {
if (index == 3) return _hlw8012->getReactivePower();
if (index == 4) return _hlw8012->getApparentPower();
if (index == 5) return 100 * _hlw8012->getPowerFactor();
if (index == 6) return _hlw8012->getEnergy();
if (index == 6) return (_energy_offset + _hlw8012->getEnergy());
return 0;
}
@ -282,6 +283,7 @@ class HLW8012Sensor : public BaseSensor {
double _current_resistor = HLW8012_CURRENT_R;
double _upstream_resistor = HLW8012_VOLTAGE_R_UP;
double _downstream_resistor = HLW8012_VOLTAGE_R_DOWN;
double _energy_offset = 0;
HLW8012 * _hlw8012 = NULL;


+ 12
- 1
code/espurna/sensors/PZEM004TSensor.h View File

@ -59,6 +59,16 @@ class PZEM004TSensor : public BaseSensor {
return _pin_tx;
}
// ---------------------------------------------------------------------
void resetEnergy(double value = 0) {
if (_ready) {
_energy_offset = value - (_pzem->energy(_ip) * 3600);
} else {
_energy_offset = value;
}
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
@ -117,7 +127,7 @@ class PZEM004TSensor : public BaseSensor {
if (index == 0) response = _pzem->current(_ip);
if (index == 1) response = _pzem->voltage(_ip);
if (index == 2) response = _pzem->power(_ip);
if (index == 3) response = _pzem->energy(_ip) * 3600;
if (index == 3) response = _energy_offset + (_pzem->energy(_ip) * 3600);
if (response < 0) response = 0;
return response;
}
@ -133,6 +143,7 @@ class PZEM004TSensor : public BaseSensor {
IPAddress _ip;
HardwareSerial * _serial = NULL;
PZEM004T * _pzem = NULL;
double _energy_offset = 0;
};


+ 21
- 6
code/espurna/sensors/V9261FSensor.h View File

@ -56,6 +56,12 @@ class V9261FSensor : public BaseSensor {
return _inverted;
}
// ---------------------------------------------------------------------
void resetEnergy(double value = 0) {
_energy = value;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
@ -106,6 +112,7 @@ class V9261FSensor : public BaseSensor {
if (index == 3) return MAGNITUDE_POWER_REACTIVE;
if (index == 4) return MAGNITUDE_POWER_APPARENT;
if (index == 5) return MAGNITUDE_POWER_FACTOR;
if (index == 6) return MAGNITUDE_ENERGY;
return MAGNITUDE_NONE;
}
@ -117,6 +124,7 @@ class V9261FSensor : public BaseSensor {
if (index == 3) return _reactive;
if (index == 4) return _apparent;
if (index == 5) return _apparent > 0 ? 100 * _active / _apparent : 100;
if (index == 6) return _energy;
return 0;
}
@ -130,6 +138,7 @@ class V9261FSensor : public BaseSensor {
static unsigned char state = 0;
static unsigned long last = 0;
static unsigned long ts = 0;
static bool found = false;
static unsigned char index = 0;
@ -138,10 +147,10 @@ class V9261FSensor : public BaseSensor {
while (_serial->available()) {
_serial->flush();
found = true;
last = millis();
ts = millis();
}
if (found && (millis() - last > V9261F_SYNC_INTERVAL)) {
if (found && (millis() - ts > V9261F_SYNC_INTERVAL)) {
_serial->flush();
index = 0;
state = 1;
@ -164,7 +173,7 @@ class V9261FSensor : public BaseSensor {
_data[index] = _serial->read();
if (index++ >= 19) {
_serial->flush();
last = millis();
ts = millis();
state = 3;
}
}
@ -208,9 +217,14 @@ class V9261FSensor : public BaseSensor {
_apparent = fs_sqrt(_reactive * _reactive + _active * _active);
if (last > 0) {
_energy += (_active * (millis() - last) / 1000);
}
last = millis();
}
last = millis();
ts = millis();
index = 0;
state = 4;
@ -218,10 +232,10 @@ class V9261FSensor : public BaseSensor {
while (_serial->available()) {
_serial->flush();
last = millis();
ts = millis();
}
if (millis() - last > V9261F_SYNC_INTERVAL) {
if (millis() - ts > V9261F_SYNC_INTERVAL) {
state = 1;
}
@ -249,6 +263,7 @@ class V9261FSensor : public BaseSensor {
double _voltage = 0;
double _current = 0;
double _apparent = 0;
double _energy = 0;
double _ratioP = V9261F_POWER_FACTOR;
double _ratioC = V9261F_CURRENT_FACTOR;


+ 3053
- 3047
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 2604
- 2598
code/espurna/static/index.sensor.html.gz.h
File diff suppressed because it is too large
View File


+ 6
- 2
code/espurna/utils.ino View File

@ -93,6 +93,10 @@ String getEspurnaSensors() {
}
#endif
String getEspurnaWebUI() {
return FPSTR(espurna_webui);
}
String buildTime() {
const char time_now[] = __TIME__; // hh:mm:ss
@ -339,8 +343,8 @@ void info() {
#if SENSOR_SUPPORT
DEBUG_MSG_P(PSTR("[INIT] SENSORS: %s\n"), getEspurnaSensors().c_str());
#endif // SENSOR_SUPPORT
DEBUG_MSG_P(PSTR("[INIT] FIRMWARE CODE: %d\n"), ESPURNA_IMAGE);
DEBUG_MSG_P(PSTR("[INIT] WEBUI CODE: %u\n"), WEBUI_IMAGE);
DEBUG_MSG_P(PSTR("[INIT] FIRMWARE IMAGE: %s\n"), ESPURNA_IMAGE_NAME);
DEBUG_MSG_P(PSTR("[INIT] WEBUI IMAGE: %s\n"), getEspurnaWebUI().c_str());
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------


+ 6
- 0
code/espurna/wifi.ino View File

@ -228,6 +228,7 @@ void _wifiCallback(justwifi_messages_t code, char * parameter) {
if (MESSAGE_WPS_ERROR == code || MESSAGE_SMARTCONFIG_ERROR == code) {
_wifi_wps_running = false;
_wifi_smartconfig_running = false;
jw.enableAP(true);
}
if (MESSAGE_WPS_SUCCESS == code || MESSAGE_SMARTCONFIG_SUCCESS == code) {
@ -251,6 +252,7 @@ void _wifiCallback(justwifi_messages_t code, char * parameter) {
_wifi_wps_running = false;
_wifi_smartconfig_running = false;
jw.enableAP(true);
}
@ -558,12 +560,16 @@ void wifiStartAP() {
#if defined(JUSTWIFI_ENABLE_WPS)
void wifiStartWPS() {
jw.enableAP(false);
jw.disconnect();
jw.startWPS();
}
#endif // defined(JUSTWIFI_ENABLE_WPS)
#if defined(JUSTWIFI_ENABLE_SMARTCONFIG)
void wifiStartSmartConfig() {
jw.enableAP(false);
jw.disconnect();
jw.startSmartConfig();
}
#endif // defined(JUSTWIFI_ENABLE_SMARTCONFIG)


+ 16
- 4
code/html/index.html View File

@ -136,9 +136,9 @@
<a href="#" class="pure-menu-link" data="panel-schedule">SCHEDULE</a>
</li>
<!-- removeIf(!sensor)-->
<!-- removeIf(!sensor) -->
<li class="pure-menu-item module module-sns">
<a href="#" class="pure-menu-link" data="panel-sensors">SENSORS</a>
<a href="#" class="pure-menu-link" data="panel-sns">SENSORS</a>
</li>
<!-- endRemoveIf(!sensor) -->
@ -1141,7 +1141,7 @@
</div>
<!-- removeIf(!sensor) -->
<div class="panel" id="panel-sensors">
<div class="panel" id="panel-sns">
<div class="header">
<h1>SENSOR CONFIGURATION</h1>
@ -1183,6 +1183,18 @@
</div>
</div>
<div class="pure-g module module-pwr">
<label class="pure-u-1 pure-u-lg-1-4">Save every</label>
<div class="pure-u-1 pure-u-lg-1-4"><input name="snsSave" class="pure-u-1" type="number" min="0" step="1" max="200" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">
Save aggregated data to EEPROM after these many reports. At the moment this only applies to total energy readings.
Please mind: saving data to EEPROM too often will wear out the flash memory quickly.
Set it to 0 to disable this feature (default value).
</div>
</div>
<div class="pure-g module module-pwr">
<label class="pure-u-1 pure-u-lg-1-4">Power units</label>
<select name="pwrUnits" tabindex="16" class="pure-u-1 pure-u-lg-1-4">
@ -1191,7 +1203,7 @@
</select>
</div>
<div class="pure-g module module-hlw module-cse module-emon module-pzem">
<div class="pure-g module module-pwr">
<label class="pure-u-1 pure-u-lg-1-4">Energy units</label>
<select name="eneUnits" tabindex="16" class="pure-u-1 pure-u-lg-1-4">
<option value="0">Joules (J)</option>


+ 50
- 0
code/platformio.ini View File

@ -2436,3 +2436,53 @@ upload_speed = ${common.upload_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts}
[env:lohas-e27-9w]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DLOHAS_9W
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:lohas-e27-9w-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DLOHAS_9W
upload_speed = ${common.upload_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:allterco-sheely1]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DALLTERCO_SHELLY1
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:allterco-sheely1-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DALLTERCO_SHELLY1
upload_speed = ${common.upload_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}

BIN
images/devices/blitzwolf-bw-shp2.jpg View File

Before After
Width: 400  |  Height: 400  |  Size: 15 KiB Width: 400  |  Height: 400  |  Size: 28 KiB

Loading…
Cancel
Save