diff --git a/code/build.sh b/code/build.sh index 14c95fe0..deb5f930 100755 --- a/code/build.sh +++ b/code/build.sh @@ -9,6 +9,13 @@ is_git() { return 0 } +stat_bytes() { + case "$(uname -s)" in + Darwin) stat -f %z "$1";; + *) stat -c %s "$1";; + esac +} + # Script settings destination=../firmware @@ -104,7 +111,7 @@ build_environments() { for environment in $environments; do echo -n "* espurna-$version-$environment.bin --- " platformio run --silent --environment $environment || exit 1 - stat -c %s .pioenvs/$environment/firmware.bin + stat_bytes .pioenvs/$environment/firmware.bin [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Test" ]] || \ mv .pioenvs/$environment/firmware.bin $destination/espurna-$version/espurna-$version-$environment.bin done diff --git a/code/debug.sh b/code/debug.sh index 63e0fcc6..18f45cc9 100755 --- a/code/debug.sh +++ b/code/debug.sh @@ -19,7 +19,7 @@ rm -rf $FILE function help { echo - echo "Syntax: $0 [-e ] [-d ]" + echo "Syntax: $0 [-e ] [-f ] [-d ]" echo } @@ -29,6 +29,10 @@ while [[ $# -gt 1 ]]; do key="$1" case $key in + -f) + ELF="$2" + shift + ;; -e) ENVIRONMENT="$2" shift @@ -44,12 +48,9 @@ while [[ $# -gt 1 ]]; do done # check environment folder -if [ $ENVIRONMENT == "" ]; then - echo "No environment defined" - help - exit 1 +if [ ! -f $ELF ]; then + ELF=.pioenvs/$ENVIRONMENT/firmware.elf fi -ELF=.pioenvs/$ENVIRONMENT/firmware.elf if [ ! -f $ELF ]; then echo "Could not find ELF file for the selected environment: $ELF" exit 2 diff --git a/code/espurna/api.ino b/code/espurna/api.ino index 705fee17..f65f03f9 100644 --- a/code/espurna/api.ino +++ b/code/espurna/api.ino @@ -221,6 +221,7 @@ void apiRegister(const char * key, api_get_callback_f getFn, api_put_callback_f } void apiSetup() { + _apiConfigure(); wsOnSendRegister(_apiWebSocketOnSend); wsOnReceiveRegister(_apiWebSocketOnReceive); webRequestRegister(_apiRequestCallback); diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index 9d88cc5a..83656b1b 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -101,6 +101,7 @@ //#define PHYX_ESP12_RGB //#define IWOOLE_LED_TABLE_LAMP //#define EXS_WIFI_RELAY_V50 +//#define TECKIN_SP22_V14 //-------------------------------------------------------------------------------- // Features (values below are non-default values) @@ -173,3 +174,4 @@ //#define SONAR_SUPPORT 1 //#define TMP3X_SUPPORT 1 //#define V9261F_SUPPORT 1 +//#define VL53L1X_SUPPORT 1 diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 2ab3040c..307c6eb7 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -237,6 +237,9 @@ #ifndef BUTTON_LNGLNGCLICK_DELAY #define BUTTON_LNGLNGCLICK_DELAY 10000 // Time in ms holding the button down to get a long-long click +#endif + +#ifndef BUTTON_MQTT_SEND_ALL_EVENTS #define BUTTON_MQTT_SEND_ALL_EVENTS 0 // 0 - to send only events the are bound to actions // 1 - to send all button events to MQTT #endif @@ -435,7 +438,9 @@ // or in the Internet. Since the WebUI is just one compressed file with HTML, CSS and JS // there are no special requirements. Any static web server will do (NGinx, Apache, Lighttpd,...). // The only requirement is that the resource must be available under this domain. +#ifndef WEB_REMOTE_DOMAIN #define WEB_REMOTE_DOMAIN "http://tinkerman.cat" +#endif // ----------------------------------------------------------------------------- // WEBSOCKETS @@ -927,8 +932,13 @@ #define HOMEASSISTANT_SUPPORT MQTT_SUPPORT // Build with home assistant support (if MQTT, 1.64Kb) #endif +#ifndef HOMEASSISTANT_ENABLED #define HOMEASSISTANT_ENABLED 0 // Integration not enabled by default +#endif + +#ifndef HOMEASSISTANT_PREFIX #define HOMEASSISTANT_PREFIX "homeassistant" // Default MQTT prefix +#endif #ifndef HOMEASSISTANT_PAYLOAD_ON #define HOMEASSISTANT_PAYLOAD_ON "1" // Payload for ON and available messages diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index ee048c94..5c5e4fc8 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -2576,6 +2576,94 @@ #define HLW8012_POWER_RATIO 3414290 #define HLW8012_INTERRUPT_ON FALLING +// ----------------------------------------------------------------------------- +// Same as the above but new board version marked V2.3 +// ----------------------------------------------------------------------------- + +#elif defined(BLITZWOLF_BWSHP2_V23) + + // Info + #define MANUFACTURER "BLITZWOLF" + #define DEVICE "BWSHP2V2.3" + + // Buttons + #define BUTTON1_PIN 3 + #define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH + #define BUTTON1_RELAY 1 + + // Relays + #define RELAY1_PIN 14 + #define RELAY1_TYPE RELAY_TYPE_NORMAL + + // LEDs + #define LED1_PIN 1 + #define LED1_PIN_INVERSE 1 + #define LED2_PIN 13 + #define LED2_PIN_INVERSE 1 + #define LED2_MODE LED_MODE_FINDME + #define LED2_RELAY 1 + + // HJL01 / BL0937 + #ifndef HLW8012_SUPPORT + #define HLW8012_SUPPORT 1 + #endif + #define HLW8012_SEL_PIN 12 + #define HLW8012_CF1_PIN 5 + #define HLW8012_CF_PIN 4 + + #define HLW8012_SEL_CURRENT LOW + #define HLW8012_CURRENT_RATIO 25740 + #define HLW8012_VOLTAGE_RATIO 313400 + #define HLW8012_POWER_RATIO 3414290 + #define HLW8012_INTERRUPT_ON FALLING + +// ----------------------------------------------------------------------------- +// Teckin SP22 v1.4 - v1.6 +// ----------------------------------------------------------------------------- + +#elif defined(TECKIN_SP22_V14) + + // Info + #define MANUFACTURER "TECKIN" + #define DEVICE "SP22_V14" + + // Buttons + #define BUTTON1_PIN 1 + #define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH + #define BUTTON1_RELAY 1 + + // Relays + #define RELAY1_PIN 14 + #define RELAY1_TYPE RELAY_TYPE_NORMAL + + // LEDs + #define LED1_PIN 3 + #define LED1_PIN_INVERSE 1 + #define LED2_PIN 13 + #define LED2_PIN_INVERSE 1 + #define LED2_MODE LED_MODE_FINDME + #define LED2_RELAY 1 + + // HJL01 / BL0937 + #ifndef HLW8012_SUPPORT + #define HLW8012_SUPPORT 1 + #endif + #define HLW8012_SEL_PIN 12 + #define HLW8012_CF1_PIN 5 + #define HLW8012_CF_PIN 4 + + #define HLW8012_SEL_CURRENT LOW + #define HLW8012_CURRENT_RATIO 20730 + #define HLW8012_VOLTAGE_RATIO 264935 + #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 @@ -2942,6 +3030,7 @@ #define SI7021_SUPPORT 1 #define PMSX003_SUPPORT 1 #define SENSEAIR_SUPPORT1 + #define VL53L1X_SUPPORT 1 // A bit of lights - pin 5 diff --git a/code/espurna/config/progmem.h b/code/espurna/config/progmem.h index 11811783..3fda6521 100644 --- a/code/espurna/config/progmem.h +++ b/code/espurna/config/progmem.h @@ -223,6 +223,12 @@ PROGMEM const char espurna_sensors[] = #if V9261F_SUPPORT "V9261F " #endif + #if VEML6075_SUPPORT + "VEML6075 " + #endif + #if VL53L1X_SUPPORT + "VL53L1X " + #endif ""; @@ -232,7 +238,9 @@ PROGMEM const unsigned char magnitude_decimals[] = { 3, 0, 0, 0, 0, 0, 0, 0, // Power decimals 0, 0, 0, // analog, digital, event 0, 0, 0, // PM - 0, 0, 3, 3, 0, + 0, 0, + 0, 0, 3, // UVA, UVB, UVI + 3, 0, 4, 4, // Geiger Counter decimals 0, 0, 0, 0 // NO2, CO, Ohms @@ -258,7 +266,9 @@ PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5"; PROGMEM const char magnitude_pm10_topic[] = "pm10"; PROGMEM const char magnitude_co2_topic[] = "co2"; PROGMEM const char magnitude_lux_topic[] = "lux"; -PROGMEM const char magnitude_uv_topic[] = "uv"; +PROGMEM const char magnitude_uva_topic[] = "uva"; +PROGMEM const char magnitude_uvb_topic[] = "uvb"; +PROGMEM const char magnitude_uvi_topic[] = "uvi"; PROGMEM const char magnitude_distance_topic[] = "distance"; PROGMEM const char magnitude_hcho_topic[] = "hcho"; PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute] @@ -275,7 +285,8 @@ PROGMEM const char* const magnitude_topics[] = { magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic, magnitude_analog_topic, magnitude_digital_topic, magnitude_event_topic, magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic, - magnitude_co2_topic, magnitude_lux_topic, magnitude_uv_topic, + magnitude_co2_topic, magnitude_lux_topic, + magnitude_uva_topic, magnitude_uvb_topic, magnitude_uvi_topic, magnitude_distance_topic, magnitude_hcho_topic, magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic, magnitude_count_topic, @@ -296,7 +307,6 @@ PROGMEM const char magnitude_kwh[] = "kWh"; PROGMEM const char magnitude_ugm3[] = "µg/m³"; PROGMEM const char magnitude_ppm[] = "ppm"; PROGMEM const char magnitude_lux[] = "lux"; -PROGMEM const char magnitude_uv[] = "uv"; PROGMEM const char magnitude_distance[] = "m"; PROGMEM const char magnitude_mgm3[] = "mg/m³"; PROGMEM const char magnitude_geiger_cpm[] = "cpm"; // Counts per Minute: Unit of local dose rate (Geiger counting) @@ -311,7 +321,8 @@ PROGMEM const char* const magnitude_units[] = { magnitude_percentage, magnitude_joules, magnitude_joules, magnitude_empty, magnitude_empty, magnitude_empty, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, - magnitude_ppm, magnitude_lux, magnitude_uv, + magnitude_ppm, magnitude_lux, + magnitude_empty, magnitude_empty, magnitude_empty, magnitude_distance, magnitude_mgm3, magnitude_geiger_cpm, magnitude_geiger_sv, // Geiger counter units magnitude_empty, // diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index 3e3d3579..ecc80efa 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -195,3 +195,4 @@ void webRequestRegister(web_request_callback_f callback); #include "JustWifi.h" typedef std::function wifi_callback_f; void wifiRegister(wifi_callback_f callback); +bool wifiConnected(); diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index b0b0872a..b75f0b56 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -115,6 +115,39 @@ #define BH1750_MODE BH1750_CONTINUOUS_HIGH_RES_MODE +//------------------------------------------------------------------------------ +// VL53L1X +// Enable support by passing VL53L1X_SUPPORT=1 build flag +//------------------------------------------------------------------------------ + +#ifndef VL53L1X_SUPPORT +#define VL53L1X_SUPPORT 0 +#endif + +#ifndef VL53L1X_I2C_ADDRESS +#define VL53L1X_I2C_ADDRESS 0x00 // 0x00 means auto +#endif + +#ifndef VL53L1X_DISTANCE_MODE +#define VL53L1X_DISTANCE_MODE VL53L1X::Long // The distance mode of the sensor. Can be one of +#endif // `VL53L1X::Short`, `VL53L1X::Medium`, or `VL53L1X::Long. + // Shorter distance modes are less affected by ambient light + // but have lower maximum ranges, especially in the dark. + + +#ifndef VL53L1X_MEASUREMENT_TIMING_BUDGET +#define VL53L1X_MEASUREMENT_TIMING_BUDGET 140000 // The time, in microseconds, allocated for a single + // measurement. A longer timing budget allows for more + // accurate at the cost of power. The minimum budget is + // 20 ms (20000 us) in short distance mode and 33 ms for + // medium and long distance modes. +#endif + +#ifndef VL53L1X_INTER_MEASUREMENT_PERIOD +#define VL53L1X_INTER_MEASUREMENT_PERIOD 50 // Period, in milliseconds, determining how +#endif // often the sensor takes a measurement. + + //------------------------------------------------------------------------------ // BME280/BMP280 // Enable support by passing BMX280_SUPPORT=1 build flag @@ -407,6 +440,11 @@ #define HLW8012_USE_INTERRUPTS 1 // Use interrupts to trap HLW8012 signals #endif +#ifndef HLW8012_WAIT_FOR_WIFI +#define HLW8012_WAIT_FOR_WIFI 0 // Weather to enable interrupts only after + // wifi connection has been stablished +#endif + #ifndef HLW8012_INTERRUPT_ON #define HLW8012_INTERRUPT_ON CHANGE // When to trigger the interrupt // Use CHANGE for HLW8012 @@ -702,6 +740,25 @@ #define V9261F_POWER_FACTOR 153699.0 #define V9261F_RPOWER_FACTOR V9261F_CURRENT_FACTOR +//------------------------------------------------------------------------------ +// VEML6075 based power sensor +// Enable support by passing VEML6075_SUPPORT=1 build flag +//------------------------------------------------------------------------------ + +#ifndef VEML6075_SUPPORT +#define VEML6075_SUPPORT 0 +#endif + +#ifndef VEML6075_INTEGRATION_TIME +#define VEML6075_INTEGRATION_TIME VEML6075::IT_100MS // The time, in milliseconds, allocated for a single +#endif // measurement. A longer timing budget allows for more + // accurate results at the cost of power. + +#ifndef VEML6075_DYNAMIC_MODE +#define VEML6075_DYNAMIC_MODE VEML6075::DYNAMIC_NORMAL // The dynamic mode can either be normal or high. In high +#endif // dynamic mode, the resolution increases by about two + // times. + // ============================================================================= // Sensor helpers configuration - can't move to dependencies.h // ============================================================================= @@ -736,7 +793,9 @@ SI7021_SUPPORT || \ SONAR_SUPPORT || \ TMP3X_SUPPORT || \ - V9261F_SUPPORT \ + V9261F_SUPPORT || \ + VEML6075_SUPPORT || \ + VL53L1X_SUPPORT \ ) #endif @@ -894,6 +953,14 @@ #include "../sensors/V9261FSensor.h" #endif +#if VEML6075_SUPPORT + #include "../sensors/VEML6075Sensor.h" +#endif + +#if VL53L1X_SUPPORT + #include "../sensors/VL53L1XSensor.h" +#endif + #if MAX6675_SUPPORT #include "../sensors/MAX6675.h" #endif diff --git a/code/espurna/config/types.h b/code/espurna/config/types.h index 9bb4ebcc..30cba614 100644 --- a/code/espurna/config/types.h +++ b/code/espurna/config/types.h @@ -279,7 +279,9 @@ #define SENSOR_SDS011_ID 0x27 #define SENSOR_MICS2710_ID 0x28 #define SENSOR_MICS5525_ID 0x29 -#define SENSOR_MAX6675_ID 0x30 +#define SENSOR_VEML6075_ID 0x30 +#define SENSOR_VL53L1X_ID 0x31 +#define SENSOR_MAX6675_ID 0x32 //-------------------------------------------------------------------------------- // Magnitudes @@ -305,14 +307,16 @@ #define MAGNITUDE_PM10 17 #define MAGNITUDE_CO2 18 #define MAGNITUDE_LUX 19 -#define MAGNITUDE_UV 20 -#define MAGNITUDE_DISTANCE 21 -#define MAGNITUDE_HCHO 22 -#define MAGNITUDE_GEIGER_CPM 23 -#define MAGNITUDE_GEIGER_SIEVERT 24 -#define MAGNITUDE_COUNT 25 -#define MAGNITUDE_NO2 26 -#define MAGNITUDE_CO 27 -#define MAGNITUDE_RESISTANCE 28 - -#define MAGNITUDE_MAX 29 +#define MAGNITUDE_UVA 20 +#define MAGNITUDE_UVB 21 +#define MAGNITUDE_UVI 22 +#define MAGNITUDE_DISTANCE 23 +#define MAGNITUDE_HCHO 24 +#define MAGNITUDE_GEIGER_CPM 25 +#define MAGNITUDE_GEIGER_SIEVERT 26 +#define MAGNITUDE_COUNT 27 +#define MAGNITUDE_NO2 28 +#define MAGNITUDE_CO 29 +#define MAGNITUDE_RESISTANCE 30 + +#define MAGNITUDE_MAX 31 diff --git a/code/espurna/ntp.ino b/code/espurna/ntp.ino index 5bf2f591..e4949825 100644 --- a/code/espurna/ntp.ino +++ b/code/espurna/ntp.ino @@ -128,7 +128,7 @@ void _ntpBackwards() { // ----------------------------------------------------------------------------- bool ntpSynced() { - return (year() > 2017); + return (NTP.getLastNTPSync() > 0); } String ntpDateTime(time_t t) { diff --git a/code/espurna/rfbridge.ino b/code/espurna/rfbridge.ino index e2aa4cc5..582ae38e 100644 --- a/code/espurna/rfbridge.ino +++ b/code/espurna/rfbridge.ino @@ -19,6 +19,8 @@ Copyright (C) 2017-2018 by Xose Pérez // DEFINITIONS // ----------------------------------------------------------------------------- +// EFM8 Protocol + #define RF_MESSAGE_SIZE 9 #define RF_MAX_MESSAGE_SIZE (112+4) #define RF_CODE_START 0xAA @@ -37,6 +39,10 @@ Copyright (C) 2017-2018 by Xose Pérez #define RF_CODE_RFOUT_BUCKET 0xB0 #define RF_CODE_STOP 0x55 +// Settings + +#define RF_MAX_KEY_LENGTH (9) + // ----------------------------------------------------------------------------- // GLOBALS TO THE MODULE // ----------------------------------------------------------------------------- @@ -523,13 +529,13 @@ void _rfbMqttCallback(unsigned int type, const char * topic, const char * payloa void rfbStore(unsigned char id, bool status, const char * code) { DEBUG_MSG_P(PSTR("[RFBRIDGE] Storing %d-%s => '%s'\n"), id, status ? "ON" : "OFF", code); - char key[8] = {0}; + char key[RF_MAX_KEY_LENGTH] = {0}; snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id); setSetting(key, code); } String rfbRetrieve(unsigned char id, bool status) { - char key[8] = {0}; + char key[RF_MAX_KEY_LENGTH] = {0}; snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id); return getSetting(key); } @@ -586,7 +592,7 @@ void rfbLearn(unsigned char id, bool status) { void rfbForget(unsigned char id, bool status) { - char key[8] = {0}; + char key[RF_MAX_KEY_LENGTH] = {0}; snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id); delSetting(key); diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index ad05fa11..baea2baf 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -282,7 +282,7 @@ void _sensorInitCommands() { DEBUG_MSG_P(PSTR("[SENSOR] PZEM004T\n")); unsigned char dev_count = pzem004t_sensor->getAddressesCount(); for(unsigned char dev = 0; dev < dev_count; dev++) { - DEBUG_MSG_P(PSTR("Device %d Address %s\n"), dev, pzem004t_sensor->getAddress(dev).c_str()); + DEBUG_MSG_P(PSTR("Device %d/%s\n"), dev, pzem004t_sensor->getAddress(dev).c_str()); } DEBUG_MSG_P(PSTR("+OK\n")); } else if(e->argc == 2) { @@ -299,7 +299,7 @@ void _sensorInitCommands() { } }); settingsRegisterCommand(F("PZ.RESET"), [](Embedis* e) { - if(e->argc > 2) { + if(e->argc > 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); } else { unsigned char init = e->argc == 2 ? String(e->argv[1]).toInt() : 0; @@ -308,7 +308,7 @@ void _sensorInitCommands() { for(unsigned char dev = init; dev < limit; dev++) { float offset = pzem004t_sensor->resetEnergy(dev); setSetting("pzEneTotal", dev, offset); - DEBUG_MSG_P(PSTR("Device %d Address %s - Offset: %s\n"), dev, pzem004t_sensor->getAddress(dev).c_str(), String(offset).c_str()); + DEBUG_MSG_P(PSTR("Device %d/%s - Offset: %s\n"), dev, pzem004t_sensor->getAddress(dev).c_str(), String(offset).c_str()); } DEBUG_MSG_P(PSTR("+OK\n")); } @@ -713,10 +713,25 @@ void _sensorLoad() { sensor->setSCK(MAX6675_SCK_PIN); _sensors.push_back(sensor); } - #endif - + #if VEML6075_SUPPORT + { + VEML6075Sensor * sensor = new VEML6075Sensor(); + sensor->setIntegrationTime(VEML6075_INTEGRATION_TIME); + sensor->setDynamicMode(VEML6075_DYNAMIC_MODE); + _sensors.push_back(sensor); + } + #endif + #if VL53L1X_SUPPORT + { + VL53L1XSensor * sensor = new VL53L1XSensor(); + sensor->setInterMeasurementPeriod(VL53L1X_INTER_MEASUREMENT_PERIOD); + sensor->setDistanceMode(VL53L1X_DISTANCE_MODE); + sensor->setMeasurementTimingBudget(VL53L1X_MEASUREMENT_TIMING_BUDGET); + _sensors.push_back(sensor); + } + #endif } void _sensorCallback(unsigned char i, unsigned char type, double value) { diff --git a/code/espurna/sensors/GUVAS12SDSensor.h b/code/espurna/sensors/GUVAS12SDSensor.h index f188b2b3..a4b65c54 100644 --- a/code/espurna/sensors/GUVAS12SDSensor.h +++ b/code/espurna/sensors/GUVAS12SDSensor.h @@ -104,7 +104,7 @@ class GUVAS12SDSensor : public BaseSensor { // Type for slot # index unsigned char type(unsigned char index) { - if (index == 0) return MAGNITUDE_UV; + if (index == 0) return MAGNITUDE_UVI; return MAGNITUDE_NONE; } diff --git a/code/espurna/sensors/HLW8012Sensor.h b/code/espurna/sensors/HLW8012Sensor.h index 14a5855f..bd5393f8 100644 --- a/code/espurna/sensors/HLW8012Sensor.h +++ b/code/espurna/sensors/HLW8012Sensor.h @@ -9,8 +9,6 @@ #include "Arduino.h" #include "BaseSensor.h" - -#include #include class HLW8012Sensor : public BaseSensor { @@ -148,14 +146,10 @@ class HLW8012Sensor : public BaseSensor { // Handle interrupts #if HLW8012_USE_INTERRUPTS - _enableInterrupts(true); - #else - _onconnect_handler = WiFi.onStationModeGotIP([this](WiFiEventStationModeGotIP ipInfo) { - _enableInterrupts(true); - }); - _ondisconnect_handler = WiFi.onStationModeDisconnected([this](WiFiEventStationModeDisconnected ipInfo) { + #if HLW8012_WAIT_FOR_WIFI == 0 _enableInterrupts(false); - }); + _enableInterrupts(true); + #endif #endif _ready = true; @@ -205,6 +199,15 @@ class HLW8012Sensor : public BaseSensor { return 0; } + // Pre-read hook (usually to populate registers with up-to-date data) + #if HLW8012_USE_INTERRUPTS + #if HLW8012_WAIT_FOR_WIFI + void pre() { + _enableInterrupts(wifiConnected()); + } + #endif + #endif + // Toggle between current and voltage monitoring #if HLW8012_USE_INTERRUPTS == 0 // Post-read hook (usually to reset things) @@ -247,10 +250,15 @@ class HLW8012Sensor : public BaseSensor { } else { - _detach(_cf); - _detach(_cf1); - _interrupt_cf = GPIO_NONE; - _interrupt_cf1 = GPIO_NONE; + if (GPIO_NONE != _interrupt_cf) { + _detach(_interrupt_cf); + _interrupt_cf = GPIO_NONE; + } + + if (GPIO_NONE != _interrupt_cf1) { + _detach(_interrupt_cf1); + _interrupt_cf1 = GPIO_NONE; + } } @@ -266,11 +274,6 @@ class HLW8012Sensor : public BaseSensor { HLW8012 * _hlw8012 = NULL; - #if HLW8012_USE_INTERRUPTS == 0 - WiFiEventHandler _onconnect_handler; - WiFiEventHandler _ondisconnect_handler; - #endif - }; // ----------------------------------------------------------------------------- diff --git a/code/espurna/sensors/PMSX003Sensor.h b/code/espurna/sensors/PMSX003Sensor.h index c117849d..54f8d0a5 100644 --- a/code/espurna/sensors/PMSX003Sensor.h +++ b/code/espurna/sensors/PMSX003Sensor.h @@ -90,7 +90,7 @@ class PMSX003 { int avail = _serial->available(); #if SENSOR_DEBUG - //debugSend("[SENSOR] PMS: Packet available = %d\n", avail); + //DEBUG_MSG("[SENSOR] PMS: Packet available = %d\n", avail); #endif if (avail < PMS_PACKET_SIZE(data_count)) { break; @@ -102,7 +102,7 @@ class PMSX003 { uint16_t size = read16(sum); if (size != PMS_PAYLOAD_SIZE(data_count)) { #if SENSOR_DEBUG - debugSend(("[SENSOR] PMS: Payload size: %d != %d.\n"), size, PMS_PAYLOAD_SIZE(data_count)); + DEBUG_MSG(("[SENSOR] PMS: Payload size: %d != %d.\n"), size, PMS_PAYLOAD_SIZE(data_count)); #endif break; } @@ -110,7 +110,7 @@ class PMSX003 { for (int i = 0; i < data_count; i++) { data[i] = read16(sum); #if SENSOR_DEBUG - //debugSend(("[SENSOR] PMS: data[%d] = %d\n"), i, data[i]); + //DEBUG_MSG(("[SENSOR] PMS: data[%d] = %d\n"), i, data[i]); #endif } @@ -119,7 +119,7 @@ class PMSX003 { return true; } else { #if SENSOR_DEBUG - debugSend(("[SENSOR] PMS checksum: %04X != %04X\n"), sum, checksum); + DEBUG_MSG(("[SENSOR] PMS checksum: %04X != %04X\n"), sum, checksum); #endif } break; @@ -282,7 +282,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 { readCycle = _readCount % 30; if (readCycle == 0) { #if SENSOR_DEBUG - debugSend("[SENSOR] %s: Wake up: %d\n", pms_specs[_type].name, _readCount); + DEBUG_MSG("[SENSOR] %s: Wake up: %d\n", pms_specs[_type].name, _readCount); #endif wakeUp(); return; @@ -321,7 +321,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 { if (readCycle == 6) { sleep(); #if SENSOR_DEBUG - debugSend("[SENSOR] %s: Enter sleep mode: %d\n", pms_specs[_type].name, _readCount); + DEBUG_MSG("[SENSOR] %s: Enter sleep mode: %d\n", pms_specs[_type].name, _readCount); #endif return; } diff --git a/code/espurna/sensors/PZEM004TSensor.h b/code/espurna/sensors/PZEM004TSensor.h index 5f643ae9..8f5fda3f 100644 --- a/code/espurna/sensors/PZEM004TSensor.h +++ b/code/espurna/sensors/PZEM004TSensor.h @@ -3,6 +3,48 @@ // Copyright (C) 2018 by Xose Pérez // ----------------------------------------------------------------------------- +// Connection Diagram: +// ------------------- +// +// Needed when connecting multiple PZEM004T devices on the same UART +// *You must set the PZEM004T device address prior using this configuration* +// +// +---------+ +// | ESPurna | +VCC +// | Node | ^ +// | G T R | | +// +-+--+--+-+ R (10K) +// | | | | +// | | +-----------------+---------------+---------------+ +// | +-----------------+--|------------+--|------------+ | +// +-----------------+--|--|---------+--|--|---------+ | | +// | | | | | | | | | +// | | V | | V | | V +// | | - | | - | | - +// +-+--+--+-+ +-+--+--+-+ +-+--+--+-+ +// | G R T | | G R T | | G R T | +// |PZEM-004T| |PZEM-004T| |PZEM-004T| +// | Module | | Module | | Module | +// +---------+ +---------+ +---------+ +// +// Where: +// ------ +// G = GND +// R = ESPurna UART RX +// T = ESPurna UART TX +// V = Small Signal Schottky Diode, like BAT43, +// Cathode to PZEM TX, Anode to Espurna RX +// R = Resistor to VCC, 10K +// +// More Info: +// ---------- +// See ESPurna Wiki - https://github.com/xoseperez/espurna/wiki/Sensor-PZEM004T +// +// Reference: +// ---------- +// UART/TTL-Serial network with single master and multiple slaves: +// http://cool-emerald.blogspot.com/2009/10/multidrop-network-for-rs232.html + #if SENSOR_SUPPORT && PZEM004T_SUPPORT #pragma once diff --git a/code/espurna/sensors/VEML6075Sensor.h b/code/espurna/sensors/VEML6075Sensor.h new file mode 100644 index 00000000..60753401 --- /dev/null +++ b/code/espurna/sensors/VEML6075Sensor.h @@ -0,0 +1,96 @@ +// ----------------------------------------------------------------------------- +// VEML6075 Sensor over I2C +// Copyright (C) 2017-2018 by Xose Pérez +// ----------------------------------------------------------------------------- + +#if SENSOR_SUPPORT && VEML6075_SUPPORT + +#pragma once + +#undef I2C_SUPPORT +#define I2C_SUPPORT 1 // Explicitly request I2C support. + + +#include "Arduino.h" +#include "I2CSensor.h" +#include "SparkFun_VEML6075_Arduino_Library.h" + +class VEML6075Sensor : public I2CSensor { + + public: + + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + VEML6075Sensor(): I2CSensor() { + _count = 3; + _sensor_id = SENSOR_VEML6075_ID; + _veml6075 = new VEML6075(); + } + + ~VEML6075Sensor() { + delete _veml6075; + } + + void begin() { + if (!_veml6075->begin()) { + return; + }; + + _ready = true; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Descriptive name of the sensor + String description() { + char buffer[25]; + snprintf(buffer, sizeof(buffer), "VEML6075 @ I2C (0x%02X)", _address); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Type for slot # index + unsigned char type(unsigned char index) { + if (index == 0) return MAGNITUDE_UVA; + if (index == 1) return MAGNITUDE_UVB; + if (index == 2) return MAGNITUDE_UVI; + return MAGNITUDE_NONE; + } + + // Pre-read hook (usually to populate registers with up-to-date data) + void pre() { + _error = SENSOR_ERROR_OK; + } + + // Current value for slot # index + double value(unsigned char index) { + if (index == 0) return _veml6075->a(); + if (index == 1) return _veml6075->b(); + if (index == 2) return _veml6075->index(); + + return 0; + } + + void setIntegrationTime(VEML6075::veml6075_uv_it_t integration_time) { + _veml6075->setIntegrationTime(integration_time); + } + + void setDynamicMode(VEML6075::veml6075_hd_t dynamic_mode) { + _veml6075->setHighDynamic(dynamic_mode); + } + + protected: + + VEML6075 * _veml6075 = NULL; + +}; + +#endif // SENSOR_SUPPORT && VEML6075_SUPPORT diff --git a/code/espurna/sensors/VL53L1XSensor.h b/code/espurna/sensors/VL53L1XSensor.h new file mode 100644 index 00000000..71bf6b7a --- /dev/null +++ b/code/espurna/sensors/VL53L1XSensor.h @@ -0,0 +1,119 @@ +// ----------------------------------------------------------------------------- +// VL53L1X Sensor over I2C +// Copyright (C) 2017-2018 by Xose Pérez +// ----------------------------------------------------------------------------- + +#if SENSOR_SUPPORT && VL53L1X_SUPPORT + +#pragma once + +#undef I2C_SUPPORT +#define I2C_SUPPORT 1 // Explicitly request I2C support. + + +#include "Arduino.h" +#include "I2CSensor.h" +#include "VL53L1X.h" + +class VL53L1XSensor : public I2CSensor { + + public: + + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + VL53L1XSensor(): I2CSensor() { + _count = 1; + _sensor_id = SENSOR_VL53L1X_ID; + _vl53l1x = new VL53L1X(); + } + + ~VL53L1XSensor() { + delete _vl53l1x; + } + + // --------------------------------------------------------------------- + + void setDistanceMode(VL53L1X::DistanceMode mode) { + _vl53l1x->setDistanceMode(mode); + } + + void setMeasurementTimingBudget(uint32_t budget_us) { + _vl53l1x->setMeasurementTimingBudget(budget_us); + } + + void setInterMeasurementPeriod(unsigned int period) { + if (_inter_measurement_period == period) return; + _inter_measurement_period = period; + _dirty = true; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + void begin() { + if (!_dirty) { + return; + } + + // I2C auto-discover + unsigned char addresses[] = {0x29}; + _address = _begin_i2c(_address, sizeof(addresses), addresses); + if (_address == 0) return; + + _vl53l1x->setAddress(_address); + + if (!_vl53l1x->init()) { + return; + }; + + _vl53l1x->startContinuous(_inter_measurement_period); + + _ready = true; + _dirty = false; + } + + // Descriptive name of the sensor + String description() { + char buffer[21]; + snprintf(buffer, sizeof(buffer), "VL53L1X @ I2C (0x%02X)", _address); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Type for slot # index + unsigned char type(unsigned char index) { + if (index == 0) return MAGNITUDE_DISTANCE; + return MAGNITUDE_NONE; + } + + // Pre-read hook (usually to populate registers with up-to-date data) + void pre() { + if (!_vl53l1x->dataReady()) { + return; + } + + _distance = (double) _vl53l1x->read(false) / 1000.00; + } + + // Current value for slot # index + double value(unsigned char index) { + if (index != 0) return 0; + return _distance; + } + + protected: + + VL53L1X * _vl53l1x = NULL; + unsigned int _inter_measurement_period; + double _distance = 0; + +}; + +#endif // SENSOR_SUPPORT && VL53L1X_SUPPORT diff --git a/code/html/custom.js b/code/html/custom.js index f10f4d2c..3a9d6644 100644 --- a/code/html/custom.js +++ b/code/html/custom.js @@ -47,7 +47,7 @@ function sensorName(id) { "Events", "PMSX003", "BMX280", "MHZ19", "SI7021", "SHT3X I2C", "BH1750", "PZEM004T", "AM2320 I2C", "GUVAS12SD", "TMP3X", "Sonar", "SenseAir", "GeigerTicks", "GeigerCPM", - "NTC", "SDS011", "MICS2710", "MICS5525" + "NTC", "SDS011", "MICS2710", "MICS5525", "VL53L1X", "VEML6075" ]; if (1 <= id && id <= names.length) { return names[id - 1]; @@ -61,7 +61,7 @@ function magnitudeType(type) { "Current", "Voltage", "Active Power", "Apparent Power", "Reactive Power", "Power Factor", "Energy", "Energy (delta)", "Analog", "Digital", "Event", - "PM1.0", "PM2.5", "PM10", "CO2", "Lux", "UV", "Distance" , "HCHO", + "PM1.0", "PM2.5", "PM10", "CO2", "Lux", "UVA", "UVB", "UV Index", "Distance" , "HCHO", "Local Dose Rate", "Local Dose Rate", "Count", "NO2", "CO", "Resistance" diff --git a/code/ota.py b/code/ota.py index a52ea7e0..a7454cce 100755 --- a/code/ota.py +++ b/code/ota.py @@ -55,9 +55,9 @@ def on_service_state_change(zeroconf, service_type, name, state_change): 'app_name': '', 'app_version': '', 'target_board': '', - 'mem_size': '', - 'sdk_size': '', - 'free_space': '', + 'mem_size': 0, + 'sdk_size': 0, + 'free_space': 0, } for key, item in info.properties.items(): @@ -101,9 +101,9 @@ def list_devices(): device.get('app_name', ''), device.get('app_version', ''), device.get('target_board', ''), - device.get('mem_size', ''), - device.get('sdk_size', ''), - device.get('free_space', ''), + device.get('mem_size', 0), + device.get('sdk_size', 0), + device.get('free_space', 0), )) print() diff --git a/code/platformio.ini b/code/platformio.ini index 1a67b3ff..430cdda7 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -97,8 +97,9 @@ lib_deps = https://github.com/LowPowerLab/RFM69#1.1.3 https://github.com/xoseperez/Time NewPing + https://github.com/sparkfun/SparkFun_VEML6075_Arduino_Library#V_1.0.3 + https://github.com/pololu/vl53l1x-arduino#1.0.1 https://github.com/mcleng/MAX6675-Library#2.0.1 - lib_ignore = # ------------------------------------------------------------------------------ @@ -2553,6 +2554,58 @@ upload_port = ${common.upload_port} upload_flags = ${common.upload_flags} extra_scripts = ${common.extra_scripts} +[env:blitzwolf-bwshp2-v23] +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} -DBLITZWOLF_BWSHP2_V23 +upload_speed = ${common.upload_speed} +monitor_speed = ${common.monitor_speed} +extra_scripts = ${common.extra_scripts} + +[env:blitzwolf-bwshp2-v23-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} -DBLITZWOLF_BWSHP2_V23 +upload_speed = ${common.upload_speed} +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_flags = ${common.upload_flags} +extra_scripts = ${common.extra_scripts} + +[env:teckin-sp22-v14] +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} -DTECKIN_SP22_V14 +upload_speed = ${common.upload_speed} +monitor_speed = ${common.monitor_speed} +extra_scripts = ${common.extra_scripts} + +[env:teckin-sp22-v14-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} -DTECKIN_SP22_V14 +upload_speed = ${common.upload_speed} +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_flags = ${common.upload_flags} +extra_scripts = ${common.extra_scripts} + [env:homecube-16a] platform = ${common.platform} framework = ${common.framework}