mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-09 09:19:51 +03:00
Merge pull request #836 from MichaelDvP/dev
fixes and enhancements #826, #835, #820
This commit is contained in:
@@ -24,13 +24,16 @@
|
||||
- Add more bus-ids [#673](https://github.com/emsesp/EMS-ESP32/issues/673)
|
||||
- Use HA connectivity device class for Status, added boot time [#751](https://github.com/emsesp/EMS-ESP32/issues/751)
|
||||
- Add commands for analog sensors outputs
|
||||
- Support for multiple EMS-ESPs with MQTT and HA [#759](https://github.com/emsesp/EMS-ESP32/issues/759)
|
||||
- Settings for heatpump silent mode and additional heater [#802](https://github.com/emsesp/EMS-ESP32/issues/802)] [[#803](https://github.com/emsesp/EMS-ESP32/issues/803)
|
||||
- Support for multiple EMS-ESPs with MQTT and HA [[#759](https://github.com/emsesp/EMS-ESP32/issues/759)]
|
||||
- Settings for heatpump silent mode and additional heater [[#802](https://github.com/emsesp/EMS-ESP32/issues/802)] [[#803](https://github.com/emsesp/EMS-ESP32/issues/803)]
|
||||
- Zone module MZ100 [#826](https://github.com/emsesp/EMS-ESP32/issues/826)
|
||||
- Default MQTT hostname is blank [#829](https://github.com/emsesp/EMS-ESP32/issues/829)
|
||||
|
||||
## Fixed
|
||||
|
||||
- Factory Reset not working [#628](https://github.com/emsesp/EMS-ESP32/issues/628)
|
||||
- Valid 4 byte values [#820](https://github.com/emsesp/EMS-ESP32/issues/820)
|
||||
- Commands for multiple thermostats [#826](https://github.com/emsesp/EMS-ESP32/issues/826)
|
||||
|
||||
## Changed
|
||||
|
||||
|
||||
1211
interface/package-lock.json
generated
1211
interface/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-icons": "^4.7.1",
|
||||
"react-router-dom": "^6.6.0",
|
||||
"react-router-dom": "^6.6.1",
|
||||
"react-scripts": "5.0.1",
|
||||
"sockette": "^2.0.6",
|
||||
"typesafe-i18n": "^5.18.0",
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { Translation } from '../i18n-types';
|
||||
/* eslint-disable */
|
||||
|
||||
const de: Translation = {
|
||||
// ...en as Translation,
|
||||
LANGUAGE: 'Sprache',
|
||||
RETRY: 'Neuer Versuch',
|
||||
LOADING: 'Laden',
|
||||
@@ -205,7 +204,7 @@ const de: Translation = {
|
||||
FLASH: 'Flash Speicher (Größe / Geschwindigkeit)',
|
||||
APPSIZE: 'Programm (Genutzt / Frei)',
|
||||
FILESYSTEM: 'Dateisystem (Genutzt / Frei)',
|
||||
BUFFER_SIZE: 'Puffergröße',
|
||||
BUFFER_SIZE: 'max. Puffergröße',
|
||||
COMPACT: 'Kompakte Darstellung',
|
||||
ENABLE_OTA: 'OTA Updates verwenden',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Herunterladen der individuellen Entitätsanpassungen',
|
||||
|
||||
@@ -204,7 +204,7 @@ const en: Translation = {
|
||||
FLASH: 'Flash Chip (Size / Speed)',
|
||||
APPSIZE: 'Application (Used / Free)',
|
||||
FILESYSTEM: 'File System (Used / Free)',
|
||||
BUFFER_SIZE: 'Buffer Size',
|
||||
BUFFER_SIZE: 'Max Buffer Size',
|
||||
COMPACT: 'Compact',
|
||||
ENABLE_OTA: 'Enable OTA Updates',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Download the entity customizations',
|
||||
|
||||
@@ -204,7 +204,7 @@ const fr: Translation = {
|
||||
FLASH: 'Flash Chip (Taille / Vitesse)',
|
||||
APPSIZE: 'Application (Utilisée / Libre)',
|
||||
FILESYSTEM: 'File System (Utilisée / Libre)',
|
||||
BUFFER_SIZE: 'Taille du buffer',
|
||||
BUFFER_SIZE: 'Max taille du buffer',
|
||||
COMPACT: 'Compact',
|
||||
ENABLE_OTA: 'Activer les updates OTA',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Télécharger les personnalisations d\'entités',
|
||||
|
||||
@@ -204,7 +204,7 @@ const nl: Translation = {
|
||||
FLASH: 'Flash Chip (Size / Speed)',
|
||||
APPSIZE: 'Application (Used / Free)',
|
||||
FILESYSTEM: 'File System (Used / Free)',
|
||||
BUFFER_SIZE: 'Buffer Size',
|
||||
BUFFER_SIZE: 'Max Buffer Size',
|
||||
COMPACT: 'Compact',
|
||||
ENABLE_OTA: 'Acitveer OTA Updates',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Download alle custom instellingen',
|
||||
|
||||
@@ -204,7 +204,7 @@ const no: Translation = {
|
||||
FLASH: 'Flash Chip (Størrelse / Hastighet)',
|
||||
APPSIZE: 'Applikasjon (Brukt / Ledig)',
|
||||
FILESYSTEM: 'File System (Brukt / Ledig)',
|
||||
BUFFER_SIZE: 'Buffer Størrelse',
|
||||
BUFFER_SIZE: 'Max Buffer Størrelse',
|
||||
COMPACT: 'Komprimere',
|
||||
ENABLE_OTA: 'Aktiviser OTA oppdateringer',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Last ned objektstilpasninger',
|
||||
|
||||
@@ -204,7 +204,7 @@ const pl: BaseTranslation = {
|
||||
FLASH: 'Flash (rozmiar / taktowanie)',
|
||||
APPSIZE: 'Aplikacja (wykorzystane / wolne)',
|
||||
FILESYSTEM: 'System plików (wykorzystane / wolne)',
|
||||
BUFFER_SIZE: 'Rozmiar bufora',
|
||||
BUFFER_SIZE: 'maksymalny rozmiar bufora',
|
||||
COMPACT: 'Kompaktowy',
|
||||
ENABLE_OTA: 'Aktywuj aktualizacje OTA',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Pobierz personalizacje',
|
||||
|
||||
@@ -204,7 +204,7 @@ const se: Translation = {
|
||||
FLASH: 'Flashminne (Storlek / Hastighet)',
|
||||
APPSIZE: 'Applikationer (Använt / Ledigt)',
|
||||
FILESYSTEM: 'Filsystem (Använt / Ledigt)',
|
||||
BUFFER_SIZE: 'Bufferstorlek',
|
||||
BUFFER_SIZE: 'Max Bufferstorlek',
|
||||
COMPACT: 'Komprimera',
|
||||
ENABLE_OTA: 'Aktivera OTA-uppdateringar',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Ladda ner entitetsanpassningar',
|
||||
|
||||
@@ -249,10 +249,11 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
||||
uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * value, const bool is_admin, const int8_t id, JsonObject & output) {
|
||||
uint8_t return_code = CommandRet::OK;
|
||||
|
||||
auto dname = EMSdevice::device_type_2_device_name(device_type);
|
||||
auto dname = EMSdevice::device_type_2_device_name(device_type);
|
||||
uint8_t device_id = EMSESP::device_id_from_cmd(device_type, id, cmd);
|
||||
|
||||
// see if there is a command registered
|
||||
auto cf = find_command(device_type, cmd);
|
||||
auto cf = find_command(device_type, device_id, cmd);
|
||||
|
||||
// check if its a call to and end-point to a device
|
||||
// except for system commands as this is a special device without any queryable entities (device values)
|
||||
@@ -287,7 +288,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
||||
LOG_DEBUG(("%sCalling command %s"), ro.c_str(), info_s);
|
||||
} else {
|
||||
if (id > 0) {
|
||||
LOG_DEBUG(("%sCalling command %s with value %s and id %d"), ro.c_str(), info_s, value, id);
|
||||
LOG_DEBUG(("%sCalling command %s with value %s and id %d on device 0x%02X"), ro.c_str(), info_s, value, id, device_id);
|
||||
} else {
|
||||
LOG_DEBUG(("%sCalling command %s with value %s"), ro.c_str(), info_s, value);
|
||||
}
|
||||
@@ -300,7 +301,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
||||
|
||||
// check if read-only. This also checks for valid tags (e.g. heating circuits)
|
||||
if (cf->cmdfunction_) {
|
||||
if (EMSESP::cmd_is_readonly(device_type, cmd, id)) {
|
||||
if (EMSESP::cmd_is_readonly(device_type, device_id, cmd, id)) {
|
||||
return_code = CommandRet::INVALID; // readonly or invalid hc
|
||||
} else {
|
||||
return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR;
|
||||
@@ -321,9 +322,9 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
||||
}
|
||||
|
||||
// add a command to the list, which does not return json
|
||||
void Command::add(const uint8_t device_type, const char * cmd, const cmd_function_p cb, const char * const * description, uint8_t flags) {
|
||||
void Command::add(const uint8_t device_type, const uint8_t device_id, const char * cmd, const cmd_function_p cb, const char * const * description, uint8_t flags) {
|
||||
// if the command already exists for that device type don't add it
|
||||
if (find_command(device_type, cmd) != nullptr) {
|
||||
if (find_command(device_type, device_id, cmd) != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -332,28 +333,33 @@ void Command::add(const uint8_t device_type, const char * cmd, const cmd_functio
|
||||
flags |= CommandFlag::HIDDEN;
|
||||
}
|
||||
|
||||
cmdfunctions_.emplace_back(device_type, flags, cmd, cb, nullptr, description); // callback for json is nullptr
|
||||
cmdfunctions_.emplace_back(device_type, device_id, flags, cmd, cb, nullptr, description); // callback for json is nullptr
|
||||
}
|
||||
|
||||
// same for system/dallas/analog devices with device_id 0
|
||||
void Command::add(const uint8_t device_type, const char * cmd, const cmd_function_p cb, const char * const * description, uint8_t flags) {
|
||||
add(device_type, 0, cmd, cb, description, flags);
|
||||
}
|
||||
|
||||
// add a command to the list, which does return a json object as output
|
||||
void Command::add(const uint8_t device_type, const char * cmd, const cmd_json_function_p cb, const char * const * description, uint8_t flags) {
|
||||
// if the command already exists for that device type don't add it
|
||||
if (find_command(device_type, cmd) != nullptr) {
|
||||
if (find_command(device_type, 0, cmd) != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmdfunctions_.emplace_back(device_type, flags, cmd, nullptr, cb, description); // callback for json is included
|
||||
cmdfunctions_.emplace_back(device_type, 0, flags, cmd, nullptr, cb, description); // callback for json is included
|
||||
}
|
||||
|
||||
// see if a command exists for that device type
|
||||
// is not case sensitive
|
||||
Command::CmdFunction * Command::find_command(const uint8_t device_type, const char * cmd) {
|
||||
Command::CmdFunction * Command::find_command(const uint8_t device_type, const uint8_t device_id, const char * cmd) {
|
||||
if ((cmd == nullptr) || (strlen(cmd) == 0) || (cmdfunctions_.empty())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto & cf : cmdfunctions_) {
|
||||
if (Helpers::toLower(cmd) == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type)) {
|
||||
if (Helpers::toLower(cmd) == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type) && (!device_id || cf.device_id_ == device_id)) {
|
||||
return &cf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,19 +55,22 @@ class Command {
|
||||
public:
|
||||
struct CmdFunction {
|
||||
uint8_t device_type_; // DeviceType::
|
||||
uint8_t flags_; // mqtt flags for command subscriptions
|
||||
uint8_t device_id_;
|
||||
uint8_t flags_; // mqtt flags for command subscriptions
|
||||
const char * cmd_;
|
||||
cmd_function_p cmdfunction_;
|
||||
cmd_json_function_p cmdfunction_json_;
|
||||
const char * const * description_;
|
||||
|
||||
CmdFunction(const uint8_t device_type,
|
||||
const uint8_t device_id,
|
||||
const uint8_t flags,
|
||||
const char * cmd,
|
||||
const cmd_function_p cmdfunction,
|
||||
const cmd_json_function_p cmdfunction_json,
|
||||
const char * const * description)
|
||||
: device_type_(device_type)
|
||||
, device_id_(device_id)
|
||||
, flags_(flags)
|
||||
, cmd_(cmd)
|
||||
, cmdfunction_(cmdfunction)
|
||||
@@ -97,6 +100,14 @@ class Command {
|
||||
static uint8_t call(const uint8_t device_type, const char * cmd, const char * value);
|
||||
|
||||
// with normal call back function taking a value and id
|
||||
static void add(const uint8_t device_type,
|
||||
const uint8_t device_id,
|
||||
const char * cmd,
|
||||
const cmd_function_p cb,
|
||||
const char * const * description,
|
||||
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
||||
|
||||
// same for system/dallas/analog devices
|
||||
static void add(const uint8_t device_type,
|
||||
const char * cmd,
|
||||
const cmd_function_p cb,
|
||||
@@ -111,7 +122,7 @@ class Command {
|
||||
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
||||
|
||||
static void show_all(uuid::console::Shell & shell);
|
||||
static Command::CmdFunction * find_command(const uint8_t device_type, const char * cmd);
|
||||
static Command::CmdFunction * find_command(const uint8_t device_type, const uint8_t device_id, const char * cmd);
|
||||
|
||||
static void erase_command(const uint8_t device_type, const char * cmd);
|
||||
static void show(uuid::console::Shell & shell, uint8_t device_type, bool verbose);
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
{159, DeviceType::MIXER, "MM50", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||
{160, DeviceType::MIXER, "MM100", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||
{161, DeviceType::MIXER, "MM200", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||
{193, DeviceType::MIXER, "MZ100", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||
{204, DeviceType::MIXER, "MP100", DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool
|
||||
|
||||
// Heat Pumps - 0x38?
|
||||
|
||||
@@ -214,7 +214,9 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(const ui
|
||||
return heating_circuit;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
LOG_DEBUG("Heating circuit not fond on device 0x%02X", device_id());
|
||||
#endif
|
||||
return nullptr; // not found
|
||||
}
|
||||
|
||||
@@ -3244,7 +3246,9 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
||||
write_command(set_typeid, offset, (uint8_t)(temperature * (float)factor), validate_typeid);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
LOG_DEBUG("temperature mode %d not found", mode);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,6 +273,17 @@ bool EMSdevice::has_tag(const uint8_t tag) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if the device has a command on the with this tag.
|
||||
bool EMSdevice::has_cmd(const int8_t id, const char * cmd) const {
|
||||
uint8_t tag = DeviceValueTAG::TAG_HC1 + id - 1;
|
||||
for (const auto & dv : devicevalues_) {
|
||||
if ((id < 1 || dv.tag == tag) && dv.has_cmd && strcmp(dv.short_name, cmd) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// list of registered device entries
|
||||
// called from the command 'entities'
|
||||
void EMSdevice::list_device_entries(JsonObject & output) const {
|
||||
@@ -507,7 +518,7 @@ void EMSdevice::add_device_value(uint8_t tag,
|
||||
}
|
||||
|
||||
// add the command to our library
|
||||
Command::add(device_type_, short_name, f, fullname, flags);
|
||||
Command::add(device_type_, device_id_, short_name, f, fullname, flags);
|
||||
}
|
||||
|
||||
// single list of options
|
||||
@@ -802,9 +813,9 @@ void EMSdevice::generate_values_web(JsonObject & output) {
|
||||
} else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
|
||||
obj["v"] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
||||
} else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||
obj["v"] = dv.numeric_operator > 0 ? *(uint32_t *)(dv.value_p) / dv.numeric_operator : *(uint32_t *)(dv.value_p);
|
||||
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
|
||||
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||
obj["v"] = dv.numeric_operator > 0 ? *(uint32_t *)(dv.value_p) / dv.numeric_operator : *(uint32_t *)(dv.value_p);
|
||||
} else {
|
||||
obj["v"] = ""; // must have a value for sorting to work
|
||||
}
|
||||
@@ -912,9 +923,9 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
|
||||
} else if (dv.type == DeviceValueType::USHORT) {
|
||||
obj["v"] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit);
|
||||
} else if (dv.type == DeviceValueType::ULONG) {
|
||||
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||
obj["v"] = dv.numeric_operator > 0 ? *(uint32_t *)(dv.value_p) / dv.numeric_operator : *(uint32_t *)(dv.value_p);
|
||||
} else if (dv.type == DeviceValueType::TIME) {
|
||||
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator);
|
||||
obj["v"] = dv.numeric_operator > 0 ? *(uint32_t *)(dv.value_p) / dv.numeric_operator : *(uint32_t *)(dv.value_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ class EMSdevice {
|
||||
static std::string tag_to_mqtt(uint8_t tag);
|
||||
|
||||
bool has_tag(const uint8_t tag) const;
|
||||
bool has_cmd(const int8_t id, const char * cmd) const;
|
||||
|
||||
inline uint8_t device_id() const {
|
||||
return device_id_;
|
||||
@@ -345,21 +346,25 @@ class EMSdevice {
|
||||
};
|
||||
|
||||
// static device IDs
|
||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER = 0x08; // fixed device_id for Master Boiler/UBA
|
||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER_1 = 0x70; // fixed device_id for 1st. Cascade Boiler/UBA
|
||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER_F = 0x7F; // fixed device_id for last Cascade Boiler/UBA
|
||||
static constexpr uint8_t EMS_DEVICE_ID_AM200 = 0x60; // fixed device_id for alternative Heating AM200
|
||||
static constexpr uint8_t EMS_DEVICE_ID_RS232 = 0x04;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_TERMINAL = 0x0A;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_SERVICEKEY = 0x0B;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_CASCADE = 0x0C;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_EASYCOM = 0x0D;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_CONVERTER = 0x0E;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_CLOCK = 0x0F;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_SWITCH = 0x11; // Switch WM10
|
||||
static constexpr uint8_t EMS_DEVICE_ID_ERROR = 0x12; // Error module WM10
|
||||
static constexpr uint8_t EMS_DEVICE_ID_PUMP = 0x15; // pump module PM10
|
||||
static constexpr uint8_t EMS_DEVICE_ID_MODEM = 0x48;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER = 0x08; // fixed device_id for Master Boiler/UBA
|
||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER_1 = 0x70; // fixed device_id for 1st. Cascade Boiler/UBA
|
||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER_F = 0x7F; // fixed device_id for last Cascade Boiler/UBA
|
||||
static constexpr uint8_t EMS_DEVICE_ID_AM200 = 0x60; // fixed device_id for alternative Heating AM200
|
||||
static constexpr uint8_t EMS_DEVICE_ID_CONTROLLER = 0x09;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_RS232 = 0x04;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_TERMINAL = 0x0A;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_SERVICEKEY = 0x0B;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_CASCADE = 0x0C;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_EASYCOM = 0x0D;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_CONVERTER = 0x0E;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_CLOCK = 0x0F;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_SWITCH = 0x11; // Switch WM10
|
||||
static constexpr uint8_t EMS_DEVICE_ID_ALERT = 0x12; // Error module EM10
|
||||
static constexpr uint8_t EMS_DEVICE_ID_PUMP = 0x15; // Pump module PM10
|
||||
static constexpr uint8_t EMS_DEVICE_ID_MODEM = 0x48;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_RFSENSOR = 0x40; // RF sensor only sending, no reply
|
||||
static constexpr uint8_t EMS_DEVICE_ID_RFBASE = 0x50;
|
||||
static constexpr uint8_t EMS_DEVICE_ID_ROOMTHERMOSTAT = 0x17; //TADO using this with no version reply
|
||||
|
||||
// generic type IDs
|
||||
static constexpr uint16_t EMS_TYPE_VERSION = 0x02; // type ID for Version information. Generic across all EMS devices.
|
||||
|
||||
@@ -105,15 +105,24 @@ void EMSESP::fetch_device_values_type(const uint8_t device_type) {
|
||||
}
|
||||
}
|
||||
|
||||
bool EMSESP::cmd_is_readonly(const uint8_t device_type, const char * cmd, const int8_t id) {
|
||||
bool EMSESP::cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id) {
|
||||
for (const auto & emsdevice : emsdevices) {
|
||||
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||
if (emsdevice && (emsdevice->device_type() == device_type) && (!device_id || emsdevice->device_id() == device_id)) {
|
||||
return emsdevice->is_readonly(cmd, id);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t EMSESP::device_id_from_cmd(const uint8_t device_type, const int8_t id, const char * cmd) {
|
||||
for (const auto & emsdevice : emsdevices) {
|
||||
if (emsdevice && emsdevice->device_type() == device_type && emsdevice->has_cmd(id, cmd)) {
|
||||
return emsdevice->device_id();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clears list of recognized devices
|
||||
void EMSESP::clear_all_devices() {
|
||||
// temporarily removed: clearing the list causes a crash, the associated commands and mqtt should also be removed.
|
||||
@@ -983,11 +992,11 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
||||
// empty reply to version, read a generic device from database
|
||||
if (product_id == 0) {
|
||||
// check for known device IDs
|
||||
if (device_id == 0x40) {
|
||||
if (device_id == EMSdevice::EMS_DEVICE_ID_RFSENSOR) {
|
||||
// see: https://github.com/emsesp/EMS-ESP32/issues/103#issuecomment-911717342 and https://github.com/emsesp/EMS-ESP32/issues/624
|
||||
name = "rf room temperature sensor";
|
||||
device_type = DeviceType::THERMOSTAT;
|
||||
} else if (device_id == 0x17) {
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_ROOMTHERMOSTAT) {
|
||||
name = "generic thermostat";
|
||||
device_type = DeviceType::THERMOSTAT;
|
||||
flags = DeviceFlags::EMS_DEVICE_FLAG_RC10 | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE;
|
||||
@@ -1010,7 +1019,11 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONVERTER) {
|
||||
name = "converter"; // generic
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CLOCK) {
|
||||
name = "clock"; // generic
|
||||
name = "clock"; // generic
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONTROLLER) {
|
||||
name = "generic controller";
|
||||
device_type = DeviceType::CONTROLLER;
|
||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) {
|
||||
name = "generic boiler";
|
||||
device_type = DeviceType::BOILER;
|
||||
|
||||
@@ -129,8 +129,9 @@ class EMSESP {
|
||||
static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid);
|
||||
|
||||
static bool device_exists(const uint8_t device_id);
|
||||
static bool cmd_is_readonly(const uint8_t device_type, const char * cmd, const int8_t id);
|
||||
static bool cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id);
|
||||
|
||||
static uint8_t device_id_from_cmd(const uint8_t device_type, const int8_t id, const char * cmd);
|
||||
static uint8_t count_devices(const uint8_t device_type);
|
||||
static uint8_t count_devices();
|
||||
static uint8_t device_index(const uint8_t device_type, const uint8_t unique_id);
|
||||
|
||||
@@ -522,7 +522,7 @@ bool Helpers::hasValue(const uint16_t & value) {
|
||||
}
|
||||
|
||||
bool Helpers::hasValue(const uint32_t & value) {
|
||||
return (value < EMS_VALUE_ULONG_NOTSET);
|
||||
return (value != EMS_VALUE_ULONG_NOTSET && value != EMS_VALUE_ULLONG_NOTSET);
|
||||
}
|
||||
|
||||
// checks if we can convert a char string to an int value
|
||||
|
||||
@@ -1299,17 +1299,18 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
||||
node["pbutton gpio"] = settings.pbutton_gpio;
|
||||
node["led gpio"] = settings.led_gpio;
|
||||
}
|
||||
node["hide led"] = settings.hide_led;
|
||||
node["notoken api"] = settings.notoken_api;
|
||||
node["readonly mode"] = settings.readonly_mode;
|
||||
node["fahrenheit"] = settings.fahrenheit;
|
||||
node["dallas parasite"] = settings.dallas_parasite;
|
||||
node["bool format"] = settings.bool_format;
|
||||
node["bool dashboard"] = settings.bool_dashboard;
|
||||
node["enum format"] = settings.enum_format;
|
||||
node["analog enabled"] = settings.analog_enabled;
|
||||
node["telnet enabled"] = settings.telnet_enabled;
|
||||
node["web log buffer"] = settings.weblog_buffer;
|
||||
node["hide led"] = settings.hide_led;
|
||||
node["notoken api"] = settings.notoken_api;
|
||||
node["readonly mode"] = settings.readonly_mode;
|
||||
node["fahrenheit"] = settings.fahrenheit;
|
||||
node["dallas parasite"] = settings.dallas_parasite;
|
||||
node["bool format"] = settings.bool_format;
|
||||
node["bool dashboard"] = settings.bool_dashboard;
|
||||
node["enum format"] = settings.enum_format;
|
||||
node["analog enabled"] = settings.analog_enabled;
|
||||
node["telnet enabled"] = settings.telnet_enabled;
|
||||
node["max web log buffer"] = settings.weblog_buffer;
|
||||
node["web log buffered"] = EMSESP::webLogService.num_log_messages();
|
||||
});
|
||||
|
||||
// Devices - show EMS devices if we have any
|
||||
|
||||
@@ -46,8 +46,8 @@ static constexpr uint8_t EMS_VALUE_UINT_NOTSET = 0xFF; // for 8-bit uns
|
||||
static constexpr int8_t EMS_VALUE_INT_NOTSET = 0x7F; // for signed 8-bit ints/bytes
|
||||
static constexpr uint16_t EMS_VALUE_USHORT_NOTSET = 0x7D00; // 32000: for 2-byte unsigned shorts
|
||||
static constexpr int16_t EMS_VALUE_SHORT_NOTSET = 0x7D00; // 32000: for 2-byte signed shorts
|
||||
static constexpr uint32_t EMS_VALUE_ULONG_NOTSET = 0x00FFFFFF; // for 3-byte and 4-byte longs
|
||||
// 4 byte value is 21474836 (0x147AE14), we use only the lower one, see https://github.com/emsesp/EMS-ESP32/issues/820
|
||||
static constexpr uint32_t EMS_VALUE_ULONG_NOTSET = 0x00FFFFFF; // for 3-byte longs
|
||||
static constexpr uint32_t EMS_VALUE_ULLONG_NOTSET = 0xFFFFFFFF; // for 4-byte longs
|
||||
|
||||
static constexpr uint8_t EMS_MAX_TELEGRAM_LENGTH = 32; // max length of a complete EMS telegram
|
||||
static constexpr uint8_t EMS_MAX_TELEGRAM_MESSAGE_LENGTH = 27; // max length of message block, assuming EMS1.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define EMSESP_APP_VERSION "3.5.0b12"
|
||||
#define EMSESP_APP_VERSION "3.5.0b13"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
#define EMSESP_PLATFORM "ESP32-C3";
|
||||
|
||||
@@ -215,7 +215,12 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J
|
||||
JsonArray output = response->getRoot();
|
||||
emsdevice->generate_values_web_customization(output);
|
||||
#endif
|
||||
#if defined(EMSESP_DEBUG)
|
||||
size_t length = response->setLength();
|
||||
EMSESP::logger().debug("Customization buffer used: %d", length);
|
||||
#else
|
||||
response->setLength();
|
||||
#endif
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,12 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant &
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
size_t length = response->setLength();
|
||||
EMSESP::logger().debug("Dashboard buffer used: %d", length);
|
||||
#else
|
||||
response->setLength();
|
||||
#endif
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ void WebLogService::begin() {
|
||||
void WebLogService::start() {
|
||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||
maximum_log_messages_ = settings.weblog_buffer;
|
||||
limit_log_messages_ = maximum_log_messages_;
|
||||
compact_ = settings.weblog_compact;
|
||||
uuid::log::Logger::register_handler(this, (uuid::log::Level)settings.weblog_level);
|
||||
});
|
||||
@@ -73,12 +74,19 @@ void WebLogService::log_level(uuid::log::Level level) {
|
||||
uuid::log::Logger::register_handler(this, level);
|
||||
}
|
||||
|
||||
size_t WebLogService::num_log_messages() const {
|
||||
return log_messages_.size();
|
||||
}
|
||||
|
||||
size_t WebLogService::maximum_log_messages() const {
|
||||
return maximum_log_messages_;
|
||||
}
|
||||
|
||||
void WebLogService::maximum_log_messages(size_t count) {
|
||||
maximum_log_messages_ = std::max((size_t)1, count);
|
||||
if (limit_log_messages_ > maximum_log_messages_) {
|
||||
limit_log_messages_ = maximum_log_messages_;
|
||||
}
|
||||
while (log_messages_.size() > maximum_log_messages_) {
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
@@ -111,12 +119,14 @@ WebLogService::QueuedLogMessage::QueuedLogMessage(unsigned long id, std::shared_
|
||||
|
||||
void WebLogService::operator<<(std::shared_ptr<uuid::log::Message> message) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (maximum_log_messages_ > 10 && ESP.getMaxAllocHeap() < 41984) {
|
||||
maximum_log_messages(maximum_log_messages_ > 25 ? maximum_log_messages_ - 25 : 10);
|
||||
// EMSESP::logger().warning("Low memory: WebLog buffer reduced to %d entries", maximum_log_messages_);
|
||||
size_t maxAlloc = ESP.getMaxAllocHeap();
|
||||
if (limit_log_messages_ > 5 && maxAlloc < 46080) {
|
||||
--limit_log_messages_;
|
||||
} else if (limit_log_messages_ < maximum_log_messages_ && maxAlloc > 51200) {
|
||||
++limit_log_messages_;
|
||||
}
|
||||
#endif
|
||||
if (log_messages_.size() >= maximum_log_messages_) {
|
||||
while (log_messages_.size() >= limit_log_messages_) {
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ class WebLogService : public uuid::log::Handler {
|
||||
uuid::log::Level log_level() const;
|
||||
void log_level(uuid::log::Level level);
|
||||
size_t maximum_log_messages() const;
|
||||
size_t num_log_messages() const;
|
||||
void maximum_log_messages(size_t count);
|
||||
bool compact() const;
|
||||
void compact(bool compact);
|
||||
@@ -70,6 +71,7 @@ class WebLogService : public uuid::log::Handler {
|
||||
|
||||
uint64_t last_transmit_ = 0; // Last transmit time
|
||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; // Maximum number of log messages to buffer before they are output
|
||||
size_t limit_log_messages_ = MAX_LOG_MESSAGES; // dynamic limit
|
||||
unsigned long log_message_id_ = 0; // The next identifier to use for queued log messages
|
||||
unsigned long log_message_id_tail_ = 0; // last event shown on the screen after fetch
|
||||
std::deque<QueuedLogMessage> log_messages_; // Queued log messages, in the order they were received
|
||||
|
||||
Reference in New Issue
Block a user