moved back to std:: containers for esp32

This commit is contained in:
proddy
2021-01-03 18:03:41 +01:00
parent fa040fb2d5
commit 22f5e56622
14 changed files with 498 additions and 257 deletions

View File

@@ -1,8 +1,8 @@
; PlatformIO Project Configuration File for EMS-ESP
[platformio]
default_envs = esp8266
; default_envs = esp32
; default_envs = esp8266
default_envs = esp32
# override any settings with your own local ones in pio_local.ini
extra_configs =
@@ -12,26 +12,23 @@ extra_configs =
[common]
; default platformio compile flags are: -fno-rtti -std=c++11 -Os -mlongcalls -mtext-section-literals -falign-functions=4 -ffunction-sections -fdata-sections -fno-exceptions -Wall
core_build_flags = -Wno-deprecated-declarations
-mtarget-align
-free
-fipa-pta
-Wreturn-type
-DCORE_DEBUG_LEVEL=0
-DNDEBUG
esp8266_build_flags = -free
-mtarget-align
-fipa-pta
-Wreturn-type
-DFP_IN_IROM
-DBEARSSL_SSL_BASIC
-DVTABLES_IN_FLASH
-DPSTR_ALIGN=1 ; remove the 4-bytes alignment for PSTR()
-std=c17
-std=c++17
-std=gnu++17
-std=c17 -std=c++17 -std=gnu++17
debug_flags =
; -D EMSESP_DEBUG
; -D EMSESP_UART_DEBUG
; -D EMSESP_TEST
; -D EMSESP_FORCE_SERIAL
; -D ENABLE_CORS
esp32_build_flags = -DARDUINO_ARCH_ESP32=1
-DESP32=1
-DBOARD_HAS_PSRAM
build_flags =
${common.core_build_flags}
@@ -50,7 +47,17 @@ build_flags =
build_unflags = -Wall
-Wdeprecated-declarations
-std=gnu++11
esp8266_build_unflags = -std=gnu++11
esp32_build_unflags =
debug_flags =
; -D EMSESP_DEBUG
; -D EMSESP_UART_DEBUG
; -D EMSESP_TEST
; -D EMSESP_FORCE_SERIAL
; -D ENABLE_CORS
[env]
framework = arduino
@@ -75,7 +82,8 @@ board = esp12e
platform = espressif8266
board_build.filesystem = littlefs
board_build.f_cpu = 160000000L
build_flags = ${common.build_flags}
build_flags = ${common.build_flags} ${common.esp8266_build_flags}
build_unflags = ${common.build_unflags} ${common.esp8266_build_unflags}
; build for GitHub Actions CI
[env:esp32-ci]
@@ -84,7 +92,8 @@ extra_scripts =
board = esp32dev
platform = espressif32
board_build.partitions = min_spiffs.csv
build_flags = ${common.build_flags}
build_flags = ${common.build_flags} ${common.esp32_build_flags}
build_unflags = ${common.build_unflags} ${common.esp32_build_unflags}
[env:esp8266]
extra_scripts =
@@ -105,8 +114,8 @@ board_build.f_cpu = 160000000L ; 160MHz
; eagle.flash.4m1m.ld = 1019 KB sketch, 1000 KB SPIFFS. 4KB EEPROM, 4KB RFCAL, 12KB WIFI stack, 2052 KB OTA & buffer
; eagle.flash.4m2m.ld = 1019 KB sketch, 2024 KB SPIFFS. 4KB EEPROM, 4KB RFCAL, 12KB WIFI stack, 1028 KB OTA & buffer
; board_build.ldscript = eagle.flash.4m2m.ld
build_flags = ${common.build_flags} ${common.debug_flags}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${common.esp8266_build_flags} ${common.debug_flags}
build_unflags = ${common.build_unflags} ${common.esp8266_build_unflags}
lib_ignore =
AsyncTCP
@@ -116,6 +125,11 @@ extra_scripts =
scripts/rename_fw.py
board = esp32dev
platform = espressif32
; platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#idf-release/v4.0
; ; toolchain-xtensa32 @ 2.80200.200226
; ; toolchain-xtensa32 @ 5.100200.201223
; toolchain-xtensa32 @ 2.80400.2020 ; c70ec8a-toolchain-xtensa32-linux_x86_64-2.80400.2020.tar.gz
; platform = https://github.com/platformio/platform-espressif32.git
board_build.partitions = min_spiffs.csv ; https://github.com/espressif/arduino-esp32/blob/master/tools/partitions/
build_flags = ${common.build_flags} ${common.debug_flags}
build_flags = ${common.build_flags} ${common.esp32_build_flags} ${common.debug_flags}
build_unflags = ${common.build_unflags} ${common.esp32_build_unflags}

View File

@@ -24,11 +24,15 @@ namespace emsesp {
uuid::log::Logger Command::logger_{F_(command), uuid::log::Facility::DAEMON};
std::vector<Command::CmdFunction> Command::cmdfunctions_;
/*
static emsesp::array<Command::CmdFunction> cmdfunctions_(90, 255, 16); // reserve space for 90 commands
emsesp::array<Command::CmdFunction> * Command::commands() {
return &cmdfunctions_;
}
*/
// calls a command
// id may be used to represent a heating circuit for example
@@ -95,13 +99,15 @@ void Command::add(const uint8_t device_type, const __FlashStringHelper * cmd, cm
return;
}
/*
CmdFunction cf;
cf.cmd_ = cmd;
cf.device_type_ = device_type;
cf.cmdfunction_json_ = nullptr; // empty
cf.cmdfunction_ = cb;
cmdfunctions_.push(cf);
// cmdfunctions_.emplace_back(device_type, cmd, cb, nullptr);
*/
cmdfunctions_.emplace_back(device_type, cmd, cb, nullptr);
// see if we need to subscribe
if (Mqtt::enabled()) {
@@ -116,14 +122,16 @@ void Command::add_with_json(const uint8_t device_type, const __FlashStringHelper
return;
}
/*
CmdFunction cf;
cf.cmd_ = cmd;
cf.device_type_ = device_type;
cf.cmdfunction_json_ = cb;
cf.cmdfunction_ = nullptr; // empty
cmdfunctions_.push(cf);
*/
// cmdfunctions_.emplace_back(device_type, cmd, nullptr, cb); // add command
cmdfunctions_.emplace_back(device_type, cmd, nullptr, cb); // add command
}
// see if a command exists for that device type

View File

@@ -26,7 +26,7 @@
#include <vector>
#include <functional>
#include "containers.h"
// #include "containers.h"
#include "console.h"
@@ -46,9 +46,20 @@ class Command {
const __FlashStringHelper * cmd_;
cmdfunction_p cmdfunction_;
cmdfunction_json_p cmdfunction_json_;
CmdFunction(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_p cmdfunction, cmdfunction_json_p cmdfunction_json)
: device_type_(device_type)
, cmd_(cmd)
, cmdfunction_(cmdfunction)
, cmdfunction_json_(cmdfunction_json) {
}
};
static emsesp::array<Command::CmdFunction> * commands();
static std::vector<CmdFunction> commands() {
return cmdfunctions_;
}
// static emsesp::array<Command::CmdFunction> * commands();
static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json);
static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id);
@@ -63,6 +74,8 @@ class Command {
private:
static uuid::log::Logger logger_;
static std::vector<CmdFunction> cmdfunctions_; // list of commands
};
} // namespace emsesp

