diff --git a/CHANGELOG.md b/CHANGELOG.md index 57eb74144..187d8b8d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `boiler flowtemp` command to set the flow temperature [(issue 59)](https://github.com/proddy/EMS-ESP/issues/59) - `tx_delay` setting for circuits where we needed to slow down Tx transmission +### Changed + +- `types` renamed to `devices` to also show all detected devices + + ## [1.6.0] 2019-03-24 ### Added diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index 7cd146e48..57dc3a28e 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -55,6 +55,11 @@ Ticker scanThermostat; #define SCANTHERMOSTAT_TIME 1 uint8_t scanThermostat_count = 0; +// ems bus scan +Ticker scanDevices; +#define SCANDEVICES_TIME 1 +uint8_t scanDevices_count; + Ticker showerColdShotStopTimer; // if using the shower timer, change these settings @@ -107,9 +112,9 @@ command_t PROGMEM project_cmds[] = { {false, "log ", "set logging mode to none, basic, thermostat only, raw or verbose"}, {false, "publish", "publish all values to MQTT"}, {false, "refresh", "fetch values from the EMS devices"}, - {false, "types", "list supported EMS telegram type IDs"}, + {false, "devices", "list all supported and detected EMS devices and types IDs"}, {false, "queue", "show current Tx queue"}, - {false, "autodetect", "detect EMS devices and attempt to automatically set boiler and thermostat types"}, + {false, "autodetect [deep]", "detect EMS devices and attempt to automatically set boiler and thermostat types"}, {false, "shower ", "toggle either timer or alert on/off"}, {false, "send XX ...", "send raw telegram data as hex to EMS bus"}, {false, "thermostat read ", "send read request to the thermostat"}, @@ -814,6 +819,42 @@ void do_regularUpdates() { } } +// stop devices scan and restart all other timers +void stopDeviceScan() { + publishValuesTimer.attach(EMSESP_Status.publish_wait, do_publishValues); // post MQTT EMS values + publishSensorValuesTimer.attach(EMSESP_Status.publish_wait, do_publishSensorValues); // post MQTT sensor values + regularUpdatesTimer.attach(REGULARUPDATES_TIME, do_regularUpdates); // regular reads from the EMS + systemCheckTimer.attach(SYSTEMCHECK_TIME, do_systemCheck); // check if Boiler is online + scanThermostat_count = 0; + scanThermostat.detach(); +} + +// EMS device scan +void do_scanDevices() { + if (scanDevices_count == 0) { + // we're at the finish line + myDebug("Finished a deep EMS device scan. Type 'devices' to see what was discovered"); + stopDeviceScan(); + return; + } + + if ((ems_getBusConnected()) && (!myESP.getUseSerial())) { + myDebug("> Scanning EMS bus for a device type 0x%02X...", scanDevices_count); // TODO: remove debug line + ems_doReadCommand(EMS_TYPE_Version, scanDevices_count++); // ask for version + } +} + +// initiate a force scan by sending a version command to all type ids +void startDeviceScan() { + publishValuesTimer.detach(); + systemCheckTimer.detach(); + regularUpdatesTimer.detach(); + publishSensorValuesTimer.detach(); + scanDevices_count = 1; + myDebug("Starting a deep EMS device scan..."); + scanThermostat.attach(SCANDEVICES_TIME, do_scanDevices); +} + // initiate a force scan by sending type read requests from 0 to FF to the thermostat // used to analyze responses for debugging void startThermostatScan(uint8_t start) { @@ -1126,8 +1167,8 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) { ok = true; } - if (strcmp(first_cmd, "types") == 0) { - ems_printAllTypes(); + if (strcmp(first_cmd, "devices") == 0) { + ems_printAllDevices(); ok = true; } @@ -1137,8 +1178,16 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) { } if (strcmp(first_cmd, "autodetect") == 0) { - ems_scanDevices(); - ok = true; + if (wc == 2) { + char * second_cmd = _readWord(); + if (strcmp(second_cmd, "deep") == 0) { + startDeviceScan(); + ok = true; + } + } else { + ems_scanDevices(); + ok = true; + } } if (strcmp(first_cmd, "startup") == 0) { diff --git a/src/ems.cpp b/src/ems.cpp index 560d5d5ef..b88ae97ca 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -21,6 +21,9 @@ _EMS_Sys_Status EMS_Sys_Status; // EMS Status CircularBuffer<_EMS_TxTelegram, EMS_TX_TELEGRAM_QUEUE_MAX> EMS_TxQueue; // FIFO queue for Tx send buffer +// for storing all detected EMS devices +std::list<_Generic_Type> Devices; + // macros used in the _process* functions #define _toByte(i) (data[i]) #define _toShort(i) ((data[i] << 8) + data[i + 1]) @@ -1311,6 +1314,29 @@ void _process_RCTime(uint8_t src, uint8_t * data, uint8_t length) { EMS_Thermostat.year = _toByte(0); } +/* + * add an EMS device to our list of detected devices + */ +void _addDevice(uint8_t product_id, uint8_t type_id, char * version, const char * model_string) { + _Generic_Type device; + + // if its a duplicate don't add + bool found = false; + for (std::list<_Generic_Type>::iterator it = Devices.begin(); it != Devices.end(); it++) { + if (((it)->product_id == product_id) && ((it)->type_id == type_id)) { + found = true; + } + } + + if (!found) { + device.product_id = product_id; + device.type_id = type_id; + strlcpy(device.version, version, sizeof(device.version)); + strlcpy(device.model_string, model_string, sizeof(device.model_string)); + Devices.push_back(device); + } +} + /** * type 0x02 - get the firmware version and type of an EMS device * look up known devices via the product id and setup if not already set @@ -1344,6 +1370,9 @@ void _process_Version(uint8_t src, uint8_t * data, uint8_t length) { product_id, version); + // add to list + _addDevice(product_id, Boiler_Types[i].type_id, version, Boiler_Types[i].model_string); + // if its a boiler set it, unless it already has been set by checking for a productID // it will take the first one found in the list if (((EMS_Boiler.type_id == EMS_ID_NONE) || (EMS_Boiler.type_id == Boiler_Types[i].type_id)) && EMS_Boiler.product_id == EMS_ID_NONE) { @@ -1384,6 +1413,9 @@ void _process_Version(uint8_t src, uint8_t * data, uint8_t length) { version); } + // add to list + _addDevice(product_id, Boiler_Types[i].type_id, version, Thermostat_Types[i].model_string); + // if we don't have a thermostat set, use this one if (((EMS_Thermostat.type_id == EMS_ID_NONE) || (EMS_Thermostat.model_id == EMS_MODEL_NONE) || (EMS_Thermostat.type_id == Thermostat_Types[i].type_id)) @@ -1426,6 +1458,9 @@ void _process_Version(uint8_t src, uint8_t * data, uint8_t length) { product_id, version); + // add to list + _addDevice(product_id, Other_Types[i].type_id, version, Other_Types[i].model_string); + // see if this is a Solar Module SM10 if (Other_Types[i].type_id == EMS_ID_SM10) { EMS_Other.SM10 = true; // we have detected a SM10 @@ -1438,6 +1473,9 @@ void _process_Version(uint8_t src, uint8_t * data, uint8_t length) { } else { myDebug("Unrecognized device found. TypeID 0x%02X, ProductID %d, Version %s", src, product_id, version); + + // add to list + _addDevice(product_id, src, version, "unknown?"); } } @@ -1686,10 +1724,10 @@ void ems_scanDevices() { /** * Print out all handled types */ -void ems_printAllTypes() { +void ems_printAllDevices() { uint8_t i; - myDebug("\nThese %d devices are defined as boiler units:", _Boiler_Types_max); + myDebug("\nThese %d devices are supported as boiler units:", _Boiler_Types_max); for (i = 0; i < _Boiler_Types_max; i++) { myDebug(" %s%s%s (TypeID:0x%02X ProductID:%d)", COLOR_BOLD_ON, @@ -1699,7 +1737,7 @@ void ems_printAllTypes() { Boiler_Types[i].product_id); } - myDebug("\nThese %d devices are defined as other EMS devices:", _Other_Types_max); + myDebug("\nThese %d devices are supported as other known EMS devices:", _Other_Types_max); for (i = 0; i < _Other_Types_max; i++) { myDebug(" %s%s%s (TypeID:0x%02X ProductID:%d)", COLOR_BOLD_ON, @@ -1709,7 +1747,7 @@ void ems_printAllTypes() { Other_Types[i].product_id); } - myDebug("\nThe following telegram type IDs are recognized:"); + myDebug("\nThe following telegram type IDs are supported:"); for (i = 0; i < _EMS_Types_max; i++) { if ((EMS_Types[i].model_id == EMS_MODEL_ALL) || (EMS_Types[i].model_id == EMS_MODEL_UBA)) { myDebug(" type %02X (%s)", EMS_Types[i].type, EMS_Types[i].typeString); @@ -1727,6 +1765,21 @@ void ems_printAllTypes() { (Thermostat_Types[i].read_supported) ? 'y' : 'n', (Thermostat_Types[i].write_supported) ? 'y' : 'n'); } + + if (Devices.size() != 0) { + myDebug("\nThese %d EMS devices were detected on your system:", Devices.size()); + for (std::list<_Generic_Type>::iterator it = Devices.begin(); it != Devices.end(); it++) { + myDebug(" %s%s%s (TypeID:0x%02X ProductID:%d Version:%s)", + COLOR_BOLD_ON, + (it)->model_string, + COLOR_BOLD_OFF, + (it)->type_id, + (it)->product_id, + (it)->version); + } + } + + myDebug(""); // newline } /** diff --git a/src/ems.h b/src/ems.h index c272aea81..4e4be3631 100644 --- a/src/ems.h +++ b/src/ems.h @@ -163,6 +163,13 @@ typedef struct { bool write_supported; } _Thermostat_Type; +typedef struct { + uint8_t product_id; + uint8_t type_id; + char version[10]; + char model_string[50]; +} _Generic_Type; + /* * Telegram package defintions */ @@ -312,7 +319,7 @@ bool ems_getTxCapable(); uint32_t ems_getPollFrequency(); void ems_scanDevices(); -void ems_printAllTypes(); +void ems_printAllDevices(); char * ems_getThermostatDescription(char * buffer); void ems_printTxQueue(); char * ems_getBoilerDescription(char * buffer); diff --git a/src/emsuart.cpp b/src/emsuart.cpp index 480559de0..542539c06 100644 --- a/src/emsuart.cpp +++ b/src/emsuart.cpp @@ -109,8 +109,9 @@ void ICACHE_FLASH_ATTR emsuart_init() { // UCTOE = RX TimeOut enable (default is 1) // UCTOT = RX TimeOut Threshold (7bit) = want this when no more data after 2 characters. (default is 2) // UCFFT = RX FIFO Full Threshold (7 bit) = want this to be 31 for 32 bytes of buffer. (default was 127). + // see https://www.espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf USC1(EMSUART_UART) = 0; // reset config first - USC1(EMSUART_UART) = (31 << UCFFT) | (0x02 << UCTOT) | (1 << UCTOE); // enable interupts + USC1(EMSUART_UART) = (EMS_MAX_TELEGRAM_LENGTH << UCFFT) | (0x02 << UCTOT) | (1 << UCTOE); // enable interupts // set interrupts for triggers USIC(EMSUART_UART) = 0xffff; // clear all interupts diff --git a/src/version.h b/src/version.h index a4f69be39..a2ec016f3 100644 --- a/src/version.h +++ b/src/version.h @@ -6,5 +6,5 @@ #pragma once #define APP_NAME "EMS-ESP" -#define APP_VERSION "1.7.0b5" +#define APP_VERSION "1.7.0b6" #define APP_HOSTNAME "ems-esp"