diff --git a/code/platformio.ini b/code/platformio.ini index edc8d1d4..27a8e3b0 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -210,3 +210,24 @@ build_flags = -g -DDEBUG_PORT=Serial -DDEBUG_PORT=Serial -DESP_RELAY_BOARD -DENA upload_speed = 115200 upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 + +[env:ecoplug-debug] +platform = espressif8266 +framework = arduino +board = esp01_1m +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -Wl,-Tesp8266.flash.1m128.ld -DDEBUG_PORT=Serial -DECOPLUG + +[env:ecoplug-debug-ota] +platform = espressif8266 +framework = arduino +board = esp01_1m +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -Wl,-Tesp8266.flash.1m128.ld -DDEBUG_PORT=Serial -DECOPLUG +upload_speed = 115200 +upload_port = "192.168.4.1" +upload_flags = --auth=fibonacci --port 8266 diff --git a/code/src/config/general.h b/code/src/config/general.h index 5e2e4c77..2124af7c 100644 --- a/code/src/config/general.h +++ b/code/src/config/general.h @@ -67,7 +67,7 @@ #define MQTT_QOS 0 #define MQTT_KEEPALIVE 30 #define MQTT_RECONNECT_DELAY 10000 -#define MQTT_RELAY_TOPIC "/relay/%d" +#define MQTT_RELAY_TOPIC "/relay" #define MQTT_IP_TOPIC "/ip" #define MQTT_VERSION_TOPIC "/version" #define MQTT_FSVERSION_TOPIC "/fsversion" @@ -77,6 +77,12 @@ #define MQTT_DISCONNECT_EVENT 1 #define MQTT_MESSAGE_EVENT 2 +// Custom get and set postfixes +// Use something like "/status" or "/set", with trailing slash +#define MQTT_USE_GETTER "" +#define MQTT_USE_SETTER "" + + // ----------------------------------------------------------------------------- // NTP // ----------------------------------------------------------------------------- diff --git a/code/src/emon.ino b/code/src/emon.ino index c01ab157..7a85ba0a 100644 --- a/code/src/emon.ino +++ b/code/src/emon.ino @@ -39,10 +39,10 @@ void powerMonitorSetup() { // backwards compatibility String tmp; - tmp = getSetting("pwMainsVoltage", String() + EMON_MAINS_VOLTAGE); + tmp = getSetting("pwMainsVoltage", EMON_MAINS_VOLTAGE); setSetting("emonMains", tmp); delSetting("pwMainsVoltage"); - tmp = getSetting("pwCurrentRatio", String() + EMON_CURRENT_RATIO); + tmp = getSetting("pwCurrentRatio", EMON_CURRENT_RATIO); setSetting("emonRatio", tmp); delSetting("pwCurrentRatio"); @@ -50,7 +50,7 @@ void powerMonitorSetup() { currentCallback, EMON_ADC_BITS, EMON_REFERENCE_VOLTAGE, - getSetting("emonRatio", String(EMON_CURRENT_RATIO)).toFloat() + getSetting("emonRatio", EMON_CURRENT_RATIO).toFloat() ); emon.setPrecision(EMON_CURRENT_PRECISION); } @@ -91,7 +91,7 @@ void powerMonitorLoop() { sum += current; ++measurements; - float mainsVoltage = getSetting("emonMains", String(EMON_MAINS_VOLTAGE)).toFloat(); + float mainsVoltage = getSetting("emonMains", EMON_MAINS_VOLTAGE).toFloat(); //DEBUG_MSG("[ENERGY] Power now: %dW\n", int(current * mainsVoltage)); diff --git a/code/src/fauxmo.ino b/code/src/fauxmo.ino index 3d89669a..1d131892 100644 --- a/code/src/fauxmo.ino +++ b/code/src/fauxmo.ino @@ -18,7 +18,7 @@ fauxmoESP fauxmo; // ----------------------------------------------------------------------------- void fauxmoConfigure() { - fauxmo.enable(getSetting("fauxmoEnabled", String(FAUXMO_ENABLED)).toInt() == 1); + fauxmo.enable(getSetting("fauxmoEnabled", FAUXMO_ENABLED).toInt() == 1); } void fauxmoSetup() { diff --git a/code/src/main.ino b/code/src/main.ino index 2f1d0365..8019104d 100644 --- a/code/src/main.ino +++ b/code/src/main.ino @@ -29,9 +29,9 @@ along with this program. If not, see . #include #include #include "FS.h" -String getSetting(const String& key, String defaultValue = ""); -bool relayStatus(unsigned char id, bool status, bool report = true); void mqttRegister(void (*callback)(unsigned int, const char *, const char *)); +template bool setSetting(const String& key, T value); +template String getSetting(const String& key, T defaultValue); // ----------------------------------------------------------------------------- // METHODS @@ -112,7 +112,7 @@ void setup() { settingsSetup(); if (getSetting("hostname").length() == 0) { - setSetting("hostname", String() + getIdentifier()); + setSetting("hostname", getIdentifier()); saveSettings(); } diff --git a/code/src/mqtt.ino b/code/src/mqtt.ino index f1507512..d69b5d82 100644 --- a/code/src/mqtt.ino +++ b/code/src/mqtt.ino @@ -57,6 +57,7 @@ void _mqttOnConnect(bool sessionPresent) { // Build MQTT topics buildTopics(); + mqtt.setWill((mqttTopic + MQTT_HEARTBEAT_TOPIC).c_str(), MQTT_QOS, MQTT_RETAIN, (char *) "0"); // Say hello and report our IP and VERSION mqttSend((char *) MQTT_IP_TOPIC, (char *) getIP().c_str()); @@ -100,7 +101,7 @@ void mqttConnect() { if (!mqtt.connected()) { String host = getSetting("mqttServer", MQTT_SERVER); - String port = getSetting("mqttPort", String(MQTT_PORT)); + String port = getSetting("mqttPort", MQTT_PORT); String user = getSetting("mqttUser"); String pass = getSetting("mqttPassword"); @@ -112,12 +113,15 @@ void mqttConnect() { mqtt .setKeepAlive(MQTT_KEEPALIVE) .setCleanSession(false) - //.setWill("topic/online", 2, true, "no") .setClientId(getSetting("hostname", HOSTNAME).c_str()); - if ((user != "") & (pass != "")) { - DEBUG_MSG(" as user %s.\n", (char *) user.c_str()); - mqtt.setCredentials(user.c_str(), pass.c_str()); + if ((user != "") && (pass != "")) { + DEBUG_MSG(" as user '%s'.\n", (char *) user.c_str()); + char username[user.length()+1]; + user.toCharArray(username, user.length()+1); + char password[pass.length()+1]; + pass.toCharArray(password, pass.length()+1); + mqtt.setCredentials(username, password); } else { DEBUG_MSG(" anonymously\n"); } diff --git a/code/src/nofuss.ino b/code/src/nofuss.ino index bcb94415..35b1e20e 100644 --- a/code/src/nofuss.ino +++ b/code/src/nofuss.ino @@ -74,7 +74,7 @@ void nofussLoop() { static unsigned long last_check = 0; if (!wifiConnected()) return; -unsigned long interval = getSetting("nofussInterval", String(NOFUSS_INTERVAL)).toInt(); +unsigned long interval = getSetting("nofussInterval", NOFUSS_INTERVAL).toInt(); if ((last_check > 0) && ((millis() - last_check) < interval)) return; last_check = millis(); NoFUSSClient.handle(); diff --git a/code/src/pow.ino b/code/src/pow.ino index 0676ead5..428838e5 100644 --- a/code/src/pow.ino +++ b/code/src/pow.ino @@ -41,18 +41,18 @@ void powDettachInterrupts() { } void powSaveCalibration() { - setSetting("powPowerMult", String() + hlw8012.getPowerMultiplier()); - setSetting("powCurrentMult", String() + hlw8012.getCurrentMultiplier()); - setSetting("powVoltageMult", String() + hlw8012.getVoltageMultiplier()); + setSetting("powPowerMult", hlw8012.getPowerMultiplier()); + setSetting("powCurrentMult", hlw8012.getCurrentMultiplier()); + setSetting("powVoltageMult", hlw8012.getVoltageMultiplier()); } void powRetrieveCalibration() { double value; - value = getSetting("powPowerMult", "0").toFloat(); + value = getSetting("powPowerMult", 0).toFloat(); if (value > 0) hlw8012.setPowerMultiplier((int) value); - value = getSetting("powCurrentMult", "0").toFloat(); + value = getSetting("powCurrentMult", 0).toFloat(); if (value > 0) hlw8012.setCurrentMultiplier((int) value); - value = getSetting("powVoltageMult", "0").toFloat(); + value = getSetting("powVoltageMult", 0).toFloat(); if (value > 0) hlw8012.setVoltageMultiplier((int) value); } diff --git a/code/src/relay.ino b/code/src/relay.ino index 77b7cb92..ba26001c 100644 --- a/code/src/relay.ino +++ b/code/src/relay.ino @@ -22,8 +22,9 @@ bool recursive = false; // ----------------------------------------------------------------------------- void relayMQTT(unsigned char id) { - char buffer[10]; - sprintf(buffer, MQTT_RELAY_TOPIC, id); + String mqttGetter = getSetting("mqttGetter", MQTT_USE_GETTER); + char buffer[strlen(MQTT_RELAY_TOPIC) + mqttGetter.length() + 3]; + sprintf(buffer, "%s/%d%s", MQTT_RELAY_TOPIC, id, mqttGetter.c_str()); mqttSend(buffer, (char *) (relayStatus(id) ? "1" : "0")); } @@ -91,7 +92,11 @@ bool relayStatus(unsigned char id, bool status, bool report) { if (report) relayMQTT(id); if (!recursive) relayWS(); return changed; - + +} + +bool relayStatus(unsigned char id, bool status) { + return relayStatus(id, status, true); } void relaySync(unsigned char id) { @@ -100,7 +105,7 @@ void relaySync(unsigned char id) { recursive = true; - byte relaySync = getSetting("relaySync", String(RELAY_SYNC)).toInt(); + byte relaySync = getSetting("relaySync", RELAY_SYNC).toInt(); bool status = relayStatus(id); // If RELAY_SYNC_SAME all relays should have the same state @@ -165,36 +170,41 @@ void relayMQTTCallback(unsigned int type, const char * topic, const char * paylo static bool isFirstMessage = true; + String mqttSetter = getSetting("mqttSetter", MQTT_USE_SETTER); + String mqttGetter = getSetting("mqttGetter", MQTT_USE_GETTER); + bool sameSetGet = mqttGetter.compareTo(mqttSetter) == 0; + if (type == MQTT_CONNECT_EVENT) { relayMQTT(); - mqttSubscribe("/relay/#"); + char buffer[strlen(MQTT_RELAY_TOPIC) + mqttSetter.length() + 3]; + sprintf(buffer, "%s/+%s", MQTT_RELAY_TOPIC, mqttSetter.c_str()); + mqttSubscribe(buffer); } if (type == MQTT_MESSAGE_EVENT) { // Match topic - if (memcmp("/relay/", topic, 7) != 0) return; + String t = String(topic); + if (!t.startsWith(MQTT_RELAY_TOPIC)) return; + if (!t.endsWith(mqttSetter)) return; // If relayMode is not SAME avoid responding to a retained message - if (isFirstMessage) { + if (sameSetGet && isFirstMessage) { isFirstMessage = false; - byte relayMode = getSetting("relayMode", String(RELAY_MODE)).toInt(); + byte relayMode = getSetting("relayMode", RELAY_MODE).toInt(); if (relayMode != RELAY_MODE_SAME) return; } // Get relay ID - unsigned int relayID = topic[strlen(topic)-1] - '0'; + unsigned int relayID = topic[strlen(MQTT_RELAY_TOPIC)+1] - '0'; if (relayID >= relayCount()) relayID = 0; // Action to perform - if ((char)payload[0] == '0') { - relayStatus(relayID, false, false); - } - if ((char)payload[0] == '1') { - relayStatus(relayID, true, false); - } - if ((char)payload[0] == '2') { + unsigned int value = (char)payload[0] - '0'; + if (value == 2) { relayToggle(relayID); + } else { + relayStatus(relayID, value > 0, !sameSetGet); } } @@ -227,7 +237,7 @@ void relaySetup() { #endif EEPROM.begin(4096); - byte relayMode = getSetting("relayMode", String(RELAY_MODE)).toInt(); + byte relayMode = getSetting("relayMode", RELAY_MODE).toInt(); for (unsigned int i=0; i < _relays.size(); i++) { pinMode(_relays[i], OUTPUT); diff --git a/code/src/rf.ino b/code/src/rf.ino index 8a07f9d7..817c0a8e 100644 --- a/code/src/rf.ino +++ b/code/src/rf.ino @@ -33,7 +33,7 @@ void rfBuildCodes() { unsigned long code = 0; // channel - unsigned int channel = getSetting("rfChannel", String(RF_CHANNEL)).toInt(); + unsigned int channel = getSetting("rfChannel", RF_CHANNEL).toInt(); for (byte i = 0; i < 5; i++) { code *= 3; if (channel & 1) code += 1; @@ -41,7 +41,7 @@ void rfBuildCodes() { } // device - unsigned int device = getSetting("rfDevice", String(RF_DEVICE)).toInt(); + unsigned int device = getSetting("rfDevice", RF_DEVICE).toInt(); for (byte i = 0; i < 5; i++) { code *= 3; if (device != i) code += 2; diff --git a/code/src/settings.ino b/code/src/settings.ino index 29e0826d..b5093d72 100644 --- a/code/src/settings.ino +++ b/code/src/settings.ino @@ -20,6 +20,21 @@ Embedis embedis(Serial); // Settings // ----------------------------------------------------------------------------- +unsigned long settingsSize() { + bool zero = false; + unsigned long size = 0; + for (unsigned int i = SPI_FLASH_SEC_SIZE; i>0; i--) { + size++; + if (EEPROM.read(i) == 0) { + if (zero) break; + zero = true; + } else { + zero = false; + } + } + return size-2; +} + void settingsSetup() { EEPROM.begin(SPI_FLASH_SEC_SIZE); @@ -35,24 +50,46 @@ void settingsSetup() { #endif ); - Embedis::hardware( F("wifi"), [](Embedis* e) { + Embedis::hardware( F("WIFI"), [](Embedis* e) { StreamString s; WiFi.printDiag(s); e->response(s); }, 0); - Embedis::command( F("reconnect"), [](Embedis* e) { + Embedis::command( F("RECONNECT"), [](Embedis* e) { wifiConfigure(); wifiDisconnect(); e->response(Embedis::OK); }); - Embedis::command( F("reset"), [](Embedis* e) { + Embedis::command( F("RESET"), [](Embedis* e) { e->response(Embedis::OK); ESP.reset(); }); - DEBUG_MSG("[SETTINGS] Initialized\n"); + Embedis::command( F("EEPROM.DUMP"), [](Embedis* e) { + for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { + if (i % 16 == 0) Serial.printf("\n[%04X] ", i); + Serial.printf("%02X ", EEPROM.read(i)); + } + Serial.printf("\n"); + e->response(Embedis::OK); + }); + + Embedis::command( F("EEPROM.ERASE"), [](Embedis* e) { + for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { + EEPROM.write(i, 0xFF); + } + EEPROM.commit(); + e->response(Embedis::OK); + }); + + Embedis::command( F("SETTINGS.SIZE"), [](Embedis* e) { + e->response(String(settingsSize())); + }); + + DEBUG_MSG("[SETTINGS] EEPROM size: %d bytes\n", SPI_FLASH_SEC_SIZE); + DEBUG_MSG("[SETTINGS] Settings size: %d bytes\n", settingsSize()); } @@ -60,14 +97,18 @@ void settingsLoop() { embedis.process(); } -String getSetting(const String& key, String defaultValue) { +template String getSetting(const String& key, T defaultValue) { String value; - if (!Embedis::get(key, value)) value = defaultValue; + if (!Embedis::get(key, value)) value = String(defaultValue); return value; } -bool setSetting(const String& key, String& value) { - return Embedis::set(key, value); +String getSetting(const String& key) { + return getSetting(key, ""); +} + +template bool setSetting(const String& key, T value) { + return Embedis::set(key, String(value)); } bool delSetting(const String& key) { diff --git a/code/src/web.ino b/code/src/web.ino index 5645a24b..6419bf2a 100644 --- a/code/src/web.ino +++ b/code/src/web.ino @@ -155,12 +155,12 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) { // Checkboxes if (apiEnabled != (getSetting("apiEnabled").toInt() == 1)) { - setSetting("apiEnabled", String() + (apiEnabled ? 1 : 0)); + setSetting("apiEnabled", apiEnabled); dirty = true; } #if ENABLE_FAUXMO if (fauxmoEnabled != (getSetting("fauxmoEnabled").toInt() == 1)) { - setSetting("fauxmoEnabled", String() + (fauxmoEnabled ? 1 : 0)); + setSetting("fauxmoEnabled", fauxmoEnabled); dirty = true; } #endif @@ -224,7 +224,7 @@ void _wsStart(uint32_t client_id) { root["mqttStatus"] = mqttConnected(); root["mqttServer"] = getSetting("mqttServer", MQTT_SERVER); - root["mqttPort"] = getSetting("mqttPort", String(MQTT_PORT)); + root["mqttPort"] = getSetting("mqttPort", MQTT_PORT); root["mqttUser"] = getSetting("mqttUser"); root["mqttPassword"] = getSetting("mqttPassword"); root["mqttTopic"] = getSetting("mqttTopic", MQTT_TOPIC); @@ -233,10 +233,10 @@ void _wsStart(uint32_t client_id) { for (unsigned char relayID=0; relayID 1) { root["multirelayVisible"] = 1; - root["relaySync"] = getSetting("relaySync", String(RELAY_SYNC)); + root["relaySync"] = getSetting("relaySync", RELAY_SYNC); } root["apiEnabled"] = getSetting("apiEnabled").toInt() == 1; @@ -244,7 +244,7 @@ void _wsStart(uint32_t client_id) { #if ENABLE_FAUXMO root["fauxmoVisible"] = 1; - root["fauxmoEnabled"] = getSetting("fauxmoEnabled", String(FAUXMO_ENABLED)).toInt() == 1; + root["fauxmoEnabled"] = getSetting("fauxmoEnabled", FAUXMO_ENABLED).toInt() == 1; #endif #if ENABLE_DS18B20 @@ -260,15 +260,15 @@ void _wsStart(uint32_t client_id) { #if ENABLE_RF root["rfVisible"] = 1; - root["rfChannel"] = getSetting("rfChannel", String(RF_CHANNEL)); - root["rfDevice"] = getSetting("rfDevice", String(RF_DEVICE)); + root["rfChannel"] = getSetting("rfChannel", RF_CHANNEL); + root["rfDevice"] = getSetting("rfDevice", RF_DEVICE); #endif #if ENABLE_EMON root["emonVisible"] = 1; root["emonPower"] = getPower(); - root["emonMains"] = getSetting("emonMains", String(EMON_MAINS_VOLTAGE)); - root["emonRatio"] = getSetting("emonRatio", String(EMON_CURRENT_RATIO)); + root["emonMains"] = getSetting("emonMains", EMON_MAINS_VOLTAGE); + root["emonRatio"] = getSetting("emonRatio", EMON_CURRENT_RATIO); #endif #if ENABLE_POW @@ -502,7 +502,7 @@ void webSetup() { char lastModified[50]; sprintf(lastModified, "%s %s GMT", __DATE__, __TIME__); server.serveStatic("/", SPIFFS, "/").setLastModified(lastModified); - + // 404 server.onNotFound([](AsyncWebServerRequest *request){ request->send(404); diff --git a/code/src/wifi.ino b/code/src/wifi.ino index f291af12..e8c1bb39 100644 --- a/code/src/wifi.ino +++ b/code/src/wifi.ino @@ -164,5 +164,7 @@ void wifiSetup() { void wifiLoop() { jw.loop(); - dnsServer.processNextRequest(); + if (WiFi.getMode() == WIFI_AP) { + dnsServer.processNextRequest(); + } }