refactor: optimizations & fixes

This commit is contained in:
Yurii
2024-11-11 15:45:36 +03:00
parent 24a46f4c16
commit c6df74f06e
9 changed files with 244 additions and 205 deletions

View File

@@ -77,10 +77,19 @@ public:
return;
}
this->webServer->sendContent((const char*)this->buffer, this->bufferPos);
this->bufferPos = 0;
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
auto& client = this->webServer->client();
if (client.connected()) {
this->webServer->sendContent((const char*)this->buffer, this->bufferPos);
}
this->bufferPos = 0;
#ifdef ARDUINO_ARCH_ESP8266
::optimistic_yield(1000);
#endif
}

View File

@@ -37,7 +37,7 @@ public:
case Sensors::Purpose::DHW_RETURN_TEMP:
case Sensors::Purpose::EXHAUST_TEMP:
case Sensors::Purpose::TEMPERATURE:
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -87,7 +87,7 @@ public:
break;
case Sensors::Purpose::HUMIDITY:
doc[FPSTR(HA_DEVICE_CLASS)] = F("humidity");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_HUMIDITY);
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
break;
@@ -156,23 +156,25 @@ public:
String objId = Sensors::makeObjectId(sSensor.name);
// state topic
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(F("sensors"), objId.c_str());
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(
F("sensors"),
objId.c_str()
);
// set device class, name, value template for bluetooth sensors
// or name & value template for another sensors
String sName = sSensor.name;
if (sSensor.type == Sensors::Type::BLUETOOTH) {
// available state topic
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = doc[FPSTR(HA_STATE_TOPIC)];
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_SENSOR_CONN;
String sName = sSensor.name;
switch (vType) {
case Sensors::ValueType::TEMPERATURE:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("temp"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, F("temp"));
sName += F(" temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -184,20 +186,20 @@ public:
break;
case Sensors::ValueType::HUMIDITY:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("humidity"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_HUMIDITY));
sName += F(" humidity");
doc[FPSTR(HA_DEVICE_CLASS)] = F("humidity");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_HUMIDITY);
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
doc[FPSTR(HA_NAME)] = sName;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.humidity|float(0)|round(2) }}");
break;
case Sensors::ValueType::BATTERY:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("battery"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_BATTERY));
sName += F(" battery");
doc[FPSTR(HA_DEVICE_CLASS)] = F("battery");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_BATTERY);
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_PERCENT);
doc[FPSTR(HA_NAME)] = sName;
@@ -205,7 +207,7 @@ public:
break;
case Sensors::ValueType::RSSI:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("rssi"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_RSSI));
sName += F(" RSSI");
doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength");
@@ -223,10 +225,14 @@ public:
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_MODE)] = FPSTR(HA_MODE_BOX);
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(F("sensors"), objId.c_str(), F("set"));
doc[FPSTR(HA_COMMAND_TOPIC)] = this->getDeviceTopic(
F("sensors"),
objId.c_str(),
F("set")
);
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"value\": {{ value }}}");
doc[FPSTR(HA_NAME)] = sName;
doc[FPSTR(HA_NAME)] = sSensor.name;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.value|float(0)|round(2) }}");
} else {
@@ -234,20 +240,15 @@ public:
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_TOPIC)] = doc[FPSTR(HA_STATE_TOPIC)];
doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = AVAILABILITY_SENSOR_CONN;
doc[FPSTR(HA_NAME)] = sName;
doc[FPSTR(HA_NAME)] = sSensor.name;
doc[FPSTR(HA_VALUE_TEMPLATE)] = F("{{ value_json.value|float(0)|round(2) }}");
}
sName.clear();
// object id's
{
String objIdWithPrefix = this->getObjectIdWithPrefix(objId.c_str());
doc[FPSTR(HA_UNIQUE_ID)] = objIdWithPrefix;
doc[FPSTR(HA_OBJECT_ID)] = objIdWithPrefix;
}
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(objId.c_str());
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
String configTopic = this->makeConfigTopic(
const String& configTopic = this->makeConfigTopic(
sSensor.type == Sensors::Type::MANUAL ? FPSTR(HA_ENTITY_NUMBER) : FPSTR(HA_ENTITY_SENSOR),
objId.c_str()
);
@@ -264,32 +265,35 @@ public:
}
bool deleteDynamicSensor(Sensors::Settings& sSensor, Sensors::ValueType vType = Sensors::ValueType::PRIMARY) {
String objId = Sensors::makeObjectId(sSensor.name);
String objId;
if (sSensor.type == Sensors::Type::BLUETOOTH) {
switch (vType) {
case Sensors::ValueType::TEMPERATURE:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("temp"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, F("temp"));
break;
case Sensors::ValueType::HUMIDITY:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("humidity"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_HUMIDITY));
break;
case Sensors::ValueType::BATTERY:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("battery"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_BATTERY));
break;
case Sensors::ValueType::RSSI:
objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("rssi"));
Sensors::makeObjectIdWithSuffix(objId, sSensor.name, FPSTR(S_RSSI));
break;
default:
return false;
}
} else {
Sensors::makeObjectId(objId, sSensor.name);
}
String configTopic = this->makeConfigTopic(
const String& configTopic = this->makeConfigTopic(
sSensor.type == Sensors::Type::MANUAL ? FPSTR(HA_ENTITY_NUMBER) : FPSTR(HA_ENTITY_SENSOR),
objId.c_str()
);
@@ -303,18 +307,14 @@ public:
String objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("connected"));
// object id's
{
String objIdWithPrefix = this->getObjectIdWithPrefix(objId.c_str());
doc[FPSTR(HA_UNIQUE_ID)] = objIdWithPrefix;
doc[FPSTR(HA_OBJECT_ID)] = objIdWithPrefix;
}
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(objId.c_str());
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
// state topic
{
String parentObjId = Sensors::makeObjectId(sSensor.name);
String stateTopic = this->getDeviceTopic(F("sensors"), parentObjId.c_str());
doc[FPSTR(HA_STATE_TOPIC)] = stateTopic;
}
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSensor.name).c_str()
);
// sensor name
{
@@ -325,7 +325,7 @@ public:
doc[FPSTR(HA_NAME)] = sName;
}
String configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), objId.c_str());
const String& configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), objId.c_str());
objId.clear();
@@ -341,9 +341,10 @@ public:
}
bool deleteConnectionDynamicSensor(Sensors::Settings& sSensor) {
String objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("connected"));
String configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_BINARY_SENSOR), objId.c_str());
objId.clear();
const String& configTopic = this->makeConfigTopic(
FPSTR(HA_ENTITY_BINARY_SENSOR),
Sensors::makeObjectIdWithSuffix(sSensor.name, F("connected")).c_str()
);
return this->publish(configTopic.c_str());
}
@@ -353,18 +354,14 @@ public:
String objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("signal_quality"));
// object id's
{
String objIdWithPrefix = this->getObjectIdWithPrefix(objId.c_str());
doc[FPSTR(HA_UNIQUE_ID)] = objIdWithPrefix;
doc[FPSTR(HA_OBJECT_ID)] = objIdWithPrefix;
}
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(objId.c_str());
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
// state topic
{
String parentObjId = Sensors::makeObjectId(sSensor.name);
String stateTopic = this->getDeviceTopic(F("sensors"), parentObjId.c_str());
doc[FPSTR(HA_STATE_TOPIC)] = stateTopic;
}
doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSensor.name).c_str()
);
// sensor name
{
@@ -375,7 +372,7 @@ public:
doc[FPSTR(HA_NAME)] = sName;
}
String configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_SENSOR), objId.c_str());
const String& configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_SENSOR), objId.c_str());
objId.clear();
@@ -395,9 +392,10 @@ public:
bool deleteSignalQualityDynamicSensor(Sensors::Settings& sSensor) {
JsonDocument doc;
String objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("signal_quality"));
String configTopic = this->makeConfigTopic(FPSTR(HA_ENTITY_SENSOR), objId.c_str());
objId.clear();
const String& configTopic = this->makeConfigTopic(
FPSTR(HA_ENTITY_SENSOR),
Sensors::makeObjectIdWithSuffix(sSensor.name, F("signal_quality")).c_str()
);
return this->publish(configTopic.c_str());
}
@@ -432,7 +430,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_hysteresis"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -488,7 +486,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -522,7 +520,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -557,7 +555,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -591,7 +589,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -742,7 +740,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_min_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -776,7 +774,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_max_temp"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("temperature");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE);
if (unit == UnitSystem::METRIC) {
doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = FPSTR(HA_UNIT_OF_MEASUREMENT_C);
@@ -1119,7 +1117,7 @@ public:
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("rssi"));
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(S_RSSI));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC);
doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength");
@@ -1132,7 +1130,7 @@ public:
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_SENSOR), F("rssi")).c_str(), doc);
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_SENSOR), FPSTR(S_RSSI)).c_str(), doc);
}
bool publishUptime(bool enabledByDefault = true) {
@@ -1257,17 +1255,17 @@ public:
JsonDocument doc;
doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str();
doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault;
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("restart"));
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(S_RESTART));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("restart");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_RESTART);
doc[FPSTR(HA_NAME)] = F("Restart");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setStateTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"restart\": true}}");
doc[FPSTR(HA_EXPIRE_AFTER)] = this->expireAfter;
doc.shrinkToFit();
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_BUTTON), F("restart")).c_str(), doc);
return this->publish(this->makeConfigTopic(FPSTR(HA_ENTITY_BUTTON), FPSTR(S_RESTART)).c_str(), doc);
}
bool publishResetFaultButton(bool enabledByDefault = true) {
@@ -1280,7 +1278,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("reset_fault"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("restart");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_RESTART);
doc[FPSTR(HA_NAME)] = F("Reset fault");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setStateTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"resetFault\": true}}");
@@ -1300,7 +1298,7 @@ public:
doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("reset_diagnostic"));
doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)];
doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG);
doc[FPSTR(HA_DEVICE_CLASS)] = F("restart");
doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_RESTART);
doc[FPSTR(HA_NAME)] = F("Reset diagnostic");
doc[FPSTR(HA_COMMAND_TOPIC)] = this->setStateTopic.c_str();
doc[FPSTR(HA_COMMAND_TEMPLATE)] = F("{\"actions\": {\"resetDiagnostic\": true}}");

