diff --git a/README.md b/README.md index 2a7936c8..4799f741 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,11 @@ ESPurna ("spark" in Catalan) is a custom firmware for ESP8266 based smart switch It was originally developed with the **[IteadStudio Sonoff](https://www.itead.cc/sonoff-wifi-wireless-switch.html)** in mind but now it supports a growing number of ESP8266-based boards. It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries. -**Current Release Version is 1.9.3**, read the [changelog](https://bitbucket.org/xoseperez/espurna/src/master/CHANGELOG.md). +> **Current Release Version is 1.9.3**, read the [changelog](https://bitbucket.org/xoseperez/espurna/src/master/CHANGELOG.md). -**NOTE**: since version 1.9.0 the default **MQTT topics for commands have changed**. They all now end with "/set". This means you will have to change your controller software (Node-RED or alike) to send messages to -for instance- "/home/living/light/relay/0/set". The device will publish its state in "/home/living/light/relay/0" like before. +> **NOTICE**: Default flash layout changed in 1.8.3, as an unpredicted consequence devices will not be able to persist/retrieve configuration if flashed with 1.8.3 via **OTA** from **PlatformIO**. Please check issue #187. + +> **NOTICE**: since version 1.9.0 the default **MQTT topics for commands have changed**. They all now end with "/set". This means you will have to change your controller software (Node-RED or alike) to send messages to -for instance- "/home/living/light/relay/0/set". The device will publish its state in "/home/living/light/relay/0" like before. ## Features diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index a910a753..de5d477e 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -390,9 +390,11 @@ PROGMEM const char* const custom_reset_string[] = { #define MQTT_RETAIN true // MQTT retain flag #define MQTT_QOS 0 // MQTT QoS value for all messages #define MQTT_KEEPALIVE 30 // MQTT keepalive value -#define MQTT_RECONNECT_DELAY 10000 // Try to reconnect after 10s -#define MQTT_TRY_INTERVAL 30000 // Timeframe for disconnect retries -#define MQTT_MAX_TRIES 5 // After these many retries during the previous MQTT_TRY_INTERVAL the board will reset + +#define MQTT_RECONNECT_DELAY_MIN 5000 // Try to reconnect in 5 seconds upon disconnection +#define MQTT_RECONNECT_DELAY_STEP 5000 // Increase the reconnect delay in 5 seconds after each failed attempt +#define MQTT_RECONNECT_DELAY_MAX 120000 // Set reconnect time to 2 minutes at most + #define MQTT_SKIP_RETAINED 1 // Skip retained messages on connection #define MQTT_SKIP_TIME 1000 // Skip messages for 1 second anter connection @@ -501,6 +503,7 @@ PROGMEM const char* const custom_reset_string[] = { #define POWER_PROVIDER_EMON_ANALOG 0x10 #define POWER_PROVIDER_EMON_ADC121 0x11 #define POWER_PROVIDER_HLW8012 0x20 +#define POWER_PROVIDER_V9261F 0x30 // Available magnitudes #define POWER_MAGNITUDE_CURRENT 1 @@ -514,7 +517,7 @@ PROGMEM const char* const custom_reset_string[] = { #endif // Identify available magnitudes -#if POWER_PROVIDER == POWER_PROVIDER_HLW8012 +#if (POWER_PROVIDER == POWER_PROVIDER_HLW8012) || (POWER_PROVIDER == POWER_PROVIDER_V9261F) #define POWER_HAS_ACTIVE 1 #else #define POWER_HAS_ACTIVE 0 @@ -526,6 +529,7 @@ PROGMEM const char* const custom_reset_string[] = { #define POWER_SAMPLES 1000 #define POWER_INTERVAL 10000 #define POWER_REPORT_EVERY 6 +#define POWER_REPORT_INTERVAL 60000 #define POWER_ENERGY_FACTOR (POWER_INTERVAL * POWER_REPORT_EVERY / 1000.0 / 3600.0) #if POWER_PROVIDER == POWER_PROVIDER_EMON_ANALOG @@ -553,6 +557,15 @@ PROGMEM const char* const custom_reset_string[] = { #define HLW8012_VOLTAGE_R_DOWN ( 1000 ) // Real 1.009k #endif +#if POWER_PROVIDER == POWER_PROVIDER_V9261F + #define V9261F_SYNC_INTERVAL 600 + #define V9261F_BAUDRATE 4800 + #define V9261F_CURRENT_FACTOR 81156358 + #define V9261F_VOLTAGE_FACTOR 4178508 + #define V9261F_POWER_FACTOR 157859 + #define V9261F_RPOWER_FACTOR V9261F_CURRENT_FACTOR +#endif + // ----------------------------------------------------------------------------- // I2C // ----------------------------------------------------------------------------- diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index f01392cb..ecd9fab3 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -77,9 +77,20 @@ // Buttons #define BUTTON1_PIN 4 - #define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH #define BUTTON1_RELAY 1 + // Normal pushbutton + //#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH + + // Touch button + #define BUTTON1_MODE BUTTON_PUSHBUTTON + #define BUTTON1_PRESS BUTTON_MODE_TOGGLE + #define BUTTON1_CLICK BUTTON_MODE_NONE + #define BUTTON1_DBLCLICK BUTTON_MODE_NONE + #define BUTTON1_LNGCLICK BUTTON_MODE_NONE + #define BUTTON1_LNGLNGCLICK BUTTON_MODE_NONE + + // Relays #define RELAY1_PIN 12 #define RELAY1_TYPE RELAY_TYPE_INVERSE @@ -839,6 +850,21 @@ #define LIGHT_CH3_INVERSE 0 #define LIGHT_CH4_INVERSE 0 +// ----------------------------------------------------------------------------- +// V9261F +// ----------------------------------------------------------------------------- + +#elif defined(GENERIC_V9261F) + + // Info + #define MANUFACTURER "GENERIC" + #define DEVICE "V9261F" + + // V9261F + #define V9261F_SUPPORT 1 + #define V9261F_PIN 2 + #define V9261F_PIN_INVERSE 1 + // ----------------------------------------------------------------------------- // Unknown hardware // ----------------------------------------------------------------------------- diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index f1012566..25bc8fe9 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -220,7 +220,6 @@ void setup() { setSetting("hostname", getIdentifier()); } - delay(500); wifiSetup(); otaSetup(); #if TELNET_SUPPORT diff --git a/code/espurna/hardware.ino b/code/espurna/hardware.ino index e38ae2df..d870f514 100644 --- a/code/espurna/hardware.ino +++ b/code/espurna/hardware.ino @@ -434,6 +434,10 @@ void hwUpwardsCompatibility() { setSetting("chLogic", 4, 0); setSetting("relays", 1); + #elif defined(GENERIC_V9261F) + + setSetting("board", 37); + #else #error "UNSUPPORTED HARDWARE!" diff --git a/code/espurna/mqtt.ino b/code/espurna/mqtt.ino index 76776762..77aa237f 100644 --- a/code/espurna/mqtt.ino +++ b/code/espurna/mqtt.ino @@ -31,7 +31,7 @@ WiFiClientSecure _mqtt_client_secure; #endif // MQTT_USE_ASYNC bool _mqtt_enabled = MQTT_ENABLED; -unsigned char _mqtt_connection_tries = 0; +unsigned long _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MIN; String _mqtt_topic; String _mqtt_setter; String _mqtt_getter; @@ -216,6 +216,7 @@ void _mqttCallback(unsigned int type, const char * topic, const char * payload) void _mqttOnConnect() { DEBUG_MSG_P(PSTR("[MQTT] Connected!\n")); + _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MIN; #if MQTT_SKIP_RETAINED _mqtt_connected_at = millis(); @@ -316,137 +317,134 @@ bool mqttEnabled() { void mqttConnect() { - if (_mqtt_enabled & !_mqtt.connected()) { - - // Disable MQTT after MQTT_MAX_TRIES attemps in a row - #if MQTT_MAX_TRIES > 0 - static unsigned long last_try = millis(); - if (millis() - last_try < MQTT_TRY_INTERVAL) { - if (++_mqtt_connection_tries > MQTT_MAX_TRIES) { - DEBUG_MSG_P(PSTR("[MQTT] MQTT_MAX_TRIES met, disabling MQTT\n")); - mqttEnabled(false); - _mqtt_connection_tries = 0; - return; - } - } else { - _mqtt_connection_tries = 0; - } - last_try = millis(); - #endif + // Do not connect if disabled + if (!_mqtt_enabled) return; - if (_mqtt_user) free(_mqtt_user); - if (_mqtt_pass) free(_mqtt_pass); + // Do not connect if already connected + if (_mqtt.connected()) return; - char * host = strdup(getSetting("mqttServer", MQTT_SERVER).c_str()); - if (strlen(host) == 0) return; - unsigned int port = getSetting("mqttPort", MQTT_PORT).toInt(); - _mqtt_user = strdup(getSetting("mqttUser", MQTT_USER).c_str()); - _mqtt_pass = strdup(getSetting("mqttPassword", MQTT_PASS).c_str()); - if (_mqtt_will) free(_mqtt_will); - _mqtt_will = strdup((_mqtt_topic + MQTT_TOPIC_STATUS).c_str()); + // Check reconnect interval + static unsigned long last = 0; + if (millis() - last < _mqtt_reconnect_delay) return; + last = millis(); - DEBUG_MSG_P(PSTR("[MQTT] Connecting to broker at %s:%d\n"), host, port); + // Increase the reconnect delay + _mqtt_reconnect_delay += MQTT_RECONNECT_DELAY_STEP; + if (_mqtt_reconnect_delay > MQTT_RECONNECT_DELAY_MAX) { + _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MAX; + } - #if MQTT_USE_ASYNC + char * host = strdup(getSetting("mqttServer", MQTT_SERVER).c_str()); + if (strlen(host) == 0) return; + unsigned int port = getSetting("mqttPort", MQTT_PORT).toInt(); - _mqtt.setServer(host, port); - _mqtt.setKeepAlive(MQTT_KEEPALIVE).setCleanSession(false); - _mqtt.setWill(_mqtt_will, MQTT_QOS, MQTT_RETAIN, "0"); - if ((strlen(_mqtt_user) > 0) && (strlen(_mqtt_pass) > 0)) { - DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user); - _mqtt.setCredentials(_mqtt_user, _mqtt_pass); - } + if (_mqtt_user) free(_mqtt_user); + if (_mqtt_pass) free(_mqtt_pass); + if (_mqtt_will) free(_mqtt_will); - #if ASYNC_TCP_SSL_ENABLED + _mqtt_user = strdup(getSetting("mqttUser", MQTT_USER).c_str()); + _mqtt_pass = strdup(getSetting("mqttPassword", MQTT_PASS).c_str()); + _mqtt_will = strdup((_mqtt_topic + MQTT_TOPIC_STATUS).c_str()); - bool secure = getSetting("mqttUseSSL", MQTT_SSL_ENABLED).toInt() == 1; - _mqtt.setSecure(secure); - if (secure) { - DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n")); - unsigned char fp[20] = {0}; - if (mqttFormatFP(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) { - _mqtt.addServerFingerprint(fp); - } else { - DEBUG_MSG_P(PSTR("[MQTT] Wrong fingerprint\n")); - } + DEBUG_MSG_P(PSTR("[MQTT] Connecting to broker at %s:%d\n"), host, port); + + #if MQTT_USE_ASYNC + + _mqtt.setServer(host, port); + _mqtt.setKeepAlive(MQTT_KEEPALIVE).setCleanSession(false); + _mqtt.setWill(_mqtt_will, MQTT_QOS, MQTT_RETAIN, "0"); + if ((strlen(_mqtt_user) > 0) && (strlen(_mqtt_pass) > 0)) { + DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user); + _mqtt.setCredentials(_mqtt_user, _mqtt_pass); + } + + #if ASYNC_TCP_SSL_ENABLED + + bool secure = getSetting("mqttUseSSL", MQTT_SSL_ENABLED).toInt() == 1; + _mqtt.setSecure(secure); + if (secure) { + DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n")); + unsigned char fp[20] = {0}; + if (mqttFormatFP(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) { + _mqtt.addServerFingerprint(fp); + } else { + DEBUG_MSG_P(PSTR("[MQTT] Wrong fingerprint\n")); } + } - #endif // ASYNC_TCP_SSL_ENABLED + #endif // ASYNC_TCP_SSL_ENABLED - DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will); - DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), MQTT_QOS); - DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), MQTT_RETAIN); + DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will); + DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), MQTT_QOS); + DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), MQTT_RETAIN); - _mqtt.connect(); + _mqtt.connect(); - #else // not MQTT_USE_ASYNC + #else // not MQTT_USE_ASYNC - bool response = true; + bool response = true; - #if ASYNC_TCP_SSL_ENABLED + #if ASYNC_TCP_SSL_ENABLED - bool secure = getSetting("mqttUseSSL", MQTT_SSL_ENABLED).toInt() == 1; - if (secure) { - DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n")); - if (_mqtt_client_secure.connect(host, port)) { - char fp[60] = {0}; - if (mqttFormatFP(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) { - if (_mqtt_client_secure.verify(fp, host)) { - _mqtt.setClient(_mqtt_client_secure); - } else { - DEBUG_MSG_P(PSTR("[MQTT] Invalid fingerprint\n")); - response = false; - } - _mqtt_client_secure.stop(); - yield(); + bool secure = getSetting("mqttUseSSL", MQTT_SSL_ENABLED).toInt() == 1; + if (secure) { + DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n")); + if (_mqtt_client_secure.connect(host, port)) { + char fp[60] = {0}; + if (mqttFormatFP(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) { + if (_mqtt_client_secure.verify(fp, host)) { + _mqtt.setClient(_mqtt_client_secure); } else { - DEBUG_MSG_P(PSTR("[MQTT] Wrong fingerprint\n")); + DEBUG_MSG_P(PSTR("[MQTT] Invalid fingerprint\n")); response = false; } + _mqtt_client_secure.stop(); + yield(); } else { - DEBUG_MSG_P(PSTR("[MQTT] Client connection failed\n")); + DEBUG_MSG_P(PSTR("[MQTT] Wrong fingerprint\n")); response = false; } - } else { - _mqtt.setClient(_mqtt_client); + DEBUG_MSG_P(PSTR("[MQTT] Client connection failed\n")); + response = false; } - #else // not ASYNC_TCP_SSL_ENABLED - + } else { _mqtt.setClient(_mqtt_client); + } - #endif // ASYNC_TCP_SSL_ENABLED - - if (response) { + #else // not ASYNC_TCP_SSL_ENABLED - _mqtt.setServer(host, port); + _mqtt.setClient(_mqtt_client); - if ((strlen(_mqtt_user) > 0) && (strlen(_mqtt_pass) > 0)) { - DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user); - response = _mqtt.connect(getIdentifier().c_str(), _mqtt_user, _mqtt_pass, _mqtt_will, MQTT_QOS, MQTT_RETAIN, "0"); - } else { - response = _mqtt.connect(getIdentifier().c_str(), _mqtt_will, MQTT_QOS, MQTT_RETAIN, "0"); - } + #endif // ASYNC_TCP_SSL_ENABLED - DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will); - DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), MQTT_QOS); - DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), MQTT_RETAIN); + if (response) { - } + _mqtt.setServer(host, port); - if (response) { - _mqttOnConnect(); - _mqtt_connected = true; + if ((strlen(_mqtt_user) > 0) && (strlen(_mqtt_pass) > 0)) { + DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user); + response = _mqtt.connect(getIdentifier().c_str(), _mqtt_user, _mqtt_pass, _mqtt_will, MQTT_QOS, MQTT_RETAIN, "0"); } else { - DEBUG_MSG_P(PSTR("[MQTT] Connection failed\n")); + response = _mqtt.connect(getIdentifier().c_str(), _mqtt_will, MQTT_QOS, MQTT_RETAIN, "0"); } - #endif // MQTT_USE_ASYNC + DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will); + DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), MQTT_QOS); + DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), MQTT_RETAIN); + + } + + if (response) { + _mqttOnConnect(); + } else { + DEBUG_MSG_P(PSTR("[MQTT] Connection failed\n")); + } - free(host); + #endif // MQTT_USE_ASYNC - } + free(host); } @@ -463,7 +461,6 @@ void mqttConfigure() { _mqtt_forward = !_mqtt_getter.equals(_mqtt_setter); // Enable - _mqtt_connection_tries = 0; if (getSetting("mqttServer", MQTT_SERVER).length() == 0) { mqttEnabled(false); } else { @@ -553,22 +550,14 @@ void mqttSetup() { void mqttLoop() { - #if MQTT_USE_ASYNC + if (WiFi.status() != WL_CONNECTED) return; - if (!_mqtt_enabled) return; - if (WiFi.status() != WL_CONNECTED) return; - if (_mqtt.connected()) return; + #if MQTT_USE_ASYNC - static unsigned long last = 0; - if (millis() - last > MQTT_RECONNECT_DELAY) { - last = millis(); - mqttConnect(); - } + mqttConnect(); #else // not MQTT_USE_ASYNC - if (WiFi.status() != WL_CONNECTED) return; - if (_mqtt.connected()) { _mqtt.loop(); @@ -580,13 +569,7 @@ void mqttLoop() { _mqtt_connected = false; } - if (_mqtt_enabled) { - static unsigned long last = 0; - if (millis() - last > MQTT_RECONNECT_DELAY) { - last = millis(); - mqttConnect(); - } - } + mqttConnect(); } diff --git a/code/espurna/ota.ino b/code/espurna/ota.ino index 6f649ad3..280c3b2f 100644 --- a/code/espurna/ota.ino +++ b/code/espurna/ota.ino @@ -56,9 +56,9 @@ void otaSetup() { ArduinoOTA.begin(); // Public ESPurna related txt for OTA discovery - MDNS.addServiceTxt("arduino", "tcp", "firmware", APP_NAME); - MDNS.addServiceTxt("arduino", "tcp", "espurna_version", APP_VERSION); - MDNS.addServiceTxt("arduino", "tcp", "espurna_board", DEVICE_NAME); + MDNS.addServiceTxt("arduino", "tcp", "app_name", APP_NAME); + MDNS.addServiceTxt("arduino", "tcp", "app_version", APP_VERSION); + MDNS.addServiceTxt("arduino", "tcp", "target_board", DEVICE_NAME); } diff --git a/code/espurna/v9261f.ino b/code/espurna/v9261f.ino new file mode 100644 index 00000000..3a2aea7f --- /dev/null +++ b/code/espurna/v9261f.ino @@ -0,0 +1,319 @@ +/* + +V9261F MODULE +Support for V9261D-based power monitors + +Copyright (C) 2016-2017 by Xose PĂ©rez + +*/ + +/* + +#if V9261F_SUPPORT + +#include +#include + +SoftwareSerial * _v9261f_uart; + +bool _v9261f_enabled = false; +bool _v9261f_ready = false; +bool _v9261f_newdata = false; +int _v9261f_power = 0; +int _v9261f_rpower = 0; +int _v9261f_voltage = 0; +double _v9261f_current = 0; + +unsigned char _v9261f_data[24]; + +// ----------------------------------------------------------------------------- +// PRIVATE +// ----------------------------------------------------------------------------- + +void v9261fRead() { + + static unsigned char state = 0; + static unsigned long last = 0; + static bool found = false; + static unsigned char index = 0; + + if (state == 0) { + + while (_v9261f_uart->available()) { + _v9261f_uart->flush(); + found = true; + last = millis(); + } + + if (found && (millis() - last > V9261F_SYNC_INTERVAL)) { + _v9261f_uart->flush(); + index = 0; + state = 1; + } + + } else if (state == 1) { + + while (_v9261f_uart->available()) { + _v9261f_uart->read(); + if (index++ >= 7) { + _v9261f_uart->flush(); + index = 0; + state = 2; + } + } + + } else if (state == 2) { + + while (_v9261f_uart->available()) { + _v9261f_data[index] = _v9261f_uart->read(); + if (index++ >= 19) { + _v9261f_uart->flush(); + last = millis(); + state = 3; + } + } + + } else if (state == 3) { + + /* + for (unsigned char i=0; iavailable()) { + _v9261f_uart->flush(); + last = millis(); + } + + if (millis() - last > V9261F_SYNC_INTERVAL) { + state = 1; + } + + } + +} + +boolean checksumOK() { + unsigned char checksum = 0; + for (unsigned char i = 0; i < 19; i++) { + checksum = checksum + _v9261f_data[i]; + } + checksum = ~checksum + 0x33; + return checksum == _v9261f_data[19]; +} + +// ----------------------------------------------------------------------------- +// HAL +// ----------------------------------------------------------------------------- + +unsigned int getActivePower() { + return _v9261f_power; +} + +unsigned int getReactivePower() { + return _v9261f_rpower; +} + +unsigned int getApparentPower() { + return sqrt(_v9261f_rpower * _v9261f_rpower + _v9261f_power * _v9261f_power); +} + +unsigned int getVoltage() { + return _v9261f_voltage; +} + +double getCurrent() { + return _v9261f_current; +} + +double getPowerFactor() { + unsigned int apparent = getApparentPower(); + if (apparent > 0) return getActivePower() / getApparentPower(); + return 1; +} + +// ----------------------------------------------------------------------------- + +void v9261fSetup() { + + _v9261f_uart = new SoftwareSerial(V9261F_PIN, SW_SERIAL_UNUSED_PIN, V9261F_PIN_INVERSE, 256); + _v9261f_uart->begin(V9261F_BAUDRATE); + + // API definitions + #if WEB_SUPPORT + + apiRegister(HLW8012_POWER_TOPIC, HLW8012_POWER_TOPIC, [](char * buffer, size_t len) { + snprintf_P(buffer, len, PSTR("%d"), _v9261f_power); + }); + apiRegister(HLW8012_CURRENT_TOPIC, HLW8012_CURRENT_TOPIC, [](char * buffer, size_t len) { + dtostrf(_v9261f_current, len-1, 3, buffer); + }); + apiRegister(HLW8012_VOLTAGE_TOPIC, HLW8012_VOLTAGE_TOPIC, [](char * buffer, size_t len) { + snprintf_P(buffer, len, PSTR("%d"), _v9261f_voltage); + }); + + #endif // WEB_SUPPORT + +} + + +void v9261fLoop() { + + static int sum_power = 0; + static int sum_rpower = 0; + static int sum_voltage = 0; + static double sum_current = 0; + static int count = 0; + + // Sniff data in the UART interface + v9261fRead(); + + // Do we have new data? + if (_v9261f_newdata) { + + _v9261f_newdata = false; + + sum_power += getActivePower(); + sum_rpower += getReactivePower(); + sum_voltage += getVoltage(); + sum_current += getCurrent(); + count++; + + #if WEB_SUPPORT + { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + + char buf_current[10]; + dtostrf(getCurrent(), 6, 3, buf_current); + + root["powVisible"] = 1; + root["powActivePower"] = getActivePower(); + root["powCurrent"] = String(ltrim(buf_current)); + root["powVoltage"] = getVoltage(); + root["powApparentPower"] = getApparentPower(); + root["powReactivePower"] = getReactivePower(); + root["powPowerFactor"] = 100 * getPowerFactor(); + + String output; + root.printTo(output); + wsSend(output.c_str()); + } + #endif + + } + + // Do we have to report? + static unsigned long last = 0; + if ((count == 0) || (millis() - last < V9261F_REPORT_INTERVAL)) return; + last = millis(); + + { + + unsigned int power = sum_power / count; + unsigned int reactive = sum_rpower / count; + unsigned int voltage = sum_voltage / count; + double current = sum_current / count; + char buf_current[10]; + dtostrf(current, 6, 3, buf_current); + unsigned int apparent = sqrt(power * power + reactive * reactive); + double energy_delta = (double) power * V9261F_REPORT_INTERVAL / 1000.0 / 3600.0; + char buf_energy[10]; + dtostrf(energy_delta, 6, 3, buf_energy); + unsigned int factor = 100 * ((double) power / apparent); + + // Report values to MQTT broker + mqttSend(HLW8012_POWER_TOPIC, String(power).c_str()); + mqttSend(HLW8012_CURRENT_TOPIC, buf_current); + mqttSend(HLW8012_VOLTAGE_TOPIC, String(voltage).c_str()); + mqttSend(HLW8012_ENERGY_TOPIC, buf_energy); + mqttSend(HLW8012_APOWER_TOPIC, String(apparent).c_str()); + mqttSend(HLW8012_RPOWER_TOPIC, String(reactive).c_str()); + mqttSend(HLW8012_PFACTOR_TOPIC, String(factor).c_str()); + + // Report values to Domoticz + #if DOMOTICZ_SUPPORT + { + char buffer[20]; + snprintf_P(buffer, sizeof(buffer), PSTR("%d;%s"), power, buf_energy); + domoticzSend("dczPowIdx", 0, buffer); + snprintf_P(buffer, sizeof(buffer), PSTR("%s"), buf_energy); + domoticzSend("dczEnergyIdx", 0, buffer); + snprintf_P(buffer, sizeof(buffer), PSTR("%d"), voltage); + domoticzSend("dczVoltIdx", 0, buffer); + snprintf_P(buffer, sizeof(buffer), PSTR("%s"), buf_current); + domoticzSend("dczCurrentIdx", 0, buffer); + } + #endif + + #if INFLUXDB_SUPPORT + { + influxDBSend(HLW8012_POWER_TOPIC, String(power).c_str()); + influxDBSend(HLW8012_CURRENT_TOPIC, buf_current); + influxDBSend(HLW8012_VOLTAGE_TOPIC, String(voltage).c_str()); + influxDBSend(HLW8012_ENERGY_TOPIC, buf_energy); + influxDBSend(HLW8012_APOWER_TOPIC, String(apparent).c_str()); + influxDBSend(HLW8012_RPOWER_TOPIC, String(reactive).c_str()); + influxDBSend(HLW8012_PFACTOR_TOPIC, String(factor).c_str()); + } + #endif + + // Reset counters + sum_power = sum_rpower = sum_voltage = sum_current = count = 0; + + } + +} + +#endif + +*/ diff --git a/code/ota_flash.sh b/code/ota_flash.sh index f8c12c4a..fe6c3ba3 100755 --- a/code/ota_flash.sh +++ b/code/ota_flash.sh @@ -24,11 +24,12 @@ useAvahi() { echo_pad "#" 4 echo_pad "HOSTNAME" 20 echo_pad "IP" 20 + echo_pad "APP" 15 + echo_pad "VERSION" 15 echo_pad "DEVICE" 30 - echo_pad "VERSION" 10 echo - printf -v line '%*s\n' 84 + printf -v line '%*s\n' 104 echo ${line// /-} counter=0 @@ -40,7 +41,7 @@ useAvahi() { echo -n "" > $board_file echo -n "$counter" > $count_file - avahi-browse -t -r -p "_arduino._tcp" 2>/dev/null | grep ^= | while read line; do + avahi-browse -t -r -p "_arduino._tcp" 2>/dev/null | grep ^= | sort -t ';' -k 3 | while read line; do (( counter++ )) echo "$counter" > $count_file @@ -48,8 +49,9 @@ useAvahi() { hostname=`echo $line | cut -d ';' -f4` ip=`echo $line | cut -d ';' -f8` txt=`echo $line | cut -d ';' -f10` - board=`echo $txt | sed -n "s/.*espurna_board=\([^\"]*\).*/\1/p"` - version=`echo $txt | sed -n "s/.*espurna_version=\([^\"]*\).*/\1/p"` + app_name=`echo $txt | sed -n "s/.*app_name=\([^\"]*\).*/\1/p"` + app_version=`echo $txt | sed -n "s/.*app_version=\([^\"]*\).*/\1/p"` + board=`echo $txt | sed -n "s/.*target_board=\([^\"]*\).*/\1/p"` echo -n "$ip;" >> $ip_file echo -n "$board;" >> $board_file @@ -57,8 +59,9 @@ useAvahi() { echo_pad "$counter" 4 echo_pad "$hostname" 20 echo_pad "$ip" 20 + echo_pad "$app_name" 15 + echo_pad "$app_version" 15 echo_pad "$board" 30 - echo_pad "$version" 10 echo diff --git a/code/ota_list.sh b/code/ota_list.sh index dbbf2b49..1276745c 100755 --- a/code/ota_list.sh +++ b/code/ota_list.sh @@ -16,30 +16,33 @@ useAvahi() { echo_pad "#" 4 echo_pad "HOSTNAME" 20 echo_pad "IP" 20 + echo_pad "APP" 15 + echo_pad "VERSION" 15 echo_pad "DEVICE" 30 - echo_pad "VERSION" 10 echo - printf -v line '%*s\n' 84 + printf -v line '%*s\n' 104 echo ${line// /-} counter=0 - avahi-browse -t -r -p "_arduino._tcp" 2>/dev/null | grep ^= | while read line; do + avahi-browse -t -r -p "_arduino._tcp" 2>/dev/null | grep ^= | sort -t ';' -k 3 | while read line; do (( counter++ )) hostname=`echo $line | cut -d ';' -f4` ip=`echo $line | cut -d ';' -f8` txt=`echo $line | cut -d ';' -f10` - board=`echo $txt | sed -n "s/.*espurna_board=\([^\"]*\).*/\1/p"` - version=`echo $txt | sed -n "s/.*espurna_version=\([^\"]*\).*/\1/p"` + app_name=`echo $txt | sed -n "s/.*app_name=\([^\"]*\).*/\1/p"` + app_version=`echo $txt | sed -n "s/.*app_version=\([^\"]*\).*/\1/p"` + board=`echo $txt | sed -n "s/.*target_board=\([^\"]*\).*/\1/p"` echo_pad "$counter" 4 echo_pad "$hostname" 20 echo_pad "$ip" 20 + echo_pad "$app_name" 15 + echo_pad "$app_version" 15 echo_pad "$board" 30 - echo_pad "$version" 10 echo done diff --git a/code/platformio.ini b/code/platformio.ini index 15cf222a..d0ace3de 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -22,6 +22,7 @@ lib_deps = OneWire DallasTemperature Brzo I2C + EspSoftwareSerial https://bitbucket.org/xoseperez/justwifi.git#1.1.4 https://bitbucket.org/xoseperez/hlw8012.git#1.0.1 https://bitbucket.org/xoseperez/fauxmoesp.git#2.2.0 @@ -683,6 +684,7 @@ monitor_baud = 115200 platform = espressif8266 framework = arduino board = esp01_1m +board_flash_mode = dout lib_deps = ${common.lib_deps} lib_ignore = ${common.lib_ignore} build_flags = ${common.build_flags_1m} -DMAGICHOME_LED_CONTROLLER @@ -692,6 +694,7 @@ monitor_baud = 115200 platform = espressif8266 framework = arduino board = esp01_1m +board_flash_mode = dout lib_deps = ${common.lib_deps} lib_ignore = ${common.lib_ignore} build_flags = ${common.build_flags_1m} -DMAGICHOME_LED_CONTROLLER @@ -815,6 +818,51 @@ upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 monitor_baud = 115200 +[env:wemos-v9261f] +platform = espressif8266 +framework = arduino +board = d1_mini +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags} -DGENERIC_V9261F +upload_speed = 460800 +monitor_baud = 115200 + +[env:wemos-v9261f-ota] +platform = espressif8266 +framework = arduino +board = d1_mini +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags} -DGENERIC_V9261F +upload_speed = 115200 +upload_port = "192.168.4.1" +upload_flags = --auth=fibonacci --port 8266 +monitor_baud = 115200 + +[env:esp01-v9261f] +platform = espressif8266 +framework = arduino +board = esp01_1m +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m} -DGENERIC_V9261F +monitor_baud = 115200 + +[env:esp01-v9261f-ota] +platform = espressif8266 +framework = arduino +board = esp01_1m +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m} -DGENERIC_V9261F +upload_speed = 115200 +upload_port = "192.168.4.1" +upload_flags = --auth=fibonacci --port 8266 +monitor_baud = 115200 + # ------------------------------------------------------------------------------ # GENERIC OTA ENVIRONMENTS # ------------------------------------------------------------------------------