Browse Source

Merge branch 'dev' into MAX6675

alexa
Max Prokhorov 6 years ago
committed by GitHub
parent
commit
56865be039
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 18577 additions and 18039 deletions
  1. +1
    -1
      README.md
  2. +3
    -5
      code/espurna/api.ino
  3. +2
    -0
      code/espurna/config/arduino.h
  4. +7
    -2
      code/espurna/config/general.h
  5. +27
    -8
      code/espurna/config/hardware.h
  6. +3
    -0
      code/espurna/config/progmem.h
  7. +103
    -39
      code/espurna/config/sensors.h
  8. +33
    -32
      code/espurna/config/types.h
  9. +1
    -1
      code/espurna/config/version.h
  10. BIN
      code/espurna/data/index.all.html.gz
  11. BIN
      code/espurna/data/index.light.html.gz
  12. BIN
      code/espurna/data/index.rfbridge.html.gz
  13. BIN
      code/espurna/data/index.rfm69.html.gz
  14. BIN
      code/espurna/data/index.sensor.html.gz
  15. BIN
      code/espurna/data/index.small.html.gz
  16. +5
    -1
      code/espurna/nofuss.ino
  17. +3
    -1
      code/espurna/relay.ino
  18. +59
    -18
      code/espurna/sensor.ino
  19. +42
    -1
      code/espurna/sensors/AnalogSensor.h
  20. +231
    -0
      code/espurna/sensors/PulseMeterSensor.h
  21. +4
    -6
      code/espurna/settings.ino
  22. +3130
    -3118
      code/espurna/static/index.all.html.gz.h
  23. +2982
    -2973
      code/espurna/static/index.light.html.gz.h
  24. +2587
    -2578
      code/espurna/static/index.rfbridge.html.gz.h
  25. +4064
    -4055
      code/espurna/static/index.rfm69.html.gz.h
  26. +2641
    -2629
      code/espurna/static/index.sensor.html.gz.h
  27. +2543
    -2535
      code/espurna/static/index.small.html.gz.h
  28. +38
    -28
      code/espurna/telnet.ino
  29. +11
    -4
      code/espurna/thinkspeak.ino
  30. +3
    -0
      code/espurna/utils.ino
  31. +30
    -4
      code/html/index.html
  32. +24
    -0
      code/platformio.ini

+ 1
- 1
README.md View File

