Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes and enhancements #826, #835, #820 #836

Merged
merged 16 commits into from
Dec 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CHANGELOG_LATEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1,211 changes: 723 additions & 488 deletions interface/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion interface/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 1 addition & 2 deletions interface/src/i18n/de/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion interface/src/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion interface/src/i18n/fr/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion interface/src/i18n/nl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion interface/src/i18n/no/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion interface/src/i18n/pl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion interface/src/i18n/se/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
28 changes: 17 additions & 11 deletions src/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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;
}
}
Expand Down
15 changes: 13 additions & 2 deletions src/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/device_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
8 changes: 6 additions & 2 deletions src/devices/thermostat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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;
}

Expand Down
21 changes: 16 additions & 5 deletions src/emsdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
35 changes: 20 additions & 15 deletions src/emsdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down Expand Up @@ -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.
Expand Down
Loading