From b9acfe000ca0e55fc73d73d2ae0049c626cd903d Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Sun, 6 May 2018 18:35:31 +0200 Subject: [PATCH 1/7] Fix configuration restore regression from 5.13.1 5.13.1a * Fix configuration restore regression from 5.13.1 --- sonoff/_releasenotes.ino | 1 + sonoff/webserver.ino | 48 ++++++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 9b6207e39..cadfdfda2 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,5 +1,6 @@ /* 5.13.1a * Change user_config.h otaurl to http://sonoff.maddox.co.uk/tasmota/sonoff.bin (#2588, #2602) + * Fix configuration restore regression from 5.13.1 * Fix compile error when ADC is enabled and Rules are disabled (#2608) * Fix rule power trigger when no backlog command is used (#2613) * Fix several timer data input and output errors (#2597, #2620) diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index f0c3fc6e6..6e8361624 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -330,6 +330,8 @@ uint8_t upload_file_type; uint8_t upload_progress_dot_count; uint8_t config_block_count = 0; uint8_t config_xor_on = 0; +uint8_t config_xor_on_set = CONFIG_FILE_XOR; +uint8_t *settings_new = NULL; // Helper function to avoid code duplication (saves 4k Flash) static void WebGetArg(const char* arg, char* out, size_t max) @@ -977,10 +979,10 @@ void HandleBackupConfiguration() WebServer->send(200, FPSTR(HDR_CTYPE_STREAM), ""); memcpy(buffer, &Settings, sizeof(buffer)); buffer[0] = CONFIG_FILE_SIGN; - buffer[1] = (!CONFIG_FILE_XOR)?0:1; + buffer[1] = (!config_xor_on_set) ? 0 : 1; if (buffer[1]) { for (uint16_t i = 2; i < sizeof(buffer); i++) { - buffer[i] ^= (CONFIG_FILE_XOR +i); + buffer[i] ^= (config_xor_on_set +i); } } myClient.write((const char*)buffer, sizeof(buffer)); @@ -1236,6 +1238,14 @@ void HandleUpgradeFirmwareStart() ExecuteCommand(svalue); } +void SettingsNewFree() +{ + if (settings_new != NULL) { + free(settings_new); + settings_new = NULL; + } +} + void HandleUploadDone() { if (HttpUser()) { return; } @@ -1275,6 +1285,7 @@ void HandleUploadDone() page += FPSTR(HTTP_MSG_RSTRT); restart_flag = 2; } + SettingsNewFree(); page += F("
"); page += FPSTR(HTTP_BTN_MAIN); ShowPage(page); @@ -1302,7 +1313,13 @@ void HandleUploadLoop() SettingsSave(1); // Free flash for upload snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str()); AddLog(LOG_LEVEL_INFO); - if (!upload_file_type) { + if (upload_file_type) { + SettingsNewFree(); + if (!(settings_new = (uint8_t *)malloc(sizeof(Settings)))) { + upload_error = 2; + return; + } + } else { MqttRetryCounter(60); #ifdef USE_EMULATION UdpDisconnect(); @@ -1347,18 +1364,7 @@ void HandleUploadLoop() upload_error = 9; return; } - if (config_xor_on) { - for (uint16_t i = 2; i < upload.currentSize; i++) { - upload.buf[i] ^= (CONFIG_FILE_XOR +i); - } - } - if (0 == config_block_count) { - SettingsDefaultSet2(); - memcpy((char*)&Settings +16, upload.buf +16, upload.currentSize -16); - memcpy((char*)&Settings +8, upload.buf +8, 4); // Restore version and auto upgrade - } else { - memcpy((char*)&Settings +(config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize); - } + memcpy(settings_new + (config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize); config_block_count++; } } else { // firmware @@ -1376,7 +1382,17 @@ void HandleUploadLoop() if (_serialoutput && (upload_progress_dot_count % 80)) { Serial.println(); } - if (!upload_file_type) { + if (upload_file_type) { + if (config_xor_on) { + for (uint16_t i = 2; i < sizeof(Settings); i++) { + settings_new[i] ^= (config_xor_on_set +i); + } + } + SettingsDefaultSet2(); + memcpy((char*)&Settings +16, settings_new +16, sizeof(Settings) -16); + memcpy((char*)&Settings +8, settings_new +8, 4); // Restore version and auto upgrade + SettingsNewFree(); + } else { if (!Update.end(true)) { // true to set the size to the current progress if (_serialoutput) { Update.printError(Serial); } upload_error = 6; From 8ff8e6e69bf56f98d921038bfc6f4a81b31fa362 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Sun, 6 May 2018 18:43:34 +0200 Subject: [PATCH 2/7] Fix configuration restore regression from 5.13.1a 5.13.1a * Fix configuration restore regression from 5.13.1 --- sonoff/webserver.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 6e8361624..0439ae509 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -1360,7 +1360,6 @@ void HandleUploadLoop() if (upload_file_type) { // config if (!upload_error) { if (upload.currentSize > (sizeof(Settings) - (config_block_count * HTTP_UPLOAD_BUFLEN))) { - if (config_block_count) { SettingsDefault(); } upload_error = 9; return; } From b7b3f9b0d57fda943f579d8e12cd81c6532c21be Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Tue, 8 May 2018 17:04:35 +0200 Subject: [PATCH 3/7] Fix sensor MHZ-19 vanishing data over time 5.13.1a * Fix sensor MHZ-19 vanishing data over time (#2659) --- .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 0 .../library.json | 0 .../library.properties | 0 .../src/TasmotaSerial.cpp | 64 +++--- .../src/TasmotaSerial.h | 0 sonoff/_releasenotes.ino | 1 + sonoff/i18n.h | 1 + sonoff/xsns_15_mhz19.ino | 196 ++++++++++-------- 10 files changed, 148 insertions(+), 114 deletions(-) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/README.md (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/keywords.txt (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/library.json (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/library.properties (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/src/TasmotaSerial.cpp (77%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/src/TasmotaSerial.h (100%) diff --git a/lib/TasmotaSerial-1.2.0/README.md b/lib/TasmotaSerial-1.3.0/README.md similarity index 100% rename from lib/TasmotaSerial-1.2.0/README.md rename to lib/TasmotaSerial-1.3.0/README.md diff --git a/lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-1.2.0/keywords.txt b/lib/TasmotaSerial-1.3.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-1.2.0/keywords.txt rename to lib/TasmotaSerial-1.3.0/keywords.txt diff --git a/lib/TasmotaSerial-1.2.0/library.json b/lib/TasmotaSerial-1.3.0/library.json similarity index 100% rename from lib/TasmotaSerial-1.2.0/library.json rename to lib/TasmotaSerial-1.3.0/library.json diff --git a/lib/TasmotaSerial-1.2.0/library.properties b/lib/TasmotaSerial-1.3.0/library.properties similarity index 100% rename from lib/TasmotaSerial-1.2.0/library.properties rename to lib/TasmotaSerial-1.3.0/library.properties diff --git a/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp similarity index 77% rename from lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp index c189442e6..801384f23 100644 --- a/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp @@ -29,51 +29,51 @@ extern "C" { // As the Arduino attachInterrupt has no parameter, lists of objects // and callbacks corresponding to each possible GPIO pins have to be defined -TasmotaSerial *ObjList[16]; +TasmotaSerial *tms_obj_list[16]; #ifdef TM_SERIAL_USE_IRAM -void ICACHE_RAM_ATTR sws_isr_0() { ObjList[0]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_1() { ObjList[1]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_2() { ObjList[2]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_3() { ObjList[3]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_4() { ObjList[4]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_5() { ObjList[5]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_0() { tms_obj_list[0]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_1() { tms_obj_list[1]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_2() { tms_obj_list[2]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_3() { tms_obj_list[3]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_4() { tms_obj_list[4]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_5() { tms_obj_list[5]->rxRead(); }; // Pin 6 to 11 can not be used -void ICACHE_RAM_ATTR sws_isr_12() { ObjList[12]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_13() { ObjList[13]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_14() { ObjList[14]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_15() { ObjList[15]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_12() { tms_obj_list[12]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_13() { tms_obj_list[13]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_14() { tms_obj_list[14]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_15() { tms_obj_list[15]->rxRead(); }; #else -void sws_isr_0() { ObjList[0]->rxRead(); }; -void sws_isr_1() { ObjList[1]->rxRead(); }; -void sws_isr_2() { ObjList[2]->rxRead(); }; -void sws_isr_3() { ObjList[3]->rxRead(); }; -void sws_isr_4() { ObjList[4]->rxRead(); }; -void sws_isr_5() { ObjList[5]->rxRead(); }; +void tms_isr_0() { tms_obj_list[0]->rxRead(); }; +void tms_isr_1() { tms_obj_list[1]->rxRead(); }; +void tms_isr_2() { tms_obj_list[2]->rxRead(); }; +void tms_isr_3() { tms_obj_list[3]->rxRead(); }; +void tms_isr_4() { tms_obj_list[4]->rxRead(); }; +void tms_isr_5() { tms_obj_list[5]->rxRead(); }; // Pin 6 to 11 can not be used -void sws_isr_12() { ObjList[12]->rxRead(); }; -void sws_isr_13() { ObjList[13]->rxRead(); }; -void sws_isr_14() { ObjList[14]->rxRead(); }; -void sws_isr_15() { ObjList[15]->rxRead(); }; +void tms_isr_12() { tms_obj_list[12]->rxRead(); }; +void tms_isr_13() { tms_obj_list[13]->rxRead(); }; +void tms_isr_14() { tms_obj_list[14]->rxRead(); }; +void tms_isr_15() { tms_obj_list[15]->rxRead(); }; #endif // TM_SERIAL_USE_IRAM static void (*ISRList[16])() = { - sws_isr_0, - sws_isr_1, - sws_isr_2, - sws_isr_3, - sws_isr_4, - sws_isr_5, + tms_isr_0, + tms_isr_1, + tms_isr_2, + tms_isr_3, + tms_isr_4, + tms_isr_5, NULL, NULL, NULL, NULL, NULL, NULL, - sws_isr_12, - sws_isr_13, - sws_isr_14, - sws_isr_15 + tms_isr_12, + tms_isr_13, + tms_isr_14, + tms_isr_15 }; TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) @@ -91,7 +91,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE; pinMode(m_rx_pin, INPUT); - ObjList[m_rx_pin] = this; + tms_obj_list[m_rx_pin] = this; attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING); } if (m_tx_pin > -1) { diff --git a/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h b/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h similarity index 100% rename from lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index cadfdfda2..2ce37d699 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -5,6 +5,7 @@ * Fix rule power trigger when no backlog command is used (#2613) * Fix several timer data input and output errors (#2597, #2620) * Fix KNX config error (#2628) + * Fix sensor MHZ-19 vanishing data over time (#2659) * Add Portuguese in Brazil language file * Add rule state test for On/Off in addition to 0/1 (#2613) * Updated Italian language file (#2618) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 4bb42331f..e1d27221b 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -90,6 +90,7 @@ #define D_JSON_PRESSUREATSEALEVEL "SeaPressure" #define D_JSON_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_JSON_PROGRAMSIZE "ProgramSize" +#define D_JSON_RESET "Reset" #define D_JSON_RESTARTING "Restarting" #define D_JSON_RESTARTREASON "RestartReason" #define D_JSON_RSSI "RSSI" diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 4cbf88c9e..52765f4b5 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -24,7 +24,7 @@ /*********************************************************************************************\ * MH-Z19 - CO2 sensor * - * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) + * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) ********************************************************************************************** * Filter usage * @@ -64,17 +64,20 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT #define CO2_HIGH 1200 // Above this CO2 value show red light #endif -#define MHZ19_READ_TIMEOUT 500 // Must be way less than 1000 +#define MHZ19_READ_TIMEOUT 400 // Must be way less than 1000 but enough to read 9 bytes at 9600 bps #define MHZ19_RETRY_COUNT 8 TasmotaSerial *MhzSerial; const char kMhzTypes[] PROGMEM = "MHZ19|MHZ19B"; -const uint8_t mhz_cmnd_read_ppm[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; -const uint8_t mhz_cmnd_abc_enable[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6}; -const uint8_t mhz_cmnd_abc_disable[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; -const uint8_t mhz_cmnd_zeropoint[9] = {0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; +enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET }; +const uint8_t kMhzCommands[][2] PROGMEM = { + {0x86,0x00}, // mhz_cmnd_read_ppm + {0x79,0xA0}, // mhz_cmnd_abc_enable + {0x79,0x00}, // mhz_cmnd_abc_disable + {0x87,0x00}, // mhz_cmnd_zeropoint + {0x8D,0x00}}; // mhz_cmnd_reset uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; @@ -84,13 +87,41 @@ bool mhz_abc_must_apply = false; char mhz_types[7]; float mhz_temperature = 0; -uint8_t mhz_timer = 0; uint8_t mhz_retry = MHZ19_RETRY_COUNT; - +uint8_t mhz_received = 0; uint8_t mhz_state = 0; /*********************************************************************************************/ +byte MhzCalculateChecksum(byte *array) +{ + byte checksum = 0; + for (byte i = 1; i < 8; i++) { + checksum += array[i]; + } + checksum = 255 - checksum; + return (checksum +1); +} + +size_t MhzSendCmd(byte command_id) +{ + uint8_t mhz_send[9] = { 0 }; + + mhz_send[0] = 0xFF; // Start byte, fixed + mhz_send[1] = 0x01; // Sensor number, 0x01 by default + memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(kMhzCommands[0])); +/* + mhz_send[4] = 0x00; + mhz_send[5] = 0x00; + mhz_send[6] = 0x00; + mhz_send[7] = 0x00; +*/ + mhz_send[8] = MhzCalculateChecksum(mhz_send); + return MhzSerial->write(mhz_send, sizeof(mhz_send)); +} + +/*********************************************************************************************/ + bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) { if (1 == s) { @@ -126,89 +157,84 @@ bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) return true; } -void Mhz50ms() +void MhzEverySecond() { mhz_state++; - if (4 == mhz_state) { // Every 200 mSec + if (8 == mhz_state) { // Every 8 sec start a MH-Z19 measuring cycle (which takes 1005 +5% ms) mhz_state = 0; - uint8_t mhz_response[9]; - - mhz_timer++; - if (6 == mhz_timer) { // MH-Z19 measuring cycle takes 1005 +5% ms - mhz_timer = 0; - - MhzSerial->flush(); - MhzSerial->write(mhz_cmnd_read_ppm, 9); + if (mhz_retry) { + mhz_retry--; + if (!mhz_retry) { + mhz_last_ppm = 0; + mhz_temperature = 0; + } } - if (1 == mhz_timer) { - if (mhz_retry) { - mhz_retry--; - if (!mhz_retry) { - mhz_last_ppm = 0; - mhz_temperature = 0; - } - } + MhzSerial->flush(); // Sync reception + MhzSendCmd(MHZ_CMND_READPPM); + mhz_received = 0; + } - unsigned long start = millis(); - uint8_t counter = 0; - while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); - } - } + if ((mhz_state > 2) && !mhz_received) { // Start reading response after 3 seconds every second until received + uint8_t mhz_response[9]; - AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); - - if (counter < 9) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); - return; - } - - byte crc = 0; - for (uint8_t i = 1; i < 8; i++) { - crc += mhz_response[i]; - } - crc = 255 - crc; - crc++; - if (mhz_response[8] != crc) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); - return; - } - if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); - return; - } - - uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; - if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 - if (!mhz_abc_enable) { - // After bootup of the sensor the ABC will be enabled. - // Thus only actively disable after bootup. - mhz_abc_must_apply = true; - } + unsigned long start = millis(); + uint8_t counter = 0; + while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { + if (MhzSerial->available() > 0) { + mhz_response[counter++] = MhzSerial->read(); } else { - uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; - mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); - uint8_t s = mhz_response[5]; - mhz_type = (s) ? 1 : 2; - if (MhzCheckAndApplyFilter(ppm, s)) { - mhz_retry = MHZ19_RETRY_COUNT; - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); + delay(5); + } + } - if (0 == s || 64 == s) { // Reading is stable. - if (mhz_abc_must_apply) { - mhz_abc_must_apply = false; - if (mhz_abc_enable) { - MhzSerial->write(mhz_cmnd_abc_enable, 9); // Sent sensor ABC Enable - } else { - MhzSerial->write(mhz_cmnd_abc_disable, 9); // Sent sensor ABC Disable - } + AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + + if (counter < 9) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); + return; + } + + byte crc = MhzCalculateChecksum(mhz_response); + if (mhz_response[8] != crc) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); + return; + } + if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); + return; + } + + mhz_received = 1; + + uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; + if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 + if (!mhz_abc_enable) { + // After bootup of the sensor the ABC will be enabled. + // Thus only actively disable after bootup. + mhz_abc_must_apply = true; + } + } else { + uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; + mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); + uint8_t s = mhz_response[5]; + mhz_type = (s) ? 1 : 2; + if (MhzCheckAndApplyFilter(ppm, s)) { + mhz_retry = MHZ19_RETRY_COUNT; + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); + + if (0 == s || 64 == s) { // Reading is stable. + if (mhz_abc_must_apply) { + mhz_abc_must_apply = false; + if (mhz_abc_enable) { + MhzSendCmd(MHZ_CMND_ABCENABLE); + } else { + MhzSendCmd(MHZ_CMND_ABCDISABLE); } } - } + } } @@ -225,6 +251,8 @@ void Mhz50ms() 2 - Manual start = ABC Off 3 - Optional filter settings + + 9 - Reset */ bool MhzCommandSensor() @@ -233,9 +261,13 @@ bool MhzCommandSensor() switch (XdrvMailbox.payload) { case 2: - MhzSerial->write(mhz_cmnd_zeropoint, 9); + MhzSendCmd(MHZ_CMND_ZEROPOINT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); break; + case 9: + MhzSendCmd(MHZ_CMND_RESET); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); + break; default: serviced = false; } @@ -250,7 +282,7 @@ void MhzInit() mhz_type = 0; if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD]); - if (MhzSerial->begin()) { + if (MhzSerial->begin(9600)) { mhz_type = 1; } } @@ -288,8 +320,8 @@ boolean Xsns15(byte function) case FUNC_INIT: MhzInit(); break; - case FUNC_EVERY_50_MSECOND: - Mhz50ms(); + case FUNC_EVERY_SECOND: + MhzEverySecond(); break; case FUNC_COMMAND: if (XSNS_15 == XdrvMailbox.index) { From 458f00b2bd709b6605133e9b130aeebcd020da55 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Tue, 8 May 2018 17:05:49 +0200 Subject: [PATCH 4/7] Revert "Fix sensor MHZ-19 vanishing data over time" This reverts commit b7b3f9b0d57fda943f579d8e12cd81c6532c21be. --- .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 0 .../library.json | 0 .../library.properties | 0 .../src/TasmotaSerial.cpp | 64 +++--- .../src/TasmotaSerial.h | 0 sonoff/_releasenotes.ino | 1 - sonoff/i18n.h | 1 - sonoff/xsns_15_mhz19.ino | 200 ++++++++---------- 10 files changed, 116 insertions(+), 150 deletions(-) rename lib/{TasmotaSerial-1.3.0 => TasmotaSerial-1.2.0}/README.md (100%) rename lib/{TasmotaSerial-1.3.0 => TasmotaSerial-1.2.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-1.3.0 => TasmotaSerial-1.2.0}/keywords.txt (100%) rename lib/{TasmotaSerial-1.3.0 => TasmotaSerial-1.2.0}/library.json (100%) rename lib/{TasmotaSerial-1.3.0 => TasmotaSerial-1.2.0}/library.properties (100%) rename lib/{TasmotaSerial-1.3.0 => TasmotaSerial-1.2.0}/src/TasmotaSerial.cpp (77%) rename lib/{TasmotaSerial-1.3.0 => TasmotaSerial-1.2.0}/src/TasmotaSerial.h (100%) diff --git a/lib/TasmotaSerial-1.3.0/README.md b/lib/TasmotaSerial-1.2.0/README.md similarity index 100% rename from lib/TasmotaSerial-1.3.0/README.md rename to lib/TasmotaSerial-1.2.0/README.md diff --git a/lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-1.3.0/keywords.txt b/lib/TasmotaSerial-1.2.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-1.3.0/keywords.txt rename to lib/TasmotaSerial-1.2.0/keywords.txt diff --git a/lib/TasmotaSerial-1.3.0/library.json b/lib/TasmotaSerial-1.2.0/library.json similarity index 100% rename from lib/TasmotaSerial-1.3.0/library.json rename to lib/TasmotaSerial-1.2.0/library.json diff --git a/lib/TasmotaSerial-1.3.0/library.properties b/lib/TasmotaSerial-1.2.0/library.properties similarity index 100% rename from lib/TasmotaSerial-1.3.0/library.properties rename to lib/TasmotaSerial-1.2.0/library.properties diff --git a/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp similarity index 77% rename from lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp index 801384f23..c189442e6 100644 --- a/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp @@ -29,51 +29,51 @@ extern "C" { // As the Arduino attachInterrupt has no parameter, lists of objects // and callbacks corresponding to each possible GPIO pins have to be defined -TasmotaSerial *tms_obj_list[16]; +TasmotaSerial *ObjList[16]; #ifdef TM_SERIAL_USE_IRAM -void ICACHE_RAM_ATTR tms_isr_0() { tms_obj_list[0]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_1() { tms_obj_list[1]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_2() { tms_obj_list[2]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_3() { tms_obj_list[3]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_4() { tms_obj_list[4]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_5() { tms_obj_list[5]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_0() { ObjList[0]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_1() { ObjList[1]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_2() { ObjList[2]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_3() { ObjList[3]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_4() { ObjList[4]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_5() { ObjList[5]->rxRead(); }; // Pin 6 to 11 can not be used -void ICACHE_RAM_ATTR tms_isr_12() { tms_obj_list[12]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_13() { tms_obj_list[13]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_14() { tms_obj_list[14]->rxRead(); }; -void ICACHE_RAM_ATTR tms_isr_15() { tms_obj_list[15]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_12() { ObjList[12]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_13() { ObjList[13]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_14() { ObjList[14]->rxRead(); }; +void ICACHE_RAM_ATTR sws_isr_15() { ObjList[15]->rxRead(); }; #else -void tms_isr_0() { tms_obj_list[0]->rxRead(); }; -void tms_isr_1() { tms_obj_list[1]->rxRead(); }; -void tms_isr_2() { tms_obj_list[2]->rxRead(); }; -void tms_isr_3() { tms_obj_list[3]->rxRead(); }; -void tms_isr_4() { tms_obj_list[4]->rxRead(); }; -void tms_isr_5() { tms_obj_list[5]->rxRead(); }; +void sws_isr_0() { ObjList[0]->rxRead(); }; +void sws_isr_1() { ObjList[1]->rxRead(); }; +void sws_isr_2() { ObjList[2]->rxRead(); }; +void sws_isr_3() { ObjList[3]->rxRead(); }; +void sws_isr_4() { ObjList[4]->rxRead(); }; +void sws_isr_5() { ObjList[5]->rxRead(); }; // Pin 6 to 11 can not be used -void tms_isr_12() { tms_obj_list[12]->rxRead(); }; -void tms_isr_13() { tms_obj_list[13]->rxRead(); }; -void tms_isr_14() { tms_obj_list[14]->rxRead(); }; -void tms_isr_15() { tms_obj_list[15]->rxRead(); }; +void sws_isr_12() { ObjList[12]->rxRead(); }; +void sws_isr_13() { ObjList[13]->rxRead(); }; +void sws_isr_14() { ObjList[14]->rxRead(); }; +void sws_isr_15() { ObjList[15]->rxRead(); }; #endif // TM_SERIAL_USE_IRAM static void (*ISRList[16])() = { - tms_isr_0, - tms_isr_1, - tms_isr_2, - tms_isr_3, - tms_isr_4, - tms_isr_5, + sws_isr_0, + sws_isr_1, + sws_isr_2, + sws_isr_3, + sws_isr_4, + sws_isr_5, NULL, NULL, NULL, NULL, NULL, NULL, - tms_isr_12, - tms_isr_13, - tms_isr_14, - tms_isr_15 + sws_isr_12, + sws_isr_13, + sws_isr_14, + sws_isr_15 }; TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) @@ -91,7 +91,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE; pinMode(m_rx_pin, INPUT); - tms_obj_list[m_rx_pin] = this; + ObjList[m_rx_pin] = this; attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING); } if (m_tx_pin > -1) { diff --git a/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h b/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h similarity index 100% rename from lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 2ce37d699..cadfdfda2 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -5,7 +5,6 @@ * Fix rule power trigger when no backlog command is used (#2613) * Fix several timer data input and output errors (#2597, #2620) * Fix KNX config error (#2628) - * Fix sensor MHZ-19 vanishing data over time (#2659) * Add Portuguese in Brazil language file * Add rule state test for On/Off in addition to 0/1 (#2613) * Updated Italian language file (#2618) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index e1d27221b..4bb42331f 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -90,7 +90,6 @@ #define D_JSON_PRESSUREATSEALEVEL "SeaPressure" #define D_JSON_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_JSON_PROGRAMSIZE "ProgramSize" -#define D_JSON_RESET "Reset" #define D_JSON_RESTARTING "Restarting" #define D_JSON_RESTARTREASON "RestartReason" #define D_JSON_RSSI "RSSI" diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 52765f4b5..4cbf88c9e 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -24,7 +24,7 @@ /*********************************************************************************************\ * MH-Z19 - CO2 sensor * - * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) + * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) ********************************************************************************************** * Filter usage * @@ -64,20 +64,17 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT #define CO2_HIGH 1200 // Above this CO2 value show red light #endif -#define MHZ19_READ_TIMEOUT 400 // Must be way less than 1000 but enough to read 9 bytes at 9600 bps +#define MHZ19_READ_TIMEOUT 500 // Must be way less than 1000 #define MHZ19_RETRY_COUNT 8 TasmotaSerial *MhzSerial; const char kMhzTypes[] PROGMEM = "MHZ19|MHZ19B"; -enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET }; -const uint8_t kMhzCommands[][2] PROGMEM = { - {0x86,0x00}, // mhz_cmnd_read_ppm - {0x79,0xA0}, // mhz_cmnd_abc_enable - {0x79,0x00}, // mhz_cmnd_abc_disable - {0x87,0x00}, // mhz_cmnd_zeropoint - {0x8D,0x00}}; // mhz_cmnd_reset +const uint8_t mhz_cmnd_read_ppm[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; +const uint8_t mhz_cmnd_abc_enable[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6}; +const uint8_t mhz_cmnd_abc_disable[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; +const uint8_t mhz_cmnd_zeropoint[9] = {0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; @@ -87,41 +84,13 @@ bool mhz_abc_must_apply = false; char mhz_types[7]; float mhz_temperature = 0; +uint8_t mhz_timer = 0; uint8_t mhz_retry = MHZ19_RETRY_COUNT; -uint8_t mhz_received = 0; + uint8_t mhz_state = 0; /*********************************************************************************************/ -byte MhzCalculateChecksum(byte *array) -{ - byte checksum = 0; - for (byte i = 1; i < 8; i++) { - checksum += array[i]; - } - checksum = 255 - checksum; - return (checksum +1); -} - -size_t MhzSendCmd(byte command_id) -{ - uint8_t mhz_send[9] = { 0 }; - - mhz_send[0] = 0xFF; // Start byte, fixed - mhz_send[1] = 0x01; // Sensor number, 0x01 by default - memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(kMhzCommands[0])); -/* - mhz_send[4] = 0x00; - mhz_send[5] = 0x00; - mhz_send[6] = 0x00; - mhz_send[7] = 0x00; -*/ - mhz_send[8] = MhzCalculateChecksum(mhz_send); - return MhzSerial->write(mhz_send, sizeof(mhz_send)); -} - -/*********************************************************************************************/ - bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) { if (1 == s) { @@ -157,84 +126,89 @@ bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) return true; } -void MhzEverySecond() +void Mhz50ms() { mhz_state++; - if (8 == mhz_state) { // Every 8 sec start a MH-Z19 measuring cycle (which takes 1005 +5% ms) + if (4 == mhz_state) { // Every 200 mSec mhz_state = 0; - if (mhz_retry) { - mhz_retry--; - if (!mhz_retry) { - mhz_last_ppm = 0; - mhz_temperature = 0; - } - } - - MhzSerial->flush(); // Sync reception - MhzSendCmd(MHZ_CMND_READPPM); - mhz_received = 0; - } - - if ((mhz_state > 2) && !mhz_received) { // Start reading response after 3 seconds every second until received uint8_t mhz_response[9]; - unsigned long start = millis(); - uint8_t counter = 0; - while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); + mhz_timer++; + if (6 == mhz_timer) { // MH-Z19 measuring cycle takes 1005 +5% ms + mhz_timer = 0; + + MhzSerial->flush(); + MhzSerial->write(mhz_cmnd_read_ppm, 9); + } + + if (1 == mhz_timer) { + if (mhz_retry) { + mhz_retry--; + if (!mhz_retry) { + mhz_last_ppm = 0; + mhz_temperature = 0; + } + } + + unsigned long start = millis(); + uint8_t counter = 0; + while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { + if (MhzSerial->available() > 0) { + mhz_response[counter++] = MhzSerial->read(); + } + } + + AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + + if (counter < 9) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); + return; + } + + byte crc = 0; + for (uint8_t i = 1; i < 8; i++) { + crc += mhz_response[i]; + } + crc = 255 - crc; + crc++; + if (mhz_response[8] != crc) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); + return; + } + if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); + return; + } + + uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; + if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 + if (!mhz_abc_enable) { + // After bootup of the sensor the ABC will be enabled. + // Thus only actively disable after bootup. + mhz_abc_must_apply = true; + } } else { - delay(5); - } - } + uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; + mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); + uint8_t s = mhz_response[5]; + mhz_type = (s) ? 1 : 2; + if (MhzCheckAndApplyFilter(ppm, s)) { + mhz_retry = MHZ19_RETRY_COUNT; + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); - AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); - - if (counter < 9) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); - return; - } - - byte crc = MhzCalculateChecksum(mhz_response); - if (mhz_response[8] != crc) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); - return; - } - if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); - return; - } - - mhz_received = 1; - - uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; - if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 - if (!mhz_abc_enable) { - // After bootup of the sensor the ABC will be enabled. - // Thus only actively disable after bootup. - mhz_abc_must_apply = true; - } - } else { - uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; - mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); - uint8_t s = mhz_response[5]; - mhz_type = (s) ? 1 : 2; - if (MhzCheckAndApplyFilter(ppm, s)) { - mhz_retry = MHZ19_RETRY_COUNT; - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); - - if (0 == s || 64 == s) { // Reading is stable. - if (mhz_abc_must_apply) { - mhz_abc_must_apply = false; - if (mhz_abc_enable) { - MhzSendCmd(MHZ_CMND_ABCENABLE); - } else { - MhzSendCmd(MHZ_CMND_ABCDISABLE); + if (0 == s || 64 == s) { // Reading is stable. + if (mhz_abc_must_apply) { + mhz_abc_must_apply = false; + if (mhz_abc_enable) { + MhzSerial->write(mhz_cmnd_abc_enable, 9); // Sent sensor ABC Enable + } else { + MhzSerial->write(mhz_cmnd_abc_disable, 9); // Sent sensor ABC Disable + } } } - } + } } } @@ -251,8 +225,6 @@ void MhzEverySecond() 2 - Manual start = ABC Off 3 - Optional filter settings - - 9 - Reset */ bool MhzCommandSensor() @@ -261,13 +233,9 @@ bool MhzCommandSensor() switch (XdrvMailbox.payload) { case 2: - MhzSendCmd(MHZ_CMND_ZEROPOINT); + MhzSerial->write(mhz_cmnd_zeropoint, 9); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); break; - case 9: - MhzSendCmd(MHZ_CMND_RESET); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); - break; default: serviced = false; } @@ -282,7 +250,7 @@ void MhzInit() mhz_type = 0; if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD]); - if (MhzSerial->begin(9600)) { + if (MhzSerial->begin()) { mhz_type = 1; } } @@ -320,8 +288,8 @@ boolean Xsns15(byte function) case FUNC_INIT: MhzInit(); break; - case FUNC_EVERY_SECOND: - MhzEverySecond(); + case FUNC_EVERY_50_MSECOND: + Mhz50ms(); break; case FUNC_COMMAND: if (XSNS_15 == XdrvMailbox.index) { From 49aec2e307d8e9232e6eedec75a2de52afdd7d46 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Tue, 8 May 2018 17:07:55 +0200 Subject: [PATCH 5/7] Fix sensor MHZ-19 vanishing data over time 5.13.1a * Fix sensor MHZ-19 vanishing data over time (#2659) --- .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 0 .../library.json | 2 +- .../library.properties | 2 +- .../src/TasmotaSerial.cpp | 64 +++--- .../src/TasmotaSerial.h | 0 sonoff/_releasenotes.ino | 1 + sonoff/i18n.h | 1 + sonoff/xsns_15_mhz19.ino | 196 ++++++++++-------- 10 files changed, 150 insertions(+), 116 deletions(-) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/README.md (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/keywords.txt (100%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/library.json (93%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/library.properties (93%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/src/TasmotaSerial.cpp (77%) rename lib/{TasmotaSerial-1.2.0 => TasmotaSerial-1.3.0}/src/TasmotaSerial.h (100%) diff --git a/lib/TasmotaSerial-1.2.0/README.md b/lib/TasmotaSerial-1.3.0/README.md similarity index 100% rename from lib/TasmotaSerial-1.2.0/README.md rename to lib/TasmotaSerial-1.3.0/README.md diff --git a/lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-1.2.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-1.3.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-1.2.0/keywords.txt b/lib/TasmotaSerial-1.3.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-1.2.0/keywords.txt rename to lib/TasmotaSerial-1.3.0/keywords.txt diff --git a/lib/TasmotaSerial-1.2.0/library.json b/lib/TasmotaSerial-1.3.0/library.json similarity index 93% rename from lib/TasmotaSerial-1.2.0/library.json rename to lib/TasmotaSerial-1.3.0/library.json index e4b2ba8a3..0183c43ce 100644 --- a/lib/TasmotaSerial-1.2.0/library.json +++ b/lib/TasmotaSerial-1.3.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "1.2.0", + "version": "1.3.0", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/TasmotaSerial-1.2.0/library.properties b/lib/TasmotaSerial-1.3.0/library.properties similarity index 93% rename from lib/TasmotaSerial-1.2.0/library.properties rename to lib/TasmotaSerial-1.3.0/library.properties index d427d0fb3..531fab514 100644 --- a/lib/TasmotaSerial-1.2.0/library.properties +++ b/lib/TasmotaSerial-1.3.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=1.2.0 +version=1.3.0 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial for ESP8266. diff --git a/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp similarity index 77% rename from lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp index c189442e6..801384f23 100644 --- a/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.cpp @@ -29,51 +29,51 @@ extern "C" { // As the Arduino attachInterrupt has no parameter, lists of objects // and callbacks corresponding to each possible GPIO pins have to be defined -TasmotaSerial *ObjList[16]; +TasmotaSerial *tms_obj_list[16]; #ifdef TM_SERIAL_USE_IRAM -void ICACHE_RAM_ATTR sws_isr_0() { ObjList[0]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_1() { ObjList[1]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_2() { ObjList[2]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_3() { ObjList[3]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_4() { ObjList[4]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_5() { ObjList[5]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_0() { tms_obj_list[0]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_1() { tms_obj_list[1]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_2() { tms_obj_list[2]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_3() { tms_obj_list[3]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_4() { tms_obj_list[4]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_5() { tms_obj_list[5]->rxRead(); }; // Pin 6 to 11 can not be used -void ICACHE_RAM_ATTR sws_isr_12() { ObjList[12]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_13() { ObjList[13]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_14() { ObjList[14]->rxRead(); }; -void ICACHE_RAM_ATTR sws_isr_15() { ObjList[15]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_12() { tms_obj_list[12]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_13() { tms_obj_list[13]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_14() { tms_obj_list[14]->rxRead(); }; +void ICACHE_RAM_ATTR tms_isr_15() { tms_obj_list[15]->rxRead(); }; #else -void sws_isr_0() { ObjList[0]->rxRead(); }; -void sws_isr_1() { ObjList[1]->rxRead(); }; -void sws_isr_2() { ObjList[2]->rxRead(); }; -void sws_isr_3() { ObjList[3]->rxRead(); }; -void sws_isr_4() { ObjList[4]->rxRead(); }; -void sws_isr_5() { ObjList[5]->rxRead(); }; +void tms_isr_0() { tms_obj_list[0]->rxRead(); }; +void tms_isr_1() { tms_obj_list[1]->rxRead(); }; +void tms_isr_2() { tms_obj_list[2]->rxRead(); }; +void tms_isr_3() { tms_obj_list[3]->rxRead(); }; +void tms_isr_4() { tms_obj_list[4]->rxRead(); }; +void tms_isr_5() { tms_obj_list[5]->rxRead(); }; // Pin 6 to 11 can not be used -void sws_isr_12() { ObjList[12]->rxRead(); }; -void sws_isr_13() { ObjList[13]->rxRead(); }; -void sws_isr_14() { ObjList[14]->rxRead(); }; -void sws_isr_15() { ObjList[15]->rxRead(); }; +void tms_isr_12() { tms_obj_list[12]->rxRead(); }; +void tms_isr_13() { tms_obj_list[13]->rxRead(); }; +void tms_isr_14() { tms_obj_list[14]->rxRead(); }; +void tms_isr_15() { tms_obj_list[15]->rxRead(); }; #endif // TM_SERIAL_USE_IRAM static void (*ISRList[16])() = { - sws_isr_0, - sws_isr_1, - sws_isr_2, - sws_isr_3, - sws_isr_4, - sws_isr_5, + tms_isr_0, + tms_isr_1, + tms_isr_2, + tms_isr_3, + tms_isr_4, + tms_isr_5, NULL, NULL, NULL, NULL, NULL, NULL, - sws_isr_12, - sws_isr_13, - sws_isr_14, - sws_isr_15 + tms_isr_12, + tms_isr_13, + tms_isr_14, + tms_isr_15 }; TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) @@ -91,7 +91,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin) // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE; pinMode(m_rx_pin, INPUT); - ObjList[m_rx_pin] = this; + tms_obj_list[m_rx_pin] = this; attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING); } if (m_tx_pin > -1) { diff --git a/lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h b/lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h similarity index 100% rename from lib/TasmotaSerial-1.2.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-1.3.0/src/TasmotaSerial.h diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index cadfdfda2..2ce37d699 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -5,6 +5,7 @@ * Fix rule power trigger when no backlog command is used (#2613) * Fix several timer data input and output errors (#2597, #2620) * Fix KNX config error (#2628) + * Fix sensor MHZ-19 vanishing data over time (#2659) * Add Portuguese in Brazil language file * Add rule state test for On/Off in addition to 0/1 (#2613) * Updated Italian language file (#2618) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 4bb42331f..e1d27221b 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -90,6 +90,7 @@ #define D_JSON_PRESSUREATSEALEVEL "SeaPressure" #define D_JSON_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_JSON_PROGRAMSIZE "ProgramSize" +#define D_JSON_RESET "Reset" #define D_JSON_RESTARTING "Restarting" #define D_JSON_RESTARTREASON "RestartReason" #define D_JSON_RSSI "RSSI" diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 4cbf88c9e..52765f4b5 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -24,7 +24,7 @@ /*********************************************************************************************\ * MH-Z19 - CO2 sensor * - * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) + * Adapted from EspEasy plugin P049 by Dmitry (rel22 ___ inbox.ru) ********************************************************************************************** * Filter usage * @@ -64,17 +64,20 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT #define CO2_HIGH 1200 // Above this CO2 value show red light #endif -#define MHZ19_READ_TIMEOUT 500 // Must be way less than 1000 +#define MHZ19_READ_TIMEOUT 400 // Must be way less than 1000 but enough to read 9 bytes at 9600 bps #define MHZ19_RETRY_COUNT 8 TasmotaSerial *MhzSerial; const char kMhzTypes[] PROGMEM = "MHZ19|MHZ19B"; -const uint8_t mhz_cmnd_read_ppm[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; -const uint8_t mhz_cmnd_abc_enable[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6}; -const uint8_t mhz_cmnd_abc_disable[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; -const uint8_t mhz_cmnd_zeropoint[9] = {0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; +enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET }; +const uint8_t kMhzCommands[][2] PROGMEM = { + {0x86,0x00}, // mhz_cmnd_read_ppm + {0x79,0xA0}, // mhz_cmnd_abc_enable + {0x79,0x00}, // mhz_cmnd_abc_disable + {0x87,0x00}, // mhz_cmnd_zeropoint + {0x8D,0x00}}; // mhz_cmnd_reset uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; @@ -84,13 +87,41 @@ bool mhz_abc_must_apply = false; char mhz_types[7]; float mhz_temperature = 0; -uint8_t mhz_timer = 0; uint8_t mhz_retry = MHZ19_RETRY_COUNT; - +uint8_t mhz_received = 0; uint8_t mhz_state = 0; /*********************************************************************************************/ +byte MhzCalculateChecksum(byte *array) +{ + byte checksum = 0; + for (byte i = 1; i < 8; i++) { + checksum += array[i]; + } + checksum = 255 - checksum; + return (checksum +1); +} + +size_t MhzSendCmd(byte command_id) +{ + uint8_t mhz_send[9] = { 0 }; + + mhz_send[0] = 0xFF; // Start byte, fixed + mhz_send[1] = 0x01; // Sensor number, 0x01 by default + memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(kMhzCommands[0])); +/* + mhz_send[4] = 0x00; + mhz_send[5] = 0x00; + mhz_send[6] = 0x00; + mhz_send[7] = 0x00; +*/ + mhz_send[8] = MhzCalculateChecksum(mhz_send); + return MhzSerial->write(mhz_send, sizeof(mhz_send)); +} + +/*********************************************************************************************/ + bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) { if (1 == s) { @@ -126,89 +157,84 @@ bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) return true; } -void Mhz50ms() +void MhzEverySecond() { mhz_state++; - if (4 == mhz_state) { // Every 200 mSec + if (8 == mhz_state) { // Every 8 sec start a MH-Z19 measuring cycle (which takes 1005 +5% ms) mhz_state = 0; - uint8_t mhz_response[9]; - - mhz_timer++; - if (6 == mhz_timer) { // MH-Z19 measuring cycle takes 1005 +5% ms - mhz_timer = 0; - - MhzSerial->flush(); - MhzSerial->write(mhz_cmnd_read_ppm, 9); + if (mhz_retry) { + mhz_retry--; + if (!mhz_retry) { + mhz_last_ppm = 0; + mhz_temperature = 0; + } } - if (1 == mhz_timer) { - if (mhz_retry) { - mhz_retry--; - if (!mhz_retry) { - mhz_last_ppm = 0; - mhz_temperature = 0; - } - } + MhzSerial->flush(); // Sync reception + MhzSendCmd(MHZ_CMND_READPPM); + mhz_received = 0; + } - unsigned long start = millis(); - uint8_t counter = 0; - while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); - } - } + if ((mhz_state > 2) && !mhz_received) { // Start reading response after 3 seconds every second until received + uint8_t mhz_response[9]; - AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); - - if (counter < 9) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); - return; - } - - byte crc = 0; - for (uint8_t i = 1; i < 8; i++) { - crc += mhz_response[i]; - } - crc = 255 - crc; - crc++; - if (mhz_response[8] != crc) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); - return; - } - if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); - return; - } - - uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; - if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 - if (!mhz_abc_enable) { - // After bootup of the sensor the ABC will be enabled. - // Thus only actively disable after bootup. - mhz_abc_must_apply = true; - } + unsigned long start = millis(); + uint8_t counter = 0; + while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { + if (MhzSerial->available() > 0) { + mhz_response[counter++] = MhzSerial->read(); } else { - uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; - mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); - uint8_t s = mhz_response[5]; - mhz_type = (s) ? 1 : 2; - if (MhzCheckAndApplyFilter(ppm, s)) { - mhz_retry = MHZ19_RETRY_COUNT; - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); + delay(5); + } + } - if (0 == s || 64 == s) { // Reading is stable. - if (mhz_abc_must_apply) { - mhz_abc_must_apply = false; - if (mhz_abc_enable) { - MhzSerial->write(mhz_cmnd_abc_enable, 9); // Sent sensor ABC Enable - } else { - MhzSerial->write(mhz_cmnd_abc_disable, 9); // Sent sensor ABC Disable - } + AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + + if (counter < 9) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); + return; + } + + byte crc = MhzCalculateChecksum(mhz_response); + if (mhz_response[8] != crc) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); + return; + } + if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 bad response")); + return; + } + + mhz_received = 1; + + uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; + if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 + if (!mhz_abc_enable) { + // After bootup of the sensor the ABC will be enabled. + // Thus only actively disable after bootup. + mhz_abc_must_apply = true; + } + } else { + uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; + mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); + uint8_t s = mhz_response[5]; + mhz_type = (s) ? 1 : 2; + if (MhzCheckAndApplyFilter(ppm, s)) { + mhz_retry = MHZ19_RETRY_COUNT; + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); + + if (0 == s || 64 == s) { // Reading is stable. + if (mhz_abc_must_apply) { + mhz_abc_must_apply = false; + if (mhz_abc_enable) { + MhzSendCmd(MHZ_CMND_ABCENABLE); + } else { + MhzSendCmd(MHZ_CMND_ABCDISABLE); } } - } + } } @@ -225,6 +251,8 @@ void Mhz50ms() 2 - Manual start = ABC Off 3 - Optional filter settings + + 9 - Reset */ bool MhzCommandSensor() @@ -233,9 +261,13 @@ bool MhzCommandSensor() switch (XdrvMailbox.payload) { case 2: - MhzSerial->write(mhz_cmnd_zeropoint, 9); + MhzSendCmd(MHZ_CMND_ZEROPOINT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); break; + case 9: + MhzSendCmd(MHZ_CMND_RESET); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); + break; default: serviced = false; } @@ -250,7 +282,7 @@ void MhzInit() mhz_type = 0; if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD]); - if (MhzSerial->begin()) { + if (MhzSerial->begin(9600)) { mhz_type = 1; } } @@ -288,8 +320,8 @@ boolean Xsns15(byte function) case FUNC_INIT: MhzInit(); break; - case FUNC_EVERY_50_MSECOND: - Mhz50ms(); + case FUNC_EVERY_SECOND: + MhzEverySecond(); break; case FUNC_COMMAND: if (XSNS_15 == XdrvMailbox.index) { From 016b1dd02964dd9bf1d569dbe13d0e0ec4f856dc Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Wed, 9 May 2018 10:49:43 +0200 Subject: [PATCH 6/7] Optimize command handling Optimize command handling --- sonoff/_releasenotes.ino | 1 + sonoff/sonoff.ino | 14 +++++++------- sonoff/xdrv_00_mqtt.ino | 8 ++++++-- sonoff/xdrv_01_light.ino | 7 ++++++- sonoff/xdrv_02_irremote.ino | 1 + sonoff/xdrv_03_energy.ino | 13 ++++++++----- sonoff/xdrv_04_snfbridge.ino | 8 ++++++-- sonoff/xdrv_05_domoticz.ino | 10 +++++++--- sonoff/xdrv_08_serial_bridge.ino | 10 ++++++---- sonoff/xdrv_09_timers.ino | 7 +++++-- sonoff/xdrv_10_rules.ino | 7 +++++-- 11 files changed, 58 insertions(+), 28 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 2ce37d699..00945950d 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -9,6 +9,7 @@ * Add Portuguese in Brazil language file * Add rule state test for On/Off in addition to 0/1 (#2613) * Updated Italian language file (#2618) + * Optimize command handling * * 5.13.1 20180501 * Fix JSON buffers size too small for execution in some situations (#2580) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5d70e781e..b7b246aa5 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -437,7 +437,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) // AddLog(LOG_LEVEL_DEBUG); int command_code = GetCommandCode(command, sizeof(command), type, kTasmotaCommands); - if (CMND_BACKLOG == command_code) { + if (-1 == command_code) { + if (!XdrvCommand(grpflg, type, index, dataBuf, data_len, payload, payload16)) { + type = NULL; // Unknown command + } + } + else if (CMND_BACKLOG == command_code) { if (data_len) { uint8_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; bl_pointer--; @@ -1065,12 +1070,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) I2cScan(mqtt_data, sizeof(mqtt_data)); } #endif // USE_I2C - else if (XdrvCommand(grpflg, type, index, dataBuf, data_len, payload, payload16)) { - // Serviced - } - else { - type = NULL; - } + else type = NULL; // Unknown command } if (type == NULL) { blinks = 201; diff --git a/sonoff/xdrv_00_mqtt.ino b/sonoff/xdrv_00_mqtt.ino index 8328cef82..d90ae2591 100644 --- a/sonoff/xdrv_00_mqtt.ino +++ b/sonoff/xdrv_00_mqtt.ino @@ -541,7 +541,10 @@ bool MqttCommand() char *dataBuf = XdrvMailbox.data; int command_code = GetCommandCode(command, sizeof(command), type, kMqttCommands); - if (CMND_MQTTHOST == command_code) { + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if (CMND_MQTTHOST == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_host))) { strlcpy(Settings.mqtt_host, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_HOST : dataBuf, sizeof(Settings.mqtt_host)); restart_flag = 2; @@ -740,7 +743,8 @@ bool MqttCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain)); } - else serviced = false; + else serviced = false; // Unknown command + return serviced; } diff --git a/sonoff/xdrv_01_light.ino b/sonoff/xdrv_01_light.ino index 9230c1529..a72ada7f6 100644 --- a/sonoff/xdrv_01_light.ino +++ b/sonoff/xdrv_01_light.ino @@ -1034,7 +1034,10 @@ boolean LightCommand() char option = (1 == XdrvMailbox.data_len) ? XdrvMailbox.data[0] : '\0'; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kLightCommands); - if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { if (XdrvMailbox.data_len > 0) { valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); if (valid_entry) { @@ -1272,9 +1275,11 @@ boolean LightCommand() else { serviced = false; // Unknown command } + if (coldim) { LightPreparePower(); } + return serviced; } diff --git a/sonoff/xdrv_02_irremote.ino b/sonoff/xdrv_02_irremote.ino index 896faa37a..99f4dfed7 100644 --- a/sonoff/xdrv_02_irremote.ino +++ b/sonoff/xdrv_02_irremote.ino @@ -384,6 +384,7 @@ boolean IrSendCommand() } #endif // USE_IR_HVAC else serviced = false; // Unknown command + return serviced; } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 264613429..499162223 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -803,7 +803,10 @@ boolean EnergyCommand() unsigned long nvalue = 0; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kEnergyCommands); - if (CMND_POWERDELTA == command_code) { + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if (CMND_POWERDELTA == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 101)) { Settings.energy_power_delta = (1 == XdrvMailbox.payload) ? DEFAULT_POWER_DELTA : XdrvMailbox.payload; } @@ -1005,16 +1008,16 @@ boolean EnergyCommand() unit = UNIT_HOUR; } #endif // FEATURE_POWER_LIMIT - else { - serviced = false; - } - if (!status_flag) { + else serviced = false; // Unknown command + + if (serviced && !status_flag) { if (Settings.flag.value_units) { snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE_SPACE_UNIT, command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, nvalue); } } + return serviced; } diff --git a/sonoff/xdrv_04_snfbridge.ino b/sonoff/xdrv_04_snfbridge.ino index a17558ca1..20c9fa3d1 100644 --- a/sonoff/xdrv_04_snfbridge.ino +++ b/sonoff/xdrv_04_snfbridge.ino @@ -198,7 +198,10 @@ boolean SonoffBridgeCommand() boolean serviced = true; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kSonoffBridgeCommands); - if ((command_code >= CMND_RFSYNC) && (command_code <= CMND_RFCODE)) { // RfSync, RfLow, RfHigh, RfHost and RfCode + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if ((command_code >= CMND_RFSYNC) && (command_code <= CMND_RFCODE)) { // RfSync, RfLow, RfHigh, RfHost and RfCode char *p; char stemp [10]; uint32_t code = 0; @@ -290,7 +293,8 @@ boolean SonoffBridgeCommand() } else { snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, sonoff_bridge_learn_key, D_JSON_LEARNING_ACTIVE); } - } else serviced = false; + } else serviced = false; // Unknown command + return serviced; } diff --git a/sonoff/xdrv_05_domoticz.ino b/sonoff/xdrv_05_domoticz.ino index 38a979916..bf9ae023e 100644 --- a/sonoff/xdrv_05_domoticz.ino +++ b/sonoff/xdrv_05_domoticz.ino @@ -228,7 +228,10 @@ boolean DomoticzCommand() if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_DOMOTICZ), dmtcz_len)) { // Prefix int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic +dmtcz_len, kDomoticzCommands); - if ((CMND_IDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if ((CMND_IDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; restart_flag = 2; @@ -259,9 +262,10 @@ boolean DomoticzCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s\":%d}"), command, Settings.domoticz_update_timer); } - else serviced = false; + else serviced = false; // Unknown command } - else serviced = false; + else serviced = false; // Unknown command + return serviced; } diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 428dc5e35..455179f98 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -89,7 +89,10 @@ boolean SerialBridgeCommand() boolean serviced = true; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kSerialBridgeCommands); - if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { if (XdrvMailbox.data_len > 0) { if (1 == XdrvMailbox.index) { SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); @@ -114,9 +117,8 @@ boolean SerialBridgeCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, Settings.sbaudrate * 1200); } - else { - serviced = false; // Unknown command - } + else serviced = false; // Unknown command + return serviced; } diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 533ee818e..889a92937 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -345,7 +345,10 @@ boolean TimerCommand() UpperCase(dataBufUc, XdrvMailbox.data); int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kTimerCommands); - if ((CMND_TIMER == command_code) && (index > 0) && (index <= MAX_TIMERS)) { + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if ((CMND_TIMER == command_code) && (index > 0) && (index <= MAX_TIMERS)) { uint8_t error = 0; if (XdrvMailbox.data_len) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_TIMERS)) { @@ -484,7 +487,7 @@ boolean TimerCommand() snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, lbuff); } #endif - else serviced = false; + else serviced = false; // Unknown command return serviced; } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 0690c61b5..fa71d0a12 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -391,7 +391,10 @@ boolean RulesCommand() uint8_t index = XdrvMailbox.index; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kRulesCommands); - if (CMND_RULE == command_code) { + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if (CMND_RULE == command_code) { if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules))) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) { switch (XdrvMailbox.payload) { @@ -447,7 +450,7 @@ boolean RulesCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } - else serviced = false; + else serviced = false; // Unknown command return serviced; } From 0aea9ba572f6494e956ef063004aff0bedc59019 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Wed, 9 May 2018 13:43:22 +0200 Subject: [PATCH 7/7] Add hardware serial option to MHZ-19 Add hardware serial option to MHZ-19 (#2659) --- sonoff/_releasenotes.ino | 1 + sonoff/sonoff.ino | 3 +- sonoff/support.ino | 8 +++++ sonoff/xsns_15_mhz19.ino | 65 +++++++++++++++++++++++++++++++++++----- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 00945950d..2e6c44bf9 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -8,6 +8,7 @@ * Fix sensor MHZ-19 vanishing data over time (#2659) * Add Portuguese in Brazil language file * Add rule state test for On/Off in addition to 0/1 (#2613) + * Add hardware serial option to MHZ-19 sensor (#2659) * Updated Italian language file (#2618) * Optimize command handling * diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b7b246aa5..11c9cb29c 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -100,6 +100,7 @@ const char kTasmotaCommands[] PROGMEM = int baudrate = APP_BAUDRATE; // Serial interface baud rate SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit byte serial_in_byte; // Received byte +uint8_t serial_local = 0; // Handle serial locally; unsigned long serial_polling_window = 0; // Serial polling window int serial_in_byte_counter = 0; // Index in receive buffer byte dual_hex_code = 0; // Sonoff dual input flag @@ -2431,7 +2432,7 @@ void loop() if (millis() >= state_loop_timer) StateLoop(); - SerialInput(); + if (!serial_local) SerialInput(); #ifdef USE_ARDUINO_OTA ArduinoOTA.handle(); diff --git a/sonoff/support.ino b/sonoff/support.ino index 8f18c5a55..1cf6713ab 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -486,6 +486,14 @@ void SetSerialBaudrate(int baudrate) } } +void SetSerialLocal(bool slocal) +{ + serial_local = slocal; + if (slocal) { + SetSeriallog(LOG_LEVEL_NONE); + } +} + uint32_t GetHash(const char *buffer, size_t size) { uint32_t hash = 0; diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 52765f4b5..81069954a 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -91,6 +91,46 @@ uint8_t mhz_retry = MHZ19_RETRY_COUNT; uint8_t mhz_received = 0; uint8_t mhz_state = 0; +uint8_t mhz_hard_serial = 0; + +/*********************************************************************************************/ + +size_t MhzSerialAvailable() +{ + if (mhz_hard_serial) { + return Serial.available(); + } else { + return MhzSerial->available(); + } +} + +void MhzSerialFlush() +{ + if (mhz_hard_serial) { + Serial.flush(); + } else { + MhzSerial->flush(); + } +} + +size_t MhzSerialWrite(byte *array, size_t size) +{ + if (mhz_hard_serial) { + return Serial.write(array, size); + } else { + return MhzSerial->write(array, size); + } +} + +int MhzSerialRead() +{ + if (mhz_hard_serial) { + return Serial.read(); + } else { + return MhzSerial->read(); + } +} + /*********************************************************************************************/ byte MhzCalculateChecksum(byte *array) @@ -117,7 +157,8 @@ size_t MhzSendCmd(byte command_id) mhz_send[7] = 0x00; */ mhz_send[8] = MhzCalculateChecksum(mhz_send); - return MhzSerial->write(mhz_send, sizeof(mhz_send)); + + return MhzSerialWrite(mhz_send, sizeof(mhz_send)); } /*********************************************************************************************/ @@ -160,7 +201,7 @@ bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) void MhzEverySecond() { mhz_state++; - if (8 == mhz_state) { // Every 8 sec start a MH-Z19 measuring cycle (which takes 1005 +5% ms) + if (8 == mhz_state) { // Every 8 sec start a MH-Z19 measuring cycle (which takes 1005 +5% ms) mhz_state = 0; if (mhz_retry) { @@ -171,7 +212,7 @@ void MhzEverySecond() } } - MhzSerial->flush(); // Sync reception + MhzSerialFlush(); // Sync reception MhzSendCmd(MHZ_CMND_READPPM); mhz_received = 0; } @@ -182,8 +223,8 @@ void MhzEverySecond() unsigned long start = millis(); uint8_t counter = 0; while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); + if (MhzSerialAvailable() > 0) { + mhz_response[counter++] = MhzSerialRead(); } else { delay(5); } @@ -281,9 +322,19 @@ void MhzInit() { mhz_type = 0; if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { - MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD]); - if (MhzSerial->begin(9600)) { + if ((1 == pin[GPIO_MHZ_RXD]) && (3 == pin[GPIO_MHZ_TXD])) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MHZ: Hardware serial")); + baudrate = 9600; + SetSerialBaudrate(baudrate); + SetSerialLocal(true); + mhz_hard_serial = 1; mhz_type = 1; + } else { + MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD]); + if (MhzSerial->begin(9600)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MHZ: Software serial")); + mhz_type = 1; + } } } }