@ -3,7 +3,7 @@
ESPurna ("spark" in Catalan) is a custom firmware for ESP8285/ESP8266 based smart switches, lights and sensors.
It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries.
[![version](https://img.shields.io/badge/version-1.13.3-brightgreen.svg)](CHANGELOG.md)
[![version](https://img.shields.io/badge/version-1.13.4-DEV-brightgreen.svg)](CHANGELOG.md)
[![branch](https://img.shields.io/badge/branch-dev-orange.svg)](https://github.com/xoseperez/espurna/tree/dev/)
[![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=dev)](https://travis-ci.org/xoseperez/espurna)


+ 3
- 5
code/espurna/api.ino View File

@ -19,7 +19,6 @@ typedef struct {
api_put_callback_f putFn = NULL;
} web_api_t;
std::vector<web_api_t> _apis;
bool _api_restful = API_RESTFUL;
// -----------------------------------------------------------------------------
@ -32,14 +31,13 @@ void _apiWebSocketOnSend(JsonObject& root) {
root["apiEnabled"] = getSetting("apiEnabled", API_ENABLED).toInt() == 1;
root["apiKey"] = getSetting("apiKey");
root["apiRealTime"] = getSetting("apiRealTime", API_REAL_TIME_VALUES).toInt() == 1;
root["apiRestFul"] = _api_restful;
root["apiRestFul"] = getSetting("apiRestFul", API_RESTFUL).toInt() == 1;
}
void _apiConfigure() {
_api_restful = getSetting("apiRestFul", API_RESTFUL).toInt() == 1;
// Nothing to do
}
// -----------------------------------------------------------------------------
// API
// -----------------------------------------------------------------------------
@ -165,7 +163,7 @@ bool _apiRequestCallback(AsyncWebServerRequest *request) {
// Check if its a PUT
if (api.putFn != NULL) {
if (!_api_restful || (request->method() == HTTP_PUT)) {
if ((getSetting("apiRestFul", API_RESTFUL).toInt() != 1) || (request->method() == HTTP_PUT)) {
if (request->hasParam("value", request->method() == HTTP_PUT)) {
AsyncWebParameter* p = request->getParam("value", request->method() == HTTP_PUT);
(api.putFn)((p->value()).c_str());


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

@ -102,6 +102,7 @@
//#define IWOOLE_LED_TABLE_LAMP
//#define EXS_WIFI_RELAY_V50
//#define TECKIN_SP22_V14
//#define LOMBEX_LUX_NOVA2_TUNABLE_WHITE
//--------------------------------------------------------------------------------
// Features (values below are non-default values)
@ -166,6 +167,7 @@
//#define MICS5525_SUPPORT 1
//#define NTC_SUPPORT 1
//#define PMSX003_SUPPORT 1
//#define PULSEMETER_SUPPORT 1
//#define PZEM004T_SUPPORT 1
//#define SDS011_SUPPORT 1
//#define SENSEAIR_SUPPORT 1


+ 7
- 2
code/espurna/config/general.h View File

@ -110,8 +110,8 @@
#define TELNET_STA 0 // By default, disallow connections via STA interface
#endif
#ifndef TELNET_PASSWORD
#define TELNET_PASSWORD 1 // Request password to start telnet session by default
#ifndef TELNET_AUTHENTICATION
#define TELNET_AUTHENTICATION 1 // Request password to start telnet session by default
#endif
#define TELNET_PORT 23 // Port to listen to telnet clients
@ -1005,6 +1005,11 @@
#define THINGSPEAK_APIKEY "" // Default API KEY
#endif
#ifndef THINGSPEAK_CLEAR_CACHE
#define THINGSPEAK_CLEAR_CACHE 1 // Clear cache after sending values
// Not clearing it will result in latest values for each field being sent every time
#endif
#define THINGSPEAK_USE_ASYNC 1 // Use AsyncClient instead of WiFiClientSecure
// THINGSPEAK OVER SSL


+ 27
- 8
code/espurna/config/hardware.h View File

@ -2658,16 +2658,11 @@
#define HLW8012_POWER_RATIO 2533110
#define HLW8012_INTERRUPT_ON FALLING
//#define HLW8012_WAIT_FOR_WIFI 1
//#define ALEXA_SUPPORT 0
//#define DOMOTICZ_SUPPORT 0
//#define HOMEASSISTANT_SUPPORT 0
//#define THINGSPEAK_SUPPORT 0
// ----------------------------------------------------------------------------------------
// Homecube 16A is similar but some pins differ and it also has RGB LEDs
// https://www.amazon.de/gp/product/B07D7RVF56/ref=oh_aui_detailpage_o00_s01?ie=UTF8&psc=1
// ----------------------------------------------------------------------------------------
#elif defined(HOMECUBE_16A)
// Info
@ -2962,6 +2957,29 @@
#define LIGHT_CH3_INVERSE 0
#define LIGHT_CH4_INVERSE 0
// -----------------------------------------------------------------------------
// Lombex Lux Nova 2 Tunable White
// https://www.amazon.com/Lombex-Compatible-Equivalent-Dimmable-2700K-6500K/dp/B07B8K72PR
// -----------------------------------------------------------------------------
#elif defined(LOMBEX_LUX_NOVA2_TUNABLE_WHITE)
// Info
#define MANUFACTURER "LOMBEX"
#define DEVICE "LUX_NOVA2_TUNABLE_WHITE"
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY92XX
#define DUMMY_RELAY_COUNT 1
// Light
#define LIGHT_CHANNELS 5
#define MY92XX_MODEL MY92XX_MODEL_MY9291
#define MY92XX_CHIPS 1
#define MY92XX_DI_PIN 4
#define MY92XX_DCKI_PIN 5
#define MY92XX_COMMAND MY92XX_COMMAND_DEFAULT
// No RGB on this bulb. Warm white on channel 0, cool white on channel 3
#define MY92XX_MAPPING 255, 255, 255, 3, 0
// -----------------------------------------------------------------------------
// Bestek Smart Plug with 2 USB ports
// https://www.bestekcorp.com/bestek-smart-plug-works-with-amazon-alexa-google-assistant-and-ifttt-with-2-usb
@ -3029,10 +3047,9 @@
#define SHT3X_I2C_SUPPORT 1
#define SI7021_SUPPORT 1
#define PMSX003_SUPPORT 1
#define SENSEAIR_SUPPORT1
#define SENSEAIR_SUPPORT 1
#define VL53L1X_SUPPORT 1
// A bit of lights - pin 5
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
@ -3167,6 +3184,8 @@
#define EMON_ANALOG_SUPPORT 1
#endif
#define PULSEMETER_SUPPORT 1
// Test non-default modules
#define LLMNR_SUPPORT 1
#define NETBIOS_SUPPORT 1


+ 3
- 0
code/espurna/config/progmem.h View File

@ -199,6 +199,9 @@ PROGMEM const char espurna_sensors[] =
#if PMSX003_SUPPORT
"PMSX003 "
#endif
#if PULSEMETER_SUPPORT
"PULSEMETER "
#endif
#if PZEM004T_SUPPORT
"PZEM004T "
#endif


+ 103
- 39
code/espurna/config/sensors.h View File

@ -99,6 +99,25 @@
#define ANALOG_DELAY 0 // Delay between samples in micros
#endif
//Use the following to perform scaling of raw analog values
// scaledRead = ( factor * rawRead ) + offset
//
//Please take note that the offset is not affected by the scaling factor
#ifndef ANALOG_FACTOR
#define ANALOG_FACTOR 1.0 // Multiply raw reading by this factor
#endif
#ifndef ANALOG_OFFSET
#define ANALOG_OFFSET 0.0 // Add this offset to *scaled* value
#endif
// Round to this number of decimals
#ifndef ANALOG_DECIMALS
#define ANALOG_DECIMALS 2
#endif
//------------------------------------------------------------------------------
// BH1750
// Enable support by passing BH1750_SUPPORT=1 build flag
@ -276,12 +295,28 @@
#define EMON_MAX_SAMPLES 1000 // Max number of samples to get
#define EMON_MAX_TIME 250 // Max time in ms to sample
#define EMON_FILTER_SPEED 512 // Mobile average filter speed
#define EMON_MAINS_VOLTAGE 230 // Mains voltage
#define EMON_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC
#ifndef EMON_MAINS_VOLTAGE
#define EMON_MAINS_VOLTAGE 230 // Mains voltage
#endif
#ifndef EMON_CURRENT_RATIO
#define EMON_CURRENT_RATIO 30 // Current ratio in the clamp (30A/1V)
#endif
#ifndef EMON_REPORT_CURRENT
#define EMON_REPORT_CURRENT 0 // Report current
#endif
#ifndef EMON_REPORT_POWER
#define EMON_REPORT_POWER 1 // Report power
#endif
#ifndef EMON_REPORT_ENERGY
#define EMON_REPORT_ENERGY 1 // Report energy
#endif
//------------------------------------------------------------------------------
// Energy Monitor based on ADC121
@ -544,40 +579,6 @@
#define NTC_BETA 3977 // Beta coeficient
#endif
//------------------------------------------------------------------------------
// SDS011 particulates sensor
// Enable support by passing SDS011_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef SDS011_SUPPORT
#define SDS011_SUPPORT 0
#endif
#ifndef SDS011_RX_PIN
#define SDS011_RX_PIN 14
#endif
#ifndef SDS011_TX_PIN
#define SDS011_TX_PIN 12
#endif
//------------------------------------------------------------------------------
// SenseAir CO2 sensor
// Enable support by passing SENSEAIR_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef SENSEAIR_SUPPORT
#define SENSEAIR_SUPPORT 0
#endif
#ifndef SENSEAIR_RX_PIN
#define SENSEAIR_RX_PIN 0
#endif
#ifndef SENSEAIR_TX_PIN
#define SENSEAIR_TX_PIN 2
#endif
//------------------------------------------------------------------------------
// Particle Monitor based on Plantower PMS
// Enable support by passing PMSX003_SUPPORT=1 build flag
@ -599,20 +600,44 @@
#endif
#ifndef PMS_USE_SOFT
#define PMS_USE_SOFT 0 // If PMS_USE_SOFT == 1, DEBUG_SERIAL_SUPPORT must be 0
#define PMS_USE_SOFT 0 // If PMS_USE_SOFT == 1, DEBUG_SERIAL_SUPPORT must be 0
#endif
#ifndef PMS_RX_PIN
#define PMS_RX_PIN 13 // Software serial RX GPIO (if PMS_USE_SOFT == 1)
#define PMS_RX_PIN 13 // Software serial RX GPIO (if PMS_USE_SOFT == 1)
#endif
#ifndef PMS_TX_PIN
#define PMS_TX_PIN 15 // Software serial TX GPIO (if PMS_USE_SOFT == 1)
#define PMS_TX_PIN 15 // Software serial TX GPIO (if PMS_USE_SOFT == 1)
#endif
#ifndef PMS_HW_PORT
#define PMS_HW_PORT Serial // Hardware serial port (if PMS_USE_SOFT == 0)
#define PMS_HW_PORT Serial // Hardware serial port (if PMS_USE_SOFT == 0)
#endif
//------------------------------------------------------------------------------
// Pulse Meter Energy monitor
// Enable support by passing PULSEMETER_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef PULSEMETER_SUPPORT
#define PULSEMETER_SUPPORT 0
#endif
#ifndef PULSEMETER_PIN
#define PULSEMETER_PIN 5
#endif
#ifndef PULSEMETER_ENERGY_RATIO
#define PULSEMETER_ENERGY_RATIO 4000 // In pulses/kWh
#endif
#ifndef PULSEMETER_INTERRUPT_ON
#define PULSEMETER_INTERRUPT_ON FALLING
#endif
#define PULSEMETER_DEBOUNCE 50 // Do not register pulses within less than 50 millis
//------------------------------------------------------------------------------
// PZEM004T based power monitor
// Enable support by passing PZEM004T_SUPPORT=1 build flag
@ -650,6 +675,40 @@
#define PZEM004T_MAX_DEVICES 3
#endif
//------------------------------------------------------------------------------
// SDS011 particulates sensor
// Enable support by passing SDS011_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef SDS011_SUPPORT
#define SDS011_SUPPORT 0
#endif
#ifndef SDS011_RX_PIN
#define SDS011_RX_PIN 14
#endif
#ifndef SDS011_TX_PIN
#define SDS011_TX_PIN 12
#endif
//------------------------------------------------------------------------------
// SenseAir CO2 sensor
// Enable support by passing SENSEAIR_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef SENSEAIR_SUPPORT
#define SENSEAIR_SUPPORT 0
#endif
#ifndef SENSEAIR_RX_PIN
#define SENSEAIR_RX_PIN 0
#endif
#ifndef SENSEAIR_TX_PIN
#define SENSEAIR_TX_PIN 2
#endif
//------------------------------------------------------------------------------
// SHT3X I2C (Wemos) temperature & humidity sensor
// Enable support by passing SHT3X_I2C_SUPPORT=1 build flag
@ -789,6 +848,7 @@
SENSEAIR_SUPPORT || \
PMSX003_SUPPORT || \
PZEM004T_SUPPORT || \
PULSEMETER_SUPPORT || \
SHT3X_I2C_SUPPORT || \
SI7021_SUPPORT || \
SONAR_SUPPORT || \
@ -929,6 +989,10 @@
#include "../sensors/PMSX003Sensor.h"
#endif
#if PULSEMETER_SUPPORT
#include "../sensors/PulseMeterSensor.h"
#endif
#if PZEM004T_SUPPORT
#include "../sensors/PZEM004TSensor.h"
#endif


+ 33
- 32
code/espurna/config/types.h View File

@ -250,41 +250,42 @@
// These should remain over time, do not modify them, only add new ones at the end
//--------------------------------------------------------------------------------
#define SENSOR_DHTXX_ID 0x01
#define SENSOR_DALLAS_ID 0x02
#define SENSOR_EMON_ANALOG_ID 0x03
#define SENSOR_EMON_ADC121_ID 0x04
#define SENSOR_EMON_ADS1X15_ID 0x05
#define SENSOR_HLW8012_ID 0x06
#define SENSOR_V9261F_ID 0x07
#define SENSOR_ECH1560_ID 0x08
#define SENSOR_ANALOG_ID 0x09
#define SENSOR_DIGITAL_ID 0x10
#define SENSOR_EVENTS_ID 0x11
#define SENSOR_PMSX003_ID 0x12
#define SENSOR_BMX280_ID 0x13
#define SENSOR_MHZ19_ID 0x14
#define SENSOR_SI7021_ID 0x15
#define SENSOR_SHT3X_I2C_ID 0x16
#define SENSOR_BH1750_ID 0x17
#define SENSOR_PZEM004T_ID 0x18
#define SENSOR_AM2320_ID 0x19
#define SENSOR_GUVAS12SD_ID 0x20
#define SENSOR_CSE7766_ID 0x21
#define SENSOR_TMP3X_ID 0x22
#define SENSOR_SONAR_ID 0x23
#define SENSOR_SENSEAIR_ID 0x24
#define SENSOR_GEIGER_ID 0x25
#define SENSOR_NTC_ID 0x26
#define SENSOR_SDS011_ID 0x27
#define SENSOR_MICS2710_ID 0x28
#define SENSOR_MICS5525_ID 0x29
#define SENSOR_VEML6075_ID 0x30
#define SENSOR_VL53L1X_ID 0x31
#define SENSOR_MAX6675_ID 0x32
#define SENSOR_DHTXX_ID 1
#define SENSOR_DALLAS_ID 2
#define SENSOR_EMON_ANALOG_ID 3
#define SENSOR_EMON_ADC121_ID 4
#define SENSOR_EMON_ADS1X15_ID 5
#define SENSOR_HLW8012_ID 6
#define SENSOR_V9261F_ID 7
#define SENSOR_ECH1560_ID 8
#define SENSOR_ANALOG_ID 9
#define SENSOR_DIGITAL_ID 10
#define SENSOR_EVENTS_ID 11
#define SENSOR_PMSX003_ID 12
#define SENSOR_BMX280_ID 13
#define SENSOR_MHZ19_ID 14
#define SENSOR_SI7021_ID 15
#define SENSOR_SHT3X_I2C_ID 16
#define SENSOR_BH1750_ID 17
#define SENSOR_PZEM004T_ID 18
#define SENSOR_AM2320_ID 19
#define SENSOR_GUVAS12SD_ID 20
#define SENSOR_CSE7766_ID 21
#define SENSOR_TMP3X_ID 22
#define SENSOR_SONAR_ID 23
#define SENSOR_SENSEAIR_ID 24
#define SENSOR_GEIGER_ID 25
#define SENSOR_NTC_ID 26
#define SENSOR_SDS011_ID 27
#define SENSOR_MICS2710_ID 28
#define SENSOR_MICS5525_ID 29
#define SENSOR_PULSEMETER_ID 30
#define SENSOR_VEML6075_ID 31
#define SENSOR_VL53L1X_ID 32
//--------------------------------------------------------------------------------
// Magnitudes
// These should remain over time, do not modify their values, only add new ones at the end
//--------------------------------------------------------------------------------
#define MAGNITUDE_NONE 0


+ 1
- 1
code/espurna/config/version.h View File

@ -1,5 +1,5 @@
#define APP_NAME "ESPURNA"
#define APP_VERSION "1.13.3"
#define APP_VERSION "1.13.4-DEV"
#define APP_AUTHOR "xose.perez@gmail.com"
#define APP_WEBSITE "http://tinkerman.cat"
#define CFG_VERSION 3

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


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


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


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


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


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


+ 5
- 1
code/espurna/nofuss.ino View File

@ -120,6 +120,9 @@ void nofussSetup() {
#if WEB_SUPPORT
wsSend_P(PSTR("{\"message\": 1}"));
#endif
// Disabling EEPROM rotation to prevent writing to EEPROM after the upgrade
eepromRotate(false);
}
if (code == NOFUSS_FILESYSTEM_UPDATE_ERROR) {
@ -147,7 +150,8 @@ void nofussSetup() {
}
if (code == NOFUSS_END) {
DEBUG_MSG_P(PSTR("[NoFUSS] End\n"));
DEBUG_MSG_P(PSTR("[NoFUSS] End\n"));
eepromRotate(true);
}
});


+ 3
- 1
code/espurna/relay.ino View File

@ -557,6 +557,8 @@ void _relayBoot() {
void _relayConfigure() {
for (unsigned int i=0; i<_relays.size(); i++) {
if (GPIO_NONE == _relays[i].pin) continue;
pinMode(_relays[i].pin, OUTPUT);
if (GPIO_NONE != _relays[i].reset_pin) {
pinMode(_relays[i].reset_pin, OUTPUT);
@ -1006,7 +1008,7 @@ void relaySetup() {
// No delay_on or off for these devices to easily allow having more than
// 8 channels. This behaviour will be recovered with v2.
for (unsigned char i=0; i < DUMMY_RELAY_COUNT; i++) {
_relays.push_back((relay_t) {0, RELAY_TYPE_NORMAL, 0, 0, 0});
_relays.push_back((relay_t) {GPIO_NONE, RELAY_TYPE_NORMAL, 0, 0, 0});
}
#else


+ 59
- 18
code/espurna/sensor.ino View File

@ -56,6 +56,7 @@ unsigned char _magnitudeDecimals(unsigned char type) {
// Hardcoded decimals (these should be linked to the unit, instead of the magnitude)
if (type == MAGNITUDE_ANALOG) return ANALOG_DECIMALS;
if (type == MAGNITUDE_ENERGY ||
type == MAGNITUDE_ENERGY_DELTA) {
if (_sensor_energy_units == ENERGY_KWH) return 3;
@ -200,6 +201,13 @@ void _sensorWebSocketStart(JsonObject& root) {
}
#endif
#if PULSEMETER_SUPPORT
if (sensor->getID() == SENSOR_PULSEMETER_ID) {
root["pmVisible"] = 1;
root["pwrRatioE"] = ((PulseMeterSensor *) sensor)->getEnergyRatio();
}
#endif
}
if (_magnitudes.size() > 0) {
@ -408,6 +416,9 @@ void _sensorLoad() {
AnalogSensor * sensor = new AnalogSensor();
sensor->setSamples(ANALOG_SAMPLES);
sensor->setDelay(ANALOG_DELAY);
//CICM For analog scaling
sensor->setFactor(ANALOG_FACTOR);
sensor->setOffset(ANALOG_OFFSET);
_sensors.push_back(sensor);
}
#endif
@ -620,24 +631,6 @@ void _sensorLoad() {
}
#endif
#if SENSEAIR_SUPPORT
{
SenseAirSensor * sensor = new SenseAirSensor();
sensor->setRX(SENSEAIR_RX_PIN);
sensor->setTX(SENSEAIR_TX_PIN);
_sensors.push_back(sensor);
}
#endif
#if SDS011_SUPPORT
{
SDS011Sensor * sensor = new SDS011Sensor();
sensor->setRX(SDS011_RX_PIN);
sensor->setTX(SDS011_TX_PIN);
_sensors.push_back(sensor);
}
#endif
#if PMSX003_SUPPORT
{
PMSX003Sensor * sensor = new PMSX003Sensor();
@ -652,6 +645,16 @@ void _sensorLoad() {
}
#endif
#if PULSEMETER_SUPPORT
{
PulseMeterSensor * sensor = new PulseMeterSensor();
sensor->setGPIO(PULSEMETER_PIN);
sensor->setEnergyRatio(PULSEMETER_ENERGY_RATIO);
sensor->setDebounceTime(PULSEMETER_DEBOUNCE);
_sensors.push_back(sensor);
}
#endif
#if PZEM004T_SUPPORT
{
PZEM004TSensor * sensor = pzem004t_sensor = new PZEM004TSensor();
@ -672,6 +675,24 @@ void _sensorLoad() {
}
#endif
#if SENSEAIR_SUPPORT
{
SenseAirSensor * sensor = new SenseAirSensor();
sensor->setRX(SENSEAIR_RX_PIN);
sensor->setTX(SENSEAIR_TX_PIN);
_sensors.push_back(sensor);
}
#endif
#if SDS011_SUPPORT
{
SDS011Sensor * sensor = new SDS011Sensor();
sensor->setRX(SDS011_RX_PIN);
sensor->setTX(SDS011_TX_PIN);
_sensors.push_back(sensor);
}
#endif
#if SHT3X_I2C_SUPPORT
{
SHT3XI2CSensor * sensor = new SHT3XI2CSensor();
@ -890,6 +911,13 @@ void _sensorInit() {
#endif // CSE7766_SUPPORT
#if PULSEMETER_SUPPORT
if (_sensors[i]->getID() == SENSOR_PULSEMETER_ID) {
PulseMeterSensor * sensor = (PulseMeterSensor *) _sensors[i];
sensor->setEnergyRatio(getSetting("pwrRatioE", PULSEMETER_ENERGY_RATIO).toInt());
}
#endif // PULSEMETER_SUPPORT
}
}
@ -1065,6 +1093,19 @@ void _sensorConfigure() {
#endif // CSE7766_SUPPORT
#if PULSEMETER_SUPPORT
if (_sensors[i]->getID() == SENSOR_PULSEMETER_ID) {
PulseMeterSensor * sensor = (PulseMeterSensor *) _sensors[i];
if (getSetting("pwrResetE", 0).toInt() == 1) {
sensor->resetEnergy();
delSetting("eneTotal");
_sensorResetTS();
}
sensor->setEnergyRatio(getSetting("pwrRatioE", PULSEMETER_ENERGY_RATIO).toInt());
}
#endif // PULSEMETER_SUPPORT
#if PZEM004T_SUPPORT
if (_sensors[i]->getID() == SENSOR_PZEM004T_ID) {


+ 42
- 1
code/espurna/sensors/AnalogSensor.h View File

@ -35,6 +35,16 @@ class AnalogSensor : public BaseSensor {
_micros = micros;
}
void setFactor(double factor) {
//DEBUG_MSG(("[ANALOG_SENSOR] Factor set to: %s \n"), String(factor,6).c_str());
_factor = factor;
}
void setOffset(double offset) {
//DEBUG_MSG(("[ANALOG_SENSOR] Factor set to: %s \n"), String(offset,6).c_str());
_offset = offset;
}
// ---------------------------------------------------------------------
unsigned int getSamples() {
@ -45,6 +55,14 @@ class AnalogSensor : public BaseSensor {
return _micros;
}
double getFactor() {
return _factor;
}
double getOffset() {
return _offset;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
@ -77,6 +95,7 @@ class AnalogSensor : public BaseSensor {
}
// Current value for slot # index
// Changed return type as moving to scaled value
double value(unsigned char index) {
if (index == 0) return _read();
return 0;
@ -84,7 +103,9 @@ class AnalogSensor : public BaseSensor {
protected:
unsigned int _read() {
//CICM: this should be for raw values
// renaming protected function "_read" to "_rawRead"
unsigned int _rawRead() {
if (1 == _samples) return analogRead(0);
unsigned long sum = 0;
for (unsigned int i=0; i<_samples; i++) {
@ -94,8 +115,28 @@ class AnalogSensor : public BaseSensor {
return sum / _samples;
}
//CICM: and proper read should be scalable and thus needs sign
//and decimal part
double _read() {
//Raw measure could also be a class variable with getter so that can
//be reported through MQTT, ...
unsigned int rawValue;
double scaledValue;
// Debugging doubles to string
//DEBUG_MSG(("[ANALOG_SENSOR] Started standard read, factor: %s , offset: %s, decimals: %d \n"), String(_factor).c_str(), String(_offset).c_str(), ANALOG_DECIMALS);
rawValue = _rawRead();
//DEBUG_MSG(("[ANALOG_SENSOR] Raw read received: %d \n"), rawValue);
scaledValue = _factor*rawValue + _offset;
//DEBUG_MSG(("[ANALOG_SENSOR] Scaled value result: %s \n"), String(scaledValue).c_str());
return scaledValue;
}
unsigned int _samples = 1;
unsigned long _micros = 0;
//CICM: for scaling and offset, also with getters and setters
double _factor = 1.0;
double _offset = 0.0;
};


+ 231
- 0
code/espurna/sensors/PulseMeterSensor.h View File

@ -0,0 +1,231 @@
// -----------------------------------------------------------------------------
// Pulse Meter Power Monitor Sensor
// Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
// -----------------------------------------------------------------------------
#if SENSOR_SUPPORT && PULSEMETER_SUPPORT
#pragma once
#include "Arduino.h"
#include "BaseSensor.h"
class PulseMeterSensor : public BaseSensor {
public:
// ---------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------
PulseMeterSensor(): BaseSensor() {
_count = 2;
_sensor_id = SENSOR_PULSEMETER_ID;
}
~PulseMeterSensor() {
_enableInterrupts(false);
}
void resetEnergy(double value = 0) {
_energy = value;
}
// ---------------------------------------------------------------------
void setGPIO(unsigned char gpio) {
if (_gpio == gpio) return;
_gpio = gpio;
_dirty = true;
}
void setEnergyRatio(unsigned long ratio) {
if (ratio > 0) _ratio = ratio;
}
void setDebounceTime(unsigned long debounce) {
_debounce = debounce;
}
// ---------------------------------------------------------------------
unsigned char getGPIO() {
return _gpio;
}
unsigned long getEnergyRatio() {
return _ratio;
}
unsigned long getDebounceTime() {
return _debounce;
}
// ---------------------------------------------------------------------
// Sensors API
// ---------------------------------------------------------------------
// Initialization method, must be idempotent
// Defined outside the class body
void begin() {
_enableInterrupts(true);
_ready = true;
}
// Descriptive name of the sensor
String description() {
char buffer[24];
snprintf(buffer, sizeof(buffer), "PulseMeter @ GPIO(%u)", _gpio);
return String(buffer);
}
// Descriptive name of the slot # index
String slot(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);
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() {
unsigned long lapse = millis() - _previous_time;
_previous_time = millis();
unsigned long pulses = _pulses - _previous_pulses;
_previous_pulses = _pulses;
unsigned long _energy_delta = 1000 * 3600 * pulses / _ratio;
_energy += _energy_delta;
if (lapse > 0) _active = 1000 * _energy_delta / lapse;
}
// Type for slot # index
unsigned char type(unsigned char index) {
if (index == 0) return MAGNITUDE_POWER_ACTIVE;
if (index == 1) return MAGNITUDE_ENERGY;
return MAGNITUDE_NONE;
}
// Current value for slot # index
double value(unsigned char index) {
if (index == 0) return _active;
if (index == 1) return _energy;
return 0;
}
// Handle interrupt calls
void ICACHE_RAM_ATTR handleInterrupt(unsigned char gpio) {
static unsigned long last = 0;
if (millis() - last > _debounce) {
last = millis();
_pulses++;
}
}
protected:
// ---------------------------------------------------------------------
// Interrupt management
// ---------------------------------------------------------------------
void _attach(PulseMeterSensor * instance, unsigned char gpio, unsigned char mode);
void _detach(unsigned char gpio);
void _enableInterrupts(bool value) {
if (value) {
if (_gpio != _previous) {
if (_previous != GPIO_NONE) _detach(_previous);
_attach(this, _gpio, PULSEMETER_INTERRUPT_ON);
_previous = _gpio;
}
} else {
_detach(_previous);
_previous = GPIO_NONE;
}
}
// ---------------------------------------------------------------------
unsigned char _previous = GPIO_NONE;
unsigned char _gpio = GPIO_NONE;
unsigned long _ratio = PULSEMETER_ENERGY_RATIO;
unsigned long _debounce = PULSEMETER_DEBOUNCE;
double _active = 0;
double _energy = 0;
volatile unsigned long _pulses = 0;
unsigned long _previous_pulses = 0;
unsigned long _previous_time = 0;
};
// -----------------------------------------------------------------------------
// Interrupt helpers
// -----------------------------------------------------------------------------
PulseMeterSensor * _pulsemeter_sensor_instance[10] = {NULL};
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr(unsigned char gpio) {
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_pulsemeter_sensor_instance[index]) {
_pulsemeter_sensor_instance[index]->handleInterrupt(gpio);
}
}
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_0() { _pulsemeter_sensor_isr(0); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_1() { _pulsemeter_sensor_isr(1); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_2() { _pulsemeter_sensor_isr(2); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_3() { _pulsemeter_sensor_isr(3); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_4() { _pulsemeter_sensor_isr(4); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_5() { _pulsemeter_sensor_isr(5); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_12() { _pulsemeter_sensor_isr(12); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_13() { _pulsemeter_sensor_isr(13); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_14() { _pulsemeter_sensor_isr(14); }
void ICACHE_RAM_ATTR _pulsemeter_sensor_isr_15() { _pulsemeter_sensor_isr(15); }
static void (*_pulsemeter_sensor_isr_list[10])() = {
_pulsemeter_sensor_isr_0, _pulsemeter_sensor_isr_1, _pulsemeter_sensor_isr_2,
_pulsemeter_sensor_isr_3, _pulsemeter_sensor_isr_4, _pulsemeter_sensor_isr_5,
_pulsemeter_sensor_isr_12, _pulsemeter_sensor_isr_13, _pulsemeter_sensor_isr_14,
_pulsemeter_sensor_isr_15
};
void PulseMeterSensor::_attach(PulseMeterSensor * instance, unsigned char gpio, unsigned char mode) {
if (!gpioValid(gpio)) return;
_detach(gpio);
unsigned char index = gpio > 5 ? gpio-6 : gpio;
_pulsemeter_sensor_instance[index] = instance;
attachInterrupt(gpio, _pulsemeter_sensor_isr_list[index], mode);
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] GPIO%u interrupt attached to %s\n"), gpio, instance->description().c_str());
#endif
}
void PulseMeterSensor::_detach(unsigned char gpio) {
if (!gpioValid(gpio)) return;
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_pulsemeter_sensor_instance[index]) {
detachInterrupt(gpio);
#if SENSOR_DEBUG
DEBUG_MSG_P(PSTR("[SENSOR] GPIO%u interrupt detached from %s\n"), gpio, _pulsemeter_sensor_instance[index]->description().c_str());
#endif
_pulsemeter_sensor_instance[index] = NULL;
}
}
#endif // SENSOR_SUPPORT && PULSEMETER_SUPPORT

+ 4
- 6
code/espurna/settings.ino View File

@ -274,12 +274,10 @@ void _settingsInitCommands() {
DEBUG_MSG_P(PSTR("+OK\n"));
});
#if WEB_SUPPORT
settingsRegisterCommand(F("RELOAD"), [](Embedis* e) {
espurnaReload();
DEBUG_MSG_P(PSTR("+OK\n"));
});
#endif
settingsRegisterCommand(F("RELOAD"), [](Embedis* e) {
espurnaReload();
DEBUG_MSG_P(PSTR("+OK\n"));
});
settingsRegisterCommand(F("RESET"), [](Embedis* e) {
DEBUG_MSG_P(PSTR("+OK\n"));


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


+ 2982
- 2973
code/espurna/static/index.light.html.gz.h
File diff suppressed because it is too large
View File


+ 2587
- 2578
code/espurna/static/index.rfbridge.html.gz.h
File diff suppressed because it is too large
View File


+ 4064
- 4055
code/espurna/static/index.rfm69.html.gz.h
File diff suppressed because it is too large
View File


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


+ 2543
- 2535
code/espurna/static/index.small.html.gz.h
File diff suppressed because it is too large
View File


+ 38
- 28
code/espurna/telnet.ino View File

@ -15,9 +15,9 @@ Parts of the code have been borrowed from Thomas Sarlandie's NetServer
AsyncServer * _telnetServer;
AsyncClient * _telnetClients[TELNET_MAX_CLIENTS];
bool _telnetFirst = true;
#if TELNET_PASSWORD
bool _authenticated[TELNET_MAX_CLIENTS];
#endif
bool _telnetAuth = TELNET_AUTHENTICATION;
bool _telnetClientsAuth[TELNET_MAX_CLIENTS];
// -----------------------------------------------------------------------------
// Private methods
@ -32,6 +32,7 @@ bool _telnetWebSocketOnReceive(const char * key, JsonVariant& value) {
void _telnetWebSocketOnSend(JsonObject& root) {
root["telnetVisible"] = 1;
root["telnetSTA"] = getSetting("telnetSTA", TELNET_STA).toInt() == 1;
root["telnetAuth"] = getSetting("telnetAuth", TELNET_AUTHENTICATION).toInt() == 1;
}
#endif
@ -54,16 +55,12 @@ bool _telnetWrite(unsigned char clientId, void *data, size_t len) {
unsigned char _telnetWrite(void *data, size_t len) {
unsigned char count = 0;
for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) {
// Do not send broadcast messages to unauthenticated clients
if (_telnetAuth && !_telnetClientsAuth[i]) {
continue;
}
#if TELNET_PASSWORD
// Do not send broadcast messages to unauthenticated clients
if (_authenticated[i]) {
if (_telnetWrite(i, data, len)) ++count;
}
#else
if (_telnetWrite(i, data, len)) ++count;
#endif
if (_telnetWrite(i, data, len)) ++count;
}
return count;
}
@ -96,20 +93,24 @@ void _telnetData(unsigned char clientId, void *data, size_t len) {
return;
}
// Password
#if TELNET_PASSWORD
if (!_authenticated[clientId]) {
String password = getAdminPass();
if (strncmp(p, password.c_str(), password.length()) == 0) {
DEBUG_MSG_P(PSTR("[TELNET] Client #%d authenticated\n"), clientId);
_telnetWrite(clientId, "Welcome!\n");
_authenticated[clientId] = true;
} else {
_telnetWrite(clientId, "Password: ");
}
return;
// Password prompt (disable on CORE variant)
#ifdef ESPURNA_CORE
const bool authenticated = true;
#else
const bool authenticated = _telnetClientsAuth[clientId];
#endif
if (_telnetAuth && !authenticated) {
String password = getAdminPass();
if (strncmp(p, password.c_str(), password.length()) == 0) {
DEBUG_MSG_P(PSTR("[TELNET] Client #%d authenticated\n"), clientId);
_telnetWrite(clientId, "Welcome!\n");
_telnetClientsAuth[clientId] = true;
} else {
_telnetWrite(clientId, "Password: ");
}
#endif // TELNET_PASSWORD
return;
}
// Inject command
settingsInject(data, len);
@ -175,9 +176,11 @@ void _telnetNewClient(AsyncClient *client) {
debugClearCrashInfo();
#endif
#if TELNET_PASSWORD
_authenticated[i] = false;
_telnetWrite(i, "Password: ");
#ifdef ESPURNA_CORE
_telnetClientsAuth[i] = true;
#else
_telnetClientsAuth[i] = !_telnetAuth;
if (_telnetAuth) _telnetWrite(i, "Password: ");
#endif
_telnetFirst = true;
@ -214,6 +217,10 @@ unsigned char telnetWrite(unsigned char ch) {
return _telnetWrite(data, 1);
}
void _telnetConfigure() {
_telnetAuth = getSetting("telnetAuth", TELNET_AUTHENTICATION).toInt() == 1;
}
void telnetSetup() {
_telnetServer = new AsyncServer(TELNET_PORT);
@ -227,6 +234,9 @@ void telnetSetup() {
wsOnReceiveRegister(_telnetWebSocketOnReceive);
#endif
espurnaRegisterReload(_telnetConfigure);
_telnetConfigure();
DEBUG_MSG_P(PSTR("[TELNET] Listening on port %d\n"), TELNET_PORT);
}


+ 11
- 4
code/espurna/thinkspeak.ino View File

@ -25,6 +25,8 @@ const char THINGSPEAK_REQUEST_TEMPLATE[] PROGMEM =
"%s\r\n";
bool _tspk_enabled = false;
bool _tspk_clear = false;
char * _tspk_queue[THINGSPEAK_FIELDS] = {NULL};
bool _tspk_flush = false;
@ -45,6 +47,7 @@ void _tspkWebSocketOnSend(JsonObject& root) {
root["tspkEnabled"] = getSetting("tspkEnabled", THINGSPEAK_ENABLED).toInt() == 1;
root["tspkKey"] = getSetting("tspkKey");
root["tspkClear"] = getSetting("tspkClear", THINGSPEAK_CLEAR_CACHE).toInt() == 1;
JsonArray& relays = root.createNestedArray("tspkRelays");
for (byte i=0; i<relayCount(); i++) {
@ -71,6 +74,7 @@ void _tspkWebSocketOnSend(JsonObject& root) {
#endif
void _tspkConfigure() {
_tspk_clear = getSetting("tspkClear", THINGSPEAK_CLEAR_CACHE).toInt() == 1;
_tspk_enabled = getSetting("tspkEnabled", THINGSPEAK_ENABLED).toInt() == 1;
if (_tspk_enabled && (getSetting("tspkKey").length() == 0)) {
_tspk_enabled = false;
@ -221,10 +225,12 @@ void _tspkEnqueue(unsigned char index, char * payload) {
}
void _tspkClearQueue() {
for (unsigned char id=0; id<THINGSPEAK_FIELDS; id++) {
if (_tspk_queue[id] != NULL) {
free(_tspk_queue[id]);
_tspk_queue[id] = NULL;
if (_tspk_clear) {
for (unsigned char id=0; id<THINGSPEAK_FIELDS; id++) {
if (_tspk_queue[id] != NULL) {
free(_tspk_queue[id]);
_tspk_queue[id] = NULL;
}
}
}
}
@ -250,6 +256,7 @@ void _tspkFlush() {
}
}
// -----------------------------------------------------------------------------
bool tspkEnqueueRelay(unsigned char index, unsigned char status) {


+ 3
- 0
code/espurna/utils.ino View File

@ -236,6 +236,9 @@ void heartbeat() {
#if (HEARTBEAT_REPORT_FREEHEAP)
idbSend(MQTT_TOPIC_FREEHEAP, String(free_heap).c_str());
#endif
#if (HEARTBEAT_REPORT_RSSI)
idbSend(MQTT_TOPIC_RSSI, String(WiFi.RSSI()).c_str());
#endif
#endif
}


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

@ -608,6 +608,13 @@
<div class="pure-u-1 pure-u-lg-3-4 hint">Turn ON to be able to telnet to your device while connected to your home router.<br />TELNET is always enabled in AP mode.</div>
</div>
<div class="pure-g module module-telnet">
<label class="pure-u-1 pure-u-lg-1-4">TELNET Password</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="telnetAuth" /></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">Request password when starting telnet session</div>
</div>
<div class="pure-g module module-nofuss">
<label class="pure-u-1 pure-u-lg-1-4">Automatic remote updates (NoFUSS)</label>
@ -1079,9 +1086,21 @@
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="tspkEnabled" tabindex="30" /></div>
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Clear cache</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="tspkClear" tabindex="31" /></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">
With every POST to thinkspeak.com only enqueued fields are sent.
If you select to clear the cache after every sending this will result in only those fields that have changed will be posted.
If you want all fields to be sent with every POST do not clear the cache.
</div>
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Thingspeak API Key</label>
<input class="pure-u-1 pure-u-lg-3-4" name="tspkKey" type="text" tabindex="31" />
<input class="pure-u-1 pure-u-lg-3-4" name="tspkKey" type="text" tabindex="32" />
</div>
<legend>Sensors &amp; actuators</legend>
@ -1332,17 +1351,24 @@
<div class="pure-u-1 pure-u-lg-3-4 hint">In Watts (W). Calibrate your sensor connecting a pure resistive load (like a bulb) and enter here the its nominal power or use a multimeter.</div>
</div>
<div class="pure-g module module-pm">
<label class="pure-u-1 pure-u-lg-1-4">Energy Ratio</label>
<input class="pure-u-1 pure-u-lg-3-4" name="pwrRatioE" type="text" tabindex="55" placeholder="0" />
<div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Energy ratio in pulses/kWh.</div>
</div>
<div class="pure-g module module-hlw module-cse module-emon">
<label class="pure-u-1 pure-u-lg-1-4">Reset calibration</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="pwrResetCalibration" tabindex="55" /></div>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="pwrResetCalibration" tabindex="56" /></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">Move this switch to ON and press "Save" to revert to factory calibration values.</div>
</div>
<div class="pure-g module module-hlw module-cse module-emon">
<div class="pure-g module module-hlw module-cse module-emon module-pm">
<label class="pure-u-1 pure-u-lg-1-4">Reset energy</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="pwrResetE" tabindex="56" /></div>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="pwrResetE" tabindex="57" /></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">Move this switch to ON and press "Save" to set energy count to 0.</div>


+ 24
- 0
code/platformio.ini View File

@ -2305,6 +2305,30 @@ upload_flags = ${common.upload_flags}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:lombex-lux-nova2-tunable-white]
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} -DLOMBEX_LUX_NOVA2_TUNABLE_WHITE
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:lombex-lux-nova2-tunable-white-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} -DLOMBEX_LUX_NOVA2_TUNABLE_WHITE
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}
# ------------------------------------------------------------------------------
# GENERIC OTA ENVIRONMENTS


Loading…
Cancel
Save