mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-01-29 10:09:11 +03:00
Merge pull request #473 from MichaelDvP/dev
Fix #467 and master thermostat check
This commit is contained in:
@@ -152,7 +152,7 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
|
|||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<StyledTableCell>ID</StyledTableCell>
|
<StyledTableCell>ID</StyledTableCell>
|
||||||
<StyledTableCell align="left">Temperature</StyledTableCell>
|
<StyledTableCell align="right">Temperature</StyledTableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@@ -161,8 +161,8 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
|
|||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
{sensorData.id}
|
{sensorData.id}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="left">
|
<TableCell align="right">
|
||||||
{sensorData.temp}°C
|
{sensorData.temp.toFixed(1)}°C
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
@@ -285,7 +285,7 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
|
|||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
{deviceData.name}
|
{deviceData.name}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="left">
|
<TableCell align="right">
|
||||||
{deviceData.value}
|
{deviceData.value}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -100,18 +100,6 @@ function EMSESPSettingsControllerForm(props: EMSESPSettingsControllerFormProps)
|
|||||||
onChange={handleValueChange('tx_gpio')}
|
onChange={handleValueChange('tx_gpio')}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
<TextValidator
|
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
|
|
||||||
errorMessages={['LED GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 255"]}
|
|
||||||
name="led_gpio"
|
|
||||||
label="LED GPIO pin (0=none)"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={data.led_gpio}
|
|
||||||
type="number"
|
|
||||||
onChange={handleValueChange('led_gpio')}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
<TextValidator
|
<TextValidator
|
||||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
|
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
|
||||||
errorMessages={['Dallas GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 255"]}
|
errorMessages={['Dallas GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 255"]}
|
||||||
@@ -124,6 +112,18 @@ function EMSESPSettingsControllerForm(props: EMSESPSettingsControllerFormProps)
|
|||||||
onChange={handleValueChange('dallas_gpio')}
|
onChange={handleValueChange('dallas_gpio')}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
|
<TextValidator
|
||||||
|
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
|
||||||
|
errorMessages={['LED GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 255"]}
|
||||||
|
name="led_gpio"
|
||||||
|
label="LED GPIO pin (0=none)"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={data.led_gpio}
|
||||||
|
type="number"
|
||||||
|
onChange={handleValueChange('led_gpio')}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
@@ -132,7 +132,7 @@ function EMSESPSettingsControllerForm(props: EMSESPSettingsControllerFormProps)
|
|||||||
value="hide_led"
|
value="hide_led"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label="Hide LED"
|
label="Invert/Hide LED"
|
||||||
/>
|
/>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={
|
control={
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ import {
|
|||||||
|
|
||||||
import { EMSESPStatus } from "./EMSESPtypes";
|
import { EMSESPStatus } from "./EMSESPtypes";
|
||||||
|
|
||||||
|
function formatNumber(num: number) {
|
||||||
|
return new Intl.NumberFormat().format(num);
|
||||||
|
}
|
||||||
|
|
||||||
type EMSESPStatusFormProps = RestFormProps<EMSESPStatus> & WithTheme & WithWidthProps;
|
type EMSESPStatusFormProps = RestFormProps<EMSESPStatus> & WithTheme & WithWidthProps;
|
||||||
|
|
||||||
const StyledTableCell = withStyles((theme: Theme) =>
|
const StyledTableCell = withStyles((theme: Theme) =>
|
||||||
@@ -75,7 +79,7 @@ class EMSESPStatusForm extends Component<EMSESPStatusFormProps> {
|
|||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<StyledTableCell>Statistic</StyledTableCell>
|
<StyledTableCell>Statistic</StyledTableCell>
|
||||||
<StyledTableCell align="center"># Telegrams</StyledTableCell>
|
<StyledTableCell align="right"># Telegrams</StyledTableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@@ -83,25 +87,25 @@ class EMSESPStatusForm extends Component<EMSESPStatusFormProps> {
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
(Rx) Received telegrams
|
(Rx) Received telegrams
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">{data.rx_received}</TableCell>
|
<TableCell align="right">{formatNumber(data.rx_received)}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell >
|
<TableCell >
|
||||||
(Rx) Incomplete telegrams
|
(Rx) Incomplete telegrams
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">{data.crc_errors}</TableCell>
|
<TableCell align="right">{formatNumber(data.crc_errors)}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell >
|
<TableCell >
|
||||||
(Tx) Successfully sent telegrams
|
(Tx) Successfully sent telegrams
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">{data.tx_sent}</TableCell>
|
<TableCell align="right">{formatNumber(data.tx_sent)}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell >
|
<TableCell >
|
||||||
(Tx) Send Errors
|
(Tx) Send Errors
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">{data.tx_errors}</TableCell>
|
<TableCell align="right">{formatNumber(data.tx_errors)}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ void APSettingsService::begin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void APSettingsService::reconfigureAP() {
|
void APSettingsService::reconfigureAP() {
|
||||||
_lastManaged = millis() - MANAGE_NETWORK_DELAY;
|
_lastManaged = uuid::get_uptime() - MANAGE_NETWORK_DELAY;
|
||||||
_reconfigureAp = true;
|
_reconfigureAp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APSettingsService::loop() {
|
void APSettingsService::loop() {
|
||||||
unsigned long currentMillis = millis();
|
unsigned long currentMillis = uuid::get_uptime();
|
||||||
unsigned long manageElapsed = (unsigned long)(currentMillis - _lastManaged);
|
unsigned long manageElapsed = (unsigned long)(currentMillis - _lastManaged);
|
||||||
if (manageElapsed >= MANAGE_NETWORK_DELAY) {
|
if (manageElapsed >= MANAGE_NETWORK_DELAY) {
|
||||||
_lastManaged = currentMillis;
|
_lastManaged = currentMillis;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
#include <IPAddress.h>
|
#include <IPAddress.h>
|
||||||
|
#include <uuid/common.h>
|
||||||
|
|
||||||
|
|
||||||
#define MANAGE_NETWORK_DELAY 10000
|
#define MANAGE_NETWORK_DELAY 10000
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ void MqttSettingsService::begin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MqttSettingsService::loop() {
|
void MqttSettingsService::loop() {
|
||||||
if (_reconfigureMqtt || (_disconnectedAt && (unsigned long)(millis() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) {
|
if (_reconfigureMqtt || (_disconnectedAt && (unsigned long)(uuid::get_uptime() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) {
|
||||||
// reconfigure MQTT client
|
// reconfigure MQTT client
|
||||||
configureMqtt();
|
configureMqtt();
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ void MqttSettingsService::onMqttDisconnect(AsyncMqttClientDisconnectReason reaso
|
|||||||
// Serial.print(F("Disconnected from MQTT reason: "));
|
// Serial.print(F("Disconnected from MQTT reason: "));
|
||||||
// Serial.println((uint8_t)reason);
|
// Serial.println((uint8_t)reason);
|
||||||
_disconnectReason = reason;
|
_disconnectReason = reason;
|
||||||
_disconnectedAt = millis();
|
_disconnectedAt = uuid::get_uptime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttSettingsService::onConfigUpdated() {
|
void MqttSettingsService::onConfigUpdated() {
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
#include <FSPersistence.h>
|
#include <FSPersistence.h>
|
||||||
#include <AsyncMqttClient.h>
|
#include <AsyncMqttClient.h>
|
||||||
#include <ESPUtils.h>
|
#include <ESPUtils.h>
|
||||||
|
#include <uuid/common.h>
|
||||||
|
|
||||||
#include "../../src/system.h"
|
#include "../../src/system.h"
|
||||||
#include "../../src/mqtt.h"
|
#include "../../src/mqtt.h"
|
||||||
#include "../../src/sensors.h"
|
#include "../../src/sensors.h"
|
||||||
|
|
||||||
#define MQTT_RECONNECTION_DELAY 5000
|
#define MQTT_RECONNECTION_DELAY 1000
|
||||||
|
|
||||||
#define MQTT_SETTINGS_FILE "/config/mqttSettings.json"
|
#define MQTT_SETTINGS_FILE "/config/mqttSettings.json"
|
||||||
#define MQTT_SETTINGS_SERVICE_PATH "/rest/mqttSettings"
|
#define MQTT_SETTINGS_SERVICE_PATH "/rest/mqttSettings"
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ void NTPStatus::ntpStatus(AsyncWebServerRequest* request) {
|
|||||||
root["server"] = sntp_getservername(0);
|
root["server"] = sntp_getservername(0);
|
||||||
|
|
||||||
// device uptime in seconds
|
// device uptime in seconds
|
||||||
root["uptime"] = millis() / 1000;
|
root["uptime"] = uuid::get_uptime() / 1000;
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
#include <uuid/common.h>
|
||||||
|
|
||||||
|
|
||||||
#define MAX_NTP_STATUS_SIZE 1024
|
#define MAX_NTP_STATUS_SIZE 1024
|
||||||
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"
|
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"
|
||||||
|
|||||||
@@ -26,7 +26,20 @@ uuid::log::Logger Thermostat::logger_{F_(thermostat), uuid::log::Facility::CONSO
|
|||||||
|
|
||||||
Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
|
Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
if (EMSESP::actual_master_thermostat() == 0) {
|
|
||||||
|
uint8_t actual_master_thermostat = EMSESP::actual_master_thermostat(); // what we're actually using
|
||||||
|
uint8_t master_thermostat = EMSESP_DEFAULT_MASTER_THERMOSTAT;
|
||||||
|
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
|
||||||
|
master_thermostat = settings.master_thermostat; // what the user has defined
|
||||||
|
});
|
||||||
|
// if we're on auto mode, register this thermostat if it has a device id of 0x10, 0x17 or 0x18
|
||||||
|
// or if its the master thermostat we defined
|
||||||
|
// see https://github.com/proddy/EMS-ESP/issues/362#issuecomment-629628161
|
||||||
|
if ((master_thermostat == device_id) || ((master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT) && (device_id < 0x19) &&
|
||||||
|
((actual_master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT) || (device_id < actual_master_thermostat)))) {
|
||||||
|
|
||||||
|
EMSESP::actual_master_thermostat(device_id);
|
||||||
|
actual_master_thermostat = device_id;
|
||||||
this->reserve_mem(25); // reserve some space for the telegram registries, to avoid memory fragmentation
|
this->reserve_mem(25); // reserve some space for the telegram registries, to avoid memory fragmentation
|
||||||
|
|
||||||
// common telegram handlers
|
// common telegram handlers
|
||||||
@@ -58,7 +71,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20) {
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20) {
|
||||||
monitor_typeids = {0x91};
|
monitor_typeids = {0x91};
|
||||||
set_typeids = {0xA8};
|
set_typeids = {0xA8};
|
||||||
if (EMSESP::actual_master_thermostat() == 0) {
|
if (actual_master_thermostat == device_id) {
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC20Monitor"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Monitor(t); });
|
register_telegram_type(monitor_typeids[i], F("RC20Monitor"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Monitor(t); });
|
||||||
register_telegram_type(set_typeids[i], F("RC20Set"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Set(t); });
|
register_telegram_type(set_typeids[i], F("RC20Set"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Set(t); });
|
||||||
@@ -70,7 +83,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) {
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) {
|
||||||
monitor_typeids = {0xAE};
|
monitor_typeids = {0xAE};
|
||||||
set_typeids = {0xAD};
|
set_typeids = {0xAD};
|
||||||
if (EMSESP::actual_master_thermostat() == 0) {
|
if (actual_master_thermostat == device_id) {
|
||||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||||
register_telegram_type(monitor_typeids[i], F("RC20Monitor"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Monitor_2(t); });
|
register_telegram_type(monitor_typeids[i], F("RC20Monitor"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Monitor_2(t); });
|
||||||
register_telegram_type(set_typeids[i], F("RC20Set"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Set_2(t); });
|
register_telegram_type(set_typeids[i], F("RC20Set"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Set_2(t); });
|
||||||
@@ -122,29 +135,16 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t master_thermostat = 0;
|
|
||||||
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
|
|
||||||
master_thermostat = settings.master_thermostat; // what the user has defined
|
|
||||||
});
|
|
||||||
|
|
||||||
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & settings) {
|
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & settings) {
|
||||||
mqtt_format_ = settings.mqtt_format; // single, nested or ha
|
mqtt_format_ = settings.mqtt_format; // single, nested or ha
|
||||||
});
|
});
|
||||||
|
|
||||||
uint8_t actual_master_thermostat = EMSESP::actual_master_thermostat(); // what we're actually using
|
if (actual_master_thermostat != device_id) {
|
||||||
uint8_t num_devices = EMSESP::count_devices(EMSdevice::DeviceType::THERMOSTAT) + 1; // including this thermostat
|
|
||||||
|
|
||||||
// if we're on auto mode, register this thermostat if it has a device id of 0x10, 0x17 or 0x18
|
|
||||||
// or if its the master thermostat we defined
|
|
||||||
// see https://github.com/proddy/EMS-ESP/issues/362#issuecomment-629628161
|
|
||||||
if (((num_devices == 1) && (actual_master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT)) || (master_thermostat == device_id)) {
|
|
||||||
EMSESP::actual_master_thermostat(device_id);
|
|
||||||
LOG_DEBUG(F("Adding new thermostat with device ID 0x%02X (as master)"), device_id);
|
|
||||||
add_commands();
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG(F("Adding new thermostat with device ID 0x%02X"), device_id);
|
LOG_DEBUG(F("Adding new thermostat with device ID 0x%02X"), device_id);
|
||||||
return; // don't fetch data if more than 1 thermostat
|
return; // don't fetch data if more than 1 thermostat
|
||||||
}
|
}
|
||||||
|
LOG_DEBUG(F("Adding new thermostat with device ID 0x%02X (as master)"), device_id);
|
||||||
|
add_commands();
|
||||||
|
|
||||||
// reserve some memory for the heating circuits (max 4 to start with)
|
// reserve some memory for the heating circuits (max 4 to start with)
|
||||||
heating_circuits_.reserve(4);
|
heating_circuits_.reserve(4);
|
||||||
@@ -275,7 +275,8 @@ void Thermostat::publish_values() {
|
|||||||
JsonObject dataThermostat;
|
JsonObject dataThermostat;
|
||||||
|
|
||||||
// add external temp and other stuff specific to the RC30 and RC35
|
// add external temp and other stuff specific to the RC30 and RC35
|
||||||
if ((flags == EMS_DEVICE_FLAG_RC35 || flags == EMS_DEVICE_FLAG_RC30_1) && (mqtt_format_ == MQTT_format::SINGLE || mqtt_format_ == MQTT_format::CUSTOM)) {
|
// if ((flags == EMS_DEVICE_FLAG_RC35 || flags == EMS_DEVICE_FLAG_RC30_1) && (mqtt_format_ == MQTT_format::SINGLE || mqtt_format_ == MQTT_format::CUSTOM)) {
|
||||||
|
if (flags == EMS_DEVICE_FLAG_RC35 || flags == EMS_DEVICE_FLAG_RC30_1) {
|
||||||
if (datetime_.size()) {
|
if (datetime_.size()) {
|
||||||
rootThermostat["time"] = datetime_.c_str();
|
rootThermostat["time"] = datetime_.c_str();
|
||||||
}
|
}
|
||||||
@@ -579,9 +580,24 @@ void Thermostat::register_mqtt_ha_config(uint8_t hc_num) {
|
|||||||
doc["temp_step"] = "0.5";
|
doc["temp_step"] = "0.5";
|
||||||
|
|
||||||
JsonArray modes = doc.createNestedArray("modes");
|
JsonArray modes = doc.createNestedArray("modes");
|
||||||
modes.add("off");
|
uint8_t flags = (this->flags() & 0x0F);
|
||||||
modes.add("heat");
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) {
|
||||||
modes.add("auto");
|
modes.add("night");
|
||||||
|
modes.add("day");
|
||||||
|
} else if ((flags == EMSdevice::EMS_DEVICE_FLAG_RC300) || (flags == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
|
||||||
|
modes.add("eco");
|
||||||
|
modes.add("comfort");
|
||||||
|
modes.add("auto");
|
||||||
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||||
|
modes.add("nofrost");
|
||||||
|
modes.add("eco");
|
||||||
|
modes.add("heat");
|
||||||
|
modes.add("auto");
|
||||||
|
} else { // default for all other thermostats
|
||||||
|
modes.add("night");
|
||||||
|
modes.add("day");
|
||||||
|
modes.add("auto");
|
||||||
|
}
|
||||||
|
|
||||||
std::string topic(100, '\0'); // e.g homeassistant/climate/hc1/thermostat/config
|
std::string topic(100, '\0'); // e.g homeassistant/climate/hc1/thermostat/config
|
||||||
snprintf_P(&topic[0], topic.capacity() + 1, PSTR("homeassistant/climate/ems-esp/hc%d/config"), hc_num);
|
snprintf_P(&topic[0], topic.capacity() + 1, PSTR("homeassistant/climate/ems-esp/hc%d/config"), hc_num);
|
||||||
@@ -1146,7 +1162,6 @@ void Thermostat::console_commands(Shell & shell, unsigned int context) {
|
|||||||
flash_string_vector{F_(deviceid_mandatory)},
|
flash_string_vector{F_(deviceid_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||||
uint8_t value = Helpers::hextoint(arguments.front().c_str());
|
uint8_t value = Helpers::hextoint(arguments.front().c_str());
|
||||||
|
|
||||||
EMSESP::emsespSettingsService.update(
|
EMSESP::emsespSettingsService.update(
|
||||||
[&](EMSESPSettings & settings) {
|
[&](EMSESPSettings & settings) {
|
||||||
settings.master_thermostat = value;
|
settings.master_thermostat = value;
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
|||||||
char valuestr[8] = {0}; // for formatting temp
|
char valuestr[8] = {0}; // for formatting temp
|
||||||
shell.printfln(F("Dallas temperature sensors:"));
|
shell.printfln(F("Dallas temperature sensors:"));
|
||||||
for (const auto & device : sensor_devices()) {
|
for (const auto & device : sensor_devices()) {
|
||||||
shell.printfln(F(" ID: %s, Temperature: %s°C"), device.to_string().c_str(), Helpers::render_value(valuestr, device.temperature_c, 2));
|
shell.printfln(F(" ID: %s, Temperature: %s°C"), device.to_string().c_str(), Helpers::render_value(valuestr, device.temperature_c, 1));
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,27 +183,27 @@ float Sensors::get_temperature_c(const uint8_t addr[]) {
|
|||||||
|
|
||||||
int16_t raw_value = ((int16_t)scratchpad[SCRATCHPAD_TEMP_MSB] << 8) | scratchpad[SCRATCHPAD_TEMP_LSB];
|
int16_t raw_value = ((int16_t)scratchpad[SCRATCHPAD_TEMP_MSB] << 8) | scratchpad[SCRATCHPAD_TEMP_LSB];
|
||||||
|
|
||||||
// Adjust based on device resolution
|
if (addr[0] == TYPE_DS18S20) {
|
||||||
int resolution = 9 + ((scratchpad[SCRATCHPAD_CONFIG] >> 5) & 0x3);
|
raw_value = (raw_value << 3) + 12 - scratchpad[SCRATCHPAD_CNT_REM];
|
||||||
switch (resolution) {
|
} else {
|
||||||
case 9:
|
// Adjust based on device resolution
|
||||||
raw_value &= ~0x1;
|
int resolution = 9 + ((scratchpad[SCRATCHPAD_CONFIG] >> 5) & 0x3);
|
||||||
break;
|
switch (resolution) {
|
||||||
|
case 9:
|
||||||
case 10:
|
raw_value &= ~0x7;
|
||||||
raw_value &= ~0x3;
|
break;
|
||||||
break;
|
case 10:
|
||||||
|
raw_value &= ~0x3;
|
||||||
case 11:
|
break;
|
||||||
raw_value &= ~0x7;
|
case 11:
|
||||||
break;
|
raw_value &= ~0x1;
|
||||||
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
uint32_t raw = (raw_value * 625 + 500) / 1000; // round to 0.1
|
||||||
uint32_t raw = (raw_value * 625) / 100; // round to 0.01
|
return (float)raw / 10;
|
||||||
return (float)raw / 100;
|
|
||||||
#else
|
#else
|
||||||
return NAN;
|
return NAN;
|
||||||
#endif
|
#endif
|
||||||
@@ -254,7 +254,7 @@ void Sensors::publish_values() {
|
|||||||
StaticJsonDocument<100> doc;
|
StaticJsonDocument<100> doc;
|
||||||
for (const auto & device : devices_) {
|
for (const auto & device : devices_) {
|
||||||
char s[7]; // sensorrange -55.00 to 125.00
|
char s[7]; // sensorrange -55.00 to 125.00
|
||||||
doc["temp"] = Helpers::render_value(s, device.temperature_c, 2);
|
doc["temp"] = Helpers::render_value(s, device.temperature_c, 1);
|
||||||
char topic[60]; // sensors{1-n}
|
char topic[60]; // sensors{1-n}
|
||||||
strlcpy(topic, "sensor_", 50); // create topic, e.g. home/ems-esp/sensor_28-EA41-9497-0E03-5F
|
strlcpy(topic, "sensor_", 50); // create topic, e.g. home/ems-esp/sensor_28-EA41-9497-0E03-5F
|
||||||
strlcat(topic, device.to_string().c_str(), 60);
|
strlcat(topic, device.to_string().c_str(), 60);
|
||||||
@@ -264,20 +264,13 @@ void Sensors::publish_values() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const size_t capacity = num_devices * JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(num_devices);
|
|
||||||
DynamicJsonDocument doc(100 * num_devices);
|
DynamicJsonDocument doc(100 * num_devices);
|
||||||
uint8_t i = 1; // sensor count
|
uint8_t i = 1; // sensor count
|
||||||
for (const auto & device : devices_) {
|
for (const auto & device : devices_) {
|
||||||
char s[7];
|
char s[7];
|
||||||
|
|
||||||
if (mqtt_format_ == MQTT_format::CUSTOM) {
|
if (mqtt_format_ == MQTT_format::CUSTOM) {
|
||||||
doc[device.to_string()] = Helpers::render_value(s, device.temperature_c, 2);
|
doc[device.to_string()] = Helpers::render_value(s, device.temperature_c, 1);
|
||||||
} else if (mqtt_format_ == MQTT_format::SINGLE) {
|
|
||||||
doc["id"] = device.to_string();
|
|
||||||
doc["temp"] = Helpers::render_value(s, device.temperature_c, 2);
|
|
||||||
std::string topic(100, '\0');
|
|
||||||
snprintf_P(&topic[0], 50, PSTR("sensor%d"), i);
|
|
||||||
Mqtt::publish(topic, doc);
|
|
||||||
} else if ((mqtt_format_ == MQTT_format::NESTED) || (mqtt_format_ == MQTT_format::HA)) {
|
} else if ((mqtt_format_ == MQTT_format::NESTED) || (mqtt_format_ == MQTT_format::HA)) {
|
||||||
// e.g. {"sensor1":{"id":"28-EA41-9497-0E03-5F","temp":"23.30"},"sensor2":{"id":"28-233D-9497-0C03-8B","temp":"24.0"}}
|
// e.g. {"sensor1":{"id":"28-EA41-9497-0E03-5F","temp":"23.30"},"sensor2":{"id":"28-233D-9497-0C03-8B","temp":"24.0"}}
|
||||||
char sensorID[10]; // sensor{1-n}
|
char sensorID[10]; // sensor{1-n}
|
||||||
@@ -285,7 +278,7 @@ void Sensors::publish_values() {
|
|||||||
strlcat(sensorID, Helpers::itoa(s, i), 10);
|
strlcat(sensorID, Helpers::itoa(s, i), 10);
|
||||||
JsonObject dataSensor = doc.createNestedObject(sensorID);
|
JsonObject dataSensor = doc.createNestedObject(sensorID);
|
||||||
dataSensor["id"] = device.to_string();
|
dataSensor["id"] = device.to_string();
|
||||||
dataSensor["temp"] = Helpers::render_value(s, device.temperature_c, 2);
|
dataSensor["temp"] = Helpers::render_value(s, device.temperature_c, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// special for HA
|
// special for HA
|
||||||
|
|||||||
@@ -74,12 +74,13 @@ class Sensors {
|
|||||||
static constexpr size_t SCRATCHPAD_TEMP_MSB = 1;
|
static constexpr size_t SCRATCHPAD_TEMP_MSB = 1;
|
||||||
static constexpr size_t SCRATCHPAD_TEMP_LSB = 0;
|
static constexpr size_t SCRATCHPAD_TEMP_LSB = 0;
|
||||||
static constexpr size_t SCRATCHPAD_CONFIG = 4;
|
static constexpr size_t SCRATCHPAD_CONFIG = 4;
|
||||||
|
static constexpr size_t SCRATCHPAD_CNT_REM = 6;
|
||||||
|
|
||||||
// dallas chips
|
// dallas chips
|
||||||
static constexpr uint8_t TYPE_DS18B20 = 0x28;
|
static constexpr uint8_t TYPE_DS18B20 = 0x28;
|
||||||
static constexpr uint8_t TYPE_DS18S20 = 0x10;
|
static constexpr uint8_t TYPE_DS18S20 = 0x10;
|
||||||
static constexpr uint8_t TYPE_DS1822 = 0x22;
|
static constexpr uint8_t TYPE_DS1822 = 0x22;
|
||||||
static constexpr uint8_t TYPE_DS1825 = 0x3B;
|
static constexpr uint8_t TYPE_DS1825 = 0x3B; // also DS1826
|
||||||
|
|
||||||
static constexpr uint32_t READ_INTERVAL_MS = 5000; // 5 seconds
|
static constexpr uint32_t READ_INTERVAL_MS = 5000; // 5 seconds
|
||||||
static constexpr uint32_t CONVERSION_MS = 1000; // 1 seconds
|
static constexpr uint32_t CONVERSION_MS = 1000; // 1 seconds
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
|||||||
// check if queue is full, if so remove top item to make space
|
// check if queue is full, if so remove top item to make space
|
||||||
if (rx_telegrams_.size() >= MAX_RX_TELEGRAMS) {
|
if (rx_telegrams_.size() >= MAX_RX_TELEGRAMS) {
|
||||||
rx_telegrams_.pop_front();
|
rx_telegrams_.pop_front();
|
||||||
|
increment_telegram_error_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
rx_telegrams_.emplace_back(rx_telegram_id_++, std::move(telegram)); // add to queue
|
rx_telegrams_.emplace_back(rx_telegram_id_++, std::move(telegram)); // add to queue
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ class RxService : public EMSbus {
|
|||||||
void loop();
|
void loop();
|
||||||
void add(uint8_t * data, uint8_t length);
|
void add(uint8_t * data, uint8_t length);
|
||||||
|
|
||||||
uint16_t telegram_count() const {
|
uint32_t telegram_count() const {
|
||||||
return telegram_count_;
|
return telegram_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ class RxService : public EMSbus {
|
|||||||
telegram_count_++;
|
telegram_count_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t telegram_error_count() const {
|
uint32_t telegram_error_count() const {
|
||||||
return telegram_error_count_;
|
return telegram_error_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,8 +235,8 @@ class RxService : public EMSbus {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t rx_telegram_id_ = 0; // queue counter
|
uint8_t rx_telegram_id_ = 0; // queue counter
|
||||||
uint16_t telegram_count_ = 0; // # Rx received
|
uint32_t telegram_count_ = 0; // # Rx received
|
||||||
uint16_t telegram_error_count_ = 0; // # Rx CRC errors
|
uint32_t telegram_error_count_ = 0; // # Rx CRC errors
|
||||||
std::shared_ptr<const Telegram> rx_telegram; // the incoming Rx telegram
|
std::shared_ptr<const Telegram> rx_telegram; // the incoming Rx telegram
|
||||||
|
|
||||||
std::list<QueuedRxTelegram> rx_telegrams_; // the Rx Queue
|
std::list<QueuedRxTelegram> rx_telegrams_; // the Rx Queue
|
||||||
@@ -288,7 +288,7 @@ class TxService : public EMSbus {
|
|||||||
telegram_last_post_send_query_ = type_id;
|
telegram_last_post_send_query_ = type_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t telegram_read_count() const {
|
uint32_t telegram_read_count() const {
|
||||||
return telegram_read_count_;
|
return telegram_read_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +300,7 @@ class TxService : public EMSbus {
|
|||||||
telegram_read_count_++;
|
telegram_read_count_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t telegram_fail_count() const {
|
uint32_t telegram_fail_count() const {
|
||||||
return telegram_fail_count_;
|
return telegram_fail_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ class TxService : public EMSbus {
|
|||||||
telegram_fail_count_++;
|
telegram_fail_count_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t telegram_write_count() const {
|
uint32_t telegram_write_count() const {
|
||||||
return telegram_write_count_;
|
return telegram_write_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,9 +355,9 @@ class TxService : public EMSbus {
|
|||||||
private:
|
private:
|
||||||
std::list<QueuedTxTelegram> tx_telegrams_; // the Tx queue
|
std::list<QueuedTxTelegram> tx_telegrams_; // the Tx queue
|
||||||
|
|
||||||
uint16_t telegram_read_count_ = 0; // # Tx successful reads
|
uint32_t telegram_read_count_ = 0; // # Tx successful reads
|
||||||
uint16_t telegram_write_count_ = 0; // # Tx successful writes
|
uint32_t telegram_write_count_ = 0; // # Tx successful writes
|
||||||
uint16_t telegram_fail_count_ = 0; // # Tx unsuccessful transmits
|
uint32_t telegram_fail_count_ = 0; // # Tx unsuccessful transmits
|
||||||
|
|
||||||
std::shared_ptr<Telegram> telegram_last_;
|
std::shared_ptr<Telegram> telegram_last_;
|
||||||
uint16_t telegram_last_post_send_query_; // which type ID to query after a successful send, to read back the values just written
|
uint16_t telegram_last_post_send_query_; // which type ID to query after a successful send, to read back the values just written
|
||||||
|
|||||||
Reference in New Issue
Block a user