View File

@@ -76,17 +76,6 @@ protected:
vars.actions.restart = false;
this->restartSignalTime = millis();
// save settings
fsSettings.updateNow();
// save sensors settings
fsSensorsSettings.updateNow();
// force save network settings
if (fsNetworkSettings.updateNow() == FD_FILE_ERR && LittleFS.begin()) {
fsNetworkSettings.write();
}
Log.sinfoln(FPSTR(L_MAIN), F("Restart signal received. Restart after 10 sec."));
}
@@ -147,8 +136,9 @@ protected:
for (Stream* stream : Log.getStreams()) {
while (stream->available() > 0) {
stream->read();
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
}
}
@@ -159,7 +149,19 @@ protected:
// restart
if (this->restartSignalTime > 0 && millis() - this->restartSignalTime > 10000) {
// save settings
fsSettings.updateNow();
// save sensors settings
fsSensorsSettings.updateNow();
// force save network settings
if (fsNetworkSettings.updateNow() == FD_FILE_ERR && LittleFS.begin()) {
fsNetworkSettings.write();
}
this->restartSignalTime = 0;
this->delay(500);
ESP.restart();
}
}

View File

@@ -129,7 +129,7 @@ protected:
#endif
this->client->onMessage([this] (void*, size_t length) {
String topic = this->client->messageTopic();
const String& topic = this->client->messageTopic();
if (!length || length > 2048 || !topic.length()) {
return;
}
@@ -139,7 +139,7 @@ protected:
payload[i] = this->client->read();
}
this->onMessage(topic.c_str(), payload, length);
this->onMessage(topic, payload, length);
});
// writer settings
@@ -153,7 +153,7 @@ protected:
Log.straceln(FPSTR(L_MQTT), F("%s publish %u of %u bytes to topic: %s"), result ? F("Successfully") : F("Failed"), written, length, topic);
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
//this->client->poll();
@@ -162,13 +162,13 @@ protected:
#ifdef ARDUINO_ARCH_ESP8266
this->writer->setFlushEventCallback([this] (size_t, size_t) {
::delay(0);
::optimistic_yield(1000);
if (this->wifiClient->connected()) {
this->wifiClient->flush();
}
::delay(0);
::optimistic_yield(1000);
});
#endif
@@ -222,7 +222,7 @@ protected:
}
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
// publish variables and status
@@ -295,14 +295,14 @@ protected:
this->haHelper->deleteDynamicSensor(prevSettings, Sensors::ValueType::TEMPERATURE);
break;
case Sensors::Type::MANUAL: {
String topic = this->haHelper->getDeviceTopic(
case Sensors::Type::MANUAL:
this->client->unsubscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(prevSettings.name).c_str(),
F("set")
).c_str()
);
this->client->unsubscribe(topic.c_str());
}
default:
this->haHelper->deleteDynamicSensor(prevSettings, Sensors::ValueType::PRIMARY);
@@ -331,14 +331,14 @@ protected:
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
break;
case Sensors::Type::MANUAL: {
String topic = this->haHelper->getDeviceTopic(
case Sensors::Type::MANUAL:
this->client->subscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(prevSettings.name).c_str(),
F("set")
).c_str()
);
this->client->subscribe(topic.c_str());
}
default:
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);
@@ -372,13 +372,13 @@ protected:
Log.swarningln(FPSTR(L_MQTT), F("Disconnected (reason: %d uptime: %lu s.)"), this->client->connectError(), uptime);
}
void onMessage(const char* topic, uint8_t* payload, size_t length) {
void onMessage(const String& topic, uint8_t* payload, size_t length) {
if (!length) {
return;
}
if (settings.system.logLevel >= TinyLogger::Level::TRACE) {
Log.strace(FPSTR(L_MQTT_MSG), F("Topic: %s\r\n> "), topic);
Log.strace(FPSTR(L_MQTT_MSG), F("Topic: %s\r\n> "), topic.c_str());
if (Log.lock()) {
for (size_t i = 0; i < length; i++) {
if (payload[i] == 0) {
@@ -409,31 +409,27 @@ protected:
}
doc.shrinkToFit();
if (this->haHelper->getDeviceTopic(F("state/set")).equals(topic)) {
this->writer->publish(topic, nullptr, 0, true);
// delete topic
this->writer->publish(topic.c_str(), nullptr, 0, true);
if (this->haHelper->getDeviceTopic(F("state/set")).equals(topic)) {
if (jsonToVars(doc, vars)) {
this->resetPublishedVarsTime();
}
} else if (this->haHelper->getDeviceTopic(F("settings/set")).equals(topic)) {
this->writer->publish(topic, nullptr, 0, true);
if (safeJsonToSettings(doc, settings)) {
this->resetPublishedSettingsTime();
fsSettings.update();
}
} else {
this->writer->publish(topic, nullptr, 0, true);
String _topic = topic;
String sensorsTopic = this->haHelper->getDeviceTopic(F("sensors/"));
const String& sensorsTopic = this->haHelper->getDeviceTopic(F("sensors/"));
auto stLength = sensorsTopic.length();
if (_topic.startsWith(sensorsTopic) && _topic.endsWith(F("/set"))) {
if (_topic.length() > stLength + 4) {
String name = _topic.substring(stLength, _topic.indexOf('/', stLength));
if (topic.startsWith(sensorsTopic) && topic.endsWith(F("/set"))) {
if (topic.length() > stLength + 4) {
const String& name = topic.substring(stLength, topic.indexOf('/', stLength));
int16_t id = Sensors::getIdByObjectId(name.c_str());
if (id == -1) {
@@ -515,14 +511,14 @@ protected:
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::TEMPERATURE, settings.system.unitSystem);
break;
case Sensors::Type::MANUAL: {
String topic = this->haHelper->getDeviceTopic(
case Sensors::Type::MANUAL:
this->client->subscribe(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSettings.name).c_str(),
F("set")
).c_str()
);
this->client->subscribe(topic.c_str());
}
default:
this->haHelper->publishDynamicSensor(sSettings, Sensors::ValueType::PRIMARY, settings.system.unitSystem);
@@ -603,12 +599,14 @@ protected:
sensorResultToJson(sensorId, doc);
doc.shrinkToFit();
String topic = this->haHelper->getDeviceTopic(
return this->writer->publish(
this->haHelper->getDeviceTopic(
F("sensors"),
Sensors::makeObjectId(sSettings.name).c_str()
).c_str(),
doc,
true
);
return this->writer->publish(topic.c_str(), doc, true);
}
bool publishVariables(const char* topic) {

View File

@@ -232,7 +232,7 @@ protected:
}
}
String plain = this->webServer->arg(0);
const String& plain = this->webServer->arg(0);
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Request /api/backup/restore %d bytes: %s"), plain.length(), plain.c_str());
if (plain.length() < 5) {
@@ -246,7 +246,6 @@ protected:
JsonDocument doc;
DeserializationError dErr = deserializeJson(doc, plain);
plain.clear();
if (dErr != DeserializationError::Ok || doc.isNull() || !doc.size()) {
this->webServer->send(400);
@@ -254,12 +253,6 @@ protected:
}
bool changed = false;
if (!doc[FPSTR(S_SETTINGS)].isNull() && jsonToSettings(doc[FPSTR(S_SETTINGS)], settings)) {
vars.actions.restart = true;
fsSettings.update();
changed = true;
}
if (!doc[FPSTR(S_NETWORK)].isNull() && jsonToNetworkSettings(doc[FPSTR(S_NETWORK)], networkSettings)) {
fsNetworkSettings.update();
network->setHostname(networkSettings.hostname)
@@ -271,19 +264,28 @@ protected:
networkSettings.staticConfig.gateway,
networkSettings.staticConfig.subnet,
networkSettings.staticConfig.dns
)
->reconnect();
);
changed = true;
}
if (!doc[FPSTR(S_SETTINGS)].isNull() && jsonToSettings(doc[FPSTR(S_SETTINGS)], settings)) {
fsSettings.update();
changed = true;
}
if (!doc[FPSTR(S_SENSORS)].isNull()) {
for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) {
if (doc[FPSTR(S_SENSORS)][sensorId].isNull()) {
for (auto sensor : doc[FPSTR(S_SENSORS)].as<JsonObject>()) {
if (!isDigit(sensor.key().c_str())) {
continue;
}
auto sensorSettingsDoc = doc[FPSTR(S_SENSORS)][sensorId].to<JsonObject>();
if (jsonToSensorSettings(sensorId, sensorSettingsDoc, Sensors::settings[sensorId])){
int sensorId = atoi(sensor.key().c_str());
if (sensorId < 0 || sensorId > 255 || !Sensors::isValidSensorId(sensorId)) {
continue;
}
if (jsonToSensorSettings(sensorId, sensor.value(), Sensors::settings[sensorId])) {
fsSensorsSettings.update();
changed = true;
}
}
@@ -292,6 +294,10 @@ protected:
doc.clear();
doc.shrinkToFit();
if (changed) {
vars.actions.restart = true;
}
this->webServer->send(changed ? 201 : 200);
});
@@ -317,7 +323,7 @@ protected:
}
}
String plain = this->webServer->arg(0);
const String& plain = this->webServer->arg(0);
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Request /api/network/settings %d bytes: %s"), plain.length(), plain.c_str());
if (plain.length() < 5) {
@@ -331,7 +337,6 @@ protected:
JsonDocument doc;
DeserializationError dErr = deserializeJson(doc, plain);
plain.clear();
if (dErr != DeserializationError::Ok || doc.isNull() || !doc.size()) {
this->webServer->send(400);
@@ -390,7 +395,7 @@ protected:
JsonDocument doc;
for (short int i = 0; i < apCount; i++) {
String ssid = WiFi.SSID(i);
const String& ssid = WiFi.SSID(i);
doc[i][FPSTR(S_SSID)] = ssid;
doc[i][FPSTR(S_BSSID)] = WiFi.BSSIDstr(i);
doc[i][FPSTR(S_SIGNAL_QUALITY)] = NetworkMgr::rssiToSignalQuality(WiFi.RSSI(i));
@@ -433,7 +438,7 @@ protected:
}
}
String plain = this->webServer->arg(0);
const String& plain = this->webServer->arg(0);
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Request /api/settings %d bytes: %s"), plain.length(), plain.c_str());
if (plain.length() < 5) {
@@ -447,7 +452,6 @@ protected:
JsonDocument doc;
DeserializationError dErr = deserializeJson(doc, plain);
plain.clear();
if (dErr != DeserializationError::Ok || doc.isNull() || !doc.size()) {
this->webServer->send(400);
@@ -618,7 +622,7 @@ protected:
}
}
String plain = this->webServer->arg(0);
const String& plain = this->webServer->arg(0);
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Request /api/vars %d bytes: %s"), plain.length(), plain.c_str());
if (plain.length() < 5) {
@@ -632,7 +636,6 @@ protected:
JsonDocument doc;
DeserializationError dErr = deserializeJson(doc, plain);
plain.clear();
if (dErr != DeserializationError::Ok || doc.isNull() || !doc.size()) {
this->webServer->send(400);
@@ -829,7 +832,7 @@ protected:
this->webServer->onNotFound([this]() {
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Page not found, uri: %s"), this->webServer->uri().c_str());
const String uri = this->webServer->uri();
const String& uri = this->webServer->uri();
if (uri.equals(F("/"))) {
this->webServer->send(200, F("text/plain"), F("The file system is not flashed!"));
@@ -856,7 +859,7 @@ protected:
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Started: AP up or STA connected"));
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
} else if (this->stateWebServer() && !network->isApEnabled() && !network->isStaEnabled()) {
@@ -864,7 +867,7 @@ protected:
Log.straceln(FPSTR(L_PORTAL_WEBSERVER), F("Stopped: AP and STA down"));
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
}
@@ -874,7 +877,7 @@ protected:
Log.straceln(FPSTR(L_PORTAL_DNSSERVER), F("Started: AP up"));
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
} else if (this->stateDnsServer() && (!network->isApEnabled() || !this->stateWebServer())) {
@@ -882,14 +885,15 @@ protected:
Log.straceln(FPSTR(L_PORTAL_DNSSERVER), F("Stopped: AP down"));
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
}
if (this->stateDnsServer()) {
this->dnsServer->processNextRequest();
#ifdef ARDUINO_ARCH_ESP8266
::delay(0);
::optimistic_yield(1000);
#endif
}
@@ -907,7 +911,7 @@ protected:
}
void onCaptivePortal() {
const String uri = this->webServer->uri();
const String& uri = this->webServer->uri();
if (uri.equals(F("/connecttest.txt"))) {
this->webServer->sendHeader(F("Location"), F("http://logout.net"));
@@ -927,10 +931,10 @@ protected:
} else {
String portalUrl = F("http://");
portalUrl += network->getApIp().toString();
portalUrl += network->getApIp().toString().c_str();
portalUrl += '/';
this->webServer->sendHeader(F("Location"), portalUrl.c_str());
this->webServer->sendHeader(F("Location"), portalUrl);
this->webServer->send(302);
Log.straceln(FPSTR(L_PORTAL_CAPTIVE), F("Redirect to portal page with 302 code"));

View File

@@ -146,9 +146,10 @@ public:
return 0;
}
String refObjectId;
for (uint8_t id = 0; id < getMaxSensorId(); id++) {
String _objectId = Sensors::makeObjectId(settings[id].name);
if (strcmp(_objectId.c_str(), objectId) == 0) {
Sensors::makeObjectId(refObjectId, settings[id].name);
if (refObjectId.equals(objectId)) {
return id;
}
}
@@ -351,13 +352,10 @@ public:
return false;
}
template <class T>
static String cleanName(T value, char space = ' ') {
String clean = value;
static String& cleanName(String& value, char space = ' ') {
// only valid symbols
for (uint8_t pos = 0; pos < clean.length(); pos++) {
char symbol = clean.charAt(pos);
for (uint8_t pos = 0; pos < value.length(); pos++) {
char symbol = value.charAt(pos);
// 0..9
if (symbol >= 48 && symbol <= 57) {
@@ -379,39 +377,68 @@ public:
continue;
}
clean.setCharAt(pos, space);
value.setCharAt(pos, space);
}
clean.trim();
value.trim();
return clean;
return value;
}
template <class T>
static String cleanName(T value, char space = ' ') {
String res = value;
return cleanName(res, space);
}
template <class T>
static String& makeObjectId(String& res, T value, char separator = '_') {
res = value;
cleanName(res);
res.toLowerCase();
res.replace(' ', separator);
return res;
}
template <class T>
static String makeObjectId(T value, char separator = '_') {
auto objId = cleanName(value);
objId.toLowerCase();
objId.replace(' ', separator);
String res;
makeObjectId(res, value, separator);
return objId;
return res;
}
template <class TV, class TS>
static auto makeObjectIdWithSuffix(TV value, TS suffix, char separator = '_') {
auto objId = makeObjectId(value, separator);
objId += separator;
objId += suffix;
static String& makeObjectIdWithSuffix(String& res, TV value, TS suffix, char separator = '_') {
res.clear();
makeObjectId(res, value, separator);
res += separator;
res += suffix;
return objId;
return res;
}
template <class TV, class TS>
static String makeObjectIdWithSuffix(TV value, TS suffix, char separator = '_') {
String res;
makeObjectIdWithSuffix(res, value, suffix, separator);
return res;
}
template <class TV, class TP>
static auto makeObjectIdWithPrefix(TV value, TP prefix, char separator = '_') {
String objId = prefix;
objId += separator;
objId += makeObjectId(value, separator);
static String& makeObjectIdWithPrefix(String& res, TV value, TP prefix, char separator = '_') {
res = prefix;
res += separator;
res += makeObjectId(value, separator).c_str();
return objId;
return res;
}
template <class TV, class TP>
static String makeObjectIdWithPrefix(TV value, TP prefix, char separator = '_') {
String res;
return makeObjectIdWithPrefix(res, value, prefix, separator);
}
static uint8_t bluetoothRssiToQuality(int rssi) {

View File

@@ -154,7 +154,7 @@ Sensors::Settings sensorsSettings[SENSORS_AMOUNT] = {
false,
"Outdoor temp",
Sensors::Purpose::OUTDOOR_TEMP,
Sensors::Type::DALLAS_TEMP,
Sensors::Type::OT_OUTDOOR_TEMP,
DEFAULT_SENSOR_OUTDOOR_GPIO
},
{

View File

@@ -1461,7 +1461,8 @@ bool jsonToSensorSettings(const uint8_t sensorId, const JsonVariantConst src, Se
// name
if (!src[FPSTR(S_NAME)].isNull()) {
String value = Sensors::cleanName(src[FPSTR(S_NAME)].as<String>());
auto value = src[FPSTR(S_NAME)].as<String>();
Sensors::cleanName(value);
if (value.length() < sizeof(dst.name) && !value.equals(dst.name)) {
strcpy(dst.name, value.c_str());

View File

@@ -307,22 +307,6 @@ const setupRestoreBackupForm = (formSelector) => {
const data = JSON.parse(event.target.result);
console.log("Backup: ", data);
if (data.network != undefined) {
let response = await fetch(url, {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({"network": data.network})
});
if (!response.ok) {
onFailed();
return;
}
}
if (data.settings != undefined) {
let response = await fetch(url, {
method: 'POST',
@@ -362,6 +346,22 @@ const setupRestoreBackupForm = (formSelector) => {
}
}
if (data.network != undefined) {
let response = await fetch(url, {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({"network": data.network})
});
if (!response.ok) {
onFailed();
return;
}
}
onSuccess();
} catch (err) {