mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 08:19:52 +03:00
Merge branch 'dev' into dev
This commit is contained in:
@@ -41,15 +41,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Changed
|
### Changed
|
||||||
- renamed wWCircPumpType to wWChargeType
|
- renamed wWCircPumpType to wWChargeType
|
||||||
- Installation and Configuration notes moved to the official EMS-ESP documentation site
|
- Installation and Configuration notes moved to the official EMS-ESP documentation site
|
||||||
- Removed the _cmd from the MQTT topic names
|
|
||||||
- MQTT sensors topic renamed to sensor_data
|
|
||||||
- `call` commands can be done from the Console root for all devices
|
- `call` commands can be done from the Console root for all devices
|
||||||
- renamed MQTT topic for Solar Module from `sm_data` to `solar_data`
|
|
||||||
- Updated EMS-ESP official documentation (https://emsesp.github.io/docs/#/)
|
- Updated EMS-ESP official documentation (https://emsesp.github.io/docs/#/)
|
||||||
- JWT Secret renamed to Super User Password
|
- JWT Secret renamed to Super User Password
|
||||||
- EMS Devices in Web UI shows button and tooltip to remind users they can click on a device
|
- EMS Devices in Web UI shows button and tooltip to remind users they can click on a device
|
||||||
- MQTT boiler_data payload split into two topics `boiler_data_main` and `boiler_data_ww`
|
- MQTT topic name changes (see doc)
|
||||||
- "sensor" renamed to "dallassensor" as a command. MQTT topic not affected.
|
- Mixing renamed to Mixer
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Console contexts for thermostat and boiler
|
- Console contexts for thermostat and boiler
|
||||||
|
|||||||
6
example_pio_local.ini
Normal file
6
example_pio_local.ini
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[env]
|
||||||
|
upload_protocol = espota
|
||||||
|
upload_flags =
|
||||||
|
--port=8266
|
||||||
|
--auth=ems-esp-neo
|
||||||
|
upload_port = ems-esp.local
|
||||||
@@ -130,7 +130,11 @@ class EMSESPDevicesForm extends Component<
|
|||||||
onClick={() => this.handleRowClick(device.id)}
|
onClick={() => this.handleRowClick(device.id)}
|
||||||
>
|
>
|
||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
<Tooltip title="click for details..." arrow placement="right-end">
|
<Tooltip
|
||||||
|
title="click for details..."
|
||||||
|
arrow
|
||||||
|
placement="right-end"
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<ListIcon />}
|
startIcon={<ListIcon />}
|
||||||
size="small"
|
size="small"
|
||||||
@@ -195,11 +199,9 @@ class EMSESPDevicesForm extends Component<
|
|||||||
{data.sensors.map((sensorData) => (
|
{data.sensors.map((sensorData) => (
|
||||||
<TableRow key={sensorData.no}>
|
<TableRow key={sensorData.no}>
|
||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
Sensor {sensorData.no}
|
{sensorData.no}
|
||||||
</TableCell>
|
|
||||||
<TableCell align="center">
|
|
||||||
{sensorData.id}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
<TableCell align="center">{sensorData.id}</TableCell>
|
||||||
<TableCell align="right">
|
<TableCell align="right">
|
||||||
{formatTemp(sensorData.temp)}
|
{formatTemp(sensorData.temp)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ unsigned long millis() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void delay(unsigned long millis) {
|
void delay(unsigned long millis) {
|
||||||
__millis += millis;
|
// __millis += millis;
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield(void) {
|
void yield(void) {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class DummySettings {
|
|||||||
uint16_t publish_time_boiler = 10;
|
uint16_t publish_time_boiler = 10;
|
||||||
uint16_t publish_time_thermostat = 10;
|
uint16_t publish_time_thermostat = 10;
|
||||||
uint16_t publish_time_solar = 10;
|
uint16_t publish_time_solar = 10;
|
||||||
uint16_t publish_time_mixing = 10;
|
uint16_t publish_time_mixer = 10;
|
||||||
uint16_t publish_time_other = 10;
|
uint16_t publish_time_other = 10;
|
||||||
uint16_t publish_time_sensor = 10;
|
uint16_t publish_time_sensor = 10;
|
||||||
uint8_t bool_format = 1; // on off
|
uint8_t bool_format = 1; // on off
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ void Command::show_devices(uuid::console::Shell & shell) {
|
|||||||
|
|
||||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if ((emsdevice) && (emsdevice->device_type() == device_class.first)) {
|
if ((emsdevice) && (emsdevice->device_type() == device_class.first) && (device_has_commands(device_class.first))) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first).c_str());
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first).c_str());
|
||||||
break; // we only want to show one (not multiple of the same device types)
|
break; // we only want to show one (not multiple of the same device types)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void EMSESPShell::started() {
|
|||||||
|
|
||||||
void EMSESPShell::stopped() {
|
void EMSESPShell::stopped() {
|
||||||
if (has_flags(CommandFlags::ADMIN)) {
|
if (has_flags(CommandFlags::ADMIN)) {
|
||||||
logger().log(LogLevel::INFO, LogFacility::AUTH, F("Admin session closed on console %s"), console_name().c_str());
|
logger().log(LogLevel::INFO, LogFacility::AUTH, F("su session closed on console %s"), console_name().c_str());
|
||||||
}
|
}
|
||||||
logger().log(LogLevel::INFO, LogFacility::CONSOLE, F("User session closed on console %s"), console_name().c_str());
|
logger().log(LogLevel::INFO, LogFacility::CONSOLE, F("User session closed on console %s"), console_name().c_str());
|
||||||
|
|
||||||
@@ -570,7 +570,7 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
flash_string_vector{F_(su)},
|
flash_string_vector{F_(su)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
auto become_admin = [](Shell & shell) {
|
auto become_admin = [](Shell & shell) {
|
||||||
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Admin session opened on console"));
|
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("su session opened on console"));
|
||||||
shell.add_flags(CommandFlags::ADMIN);
|
shell.add_flags(CommandFlags::ADMIN);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -586,7 +586,7 @@ void Console::load_standard_commands(unsigned int context) {
|
|||||||
become_admin(shell);
|
become_admin(shell);
|
||||||
} else {
|
} else {
|
||||||
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
|
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
|
||||||
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Invalid admin password on console"));
|
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Invalid su password on console"));
|
||||||
shell.println(F("su: incorrect password"));
|
shell.println(F("su: incorrect password"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject
|
|||||||
|
|
||||||
// creates JSON doc from values
|
// creates JSON doc from values
|
||||||
// returns false if empty
|
// returns false if empty
|
||||||
// e.g. sensor_data = {"sensor1":{"id":"28-EA41-9497-0E03-5F","temp":23.30},"sensor2":{"id":"28-233D-9497-0C03-8B","temp":24.0}}
|
// e.g. dallassensor_data = {"sensor1":{"id":"28-EA41-9497-0E03-5F","temp":23.30},"sensor2":{"id":"28-233D-9497-0C03-8B","temp":24.0}}
|
||||||
bool DallasSensor::export_values(JsonObject & json) {
|
bool DallasSensor::export_values(JsonObject & json) {
|
||||||
if (sensors_.size() == 0) {
|
if (sensors_.size() == 0) {
|
||||||
return false;
|
return false;
|
||||||
@@ -324,12 +324,12 @@ void DallasSensor::publish_values() {
|
|||||||
char sensorID[10]; // sensor{1-n}
|
char sensorID[10]; // sensor{1-n}
|
||||||
snprintf_P(sensorID, 10, PSTR("sensor%d"), sensor_no);
|
snprintf_P(sensorID, 10, PSTR("sensor%d"), sensor_no);
|
||||||
if (mqtt_format_ == Mqtt::Format::SINGLE) {
|
if (mqtt_format_ == Mqtt::Format::SINGLE) {
|
||||||
// e.g. sensor_data = {"28-EA41-9497-0E03":23.3,"28-233D-9497-0C03":24.0}
|
// e.g. dallassensor_data = {"28-EA41-9497-0E03":23.3,"28-233D-9497-0C03":24.0}
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
doc[sensor.to_string()] = (float)(sensor.temperature_c) / 10;
|
doc[sensor.to_string()] = (float)(sensor.temperature_c) / 10;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// e.g. sensor_data = {"sensor1":{"id":"28-EA41-9497-0E03","temp":23.3},"sensor2":{"id":"28-233D-9497-0C03","temp":24.0}}
|
// e.g. dallassensor_data = {"sensor1":{"id":"28-EA41-9497-0E03","temp":23.3},"sensor2":{"id":"28-233D-9497-0C03","temp":24.0}}
|
||||||
JsonObject dataSensor = doc.createNestedObject(sensorID);
|
JsonObject dataSensor = doc.createNestedObject(sensorID);
|
||||||
dataSensor["id"] = sensor.to_string();
|
dataSensor["id"] = sensor.to_string();
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
@@ -345,7 +345,7 @@ void DallasSensor::publish_values() {
|
|||||||
config["dev_cla"] = F("temperature");
|
config["dev_cla"] = F("temperature");
|
||||||
|
|
||||||
char stat_t[50];
|
char stat_t[50];
|
||||||
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/sensor_data"), System::hostname().c_str());
|
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/dallassensor_data"), System::hostname().c_str());
|
||||||
config["stat_t"] = stat_t;
|
config["stat_t"] = stat_t;
|
||||||
|
|
||||||
config["unit_of_meas"] = F("°C");
|
config["unit_of_meas"] = F("°C");
|
||||||
@@ -376,7 +376,7 @@ void DallasSensor::publish_values() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doc.shrinkToFit();
|
doc.shrinkToFit();
|
||||||
Mqtt::publish(F("sensor_data"), doc.as<JsonObject>());
|
Mqtt::publish(F("dallassensor_data"), doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
|||||||
return read_flash_string(F_(solar));
|
return read_flash_string(F_(solar));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DeviceType::CONNECT:
|
||||||
|
return read_flash_string(F_(connect));
|
||||||
|
break;
|
||||||
|
|
||||||
case DeviceType::MIXER:
|
case DeviceType::MIXER:
|
||||||
return read_flash_string(F_(mixer));
|
return read_flash_string(F_(mixer));
|
||||||
break;
|
break;
|
||||||
@@ -89,8 +93,12 @@ std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
|||||||
return read_flash_string(F_(switch));
|
return read_flash_string(F_(switch));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DeviceType::GATEWAY:
|
||||||
|
return read_flash_string(F_(gateway));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return std::string{};
|
return read_flash_string(F_(unknown));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,55 +129,18 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) {
|
|||||||
return DeviceType::MIXER;
|
return DeviceType::MIXER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp_P(topic, reinterpret_cast<PGM_P>(F_(sensor)))) {
|
if (!strcmp_P(topic, reinterpret_cast<PGM_P>(F_(dallassensor)))) {
|
||||||
return DeviceType::DALLASSENSOR;
|
return DeviceType::DALLASSENSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DeviceType::UNKNOWN;
|
return DeviceType::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return name of the device type, capitalized
|
||||||
std::string EMSdevice::device_type_name() const {
|
std::string EMSdevice::device_type_name() const {
|
||||||
switch (device_type_) {
|
std::string s = device_type_2_device_name(device_type_);
|
||||||
case DeviceType::BOILER:
|
s[0] = toupper(s[0]);
|
||||||
return read_flash_string(F("Boiler"));
|
return s;
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::THERMOSTAT:
|
|
||||||
return read_flash_string(F("Thermostat"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::HEATPUMP:
|
|
||||||
return read_flash_string(F("Heat Pump"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::SOLAR:
|
|
||||||
return read_flash_string(F("Solar"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::CONNECT:
|
|
||||||
return read_flash_string(F("Connect"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::CONTROLLER:
|
|
||||||
return read_flash_string(F("Controller"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::MIXER:
|
|
||||||
return read_flash_string(F("Mixer"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::SWITCH:
|
|
||||||
return read_flash_string(F("Switch"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DeviceType::GATEWAY:
|
|
||||||
return read_flash_string(F("Gateway"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return read_flash_string(F("Unknown"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0=unknown, 1=bosch, 2=junkers, 3=buderus, 4=nefit, 5=sieger, 11=worcester
|
// 0=unknown, 1=bosch, 2=junkers, 3=buderus, 4=nefit, 5=sieger, 11=worcester
|
||||||
|
|||||||
@@ -714,35 +714,14 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
|
|||||||
LOG_DEBUG(F("Adding new device %s (device ID 0x%02X, product ID %d, version %s)"), name.c_str(), device_id, product_id, version.c_str());
|
LOG_DEBUG(F("Adding new device %s (device ID 0x%02X, product ID %d, version %s)"), name.c_str(), device_id, product_id, version.c_str());
|
||||||
fetch_device_values(device_id); // go and fetch its data
|
fetch_device_values(device_id); // go and fetch its data
|
||||||
|
|
||||||
switch (device_p->device_type) {
|
// add info command, but not for all devices
|
||||||
case EMSdevice::DeviceType::BOILER:
|
uint8_t device_type = device_p->device_type;
|
||||||
Command::add_with_json(device_p->device_type, F_(info), [&](const char * value, const int8_t id, JsonObject & json) {
|
if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) {
|
||||||
return command_info(EMSdevice::DeviceType::BOILER, json);
|
return true;
|
||||||
});
|
|
||||||
break;
|
|
||||||
case EMSdevice::DeviceType::MIXER:
|
|
||||||
Command::add_with_json(device_p->device_type, F_(info), [&](const char * value, const int8_t id, JsonObject & json) {
|
|
||||||
return command_info(EMSdevice::DeviceType::MIXER, json);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case EMSdevice::DeviceType::SOLAR:
|
|
||||||
Command::add_with_json(device_p->device_type, F_(info), [&](const char * value, const int8_t id, JsonObject & json) {
|
|
||||||
return command_info(EMSdevice::DeviceType::SOLAR, json);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case EMSdevice::DeviceType::THERMOSTAT:
|
|
||||||
Command::add_with_json(device_p->device_type, F_(info), [&](const char * value, const int8_t id, JsonObject & json) {
|
|
||||||
return command_info(EMSdevice::DeviceType::THERMOSTAT, json);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case EMSdevice::DeviceType::HEATPUMP:
|
|
||||||
Command::add_with_json(device_p->device_type, F_(info), [&](const char * value, const int8_t id, JsonObject & json) {
|
|
||||||
return command_info(EMSdevice::DeviceType::HEATPUMP, json);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
Command::add_with_json(device_type, F_(info), [device_type](const char * value, const int8_t id, JsonObject & json) {
|
||||||
|
return command_info(device_type, json);
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ MAKE_PSTR_WORD(connect)
|
|||||||
MAKE_PSTR_WORD(heatpump)
|
MAKE_PSTR_WORD(heatpump)
|
||||||
MAKE_PSTR_WORD(generic)
|
MAKE_PSTR_WORD(generic)
|
||||||
MAKE_PSTR_WORD(dallassensor)
|
MAKE_PSTR_WORD(dallassensor)
|
||||||
MAKE_PSTR_WORD(sensor)
|
MAKE_PSTR_WORD(unknown)
|
||||||
|
|
||||||
MAKE_PSTR(1space, " ")
|
MAKE_PSTR(1space, " ")
|
||||||
MAKE_PSTR(2spaces, " ")
|
MAKE_PSTR(2spaces, " ")
|
||||||
@@ -269,7 +269,7 @@ MAKE_PSTR(modetype, "Mode type")
|
|||||||
MAKE_PSTR(airHumidity, "Relative air humidity")
|
MAKE_PSTR(airHumidity, "Relative air humidity")
|
||||||
MAKE_PSTR(dewTemperature, "Dew point temperature")
|
MAKE_PSTR(dewTemperature, "Dew point temperature")
|
||||||
|
|
||||||
// HA icons
|
// Home Assistant icons
|
||||||
MAKE_PSTR(icontemperature, "mdi:coolant-temperature")
|
MAKE_PSTR(icontemperature, "mdi:coolant-temperature")
|
||||||
MAKE_PSTR(iconpercent, "mdi:sine-wave")
|
MAKE_PSTR(iconpercent, "mdi:sine-wave")
|
||||||
MAKE_PSTR(iconfire, "mdi:fire")
|
MAKE_PSTR(iconfire, "mdi:fire")
|
||||||
@@ -285,5 +285,4 @@ MAKE_PSTR(iconthermostat, "mdi:home-thermometer-outline")
|
|||||||
MAKE_PSTR(iconheatpump, "mdi:water-pump")
|
MAKE_PSTR(iconheatpump, "mdi:water-pump")
|
||||||
|
|
||||||
// MQTT topic suffix
|
// MQTT topic suffix
|
||||||
// MAKE_PSTR(mqtt_suffix_main, "_main")
|
|
||||||
MAKE_PSTR(mqtt_suffix_ww, "_ww")
|
MAKE_PSTR(mqtt_suffix_ww, "_ww")
|
||||||
|
|||||||
@@ -542,7 +542,7 @@ void System::console_commands(Shell & shell, unsigned int context) {
|
|||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
},
|
},
|
||||||
"local");
|
"local");
|
||||||
shell.println(F("Admin password updated"));
|
shell.println(F("su password updated"));
|
||||||
} else {
|
} else {
|
||||||
shell.println(F("Passwords do not match"));
|
shell.println(F("Passwords do not match"));
|
||||||
}
|
}
|
||||||
@@ -847,7 +847,7 @@ bool System::check_upgrade() {
|
|||||||
// value and id are ignored
|
// value and id are ignored
|
||||||
bool System::command_info(const char * value, const int8_t id, JsonObject & json) {
|
bool System::command_info(const char * value, const int8_t id, JsonObject & json) {
|
||||||
#ifdef EMSESP_STANDALONE
|
#ifdef EMSESP_STANDALONE
|
||||||
json["test"] = "testing info command";
|
json["test"] = "testing system info command";
|
||||||
#else
|
#else
|
||||||
EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & settings) {
|
EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & settings) {
|
||||||
char s[7];
|
char s[7];
|
||||||
|
|||||||
@@ -820,8 +820,11 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EMSESP::rxservice_.ems_mask(EMSbus::EMS_MASK_BUDERUS);
|
EMSESP::rxservice_.ems_mask(EMSbus::EMS_MASK_BUDERUS);
|
||||||
|
|
||||||
std::string version("1.2.3");
|
std::string version("1.2.3");
|
||||||
|
|
||||||
|
// add controller
|
||||||
|
EMSESP::add_device(0x09, 114, version, EMSdevice::Brand::BUDERUS);
|
||||||
|
|
||||||
EMSESP::add_device(0x28, 160, version, EMSdevice::Brand::BUDERUS); // MM100, WWC
|
EMSESP::add_device(0x28, 160, version, EMSdevice::Brand::BUDERUS); // MM100, WWC
|
||||||
EMSESP::add_device(0x29, 161, version, EMSdevice::Brand::BUDERUS); // MM200, WWC
|
EMSESP::add_device(0x29, 161, version, EMSdevice::Brand::BUDERUS); // MM200, WWC
|
||||||
EMSESP::add_device(0x20, 160, version, EMSdevice::Brand::BOSCH); // MM100
|
EMSESP::add_device(0x20, 160, version, EMSdevice::Brand::BOSCH); // MM100
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "2.1.0b11"
|
#define EMSESP_APP_VERSION "2.1.0b12"
|
||||||
|
|||||||
Reference in New Issue
Block a user