mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
optimize detection of EMS devices
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
// Dallas external temp sensors
|
// Dallas external temp sensors
|
||||||
#include "ds18.h"
|
#include "ds18.h"
|
||||||
DS18 ds18;
|
DS18 ds18;
|
||||||
#define DS18_MQTT_PAYLOAD_MAXSIZE 400
|
#define DS18_MQTT_PAYLOAD_MAXSIZE 600
|
||||||
|
|
||||||
// public libraries
|
// public libraries
|
||||||
#include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson
|
#include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson
|
||||||
@@ -115,7 +115,7 @@ static const command_t project_cmds[] PROGMEM = {
|
|||||||
|
|
||||||
{false, "publish", "publish all values to MQTT"},
|
{false, "publish", "publish all values to MQTT"},
|
||||||
{false, "refresh", "fetch values from the EMS devices"},
|
{false, "refresh", "fetch values from the EMS devices"},
|
||||||
{false, "devices [scan [deep]]", "list, ask Master or perform deep scan of EMS devices"},
|
{false, "devices [scan] | [scan deep] | [save]", "list detected devices, quick scan or deep scan and save as known devices"},
|
||||||
{false, "queue", "show current Tx queue"},
|
{false, "queue", "show current Tx queue"},
|
||||||
{false, "send XX ...", "send raw telegram data to EMS bus (XX are hex values)"},
|
{false, "send XX ...", "send raw telegram data to EMS bus (XX are hex values)"},
|
||||||
{false, "thermostat read <type ID>", "send read request to the thermostat for heating circuit hc 1-4"},
|
{false, "thermostat read <type ID>", "send read request to the thermostat for heating circuit hc 1-4"},
|
||||||
@@ -581,6 +581,7 @@ void publishSensorValues() {
|
|||||||
|
|
||||||
bool hasdata = false;
|
bool hasdata = false;
|
||||||
char buffer[128] = {0}; // temp string buffer
|
char buffer[128] = {0}; // temp string buffer
|
||||||
|
|
||||||
// see if the sensor values have changed, if so send it on
|
// see if the sensor values have changed, if so send it on
|
||||||
for (uint8_t i = 0; i < EMSESP_Settings.dallas_sensors; i++) {
|
for (uint8_t i = 0; i < EMSESP_Settings.dallas_sensors; i++) {
|
||||||
float sensorValue = ds18.getValue(i);
|
float sensorValue = ds18.getValue(i);
|
||||||
@@ -597,12 +598,26 @@ void publishSensorValues() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* test code - https://github.com/proddy/EMS-ESP/issues/326
|
||||||
|
float sensorValue = 23.43;
|
||||||
|
hasdata = true;
|
||||||
|
char sensorID[10]; // sensor{1-n}
|
||||||
|
for (uint8_t i = 0; i < 10; i++) {
|
||||||
|
strlcpy(sensorID, PAYLOAD_EXTERNAL_SENSOR_NUM, sizeof(sensorID));
|
||||||
|
strlcat(sensorID, _int_to_char(buffer, i + 1), sizeof(sensorID));
|
||||||
|
JsonObject dataSensor = sensors.createNestedObject(sensorID);
|
||||||
|
dataSensor[PAYLOAD_EXTERNAL_SENSOR_ID] = "28D45A79A2190310";
|
||||||
|
dataSensor[PAYLOAD_EXTERNAL_SENSOR_TEMP] = sensorValue;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (!hasdata) {
|
if (!hasdata) {
|
||||||
return; // nothing to send
|
return; // nothing to send
|
||||||
}
|
}
|
||||||
|
|
||||||
char data[DS18_MQTT_PAYLOAD_MAXSIZE] = {0};
|
char data[DS18_MQTT_PAYLOAD_MAXSIZE] = {0};
|
||||||
serializeJson(doc, data, sizeof(data));
|
serializeJson(doc, data, sizeof(data));
|
||||||
|
|
||||||
myDebugLog("Publishing external sensor data via MQTT");
|
myDebugLog("Publishing external sensor data via MQTT");
|
||||||
myESP.mqttPublish(TOPIC_EXTERNAL_SENSORS, data);
|
myESP.mqttPublish(TOPIC_EXTERNAL_SENSORS, data);
|
||||||
}
|
}
|
||||||
@@ -1222,7 +1237,7 @@ bool SetListCallback(MYESP_FSACTION_t action, uint8_t wc, const char * setting,
|
|||||||
EMSESP_Settings.master_thermostat = pid;
|
EMSESP_Settings.master_thermostat = pid;
|
||||||
ems_setMasterThermostat(pid);
|
ems_setMasterThermostat(pid);
|
||||||
// force a scan
|
// force a scan
|
||||||
ems_clearDeviceList();
|
Devices.clear(); // init the device map
|
||||||
ems_doReadCommand(EMS_TYPE_UBADevices, EMS_Boiler.device_id);
|
ems_doReadCommand(EMS_TYPE_UBADevices, EMS_Boiler.device_id);
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
@@ -1361,7 +1376,7 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
|
|||||||
// just scan use UBA 0x07 telegram
|
// just scan use UBA 0x07 telegram
|
||||||
myDebug_P(PSTR("Requesting EMS bus master for its device list and scanning for external sensors..."));
|
myDebug_P(PSTR("Requesting EMS bus master for its device list and scanning for external sensors..."));
|
||||||
scanDallas();
|
scanDallas();
|
||||||
ems_clearDeviceList();
|
Devices.clear(); // init the device map
|
||||||
ems_doReadCommand(EMS_TYPE_UBADevices, EMS_Boiler.device_id);
|
ems_doReadCommand(EMS_TYPE_UBADevices, EMS_Boiler.device_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1370,7 +1385,7 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
|
|||||||
char * third_cmd = _readWord();
|
char * third_cmd = _readWord();
|
||||||
if (strcmp(third_cmd, "deep") == 0) {
|
if (strcmp(third_cmd, "deep") == 0) {
|
||||||
myDebug_P(PSTR("Started deep scan of EMS bus for our known devices. This can take up to 10 seconds..."));
|
myDebug_P(PSTR("Started deep scan of EMS bus for our known devices. This can take up to 10 seconds..."));
|
||||||
ems_clearDeviceList();
|
Devices.clear(); // init the device map
|
||||||
ems_scanDevices();
|
ems_scanDevices();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2204,7 +2219,6 @@ void setup() {
|
|||||||
startupEMSscan();
|
startupEMSscan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// enable regular checks to fetch data and publish using Tx (unless listen_mode is enabled)
|
// enable regular checks to fetch data and publish using Tx (unless listen_mode is enabled)
|
||||||
if (!EMSESP_Settings.listen_mode) {
|
if (!EMSESP_Settings.listen_mode) {
|
||||||
regularUpdatesTimer.attach(REGULARUPDATES_TIME, do_regularUpdates); // regular reads from the EMS
|
regularUpdatesTimer.attach(REGULARUPDATES_TIME, do_regularUpdates); // regular reads from the EMS
|
||||||
|
|||||||
93
src/ems.cpp
93
src/ems.cpp
@@ -78,7 +78,7 @@ bool ems_isHT3() {
|
|||||||
|
|
||||||
// init EMS device values, counters and buffers
|
// init EMS device values, counters and buffers
|
||||||
void ems_init() {
|
void ems_init() {
|
||||||
ems_clearDeviceList(); // init the device map
|
Devices.clear(); // init the device map
|
||||||
|
|
||||||
// overall status
|
// overall status
|
||||||
EMS_Sys_Status.emsRxPgks = 0;
|
EMS_Sys_Status.emsRxPgks = 0;
|
||||||
@@ -445,6 +445,10 @@ void ems_setTxMode(uint8_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ems_setEMSbusid(uint8_t id) {
|
void ems_setEMSbusid(uint8_t id) {
|
||||||
|
if ((id != 0x0B) && (id != 0x0A) && (id != 0x0D) && (id != 0x0F) && (id != 0x12)) {
|
||||||
|
id = EMS_BUSID_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
EMS_Sys_Status.emsbusid = id;
|
EMS_Sys_Status.emsbusid = id;
|
||||||
EMS_Sys_Status.emsPollAck[0] = id;
|
EMS_Sys_Status.emsPollAck[0] = id;
|
||||||
}
|
}
|
||||||
@@ -1679,17 +1683,6 @@ void _process_RCTime(_EMS_RxTelegram * EMS_RxTelegram) {
|
|||||||
strlcpy(EMS_Thermostat.datetime, time_sp, sizeof(time_sp)); // store
|
strlcpy(EMS_Thermostat.datetime, time_sp, sizeof(time_sp)); // store
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Clear devices list
|
|
||||||
*/
|
|
||||||
void ems_clearDeviceList() {
|
|
||||||
Devices.clear();
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < EMS_SYS_DEVICEMAP_LENGTH; i++) {
|
|
||||||
EMS_Sys_Status.emsDeviceMap[i] = 0x00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add an EMS device to our list of detected devices if its unique
|
* add an EMS device to our list of detected devices if its unique
|
||||||
* returns true if already in list
|
* returns true if already in list
|
||||||
@@ -1761,35 +1754,41 @@ bool _addDevice(_EMS_DEVICE_TYPE device_type, uint8_t product_id, uint8_t device
|
|||||||
* type 0x07 - shows us the connected EMS devices
|
* type 0x07 - shows us the connected EMS devices
|
||||||
* e.g. 08 00 07 00 0B 80 00 00 00 00 00 00 00 00 00 00 00 (CRC=47) #data=13
|
* e.g. 08 00 07 00 0B 80 00 00 00 00 00 00 00 00 00 00 00 (CRC=47) #data=13
|
||||||
* Junkers has 15 bytes of data
|
* Junkers has 15 bytes of data
|
||||||
|
* each byte is a bitmask for which devices are active
|
||||||
|
* byte 1 = range 0x08 - 0x0F, byte 2=0x10 - 0x17 etc...
|
||||||
*/
|
*/
|
||||||
void _process_UBADevices(_EMS_RxTelegram * EMS_RxTelegram) {
|
void _process_UBADevices(_EMS_RxTelegram * EMS_RxTelegram) {
|
||||||
if (EMS_RxTelegram->data_length > EMS_SYS_DEVICEMAP_LENGTH) {
|
// exit it length is incorrect (13 or 15 bytes long)
|
||||||
return; // should be 13 or 15 bytes long
|
// or didn't come from the boiler
|
||||||
|
// or we can't write to the EMS bus yet
|
||||||
|
if ((EMS_RxTelegram->data_length > EMS_SYS_DEVICEMAP_LENGTH) || (EMS_RxTelegram->src != EMS_ID_BOILER) || (ems_getTxDisabled())) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for each byte, check the bits and determine the device_id
|
||||||
for (uint8_t data_byte = 0; data_byte < EMS_RxTelegram->data_length; data_byte++) {
|
for (uint8_t data_byte = 0; data_byte < EMS_RxTelegram->data_length; data_byte++) {
|
||||||
uint8_t byte = EMS_RxTelegram->data[data_byte];
|
uint8_t byte = EMS_RxTelegram->data[data_byte];
|
||||||
uint8_t saved_byte = EMS_Sys_Status.emsDeviceMap[data_byte];
|
if (byte) {
|
||||||
|
for (uint8_t bit = 0; bit < 8; bit++) {
|
||||||
// see if this matches what we already have stored
|
if (byte & 0x01) {
|
||||||
if (byte != saved_byte) {
|
uint8_t device_id = ((data_byte + 1) * 8) + bit;
|
||||||
// we have something new
|
// ignore ourselves, we're not an EMS device
|
||||||
EMS_Sys_Status.emsDeviceMap[data_byte] = byte; // save new value
|
if ((device_id != EMS_Sys_Status.emsbusid) && (!Devices.empty())) {
|
||||||
// go through all bits
|
// see if we already have this device in our list
|
||||||
// myDebug("Byte #%d 0x%02X", data_byte, byte); // for debugging
|
bool exists = false;
|
||||||
if (byte) {
|
for (std::list<_Detected_Device>::iterator it = Devices.begin(); it != Devices.end(); ++it) {
|
||||||
for (uint8_t bit = 0; bit < 8; bit++) {
|
if (it->device_id == device_id) {
|
||||||
if ((byte & 0x01) && ((saved_byte & 0x01) == 0)) {
|
exists = true;
|
||||||
uint8_t device_id = ((data_byte + 1) * 8) + bit;
|
break;
|
||||||
if (device_id != EMS_Sys_Status.emsbusid) {
|
|
||||||
myDebug("[EMS] Detected new EMS Device with ID 0x%02X. Fetching version information...", device_id);
|
|
||||||
if (!ems_getTxDisabled()) {
|
|
||||||
ems_doReadCommand(EMS_TYPE_Version, device_id); // get version, but ignore ourselves
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!exists) {
|
||||||
|
myDebug("[EMS] Detected new EMS Device with ID 0x%02X. Fetching version information...", device_id);
|
||||||
|
ems_doReadCommand(EMS_TYPE_Version, device_id); // get version, but ignore ourselves
|
||||||
|
}
|
||||||
}
|
}
|
||||||
byte = byte >> 1;
|
// advance 1 bit
|
||||||
saved_byte = saved_byte >> 1;
|
byte = byte >> 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2219,38 +2218,12 @@ char * ems_getDeviceDescription(_EMS_DEVICE_TYPE device_type, char * buffer, boo
|
|||||||
* print out contents of the device list that was captured
|
* print out contents of the device list that was captured
|
||||||
*/
|
*/
|
||||||
void ems_printDevices() {
|
void ems_printDevices() {
|
||||||
char s[100];
|
|
||||||
char buffer[16] = {0};
|
|
||||||
|
|
||||||
strlcpy(s, "These device IDs are on the EMS Bus:", sizeof(s));
|
|
||||||
strlcat(s, COLOR_BOLD_ON, sizeof(s));
|
|
||||||
|
|
||||||
for (uint8_t data_byte = 0; data_byte < EMS_SYS_DEVICEMAP_LENGTH; data_byte++) {
|
|
||||||
uint8_t byte = EMS_Sys_Status.emsDeviceMap[data_byte];
|
|
||||||
if (byte) {
|
|
||||||
// go through all bits
|
|
||||||
for (uint8_t bit = 0; bit < 8; bit++) {
|
|
||||||
if (byte & 0x01) {
|
|
||||||
uint8_t device_id = ((data_byte + 1) * 8) + bit;
|
|
||||||
if (device_id != EMS_Sys_Status.emsbusid) {
|
|
||||||
strlcat(s, " 0x", sizeof(s));
|
|
||||||
strlcat(s, _hextoa(device_id, buffer), sizeof(s));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
byte = byte >> 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strlcat(s, COLOR_BOLD_OFF, sizeof(s));
|
|
||||||
myDebug(s);
|
|
||||||
|
|
||||||
// print out the ones we recognized
|
// print out the ones we recognized
|
||||||
if (!Devices.empty()) {
|
if (!Devices.empty()) {
|
||||||
bool have_unknowns = false;
|
bool have_unknowns = false;
|
||||||
char device_string[100];
|
char device_string[100];
|
||||||
char device_type[30];
|
char device_type[30];
|
||||||
myDebug_P(PSTR("and %d were recognized by EMS-ESP as:"), Devices.size());
|
myDebug_P(PSTR("These %d were recognized by EMS-ESP:"), Devices.size());
|
||||||
for (std::list<_Detected_Device>::iterator it = Devices.begin(); it != Devices.end(); ++it) {
|
for (std::list<_Detected_Device>::iterator it = Devices.begin(); it != Devices.end(); ++it) {
|
||||||
ems_getDeviceTypeName(it->device_type, device_type); // get type string, e.g. "Boiler"
|
ems_getDeviceTypeName(it->device_type, device_type); // get type string, e.g. "Boiler"
|
||||||
if (it->known) {
|
if (it->known) {
|
||||||
|
|||||||
38
src/ems.h
38
src/ems.h
@@ -134,25 +134,24 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
_EMS_RX_STATUS emsRxStatus;
|
_EMS_RX_STATUS emsRxStatus;
|
||||||
_EMS_TX_STATUS emsTxStatus;
|
_EMS_TX_STATUS emsTxStatus;
|
||||||
uint16_t emsRxPgks; // # successfull received
|
uint16_t emsRxPgks; // # successfull received
|
||||||
uint16_t emsTxPkgs; // # successfull sent
|
uint16_t emsTxPkgs; // # successfull sent
|
||||||
uint16_t emxCrcErr; // CRC errors
|
uint16_t emxCrcErr; // CRC errors
|
||||||
bool emsPollEnabled; // flag enable the response to poll messages
|
bool emsPollEnabled; // flag enable the response to poll messages
|
||||||
_EMS_SYS_LOGGING emsLogging; // logging
|
_EMS_SYS_LOGGING emsLogging; // logging
|
||||||
uint16_t emsLogging_ID; // the type or device ID to watch
|
uint16_t emsLogging_ID; // the type or device ID to watch
|
||||||
uint8_t emsRefreshedFlags; // fresh data, needs to be pushed out to MQTT
|
uint8_t emsRefreshedFlags; // fresh data, needs to be pushed out to MQTT
|
||||||
bool emsBusConnected; // is there an active bus
|
bool emsBusConnected; // is there an active bus
|
||||||
uint32_t emsRxTimestamp; // timestamp of last EMS message received
|
uint32_t emsRxTimestamp; // timestamp of last EMS message received
|
||||||
uint32_t emsPollFrequency; // time between EMS polls
|
uint32_t emsPollFrequency; // time between EMS polls
|
||||||
bool emsTxCapable; // able to send via Tx
|
bool emsTxCapable; // able to send via Tx
|
||||||
bool emsTxDisabled; // true to prevent all Tx
|
bool emsTxDisabled; // true to prevent all Tx
|
||||||
uint8_t txRetryCount; // # times the last Tx was re-sent
|
uint8_t txRetryCount; // # times the last Tx was re-sent
|
||||||
uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80
|
uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80
|
||||||
uint8_t emsPollAck[1]; // acknowledge buffer for Poll
|
uint8_t emsPollAck[1]; // acknowledge buffer for Poll
|
||||||
uint8_t emsTxMode; // Tx mode 1, 2 or 3
|
uint8_t emsTxMode; // Tx mode 1, 2 or 3
|
||||||
uint8_t emsbusid; // EMS bus ID, default 0x0B for Service Key
|
uint8_t emsbusid; // EMS bus ID, default 0x0B for Service Key
|
||||||
uint8_t emsMasterThermostat; // product ID for the default thermostat to use
|
uint8_t emsMasterThermostat; // product ID for the default thermostat to use
|
||||||
char emsDeviceMap[EMS_SYS_DEVICEMAP_LENGTH]; // contents of 0x07 telegram with bitmasks for all active EMS devices
|
|
||||||
} _EMS_Sys_Status;
|
} _EMS_Sys_Status;
|
||||||
|
|
||||||
// The Tx send package
|
// The Tx send package
|
||||||
@@ -450,7 +449,6 @@ void ems_printTxQueue();
|
|||||||
void ems_testTelegram(uint8_t test_num);
|
void ems_testTelegram(uint8_t test_num);
|
||||||
void ems_startupTelegrams();
|
void ems_startupTelegrams();
|
||||||
bool ems_checkEMSBUSAlive();
|
bool ems_checkEMSBUSAlive();
|
||||||
void ems_clearDeviceList();
|
|
||||||
void ems_setThermostatTemp(float temperature, uint8_t hc, uint8_t temptype = 0);
|
void ems_setThermostatTemp(float temperature, uint8_t hc, uint8_t temptype = 0);
|
||||||
void ems_setThermostatMode(uint8_t mode, uint8_t hc);
|
void ems_setThermostatMode(uint8_t mode, uint8_t hc);
|
||||||
void ems_setWarmWaterTemp(uint8_t temperature);
|
void ems_setWarmWaterTemp(uint8_t temperature);
|
||||||
|
|||||||
Reference in New Issue
Block a user