View File

@@ -422,7 +422,7 @@ void EMSESPShell::add_console_commands() {
std::vector<std::string> command_list;
uint8_t device_type = EMSdevice::device_name_2_device_type(arguments[0].c_str());
if (Command::device_has_commands(device_type)) {
for (const auto & cf : *Command::commands()) {
for (const auto & cf : Command::commands()) {
if (cf.device_type_ == device_type) {
command_list.emplace_back(uuid::read_flash_string(cf.cmd_));
}

View File

@@ -2067,32 +2067,21 @@ void Thermostat::add_commands() {
// register main device values, top level for all thermostats (non heating circuit)
void Thermostat::register_device_values() {
/*
uint8_t model = this->model();
// Common for all thermostats
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::TEXT,nullptr, F("dateTime"), F("Date/Time"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &errorCode_, DeviceValueType::TEXT,nullptr, F("errorCode"), F("Error code"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &lastCode_, DeviceValueType::TEXT,nullptr, F("lastCode"), F("Last error"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &wwTemp_, DeviceValueType::UINT,nullptr, F("wwTemp"), F("Warm water high temperature"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &wwTempLow_, DeviceValueType::UINT,nullptr, F("wwTempLow"), F("Warm water low temperature"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &wwExtra1_, DeviceValueType::UINT,nullptr, F("wwExtra1"), F("Warm water circuit 1 extra"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &wwExtra2_, DeviceValueType::UINT,nullptr, F("wwExtra2"), F("Warm water circuit 2 extra"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&tempsensor1_,
DeviceValueType::USHORT,
FL_(div10),
F("inttemp1"),
F("Temperature sensor 1"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&tempsensor2_,
DeviceValueType::USHORT,
FL_(div10),
F("inttemp2"),
F("Temperature sensor 2"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::TEXT, nullptr, F("dateTime"), F("Date/Time"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &errorCode_, DeviceValueType::TEXT, nullptr, F("errorCode"), F("Error code"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &lastCode_, DeviceValueType::TEXT, nullptr, F("lastCode"), F("Last error"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &wwTemp_, DeviceValueType::UINT, nullptr, F("wwTemp"), F("Warm water high temperature"), DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_NONE, &wwTempLow_, DeviceValueType::UINT, nullptr, F("wwTempLow"), F("Warm water low temperature"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &wwExtra1_, DeviceValueType::UINT, nullptr, F("wwExtra1"), F("Warm water circuit 1 extra"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &wwExtra2_, DeviceValueType::UINT, nullptr, F("wwExtra2"), F("Warm water circuit 2 extra"), DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_NONE, &tempsensor1_, DeviceValueType::USHORT, FL_(div10), F("inttemp1"), F("Temperature sensor 1"), DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_NONE, &tempsensor2_, DeviceValueType::USHORT, FL_(div10), F("inttemp2"), F("Temperature sensor 2"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaCalIntTemperature_,
DeviceValueType::INT,
@@ -2113,25 +2102,12 @@ void Thermostat::register_device_values() {
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaMainDisplay_,
DeviceValueType::ENUM,
flash_string_vector{F("internal temperature"),
F("internal setpoint"),
F("external temperature"),
F("burner temperature"),
F("WW temperature"),
F("functioning mode"),
F("time"),
F("date"),
F("smoke temperature")},
FL_(enum_ibaMainDisplay),
F("ibaMainDisplay"),
F("Display"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaLanguage_,
DeviceValueType::ENUM,
flash_string_vector{F("German"), F("Dutch"), F("French"), F("Italian")},
F("ibaLanguage"),
F("Language"),
DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_NONE, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), F("ibaLanguage"), F("Language"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaClockOffset_,
DeviceValueType::UINT,
@@ -2146,7 +2122,7 @@ void Thermostat::register_device_values() {
register_device_value(DeviceValueTAG::TAG_NONE,
&floordrystatus_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("start"), F("heat"), F("hold"), F("cool"), F("end")},
FL_(enum_floordrystatus),
F("floordry"),
F("Floor drying"),
DeviceValueUOM::NONE);
@@ -2157,26 +2133,20 @@ void Thermostat::register_device_values() {
F("dampedtemp"),
F("Damped outdoor temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&floordrytemp_,
DeviceValueType::UINT,
nullptr,
F("floordrytemp"),
F("Floor drying temperature"),
DeviceValueUOM::DEGREES);
register_device_value(
DeviceValueTAG::TAG_NONE, &floordrytemp_, DeviceValueType::UINT,nullptr, F("floordrytemp"), F("Floor drying temperature"), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaBuildingType_,
DeviceValueType::ENUM,
flash_string_vector{F(""), F("light"), F("medium"), F("heavy")},
F("building"),
F("Building"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&wwMode_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("low"), F("high"), F("auto"), F("own_prog")},
F("wwmode"),
F("Warm water mode"),
DeviceValueUOM::NONE);
DeviceValueTAG::TAG_NONE, &ibaBuildingType_, DeviceValueType::ENUM, FL_(enum_ibaBuildingType), F("building"), F("Building"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode), F("wwmode"), F("Warm water mode"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&wwCircMode_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("on"), F("auto"), F("own_prog")},
FL_(enum_wwCircMode),
F("wwcircmode"),
F("Warm water circulation mode"),
DeviceValueUOM::NONE);
@@ -2191,41 +2161,30 @@ void Thermostat::register_device_values() {
F("dampedtemp"),
F("Damped outdoor temperature"),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE,
&ibaBuildingType_,
DeviceValueType::ENUM,
flash_string_vector{F("light"), F("medium"), F("heavy")},
F("building"),
F("Building"),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&wwMode_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("on"), F("auto")},
F("wwmode"),
F("Warm water mode"),
DeviceValueUOM::NONE);
register_device_value(
DeviceValueTAG::TAG_NONE, &ibaBuildingType_, DeviceValueType::ENUM, FL_(enum_ibaBuildingType2), F("building"), F("Building"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &wwMode_, DeviceValueType::ENUM, FL_(enum_wwMode2), F("wwmode"), F("Warm water mode"), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE,
&wwCircMode_,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("on"), F("auto")},
FL_(enum_wwCircMode2),
F("wwcircmode"),
F("Warm water circulation mode"),
DeviceValueUOM::NONE);
}
*/
}
// registers the values for a heating circuit
void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::HeatingCircuit> hc) {
/*
uint8_t model = hc->get_model();
// heating circuit
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc->hc_num() - 1;
// different logic on how temperature values are stored, depending on model
flash_string_vector setpoint_temp_divider, curr_temp_divider;
const __FlashStringHelper * const * setpoint_temp_divider;
const __FlashStringHelper * const * curr_temp_divider;
if (model == EMS_DEVICE_FLAG_EASY) {
setpoint_temp_divider = FL_(div100);
curr_temp_divider = FL_(div100);
@@ -2255,132 +2214,79 @@ void Thermostat::register_device_values_hc(std::shared_ptr<emsesp::Thermostat::H
F("HA current room temperature"),
DeviceValueUOM::DEGREES);
} else if (option == Mqtt::HA_Climate_Format::ZERO) {
register_device_value(tag, &zero_value_, DeviceValueType::UINT,nullptr, F("hatemp"), nullptr, DeviceValueUOM::DEGREES);
register_device_value(tag, &zero_value_, DeviceValueType::UINT, nullptr, F("hatemp"), nullptr, DeviceValueUOM::DEGREES);
}
// if we're sending to HA the only valid mode types are heat, auto and off
// manual & day = heat
// night & off = off
// everything else auto
register_device_value(tag,
&hc->mode,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("heat"), F("auto"), F("heat"), F("off"), F("heat"), F("auto"), F("auto"), F("auto"), F("auto")},
F("hamode"),
nullptr,
DeviceValueUOM::NONE);
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_hamode), F("hamode"), nullptr, DeviceValueUOM::NONE);
}
if (model == EMSdevice::EMS_DEVICE_FLAG_RC300 || model == EMSdevice::EMS_DEVICE_FLAG_RC100) {
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, {F("manual"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, {F("eco"), F("comfort")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, {F("2")}, F("ecotemp"), F("Eco temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->manualtemp, DeviceValueType::UINT, {F("2")}, F("manualtemp"), F("Manual temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, {F("2")}, F("comforttemp"), F("Comfort temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT,nullptr, F("summertemp"), F("Summer temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT,nullptr, F("designtemp"), F("Design temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->offsettemp, DeviceValueType::INT,nullptr, F("offsettemp"), F("Offset temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT,nullptr, F("minflowtemp"), F("Min flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT,nullptr, F("maxflowtemp"), F("Max flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT,nullptr, F("roominfluence"), F("Room influence"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT,nullptr, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT,nullptr, F("targetflowtemp"), F("Target flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag,
&hc->heatingtype,
DeviceValueType::ENUM,
{F("off"), F("radiator"), F("convector"), F("floor")},
F("heatingtype"),
F("Heating type"),
DeviceValueUOM::NONE);
register_device_value(tag,
&hc->summer_setmode,
DeviceValueType::ENUM,
flash_string_vector{F("summer"), F("auto"), F("winter")},
F("summermode"),
F("Summer mode"),
DeviceValueUOM::NONE);
register_device_value(tag,
&hc->controlmode,
DeviceValueType::ENUM,
flash_string_vector{F("off"), F("outdoor"), F("simple"), F("MPC"), F("room"), F("power"), F("const.")},
F("controlmode"),
F("Control mode"),
DeviceValueUOM::NONE);
register_device_value(tag, &hc->program, DeviceValueType::UINT,nullptr, F("program"), F("Program"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode), F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype), F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), F("ecotemp"), F("Eco temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->manualtemp, DeviceValueType::UINT, FL_(div2), F("manualtemp"), F("Manual temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), F("comforttemp"), F("Comfort temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, nullptr, F("summertemp"), F("Summer temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, nullptr, F("designtemp"), F("Design temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->offsettemp, DeviceValueType::INT, nullptr, F("offsettemp"), F("Offset temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, F("minflowtemp"), F("Min flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, F("maxflowtemp"), F("Max flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, F("roominfluence"), F("Room influence"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, F("targetflowtemp"), F("Target flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), F("heatingtype"), F("Heating type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->summer_setmode, DeviceValueType::ENUM, FL_(enum_summermode), F("summermode"), F("Summer mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), F("controlmode"), F("Control mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, F("program"), F("Program"), DeviceValueUOM::NONE);
}
if (model == EMS_DEVICE_FLAG_RC20) {
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, flash_string_vector{F("off"), F("manual"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, flash_string_vector{F("day")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype2), F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
}
if (model == EMS_DEVICE_FLAG_RC20_2) {
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, flash_string_vector{F("off"), F("manual"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, flash_string_vector{F("day")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode2), F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype2), F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), F("daytemp"), F("Day temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), F("nighttemp"), F("Night temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->program, DeviceValueType::UINT,nullptr, F("program"), F("Program"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, F("program"), F("Program"), DeviceValueUOM::NONE);
}
if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC30_1) {
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, {F("night"), F("day"), F("auto")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, {F("night"), F("day")}, F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, {F("2")}, F("daytemp"), F("Day temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, {F("2")}, F("nighttemp"), F("Night temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT,nullptr, F("designtemp"), F("Design temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->offsettemp, DeviceValueType::INT, {F("2")}, F("offsettemp"), F("Offset temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->holidaytemp, DeviceValueType::UINT, {F("2")}, F("holidaytemp"), F("Holiday temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT,nullptr, F("targetflowtemp"), F("Target flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT,nullptr, F("summertemp"), F("Summer temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL,nullptr, F("summermode"), F("Summer mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL,nullptr, F("holidaymode"), F("Holiday mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT,nullptr, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT,nullptr, F("roominfluence"), F("Room influence"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT,nullptr, F("minflowtemp"), F("Min flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT,nullptr, F("maxflowtemp"), F("Max flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->flowtempoffset, DeviceValueType::UINT,nullptr, F("flowtempoffset"), F("Flow temperature offset"), DeviceValueUOM::DEGREES);
register_device_value(tag,
&hc->heatingtype,
DeviceValueType::ENUM,
{F("off"), F("radiator"), F("convector"), F("floor")},
F("heatingtype"),
F("Heating type"),
DeviceValueUOM::NONE);
register_device_value(tag,
&hc->reducemode,
DeviceValueType::ENUM,
flash_string_vector{F("nofrost"), F("reduce"), F("room"), F("outdoor")},
F("reducemode"),
F("Reduce mode"),
DeviceValueUOM::NONE);
register_device_value(tag,
&hc->controlmode,
DeviceValueType::ENUM,
flash_string_vector{F("outdoor"), F("room")},
F("controlmode"),
F("Control mode"),
DeviceValueUOM::NONE);
register_device_value(tag, &hc->program, DeviceValueType::UINT,nullptr, F("program"), F("Program"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), F("daytemp"), F("Day temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), F("nighttemp"), F("Night temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, nullptr, F("designtemp"), F("Design temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->offsettemp, DeviceValueType::INT, FL_(div2), F("offsettemp"), F("Offset temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->holidaytemp, DeviceValueType::UINT, FL_(div2), F("holidaytemp"), F("Holiday temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, F("targetflowtemp"), F("Target flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, nullptr, F("summertemp"), F("Summer temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summermode, DeviceValueType::BOOL, nullptr, F("summermode"), F("Summer mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->holidaymode, DeviceValueType::BOOL, nullptr, F("holidaymode"), F("Holiday mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->roominfluence, DeviceValueType::UINT, nullptr, F("roominfluence"), F("Room influence"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->minflowtemp, DeviceValueType::UINT, nullptr, F("minflowtemp"), F("Min flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->maxflowtemp, DeviceValueType::UINT, nullptr, F("maxflowtemp"), F("Max flow temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->flowtempoffset, DeviceValueType::UINT, nullptr, F("flowtempoffset"), F("Flow temperature offset"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->heatingtype, DeviceValueType::ENUM, FL_(enum_heatingtype), F("heatingtype"), F("Heating type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->reducemode, DeviceValueType::ENUM, FL_(enum_reducemode), F("reducemode"), F("Reduce mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode2), F("controlmode"), F("Control mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->program, DeviceValueType::UINT, nullptr, F("program"), F("Program"), DeviceValueUOM::NONE);
}
if (model == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
register_device_value(
tag, &hc->mode, DeviceValueType::ENUM, flash_string_vector{F("manual"), F("auto"), F("holiday")}, F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag,
&hc->modetype,
DeviceValueType::ENUM,
flash_string_vector{F("heat"), F("eco"), F("nofrost")},
F("modetype"),
F("Mode type"),
DeviceValueUOM::NONE);
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode4), F("mode"), F("Mode"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype4), F("modetype"), F("Mode type"), DeviceValueUOM::NONE);
register_device_value(tag, &hc->daytemp, DeviceValueType::UINT, FL_(div2), F("heattemp"), F("Heat temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->nighttemp, DeviceValueType::UINT, FL_(div2), F("ecotemp"), F("Eco temperature"), DeviceValueUOM::DEGREES);
register_device_value(
tag, &hc->nofrosttemp, DeviceValueType::INT, FL_(div2), F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, FL_(div2), F("nofrosttemp"), F("Nofrost temperature"), DeviceValueUOM::DEGREES);
}
*/
}
} // namespace emsesp

View File

@@ -69,6 +69,10 @@ const std::string EMSdevice::tag_to_string(uint8_t tag) {
return uuid::read_flash_string(DeviceValueTAG_s[tag - 1]); // offset by 1 to account for NONE
}
const std::vector<EMSdevice::DeviceValue> EMSdevice::devicevalues() const {
return devicevalues_;
}
std::string EMSdevice::brand_to_string() const {
switch (brand_) {
case EMSdevice::Brand::BOSCH:
@@ -260,7 +264,8 @@ std::string EMSdevice::to_string_short() const {
void EMSdevice::fetch_values() {
EMSESP::logger().debug(F("Fetching values for device ID 0x%02X"), device_id());
for (const auto & tf : *telegram_functions_) {
// for (const auto & tf : *telegram_functions_) {
for (const auto & tf : telegram_functions_) {
if (tf.fetch_) {
read_command(tf.telegram_type_id_);
}
@@ -271,7 +276,8 @@ void EMSdevice::fetch_values() {
void EMSdevice::toggle_fetch(uint16_t telegram_id, bool toggle) {
EMSESP::logger().debug(F("Toggling fetch for device ID 0x%02X, telegram ID 0x%02X to %d"), device_id(), telegram_id, toggle);
for (auto & tf : *telegram_functions_) {
for (auto & tf : telegram_functions_) {
// for (auto & tf : *telegram_functions_) {
if (tf.telegram_type_id_ == telegram_id) {
tf.fetch_ = toggle;
}
@@ -280,7 +286,8 @@ void EMSdevice::toggle_fetch(uint16_t telegram_id, bool toggle) {
// get status of automatic fetch for a telegram id
bool EMSdevice::get_toggle_fetch(uint16_t telegram_id) {
for (auto & tf : *telegram_functions_) {
for (auto & tf : telegram_functions_) {
// for (auto & tf : *telegram_functions_) {
if (tf.telegram_type_id_ == telegram_id) {
return tf.fetch_;
}
@@ -292,7 +299,8 @@ bool EMSdevice::get_toggle_fetch(uint16_t telegram_id) {
void EMSdevice::show_device_values(uuid::console::Shell & shell) {
size_t total_s = 0;
uint8_t count = 0;
for (const auto & dv : *devicevalues_) {
// for (const auto & dv : *devicevalues_) {
for (const auto & dv : devicevalues_) {
size_t s = sizeof(dv);
if (dv.full_name) {
shell.printfln("[%s] %d", uuid::read_flash_string(dv.full_name).c_str(), s);
@@ -309,12 +317,14 @@ void EMSdevice::show_device_values(uuid::console::Shell & shell) {
// list all the telegram type IDs for this device
void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) {
if (telegram_functions_->size() == 0) {
// if (telegram_functions_->size() == 0) {
if (telegram_functions_.size() == 0) {
return;
}
shell.printf(F(" This %s will respond to telegram type IDs: "), device_type_name().c_str());
for (const auto & tf : *telegram_functions_) {
for (const auto & tf : telegram_functions_) {
// for (const auto & tf : *telegram_functions_) {
shell.printf(F("0x%02X "), tf.telegram_type_id_);
}
shell.println();
@@ -322,7 +332,8 @@ void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) {
// list all the telegram type IDs for this device, outputting to a string (max size 200)
char * EMSdevice::show_telegram_handlers(char * result) {
uint8_t size = telegram_functions_->size();
// uint8_t size = telegram_functions_->size();
uint8_t size = telegram_functions_.size();
strlcpy(result, "", 200);
@@ -332,7 +343,8 @@ char * EMSdevice::show_telegram_handlers(char * result) {
char str[10];
uint8_t i = 0;
for (const auto & tf : *telegram_functions_) {
// for (const auto & tf : *telegram_functions_) {
for (const auto & tf : telegram_functions_) {
snprintf_P(str, sizeof(str), PSTR("0x%02X"), tf.telegram_type_id_);
strlcat(result, str, 200);
if (++i < size) {
@@ -359,21 +371,16 @@ void EMSdevice::register_mqtt_cmd(const __FlashStringHelper * cmd, cmdfunction_p
// register a call back function for a specific telegram type
void EMSdevice::register_telegram_type(const uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, process_function_p f) {
/*
TelegramFunction tf;
tf.fetch_ = fetch;
tf.process_function_ = f;
tf.telegram_type_id_ = telegram_type_id;
tf.telegram_type_name_ = telegram_type_name;
telegram_functions_->push(tf);
*/
// TelegramFunction(uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, process_function_p process_function)
// : telegram_type_id_(telegram_type_id)
// , telegram_type_name_(telegram_type_name)
// , fetch_(fetch)
// , process_function_(process_function) {
// }
// telegram_functions_.emplace_back(telegram_type_id, telegram_type_name, fetch, f);
telegram_functions_.emplace_back(telegram_type_id, telegram_type_name, fetch, f);
}
// add to device value library
@@ -410,6 +417,8 @@ void EMSdevice::register_device_value(uint8_t tag,
}
// add to our library
/*
DeviceValue dv;
dv.device_type = device_type_;
dv.tag = tag;
@@ -430,6 +439,18 @@ void EMSdevice::register_device_value(uint8_t tag,
}
devicevalues_->push(dv);
*/
// count #options
uint8_t options_size = 0;
if (options != nullptr) {
uint8_t i = 0;
while (options[i++]) {
options_size++;
};
}
devicevalues_.emplace_back(device_type_, tag, value_p, type, options, options_size, short_name, full_name, uom);
}
// looks up the uom (suffix) for a given key from the device value table
@@ -445,9 +466,12 @@ std::string EMSdevice::get_value_uom(const char * key) {
}
// find the key (p) in the name
// because the new container is not multi-threaded can't use the iterator
for (uint8_t i = 0; i < devicevalues_->size(); i++) {
//
for (const auto & dv : devicevalues_) {
/*
for (uint8_t i = 0; i < devicevalues_->size(); i++) { // because the new container is not multi-threaded can't use the iterator
auto dv = (*devicevalues_)[i];
*/
if (dv.full_name != nullptr) {
if (uuid::read_flash_string(dv.full_name) == p) {
// ignore TIME since "minutes" is already included
@@ -469,8 +493,12 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
JsonArray data = json.createNestedArray("data");
uint8_t num_elements = 0;
for (const auto & dv : devicevalues_) {
/*
for (uint8_t i = 0; i < devicevalues_->size(); i++) {
auto dv = (*devicevalues_)[i];
*/
// for (const auto & dv : devicevalues()) {
// ignore if full_name empty
@@ -479,6 +507,8 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
if ((dv.type == DeviceValueType::BOOL) && Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
// see if we have options for the bool's
if (dv.options_size == 2) {
// if (dv.options_size == 2) {
data.add(*(uint8_t *)(dv.value_p) ? dv.options[0] : dv.options[1]);
} else {
// see how to render the value depending on the setting
@@ -502,6 +532,7 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
// handle ENUMs
else if ((dv.type == DeviceValueType::ENUM) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
// if (*(uint8_t *)(dv.value_p) < dv.options_size) {
if (*(uint8_t *)(dv.value_p) < dv.options_size) {
data.add(dv.options[*(uint8_t *)(dv.value_p)]);
}
@@ -512,7 +543,8 @@ bool EMSdevice::generate_values_json_web(JsonObject & json) {
// If a divider is specified, do the division to 2 decimals places and send back as double/float
// otherwise force as an integer whole
// the nested if's is necessary due to the way the ArduinoJson templates are pre-processed by the compiler
uint8_t divider = ((dv.options_size) == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0;
// uint8_t divider = ((dv.options_size) == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0;
uint8_t divider = (dv.options_size == 1) ? Helpers::atoint(uuid::read_flash_string(dv.options[0]).c_str()) : 0;
// INT
if ((dv.type == DeviceValueType::INT) && Helpers::hasValue(*(int8_t *)(dv.value_p))) {
@@ -589,8 +621,12 @@ bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter
uint8_t old_tag = 255;
JsonObject json = root;
for (const auto & dv : devicevalues_) {
/*
for (uint8_t i = 0; i < devicevalues_->size(); i++) {
auto dv = (*devicevalues_)[i];
*/
// for (const auto & dv : devicevalues()) {
// only show if tag is either empty or matches a value, and don't show if full_name is empty unless we're outputing for mqtt payloads
if (((tag_filter == DeviceValueTAG::TAG_NONE) || (tag_filter == dv.tag)) && (dv.full_name != nullptr || !verbose)) {
@@ -616,6 +652,7 @@ bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter
// handle Booleans (true, false)
if ((dv.type == DeviceValueType::BOOL) && Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) {
// see if we have options for the bool's
// if (dv.options_size == 2) {
if (dv.options_size == 2) {
json[name] = *(uint8_t *)(dv.value_p) ? dv.options[0] : dv.options[1];
has_value = true;
@@ -645,6 +682,7 @@ bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter
// handle ENUMs
else if ((dv.type == DeviceValueType::ENUM) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
// if (*(uint8_t *)(dv.value_p) < dv.options_size) {
if (*(uint8_t *)(dv.value_p) < dv.options_size) {
json[name] = dv.options[*(uint8_t *)(dv.value_p)];
has_value = true;
@@ -715,7 +753,8 @@ bool EMSdevice::generate_values_json(JsonObject & root, const uint8_t tag_filter
// create the Home Assistant configs for each value as a sensor
void EMSdevice::publish_mqtt_ha_sensor() {
for (const auto & dv : *devicevalues_) {
// for (const auto & dv : *devicevalues_) {
for (const auto & dv : devicevalues_) {
Mqtt::register_mqtt_ha_sensor(dv.type, dv.tag, dv.full_name, device_type_, dv.short_name, dv.uom);
}
@@ -733,7 +772,7 @@ std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegr
return read_flash_string(F("UBADevices"));
}
for (const auto & tf : *telegram_functions_) {
for (const auto & tf : telegram_functions_) {
if ((tf.telegram_type_id_ == telegram->type_id) && (telegram->type_id != 0xFF)) {
return uuid::read_flash_string(tf.telegram_type_name_);
}
@@ -745,7 +784,7 @@ std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegr
// take a telegram_type_id and call the matching handler
// return true if match found
bool EMSdevice::handle_telegram(std::shared_ptr<const Telegram> telegram) {
for (const auto & tf : *telegram_functions_) {
for (const auto & tf : telegram_functions_) {
if (tf.telegram_type_id_ == telegram->type_id) {
// if the data block is empty, assume that this telegram is not recognized by the bus master
// so remove it from the automatic fetch list

View File

@@ -23,7 +23,7 @@
#include <vector>
#include <functional>
#include "containers.h"
// #include "containers.h"
#include "emsfactory.h"
#include "telegram.h"
#include "mqtt.h"
@@ -320,13 +320,15 @@ class EMSdevice {
static constexpr uint8_t EMS_DEVICE_FLAG_JUNKERS = 10;
void reserve_device_values(uint8_t elements) {
static auto dv_ = emsesp::array<DeviceValue>(elements, 255, 16);
devicevalues_ = &dv_;
devicevalues_.reserve(elements);
// static auto dv_ = emsesp::array<DeviceValue>(elements, 255, 16);
// devicevalues_ = &dv_;
}
void reserve_telgram_functions(uint8_t elements) {
static auto tf_ = emsesp::array<TelegramFunction>(elements, 255, 16);
telegram_functions_ = &tf_;
telegram_functions_.reserve(elements);
// static auto tf_ = emsesp::array<TelegramFunction>(elements, 255, 16);
// telegram_functions_ = &tf_;
}
private:
@@ -347,8 +349,15 @@ class EMSdevice {
const __FlashStringHelper * telegram_type_name_; // e.g. RC20Message
bool fetch_; // if this type_id be queried automatically
process_function_p process_function_;
TelegramFunction(uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, process_function_p process_function)
: telegram_type_id_(telegram_type_id)
, telegram_type_name_(telegram_type_name)
, fetch_(fetch)
, process_function_(process_function) {
}
};
emsesp::array<TelegramFunction> * telegram_functions_; // each EMS device has its own set of registered telegram types
// emsesp::array<TelegramFunction> * telegram_functions_; // each EMS device has its own set of registered telegram types
struct DeviceValue {
uint8_t device_type; // EMSdevice::DeviceType
@@ -360,8 +369,37 @@ class EMSdevice {
const __FlashStringHelper * short_name; // used in MQTT
const __FlashStringHelper * full_name; // used in Web and Console
uint8_t uom; // DeviceValueUOM::*
DeviceValue(uint8_t device_type,
uint8_t tag,
void * value_p,
uint8_t type,
const __FlashStringHelper * const * options,
uint8_t options_size,
const __FlashStringHelper * short_name,
const __FlashStringHelper * full_name,
uint8_t uom)
: device_type(device_type)
, tag(tag)
, value_p(value_p)
, type(type)
, options(options)
, options_size(options_size)
, short_name(short_name)
, full_name(full_name)
, uom(uom) {
}
};
emsesp::array<DeviceValue> * devicevalues_;
const std::vector<DeviceValue> devicevalues() const;
void init_devicevalues(uint8_t size) {
devicevalues_.reserve(size);
}
std::vector<TelegramFunction> telegram_functions_; // each EMS device has its own set of registered telegram types
// emsesp::array<DeviceValue> * devicevalues_;
std::vector<DeviceValue> devicevalues_;
};
} // namespace emsesp

View File

@@ -40,7 +40,7 @@
#include "WebSettingsService.h"
#include "WebAPIService.h"
#include "containers.h"
// #include "containers.h"
#include "emsdevice.h"
#include "emsfactory.h"
#include "telegram.h"

View File

@@ -138,6 +138,8 @@ MAKE_PSTR_LIST(div10, F_(10))
MAKE_PSTR_LIST(div100, F_(100))
MAKE_PSTR_LIST(div60, F_(60))
// boiler
MAKE_PSTR_WORD(time)
MAKE_PSTR_WORD(date)
MAKE_PSTR_WORD(1x3min)
@@ -157,8 +159,91 @@ MAKE_PSTR_WORD(buffer)
MAKE_PSTR(bufferedflow, "buffered flow")
MAKE_PSTR(layeredbuffer, "layered buffer")
// boiler lists
MAKE_PSTR_LIST(enum_off_time_date, F_(off), F_(time), F_(date))
MAKE_PSTR_LIST(enum_freq, F_(off), F_(1x3min), F_(2x3min), F_(3x3min), F_(4x3min), F_(5x3min), F_(6x3min), F_(continuos))
MAKE_PSTR_LIST(enum_charge, F_(3wayvalve), F_(chargepump))
MAKE_PSTR_LIST(enum_comfort, F_(hot), F_(eco), F_(intelligent))
MAKE_PSTR_LIST(enum_flow, F_(off), F_(flow), F_(bufferedflow), F_(buffer), F_(layeredbuffer))
// thermostat
MAKE_PSTR_WORD(light)
MAKE_PSTR_WORD(medium)
MAKE_PSTR_WORD(heavy)
MAKE_PSTR_WORD(own_prog)
MAKE_PSTR(blank, "")
MAKE_PSTR_WORD(start)
MAKE_PSTR_WORD(heat)
MAKE_PSTR_WORD(hold)
MAKE_PSTR_WORD(cool)
MAKE_PSTR_WORD(end)
MAKE_PSTR_WORD(German)
MAKE_PSTR_WORD(Dutch)
MAKE_PSTR_WORD(French)
MAKE_PSTR_WORD(Italian)
MAKE_PSTR_WORD(high)
MAKE_PSTR_WORD(low)
MAKE_PSTR(internal_temperature, "internal temperature")
MAKE_PSTR(internal_setpoint, "internal setpoint")
MAKE_PSTR(external_temperature, "external temperature")
MAKE_PSTR(burner_temperature, "burner temperature")
MAKE_PSTR(WW_temperature, "WW temperature")
MAKE_PSTR(functioning_mode, "functioning mode")
MAKE_PSTR(smoke_temperature, "smoke temperature")
MAKE_PSTR_WORD(radiator)
MAKE_PSTR_WORD(convector)
MAKE_PSTR_WORD(floor)
MAKE_PSTR_WORD(summer)
MAKE_PSTR_WORD(winter)
MAKE_PSTR_WORD(outdoor)
MAKE_PSTR_WORD(MPC)
MAKE_PSTR_WORD(room)
MAKE_PSTR_WORD(power)
MAKE_PSTR_WORD(constant)
MAKE_PSTR_WORD(simple)
MAKE_PSTR_WORD(nofrost)
MAKE_PSTR_WORD(comfort)
MAKE_PSTR_WORD(manual)
MAKE_PSTR_WORD(night)
MAKE_PSTR_WORD(day)
MAKE_PSTR_WORD(holiday)
MAKE_PSTR_WORD(reduce)
// thermostat lists
MAKE_PSTR_LIST(enum_ibaMainDisplay,
F_(internal_temperature),
F_(internal_setpoint),
F_(external_temperature),
F_(burner_temperature),
F_(WW_temperature),
F_(functioning_mode),
F_(time),
F_(date),
F_(smoke_temperature))
MAKE_PSTR_LIST(enum_ibaLanguage, F_(German), F_(Dutch), F_(French), F_(Italian))
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(blank), F_(light), F_(medium), F_(heavy))
MAKE_PSTR_LIST(enum_wwMode, F_(off), F_(low), F_(high), F_(auto), F_(own_prog))
MAKE_PSTR_LIST(enum_wwCircMode, F_(off), F_(on), F_(auto), F_(own_prog))
MAKE_PSTR_LIST(enum_ibaBuildingType2, F_(light), F_(medium), F_(heavy))
MAKE_PSTR_LIST(enum_wwMode2, F_(off), F_(on), F_(auto))
MAKE_PSTR_LIST(enum_wwCircMode2, F_(off), F_(on), F_(auto))
MAKE_PSTR_LIST(enum_heatingtype, F_(off), F_(radiator), F_(convector), F_(floor))
MAKE_PSTR_LIST(enum_summermode, F_(summer), F_(auto), F_(winter))
MAKE_PSTR_LIST(enum_mode, F_(manual), F_(auto))
MAKE_PSTR_LIST(enum_mode2, F_(off), F_(manual), F_(auto))
MAKE_PSTR_LIST(enum_mode3, F_(night), F_(day), F_(auto))
MAKE_PSTR_LIST(enum_mode4, F_(manual), F_(auto), F_(holiday))
MAKE_PSTR_LIST(enum_modetype, F_(eco), F_(comfort))
MAKE_PSTR_LIST(enum_modetype2, F_(day))
MAKE_PSTR_LIST(enum_modetype3, F_(night), F_(day))
MAKE_PSTR_LIST(enum_modetype4, F_(heat), F_(eco), F_(nofrost))
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(outdoor), F_(simple), F_(MPC), F_(room), F_(power), F_(constant))
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
MAKE_PSTR_LIST(enum_hamode, F_(off), F_(heat), F_(auto), F_(heat), F_(off), F_(heat), F_(auto), F_(auto), F_(auto), F_(auto))

View File

@@ -24,7 +24,6 @@ namespace emsesp {
AsyncMqttClient * Mqtt::mqttClient_;
// static parameters we make global
std::string Mqtt::hostname_;
uint8_t Mqtt::mqtt_qos_;
@@ -40,7 +39,8 @@ uint8_t Mqtt::dallas_format_;
uint8_t Mqtt::ha_climate_format_;
bool Mqtt::ha_enabled_;
static emsesp::queue<Mqtt::QueuedMqttMessage> mqtt_messages_ = emsesp::queue<Mqtt::QueuedMqttMessage>(MAX_MQTT_MESSAGES);
// static emsesp::queue<Mqtt::QueuedMqttMessage> mqtt_messages_ = emsesp::queue<Mqtt::QueuedMqttMessage>(MAX_MQTT_MESSAGES);
std::list<Mqtt::QueuedMqttMessage> Mqtt::mqtt_messages_;
std::vector<Mqtt::MQTTSubFunction> Mqtt::mqtt_subfunctions_;
@@ -547,12 +547,20 @@ std::shared_ptr<const MqttMessage> Mqtt::queue_message(const uint8_t operation,
message = std::make_shared<MqttMessage>(operation, full_topic, payload, retain);
}
// if the queue is full, make room but removing the last one
if (mqtt_messages_.size() >= MAX_MQTT_MESSAGES) {
mqtt_messages_.pop_front();
}
mqtt_messages_.emplace_back(mqtt_message_id_++, std::move(message));
/*
QueuedMqttMessage qmm;
qmm.content_ = std::move(message);
qmm.retry_count_ = 0;
qmm.packet_id_ = 0;
qmm.id_ = mqtt_message_id_++;
mqtt_messages_.push_back(qmm);
*/
return mqtt_messages_.back().content_; // this is because the message has been moved
}
@@ -710,7 +718,8 @@ void Mqtt::process_queue() {
return;
} else {
// update the record
mqtt_messages_.front_p()->retry_count_++;
// mqtt_messages_.front_p()->retry_count_++;
mqtt_messages_.front().retry_count_++;
LOG_DEBUG(F("Failed to publish to %s. Trying again, #%d"), message->topic.c_str(), mqtt_message.retry_count_ + 1);
return; // leave on queue for next time so it gets republished
}
@@ -719,7 +728,8 @@ void Mqtt::process_queue() {
// if we have ACK set with QOS 1 or 2, leave on queue and let the ACK process remove it
// but add the packet_id so we can check it later
if (mqtt_qos_ != 0) {
mqtt_messages_.front_p()->packet_id_ = packet_id;
// mqtt_messages_.front_p()->packet_id_ = packet_id;
mqtt_messages_.front().packet_id_ = packet_id;
#if defined(EMSESP_DEBUG)
LOG_DEBUG(F("[DEBUG] Setting packetID for ACK to %d"), packet_id);
#endif

View File

@@ -183,12 +183,30 @@ class Mqtt {
mqtt_retain_ = mqtt_retain;
}
/*
struct QueuedMqttMessage {
uint16_t id_;
std::shared_ptr<const MqttMessage> content_;
uint8_t retry_count_;
uint16_t packet_id_;
};
*/
struct QueuedMqttMessage {
const uint16_t id_;
const std::shared_ptr<const MqttMessage> content_;
uint8_t retry_count_;
uint16_t packet_id_;
~QueuedMqttMessage() = default;
QueuedMqttMessage(uint16_t id, std::shared_ptr<MqttMessage> && content)
: id_(id)
, content_(std::move(content)) {
retry_count_ = 0;
packet_id_ = 0;
}
};
static std::list<QueuedMqttMessage> mqtt_messages_;
private:
static uuid::log::Logger logger_;
@@ -252,7 +270,7 @@ class Mqtt {
static uint8_t dallas_format_;
static uint8_t ha_climate_format_;
static bool ha_enabled_;
}; // namespace emsesp
};
} // namespace emsesp

View File

@@ -273,7 +273,7 @@ void System::loop() {
send_heartbeat();
}
#if defined(ESP8266)
#ifndef EMSESP_STANDALONE
#if defined(EMSESP_DEBUG)
static uint32_t last_memcheck_ = 0;
if (currentMillis - last_memcheck_ > 5000) { // 5 seconds

View File

@@ -126,11 +126,19 @@ std::string Telegram::to_string_message() const {
// checks if we have an Rx telegram that needs processing
void RxService::loop() {
/*
while (!rx_telegrams_.empty()) {
auto telegram = rx_telegrams_.pop().telegram_;
(void)EMSESP::process_telegram(telegram); // further process the telegram
increment_telegram_count(); // increase rx count
// rx_telegrams_.pop_front(); // remove it from the queue
}
*/
while (!rx_telegrams_.empty()) {
auto telegram = rx_telegrams_.front().telegram_;
(void)EMSESP::process_telegram(telegram); // further process the telegram
increment_telegram_count(); // increase rx count
rx_telegrams_.pop_front(); // remove it from the queue
}
}
@@ -217,10 +225,22 @@ void RxService::add(uint8_t * data, uint8_t length) {
// if we receive a hc2.. telegram from 0x19.. match it to master_thermostat if master is 0x18
src = EMSESP::check_master_device(src, type_id, true);
// create the telegram
auto telegram = std::make_shared<Telegram>(operation, src, dest, type_id, offset, message_data, message_length);
// check if queue is full, if so remove top item to make space
if (rx_telegrams_.size() >= MAX_RX_TELEGRAMS) {
rx_telegrams_.pop_front();
}
rx_telegrams_.emplace_back(rx_telegram_id_++, std::move(telegram)); // add to queue
/*
QueuedRxTelegram qrxt;
qrxt.telegram_ = std::make_shared<Telegram>(operation, src, dest, type_id, offset, message_data, message_length);
qrxt.id_ = rx_telegram_id_++;
rx_telegrams_.push(qrxt);
*/
}
// start and initialize Tx
@@ -264,13 +284,16 @@ void TxService::send() {
return;
}
// get the Telegram, also removes from queue
auto telegram = tx_telegrams_.pop();
// auto telegram = tx_telegrams_.pop(); // get the Telegram, also removes from queue
// if we're in read-only mode (tx_mode 0) forget the Tx call
if (tx_mode() != 0) {
send_telegram(telegram);
// send_telegram(telegram);
send_telegram(tx_telegrams_.front());
}
// auto telegram = tx_telegrams_.pop();
tx_telegrams_.pop_front(); // remove the telegram from the queue
}
// process a Tx telegram
@@ -387,6 +410,32 @@ void TxService::send_telegram(const uint8_t * data, const uint8_t length) {
}
}
void TxService::add(const uint8_t operation,
const uint8_t dest,
const uint16_t type_id,
const uint8_t offset,
uint8_t * message_data,
const uint8_t message_length,
const bool front) {
auto telegram = std::make_shared<Telegram>(operation, ems_bus_id(), dest, type_id, offset, message_data, message_length);
#ifdef EMSESP_DEBUG
LOG_DEBUG(F("[DEBUG] New Tx [#%d] telegram, length %d"), tx_telegram_id_, message_length);
#endif
// if the queue is full, make room but removing the last one
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
tx_telegrams_.pop_front();
}
if (front) {
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram), false); // add to back of queue
} else {
tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false); // add to back of queue
}
}
/*
// builds a Tx telegram and adds to queue
// given some details like the destination, type, offset and message block
void TxService::add(const uint8_t operation,
@@ -411,6 +460,7 @@ void TxService::add(const uint8_t operation,
tx_telegrams_.push_back(qtxt); // add to back of queue
}
}
*/
// builds a Tx telegram and adds to queue
// this is used by the retry() function to put the last failed Tx back into the queue
@@ -467,19 +517,31 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt
EMSESP::set_read_id(type_id);
}
auto telegram = std::make_shared<Telegram>(operation, src, dest, type_id, offset, message_data, message_length); // operation is TX_WRITE or TX_READ
// if the queue is full, make room but removing the last one
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
tx_telegrams_.pop_front();
}
#ifdef EMSESP_DEBUG
LOG_DEBUG(F("[DEBUG] New Tx [#%d] telegram, length %d"), tx_telegram_id_, message_length);
#endif
/*
QueuedTxTelegram qtxt;
qtxt.id_ = tx_telegram_id_++;
qtxt.retry_ = false;
qtxt.telegram_ = std::make_shared<Telegram>(operation, ems_bus_id(), dest, type_id, offset, message_data, message_length);
*/
if (front) {
tx_telegrams_.push_front(qtxt); // add to front of queue
// tx_telegrams_.push_front(qtxt); // add to front of queue
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram), false); // add to back of queue
} else {
tx_telegrams_.push_back(qtxt); // add to back of queue
// tx_telegrams_.push_back(qtxt); // add to back of queue
tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram), false); // add to back of queue
}
}
@@ -554,11 +616,20 @@ void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const ui
Helpers::data_to_hex(data, length).c_str());
#endif
// add to the top of the queue
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
tx_telegrams_.pop_back();
}
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram_last_), true);
/*
QueuedTxTelegram qtxt;
qtxt.id_ = tx_telegram_id_++;
qtxt.retry_ = true; // this time it is a retry
qtxt.telegram_ = telegram_last_;
tx_telegrams_.push_front(qtxt); // add to front of queue
*/
}
uint16_t TxService::read_next_tx() {

View File

@@ -32,7 +32,7 @@
#include <uuid/log.h>
#include "containers.h"
// #include "containers.h"
#include "helpers.h"
#define MAX_RX_TELEGRAMS 10 // size of Rx queue
@@ -230,6 +230,23 @@ class RxService : public EMSbus {
return (q <= EMS_BUS_QUALITY_RX_THRESHOLD ? 100 : 100 - q);
}
struct QueuedRxTelegram {
public:
const uint16_t id_;
const std::shared_ptr<const Telegram> telegram_;
~QueuedRxTelegram() = default;
QueuedRxTelegram(uint16_t id, std::shared_ptr<Telegram> && telegram)
: id_(id)
, telegram_(std::move(telegram)) {
}
};
const std::list<QueuedRxTelegram> queue() const {
return rx_telegrams_;
}
/*
struct QueuedRxTelegram {
uint16_t id_;
std::shared_ptr<const Telegram> telegram_;
@@ -238,6 +255,7 @@ class RxService : public EMSbus {
const emsesp::queue<QueuedRxTelegram> queue() const {
return rx_telegrams_;
}
*/
private:
static constexpr uint8_t EMS_BUS_QUALITY_RX_THRESHOLD = 5; // % threshold before reporting quality issues
@@ -246,7 +264,8 @@ class RxService : public EMSbus {
uint32_t telegram_count_ = 0; // # Rx received
uint32_t telegram_error_count_ = 0; // # Rx CRC errors
std::shared_ptr<const Telegram> rx_telegram; // the incoming Rx telegram
emsesp::queue<QueuedRxTelegram> rx_telegrams_ = emsesp::queue<QueuedRxTelegram>(MAX_RX_TELEGRAMS); // the Rx Queue
std::list<QueuedRxTelegram> rx_telegrams_; // the Rx Queue
// emsesp::queue<QueuedRxTelegram> rx_telegrams_ = emsesp::queue<QueuedRxTelegram>(MAX_RX_TELEGRAMS); // the Rx Queue
};
class TxService : public EMSbus {
@@ -334,6 +353,24 @@ class TxService : public EMSbus {
telegram_write_count_++;
}
struct QueuedTxTelegram {
const uint16_t id_;
const std::shared_ptr<const Telegram> telegram_;
const bool retry_; // true if its a retry
~QueuedTxTelegram() = default;
QueuedTxTelegram(uint16_t id, std::shared_ptr<Telegram> && telegram, bool retry)
: id_(id)
, telegram_(std::move(telegram))
, retry_(retry) {
}
};
const std::list<QueuedTxTelegram> queue() const {
return tx_telegrams_;
}
/*
struct QueuedTxTelegram {
uint16_t id_;
std::shared_ptr<const Telegram> telegram_;
@@ -343,6 +380,7 @@ class TxService : public EMSbus {
const emsesp::queue<QueuedTxTelegram> queue() const {
return tx_telegrams_;
}
*/
#if defined(EMSESP_DEBUG)
static constexpr uint8_t MAXIMUM_TX_RETRIES = 0; // when compiled with EMSESP_DEBUG don't retry
@@ -351,7 +389,8 @@ class TxService : public EMSbus {
#endif
private:
emsesp::queue<QueuedTxTelegram> tx_telegrams_ = emsesp::queue<QueuedTxTelegram>(MAX_TX_TELEGRAMS); // the Tx Queue
std::list<QueuedTxTelegram> tx_telegrams_; // the Tx queue
// emsesp::queue<QueuedTxTelegram> tx_telegrams_ = emsesp::queue<QueuedTxTelegram>(MAX_TX_TELEGRAMS); // the Tx Queue
uint32_t telegram_read_count_ = 0; // # Tx successful reads
uint32_t telegram_write_count_ = 0; // # Tx successful writes