mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-22 16:13:36 +05:00
Merge branch 'master' into async
This commit is contained in:
@@ -70,50 +70,89 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool sendBoilerReset() {
|
||||
unsigned int data = 1;
|
||||
data <<= 8;
|
||||
unsigned long response = this->sendRequest(buildRequest(
|
||||
OpenThermMessageType::WRITE_DATA,
|
||||
OpenThermMessageID::RemoteRequest,
|
||||
data
|
||||
));
|
||||
|
||||
return isValidResponse(response) && isValidResponseId(response, OpenThermMessageID::RemoteRequest);
|
||||
inline auto sendBoilerReset() {
|
||||
return this->sendRequestCode(1);
|
||||
}
|
||||
|
||||
bool sendServiceReset() {
|
||||
unsigned int data = 10;
|
||||
data <<= 8;
|
||||
unsigned long response = this->sendRequest(buildRequest(
|
||||
OpenThermMessageType::WRITE_DATA,
|
||||
OpenThermMessageID::RemoteRequest,
|
||||
data
|
||||
));
|
||||
|
||||
return isValidResponse(response) && isValidResponseId(response, OpenThermMessageID::RemoteRequest);
|
||||
inline auto sendServiceReset() {
|
||||
return this->sendRequestCode(10);
|
||||
}
|
||||
|
||||
bool sendWaterFilling() {
|
||||
unsigned int data = 2;
|
||||
data <<= 8;
|
||||
inline auto sendWaterFilling() {
|
||||
return this->sendRequestCode(2);
|
||||
}
|
||||
|
||||
bool sendRequestCode(const uint8_t requestCode) {
|
||||
unsigned long response = this->sendRequest(buildRequest(
|
||||
OpenThermMessageType::WRITE_DATA,
|
||||
OpenThermMessageID::RemoteRequest,
|
||||
data
|
||||
static_cast<unsigned int>(requestCode) << 8
|
||||
));
|
||||
|
||||
return isValidResponse(response) && isValidResponseId(response, OpenThermMessageID::RemoteRequest);
|
||||
if (!isValidResponse(response) || !isValidResponseId(response, OpenThermMessageID::RemoteRequest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t responseRequestCode = (response & 0xFFFF) >> 8;
|
||||
const uint8_t responseCode = response & 0xFF;
|
||||
if (responseRequestCode != requestCode || responseCode < 128) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// reset
|
||||
this->sendRequest(buildRequest(
|
||||
OpenThermMessageType::WRITE_DATA,
|
||||
OpenThermMessageID::RemoteRequest,
|
||||
0u << 8
|
||||
));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getStr(OpenThermMessageID id, char* buffer, uint16_t length = 50) {
|
||||
if (buffer == nullptr || length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long response;
|
||||
uint8_t index = 0;
|
||||
uint8_t maxIndex = 255;
|
||||
|
||||
while (index <= maxIndex && index < length) {
|
||||
response = this->sendRequest(buildRequest(
|
||||
OpenThermMessageType::READ_DATA,
|
||||
id,
|
||||
static_cast<unsigned int>(index) << 8
|
||||
));
|
||||
|
||||
if (!isValidResponse(response) || !isValidResponseId(response, id)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const uint8_t character = response & 0xFF;
|
||||
if (character == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
maxIndex = (response & 0xFFFF) >> 8;
|
||||
}
|
||||
|
||||
buffer[index++] = static_cast<char>(character);
|
||||
}
|
||||
|
||||
buffer[index] = '\0';
|
||||
return index > 0;
|
||||
}
|
||||
|
||||
static bool isCh2Active(unsigned long response) {
|
||||
return response & 0x20;
|
||||
return response & 0x20;
|
||||
}
|
||||
|
||||
static bool isValidResponseId(unsigned long response, OpenThermMessageID id) {
|
||||
uint8_t responseId = (response >> 16) & 0xFF;
|
||||
const uint8_t responseId = (response >> 16) & 0xFF;
|
||||
|
||||
return (uint8_t)id == responseId;
|
||||
return static_cast<uint8_t>(id) == responseId;
|
||||
}
|
||||
|
||||
static uint8_t getResponseMessageTypeId(unsigned long response) {
|
||||
@@ -124,10 +163,10 @@ public:
|
||||
uint8_t msgType = getResponseMessageTypeId(response);
|
||||
|
||||
switch (msgType) {
|
||||
case (uint8_t) OpenThermMessageType::READ_ACK:
|
||||
case (uint8_t) OpenThermMessageType::WRITE_ACK:
|
||||
case (uint8_t) OpenThermMessageType::DATA_INVALID:
|
||||
case (uint8_t) OpenThermMessageType::UNKNOWN_DATA_ID:
|
||||
case static_cast<uint8_t>(OpenThermMessageType::READ_ACK):
|
||||
case static_cast<uint8_t>(OpenThermMessageType::WRITE_ACK):
|
||||
case static_cast<uint8_t>(OpenThermMessageType::DATA_INVALID):
|
||||
case static_cast<uint8_t>(OpenThermMessageType::UNKNOWN_DATA_ID):
|
||||
return CustomOpenTherm::messageTypeToString(
|
||||
static_cast<OpenThermMessageType>(msgType)
|
||||
);
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined(EQUITHERM_INTEGER)
|
||||
// расчёты с целыми числами
|
||||
typedef int datatype;
|
||||
#else
|
||||
// расчёты с float числами
|
||||
typedef float datatype;
|
||||
#endif
|
||||
|
||||
class Equitherm {
|
||||
public:
|
||||
datatype targetTemp = 0;
|
||||
datatype indoorTemp = 0;
|
||||
datatype outdoorTemp = 0;
|
||||
float Kn = 0.0;
|
||||
float Kk = 0.0;
|
||||
float Kt = 0.0;
|
||||
|
||||
Equitherm() = default;
|
||||
|
||||
// kn, kk, kt
|
||||
Equitherm(float new_kn, float new_kk, float new_kt) {
|
||||
Kn = new_kn;
|
||||
Kk = new_kk;
|
||||
Kt = new_kt;
|
||||
}
|
||||
|
||||
// лимит выходной величины
|
||||
void setLimits(unsigned short min_output, unsigned short max_output) {
|
||||
_minOut = min_output;
|
||||
_maxOut = max_output;
|
||||
}
|
||||
|
||||
// возвращает новое значение при вызове
|
||||
datatype getResult() {
|
||||
datatype output = getResultN() + getResultK() + getResultT();
|
||||
output = constrain(output, _minOut, _maxOut); // ограничиваем выход
|
||||
return output;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned short _minOut = 20, _maxOut = 90;
|
||||
|
||||
// температура контура отопления в зависимости от наружной температуры
|
||||
datatype getResultN() {
|
||||
float a = (-0.21 * Kn) - 0.06; // a = -0,21k — 0,06
|
||||
float b = (6.04 * Kn) + 1.98; // b = 6,04k + 1,98
|
||||
float c = (-5.06 * Kn) + 18.06; // с = -5,06k + 18,06
|
||||
float x = (-0.2 * outdoorTemp) + 5; // x = -0.2*t1 + 5
|
||||
return (a * x * x) + (b * x) + c; // Tn = ax2 + bx + c
|
||||
}
|
||||
|
||||
// поправка на желаемую комнатную температуру
|
||||
datatype getResultK() {
|
||||
return (targetTemp - 20) * Kk;
|
||||
}
|
||||
|
||||
// Расчет поправки (ошибки) термостата
|
||||
datatype getResultT() {
|
||||
return constrain((targetTemp - indoorTemp), -3, 3) * Kt;
|
||||
}
|
||||
};
|
||||
@@ -147,8 +147,19 @@ public:
|
||||
return topic;
|
||||
}
|
||||
|
||||
template <class DT, class VT>
|
||||
String getEntityIdWithPrefix(DT domain, VT value, char separator = '_') {
|
||||
String topic = "";
|
||||
topic.concat(domain);
|
||||
topic.concat('.');
|
||||
topic.concat(this->devicePrefix);
|
||||
topic.concat(separator);
|
||||
topic.concat(value);
|
||||
return topic;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
String getObjectIdWithPrefix(T value, char separator = '_') {
|
||||
String getUniqueIdWithPrefix(T value, char separator = '_') {
|
||||
String topic = "";
|
||||
topic.concat(this->devicePrefix);
|
||||
topic.concat(separator);
|
||||
|
||||
@@ -12,66 +12,67 @@ const char HA_ENTITY_SELECT[] PROGMEM = "select";
|
||||
const char HA_ENTITY_SENSOR[] PROGMEM = "sensor";
|
||||
const char HA_ENTITY_SWITCH[] PROGMEM = "switch";
|
||||
|
||||
const char HA_DEVICE[] PROGMEM = "device";
|
||||
const char HA_IDENTIFIERS[] PROGMEM = "identifiers";
|
||||
const char HA_SW_VERSION[] PROGMEM = "sw_version";
|
||||
const char HA_MANUFACTURER[] PROGMEM = "manufacturer";
|
||||
const char HA_MODEL[] PROGMEM = "model";
|
||||
// https://www.home-assistant.io/integrations/mqtt/#supported-abbreviations-in-mqtt-discovery-messages
|
||||
const char HA_DEFAULT_ENTITY_ID[] PROGMEM = "def_ent_id"; // "default_entity_id "
|
||||
const char HA_DEVICE[] PROGMEM = "dev"; // "device"
|
||||
const char HA_IDENTIFIERS[] PROGMEM = "ids"; // "identifiers"
|
||||
const char HA_SW_VERSION[] PROGMEM = "sw"; // "sw_version"
|
||||
const char HA_MANUFACTURER[] PROGMEM = "mf"; // "manufacturer"
|
||||
const char HA_MODEL[] PROGMEM = "mdl"; // "model"
|
||||
const char HA_NAME[] PROGMEM = "name";
|
||||
const char HA_CONF_URL[] PROGMEM = "configuration_url";
|
||||
const char HA_COMMAND_TOPIC[] PROGMEM = "command_topic";
|
||||
const char HA_COMMAND_TEMPLATE[] PROGMEM = "command_template";
|
||||
const char HA_ENABLED_BY_DEFAULT[] PROGMEM = "enabled_by_default";
|
||||
const char HA_UNIQUE_ID[] PROGMEM = "unique_id";
|
||||
const char HA_OBJECT_ID[] PROGMEM = "object_id";
|
||||
const char HA_ENTITY_CATEGORY[] PROGMEM = "entity_category";
|
||||
const char HA_CONF_URL[] PROGMEM = "cu"; // "configuration_url"
|
||||
const char HA_COMMAND_TOPIC[] PROGMEM = "cmd_t"; // "command_topic"
|
||||
const char HA_COMMAND_TEMPLATE[] PROGMEM = "cmd_tpl"; // "command_template"
|
||||
const char HA_ENABLED_BY_DEFAULT[] PROGMEM = "en"; // "enabled_by_default"
|
||||
const char HA_UNIQUE_ID[] PROGMEM = "uniq_id"; // "unique_id"
|
||||
const char HA_ENTITY_CATEGORY[] PROGMEM = "ent_cat"; // "entity_category"
|
||||
const char HA_ENTITY_CATEGORY_DIAGNOSTIC[] PROGMEM = "diagnostic";
|
||||
const char HA_ENTITY_CATEGORY_CONFIG[] PROGMEM = "config";
|
||||
const char HA_STATE_TOPIC[] PROGMEM = "state_topic";
|
||||
const char HA_VALUE_TEMPLATE[] PROGMEM = "value_template";
|
||||
const char HA_OPTIONS[] PROGMEM = "options";
|
||||
const char HA_AVAILABILITY[] PROGMEM = "availability";
|
||||
const char HA_AVAILABILITY_MODE[] PROGMEM = "availability_mode";
|
||||
const char HA_TOPIC[] PROGMEM = "topic";
|
||||
const char HA_DEVICE_CLASS[] PROGMEM = "device_class";
|
||||
const char HA_UNIT_OF_MEASUREMENT[] PROGMEM = "unit_of_measurement";
|
||||
const char HA_STATE_TOPIC[] PROGMEM = "stat_t"; // "state_topic"
|
||||
const char HA_VALUE_TEMPLATE[] PROGMEM = "val_tpl"; // "value_template"
|
||||
const char HA_OPTIONS[] PROGMEM = "ops"; // "options"
|
||||
const char HA_AVAILABILITY[] PROGMEM = "avty"; // "availability"
|
||||
const char HA_AVAILABILITY_MODE[] PROGMEM = "avty_mode"; // "availability_mode"
|
||||
const char HA_TOPIC[] PROGMEM = "t"; // "topic"
|
||||
const char HA_DEVICE_CLASS[] PROGMEM = "dev_cla"; // "device_class"
|
||||
const char HA_UNIT_OF_MEASUREMENT[] PROGMEM = "unit_of_meas"; // "unit_of_measurement"
|
||||
const char HA_UNIT_OF_MEASUREMENT_C[] PROGMEM = "°C";
|
||||
const char HA_UNIT_OF_MEASUREMENT_F[] PROGMEM = "°F";
|
||||
const char HA_UNIT_OF_MEASUREMENT_PERCENT[] PROGMEM = "%";
|
||||
const char HA_UNIT_OF_MEASUREMENT_L_MIN[] PROGMEM = "L/min";
|
||||
const char HA_UNIT_OF_MEASUREMENT_GAL_MIN[] PROGMEM = "gal/min";
|
||||
const char HA_ICON[] PROGMEM = "icon";
|
||||
const char HA_ICON[] PROGMEM = "ic"; // "icon"
|
||||
const char HA_MIN[] PROGMEM = "min";
|
||||
const char HA_MAX[] PROGMEM = "max";
|
||||
const char HA_STEP[] PROGMEM = "step";
|
||||
const char HA_MODE[] PROGMEM = "mode";
|
||||
const char HA_MODE_BOX[] PROGMEM = "box";
|
||||
const char HA_STATE_ON[] PROGMEM = "state_on";
|
||||
const char HA_STATE_OFF[] PROGMEM = "state_off";
|
||||
const char HA_PAYLOAD_ON[] PROGMEM = "payload_on";
|
||||
const char HA_PAYLOAD_OFF[] PROGMEM = "payload_off";
|
||||
const char HA_STATE_CLASS[] PROGMEM = "state_class";
|
||||
const char HA_STATE_ON[] PROGMEM = "stat_on"; // "state_on"
|
||||
const char HA_STATE_OFF[] PROGMEM = "stat_off"; // "state_off"
|
||||
const char HA_PAYLOAD_ON[] PROGMEM = "pl_on"; // "payload_on"
|
||||
const char HA_PAYLOAD_OFF[] PROGMEM = "pl_off"; // "payload_off"
|
||||
const char HA_STATE_CLASS[] PROGMEM = "stat_cla"; // "state_class"
|
||||
const char HA_STATE_CLASS_MEASUREMENT[] PROGMEM = "measurement";
|
||||
const char HA_EXPIRE_AFTER[] PROGMEM = "expire_after";
|
||||
const char HA_CURRENT_TEMPERATURE_TOPIC[] PROGMEM = "current_temperature_topic";
|
||||
const char HA_CURRENT_TEMPERATURE_TEMPLATE[] PROGMEM = "current_temperature_template";
|
||||
const char HA_TEMPERATURE_COMMAND_TOPIC[] PROGMEM = "temperature_command_topic";
|
||||
const char HA_TEMPERATURE_COMMAND_TEMPLATE[] PROGMEM = "temperature_command_template";
|
||||
const char HA_TEMPERATURE_STATE_TOPIC[] PROGMEM = "temperature_state_topic";
|
||||
const char HA_TEMPERATURE_STATE_TEMPLATE[] PROGMEM = "temperature_state_template";
|
||||
const char HA_TEMPERATURE_UNIT[] PROGMEM = "temperature_unit";
|
||||
const char HA_MODE_COMMAND_TOPIC[] PROGMEM = "mode_command_topic";
|
||||
const char HA_MODE_COMMAND_TEMPLATE[] PROGMEM = "mode_command_template";
|
||||
const char HA_MODE_STATE_TOPIC[] PROGMEM = "mode_state_topic";
|
||||
const char HA_MODE_STATE_TEMPLATE[] PROGMEM = "mode_state_template";
|
||||
const char HA_EXPIRE_AFTER[] PROGMEM = "exp_aft"; // "expire_after"
|
||||
const char HA_CURRENT_TEMPERATURE_TOPIC[] PROGMEM = "curr_temp_t"; // "current_temperature_topic"
|
||||
const char HA_CURRENT_TEMPERATURE_TEMPLATE[] PROGMEM = "curr_temp_tpl"; // "current_temperature_template"
|
||||
const char HA_TEMPERATURE_COMMAND_TOPIC[] PROGMEM = "temp_cmd_t"; // "temperature_command_topic"
|
||||
const char HA_TEMPERATURE_COMMAND_TEMPLATE[] PROGMEM = "temp_cmd_tpl"; // "temperature_command_template"
|
||||
const char HA_TEMPERATURE_STATE_TOPIC[] PROGMEM = "temp_stat_t"; // "temperature_state_topic"
|
||||
const char HA_TEMPERATURE_STATE_TEMPLATE[] PROGMEM = "temp_stat_tpl"; // "temperature_state_template"
|
||||
const char HA_TEMPERATURE_UNIT[] PROGMEM = "temp_unit"; // "temperature_unit"
|
||||
const char HA_MODE_COMMAND_TOPIC[] PROGMEM = "mode_cmd_t"; // "mode_command_topic"
|
||||
const char HA_MODE_COMMAND_TEMPLATE[] PROGMEM = "mode_cmd_tpl"; // "mode_command_template"
|
||||
const char HA_MODE_STATE_TOPIC[] PROGMEM = "mode_stat_t"; // "mode_state_topic"
|
||||
const char HA_MODE_STATE_TEMPLATE[] PROGMEM = "mode_stat_tpl"; // "mode_state_template"
|
||||
const char HA_MODES[] PROGMEM = "modes";
|
||||
const char HA_ACTION_TOPIC[] PROGMEM = "action_topic";
|
||||
const char HA_ACTION_TEMPLATE[] PROGMEM = "action_template";
|
||||
const char HA_ACTION_TOPIC[] PROGMEM = "act_t"; // "action_topic"
|
||||
const char HA_ACTION_TEMPLATE[] PROGMEM = "act_tpl"; // "action_template"
|
||||
const char HA_MIN_TEMP[] PROGMEM = "min_temp";
|
||||
const char HA_MAX_TEMP[] PROGMEM = "max_temp";
|
||||
const char HA_TEMP_STEP[] PROGMEM = "temp_step";
|
||||
const char HA_PRESET_MODE_COMMAND_TOPIC[] PROGMEM = "preset_mode_command_topic";
|
||||
const char HA_PRESET_MODE_COMMAND_TEMPLATE[] PROGMEM = "preset_mode_command_template";
|
||||
const char HA_PRESET_MODE_STATE_TOPIC[] PROGMEM = "preset_mode_state_topic";
|
||||
const char HA_PRESET_MODE_VALUE_TEMPLATE[] PROGMEM = "preset_mode_value_template";
|
||||
const char HA_PRESET_MODES[] PROGMEM = "preset_modes";
|
||||
const char HA_PRESET_MODE_COMMAND_TOPIC[] PROGMEM = "pr_mode_cmd_t"; // "preset_mode_command_topic"
|
||||
const char HA_PRESET_MODE_COMMAND_TEMPLATE[] PROGMEM = "pr_mode_cmd_tpl"; // "preset_mode_command_template"
|
||||
const char HA_PRESET_MODE_STATE_TOPIC[] PROGMEM = "pr_mode_stat_t"; // "preset_mode_state_topic"
|
||||
const char HA_PRESET_MODE_VALUE_TEMPLATE[] PROGMEM = "pr_mode_val_tpl"; // "preset_mode_value_template"
|
||||
const char HA_PRESET_MODES[] PROGMEM = "pr_modes"; // "preset_modes"
|
||||
|
||||
Reference in New Issue
Block a user