mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
Merge branch 'emsesp:dev' into dev
This commit is contained in:
@@ -13,6 +13,7 @@ export const readSystemStatus = () =>
|
|||||||
// commands
|
// commands
|
||||||
export const restart = () => alovaInstance.Post('/rest/restart');
|
export const restart = () => alovaInstance.Post('/rest/restart');
|
||||||
export const partition = () => alovaInstance.Post('/rest/partition');
|
export const partition = () => alovaInstance.Post('/rest/partition');
|
||||||
|
export const factoryPartition = () => alovaInstance.Post('/rest/factoryPartition');
|
||||||
export const factoryReset = () => alovaInstance.Post('/rest/factoryReset');
|
export const factoryReset = () => alovaInstance.Post('/rest/factoryReset');
|
||||||
|
|
||||||
// SystemLog
|
// SystemLog
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ const SystemStatus = () => {
|
|||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { send: factoryPartitionCommand } = useRequest(SystemApi.factoryPartition(), {
|
||||||
|
immediate: false
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: data,
|
data: data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
@@ -230,6 +234,21 @@ const SystemStatus = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const factoryPartition = async () => {
|
||||||
|
setProcessing(true);
|
||||||
|
await factoryPartitionCommand()
|
||||||
|
.then(() => {
|
||||||
|
setRestarting(true);
|
||||||
|
})
|
||||||
|
.catch((error: Error) => {
|
||||||
|
toast.error(error.message);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setConfirmRestart(false);
|
||||||
|
setProcessing(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const renderRestartDialog = () => (
|
const renderRestartDialog = () => (
|
||||||
<Dialog
|
<Dialog
|
||||||
sx={dialogStyle}
|
sx={dialogStyle}
|
||||||
@@ -248,15 +267,28 @@ const SystemStatus = () => {
|
|||||||
>
|
>
|
||||||
{LL.CANCEL()}
|
{LL.CANCEL()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
{data.has_loader && (
|
||||||
startIcon={<PowerSettingsNewIcon />}
|
<Button
|
||||||
variant="outlined"
|
startIcon={<PowerSettingsNewIcon />}
|
||||||
onClick={partition}
|
variant="outlined"
|
||||||
disabled={processing}
|
onClick={factoryPartition}
|
||||||
color="warning"
|
disabled={processing}
|
||||||
>
|
color="warning"
|
||||||
EMS-ESP Loader
|
>
|
||||||
</Button>
|
EMS-ESP Boot
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{data.has_partition && (
|
||||||
|
<Button
|
||||||
|
startIcon={<PowerSettingsNewIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={partition}
|
||||||
|
disabled={processing}
|
||||||
|
color="warning"
|
||||||
|
>
|
||||||
|
Partition
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
startIcon={<PowerSettingsNewIcon />}
|
startIcon={<PowerSettingsNewIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export interface HardwareStatus {
|
|||||||
psram: boolean;
|
psram: boolean;
|
||||||
psram_size?: number;
|
psram_size?: number;
|
||||||
free_psram?: number;
|
free_psram?: number;
|
||||||
has_loader: boolean;
|
|
||||||
free_caps: number;
|
free_caps: number;
|
||||||
model: string;
|
model: string;
|
||||||
}
|
}
|
||||||
@@ -44,6 +44,8 @@ export interface SystemStatus {
|
|||||||
ap_status: boolean;
|
ap_status: boolean;
|
||||||
network_status: NetworkConnectionStatus;
|
network_status: NetworkConnectionStatus;
|
||||||
wifi_rssi: number;
|
wifi_rssi: number;
|
||||||
|
has_loader: boolean;
|
||||||
|
has_partition: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LogLevel {
|
export enum LogLevel {
|
||||||
|
|||||||
@@ -41,8 +41,12 @@ void MqttSettingsService::startClient() {
|
|||||||
}
|
}
|
||||||
#ifndef TASMOTA_SDK
|
#ifndef TASMOTA_SDK
|
||||||
if (_state.enableTLS) {
|
if (_state.enableTLS) {
|
||||||
isSecure = true;
|
isSecure = true;
|
||||||
_mqttClient = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
|
if (emsesp::EMSESP::system_.PSram() > 0) {
|
||||||
|
_mqttClient = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::YES);
|
||||||
|
} else {
|
||||||
|
_mqttClient = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
|
||||||
|
}
|
||||||
if (_state.rootCA == "insecure") {
|
if (_state.rootCA == "insecure") {
|
||||||
static_cast<espMqttClientSecure *>(_mqttClient)->setInsecure();
|
static_cast<espMqttClientSecure *>(_mqttClient)->setInsecure();
|
||||||
} else {
|
} else {
|
||||||
@@ -59,8 +63,12 @@ void MqttSettingsService::startClient() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
isSecure = false;
|
isSecure = false;
|
||||||
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO);
|
if (emsesp::EMSESP::system_.PSram() > 0) {
|
||||||
|
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::YES);
|
||||||
|
} else {
|
||||||
|
_mqttClient = new espMqttClient(espMqttClientTypes::UseInternalTask::NO);
|
||||||
|
}
|
||||||
static_cast<espMqttClient *>(_mqttClient)->onConnect([this](bool sessionPresent) { onMqttConnect(sessionPresent); });
|
static_cast<espMqttClient *>(_mqttClient)->onConnect([this](bool sessionPresent) { onMqttConnect(sessionPresent); });
|
||||||
static_cast<espMqttClient *>(_mqttClient)->onDisconnect([this](espMqttClientTypes::DisconnectReason reason) { onMqttDisconnect(reason); });
|
static_cast<espMqttClient *>(_mqttClient)->onDisconnect([this](espMqttClientTypes::DisconnectReason reason) { onMqttDisconnect(reason); });
|
||||||
static_cast<espMqttClient *>(_mqttClient)
|
static_cast<espMqttClient *>(_mqttClient)
|
||||||
@@ -76,7 +84,9 @@ void MqttSettingsService::loop() {
|
|||||||
_disconnectedAt = configureMqtt() ? 0 : uuid::get_uptime();
|
_disconnectedAt = configureMqtt() ? 0 : uuid::get_uptime();
|
||||||
_reconfigureMqtt = false;
|
_reconfigureMqtt = false;
|
||||||
}
|
}
|
||||||
_mqttClient->loop();
|
if (emsesp::EMSESP::system_.PSram() == 0) {
|
||||||
|
_mqttClient->loop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MqttSettingsService::isEnabled() {
|
bool MqttSettingsService::isEnabled() {
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ RestartService::RestartService(AsyncWebServer * server, SecurityManager * securi
|
|||||||
server->on(PARTITION_SERVICE_PATH,
|
server->on(PARTITION_SERVICE_PATH,
|
||||||
HTTP_POST,
|
HTTP_POST,
|
||||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { partition(request); }, AuthenticationPredicates::IS_ADMIN));
|
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { partition(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||||
|
server->on(FACTORYPARTITION_SERVICE_PATH,
|
||||||
|
HTTP_POST,
|
||||||
|
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { factory(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestartService::restartNow() {
|
void RestartService::restartNow() {
|
||||||
@@ -26,14 +29,6 @@ void RestartService::restart(AsyncWebServerRequest * request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RestartService::partition(AsyncWebServerRequest * request) {
|
void RestartService::partition(AsyncWebServerRequest * request) {
|
||||||
const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
|
|
||||||
if (factory_partition) {
|
|
||||||
esp_ota_set_boot_partition(factory_partition);
|
|
||||||
emsesp::EMSESP::system_.store_nvs_values();
|
|
||||||
request->onDisconnect(RestartService::restartNow);
|
|
||||||
request->send(200);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const esp_partition_t * ota_partition = esp_ota_get_next_update_partition(nullptr);
|
const esp_partition_t * ota_partition = esp_ota_get_next_update_partition(nullptr);
|
||||||
if (!ota_partition) {
|
if (!ota_partition) {
|
||||||
request->send(400); // bad request
|
request->send(400); // bad request
|
||||||
@@ -50,3 +45,15 @@ void RestartService::partition(AsyncWebServerRequest * request) {
|
|||||||
request->onDisconnect(RestartService::restartNow);
|
request->onDisconnect(RestartService::restartNow);
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RestartService::factory(AsyncWebServerRequest * request) {
|
||||||
|
const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
|
||||||
|
if (!factory_partition) {
|
||||||
|
request->send(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
esp_ota_set_boot_partition(factory_partition);
|
||||||
|
emsesp::EMSESP::system_.store_nvs_values();
|
||||||
|
request->onDisconnect(RestartService::restartNow);
|
||||||
|
request->send(200);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#define RESTART_SERVICE_PATH "/rest/restart"
|
#define RESTART_SERVICE_PATH "/rest/restart"
|
||||||
#define PARTITION_SERVICE_PATH "/rest/partition"
|
#define PARTITION_SERVICE_PATH "/rest/partition"
|
||||||
|
#define FACTORYPARTITION_SERVICE_PATH "/rest/factoryPartition"
|
||||||
|
|
||||||
class RestartService {
|
class RestartService {
|
||||||
public:
|
public:
|
||||||
@@ -19,6 +20,7 @@ class RestartService {
|
|||||||
private:
|
private:
|
||||||
void restart(AsyncWebServerRequest * request);
|
void restart(AsyncWebServerRequest * request);
|
||||||
void partition(AsyncWebServerRequest * request);
|
void partition(AsyncWebServerRequest * request);
|
||||||
|
void factory(AsyncWebServerRequest * request);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1035,9 +1035,9 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
0,
|
0,
|
||||||
10000000UL);
|
10000000UL);
|
||||||
|
|
||||||
nrgHeatF_ = EMSESP::nvs_.getDouble(FL_(nrgHeat)[0], 0);
|
nrgHeatF_ = EMSESP::nvs_.getDouble("nrgheat", 0);
|
||||||
nrgWwF_ = EMSESP::nvs_.getDouble(FL_(nrgWw)[0], 0);
|
nrgWwF_ = EMSESP::nvs_.getDouble("nrgww", 0);
|
||||||
nomPower_ = EMSESP::nvs_.getUChar(FL_(nomPower)[0], 0);
|
nomPower_ = EMSESP::nvs_.getUChar("nompower", 0);
|
||||||
if (nrgHeatF_ < 0 || nrgHeatF_ >= EMS_VALUE_UINT32_NOTSET) {
|
if (nrgHeatF_ < 0 || nrgHeatF_ >= EMS_VALUE_UINT32_NOTSET) {
|
||||||
nrgHeatF_ = 0;
|
nrgHeatF_ = 0;
|
||||||
}
|
}
|
||||||
@@ -1057,14 +1057,14 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
|
|
||||||
void Boiler::store_energy() {
|
void Boiler::store_energy() {
|
||||||
// only write if something is changed
|
// only write if something is changed
|
||||||
if (nrgHeatF_ != EMSESP::nvs_.getDouble(FL_(nrgHeat)[0])) {
|
if (nrgHeatF_ != EMSESP::nvs_.getDouble("nrgheat")) {
|
||||||
EMSESP::nvs_.putDouble(FL_(nrgHeat)[0], nrgHeatF_);
|
EMSESP::nvs_.putDouble("nrgheat", nrgHeatF_);
|
||||||
}
|
}
|
||||||
if (nrgWwF_ != EMSESP::nvs_.getDouble(FL_(nrgWw)[0])) {
|
if (nrgWwF_ != EMSESP::nvs_.getDouble("nrgww")) {
|
||||||
EMSESP::nvs_.putDouble(FL_(nrgWw)[0], nrgWwF_);
|
EMSESP::nvs_.putDouble("nrgww", nrgWwF_);
|
||||||
}
|
}
|
||||||
if (nomPower_ != EMSESP::nvs_.getUChar(FL_(nomPower)[0])) {
|
if (nomPower_ != EMSESP::nvs_.getUChar("nopower")) {
|
||||||
EMSESP::nvs_.putUChar(FL_(nomPower)[0], nomPower_);
|
EMSESP::nvs_.putUChar("nompower", nomPower_);
|
||||||
}
|
}
|
||||||
// LOG_DEBUG("energy values stored");
|
// LOG_DEBUG("energy values stored");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1538,6 +1538,7 @@ EMSESP::EMSESP()
|
|||||||
// start all the core services
|
// start all the core services
|
||||||
// the services must be loaded in the correct order
|
// the services must be loaded in the correct order
|
||||||
void EMSESP::start() {
|
void EMSESP::start() {
|
||||||
|
system_.PSram(ESP.getPsramSize());
|
||||||
// don't need shell if running unit tests
|
// don't need shell if running unit tests
|
||||||
#ifndef EMSESP_UNITY
|
#ifndef EMSESP_UNITY
|
||||||
// Serial console's shell
|
// Serial console's shell
|
||||||
@@ -1667,6 +1668,9 @@ void EMSESP::loop() {
|
|||||||
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
|
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
|
||||||
mqtt_.loop(); // sends out anything in the MQTT queue
|
mqtt_.loop(); // sends out anything in the MQTT queue
|
||||||
webModulesService.loop(); // loop through the external library modules
|
webModulesService.loop(); // loop through the external library modules
|
||||||
|
if (system_.PSram() == 0) {
|
||||||
|
webSchedulerService.loop();
|
||||||
|
}
|
||||||
|
|
||||||
// force a query on the EMS devices to fetch latest data at a set interval (1 min)
|
// force a query on the EMS devices to fetch latest data at a set interval (1 min)
|
||||||
scheduled_fetch_values();
|
scheduled_fetch_values();
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ std::string Helpers::data_to_hex(const uint8_t * data, const uint8_t length) {
|
|||||||
return "<empty>";
|
return "<empty>";
|
||||||
}
|
}
|
||||||
|
|
||||||
char str[160] = {0};
|
char str[length * 3] = {0};
|
||||||
char buffer[4];
|
char buffer[4];
|
||||||
char * p = &str[0];
|
char * p = &str[0];
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
for (uint8_t i = 0; i < length; i++) {
|
||||||
@@ -456,16 +456,16 @@ float Helpers::transformNumFloat(float value, const int8_t numeric_operator, con
|
|||||||
|
|
||||||
switch (numeric_operator) {
|
switch (numeric_operator) {
|
||||||
case DeviceValueNumOp::DV_NUMOP_DIV2:
|
case DeviceValueNumOp::DV_NUMOP_DIV2:
|
||||||
val = ((value / 2) * 100 + 0.5);
|
val = (value * 100 / 2 + 0.5);
|
||||||
break;
|
break;
|
||||||
case DeviceValueNumOp::DV_NUMOP_DIV10:
|
case DeviceValueNumOp::DV_NUMOP_DIV10:
|
||||||
val = ((value / 10) * 100 + 0.5);
|
val = (value * 10 + 0.5);
|
||||||
break;
|
break;
|
||||||
case DeviceValueNumOp::DV_NUMOP_DIV60:
|
case DeviceValueNumOp::DV_NUMOP_DIV60:
|
||||||
val = ((value / 60) * 100 + 0.5);
|
val = (value * 10 / 6 + 0.5);
|
||||||
break;
|
break;
|
||||||
case DeviceValueNumOp::DV_NUMOP_DIV100:
|
case DeviceValueNumOp::DV_NUMOP_DIV100:
|
||||||
val = ((value / 100) * 100 + 0.5);
|
val = (value + 0.5);
|
||||||
break;
|
break;
|
||||||
case DeviceValueNumOp::DV_NUMOP_MUL5:
|
case DeviceValueNumOp::DV_NUMOP_MUL5:
|
||||||
val = value * 100 * 5;
|
val = value * 100 * 5;
|
||||||
@@ -635,6 +635,7 @@ bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * co
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
value_ui = 0;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -810,9 +811,9 @@ uint16_t Helpers::string2minutes(const std::string & str) {
|
|||||||
if (tmp > 60) {
|
if (tmp > 60) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Serial.print("*");
|
// Serial.print("*");
|
||||||
Serial.print(tmp);
|
// Serial.print(tmp);
|
||||||
Serial.println("*");
|
// Serial.println("*");
|
||||||
|
|
||||||
res += tmp;
|
res += tmp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -485,7 +485,6 @@ void System::start() {
|
|||||||
|
|
||||||
// get current memory values
|
// get current memory values
|
||||||
fstotal_ = LittleFS.totalBytes() / 1024; // read only once, it takes 500 ms to read
|
fstotal_ = LittleFS.totalBytes() / 1024; // read only once, it takes 500 ms to read
|
||||||
psram_ = ESP.getPsramSize() / 1024;
|
|
||||||
appused_ = ESP.getSketchSize() / 1024;
|
appused_ = ESP.getSketchSize() / 1024;
|
||||||
appfree_ = esp_ota_get_running_partition()->size / 1024 - appused_;
|
appfree_ = esp_ota_get_running_partition()->size / 1024 - appused_;
|
||||||
refreshHeapMem(); // refresh free heap and max alloc heap
|
refreshHeapMem(); // refresh free heap and max alloc heap
|
||||||
|
|||||||
@@ -246,6 +246,10 @@ class System {
|
|||||||
uint32_t FStotal() {
|
uint32_t FStotal() {
|
||||||
return fstotal_;
|
return fstotal_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PSram(uint32_t psram) {
|
||||||
|
psram_ = psram / 1024;
|
||||||
|
}
|
||||||
uint32_t PSram() {
|
uint32_t PSram() {
|
||||||
return psram_;
|
return psram_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,10 +68,14 @@ void WebCustomEntity::read(WebCustomEntity & webEntity, JsonObject root) {
|
|||||||
StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & webCustomEntity) {
|
StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & webCustomEntity) {
|
||||||
// reset everything to start fresh
|
// reset everything to start fresh
|
||||||
Command::erase_device_commands(EMSdevice::DeviceType::CUSTOM);
|
Command::erase_device_commands(EMSdevice::DeviceType::CUSTOM);
|
||||||
|
JsonDocument doc;
|
||||||
for (CustomEntityItem & entityItem : webCustomEntity.customEntityItems) {
|
for (CustomEntityItem & entityItem : webCustomEntity.customEntityItems) {
|
||||||
if (entityItem.raw) {
|
if (entityItem.raw) {
|
||||||
delete[] entityItem.raw;
|
delete[] entityItem.raw;
|
||||||
}
|
}
|
||||||
|
if (entityItem.ram) { // save name/value pairs for change checking
|
||||||
|
doc[entityItem.name] = entityItem.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
webCustomEntity.customEntityItems.clear();
|
webCustomEntity.customEntityItems.clear();
|
||||||
EMSESP::webCustomEntityService.ha_reset();
|
EMSESP::webCustomEntityService.ha_reset();
|
||||||
@@ -98,8 +102,9 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
|
|||||||
entityItem.writeable = true;
|
entityItem.writeable = true;
|
||||||
}
|
}
|
||||||
entityItem.raw = nullptr;
|
entityItem.raw = nullptr;
|
||||||
if (entityItem.value_type == DeviceValueType::STRING) {
|
if (entityItem.ram == 0 && entityItem.value_type == DeviceValueType::STRING) {
|
||||||
entityItem.raw = new uint8_t[(int)entityItem.factor + 1];
|
entityItem.raw = new uint8_t[(size_t)entityItem.factor + 1];
|
||||||
|
entityItem.data = "";
|
||||||
} else if (entityItem.value_type == DeviceValueType::BOOL) {
|
} else if (entityItem.value_type == DeviceValueType::BOOL) {
|
||||||
entityItem.value = EMS_VALUE_DEFAULT_BOOL;
|
entityItem.value = EMS_VALUE_DEFAULT_BOOL;
|
||||||
} else if (entityItem.value_type == DeviceValueType::INT8) {
|
} else if (entityItem.value_type == DeviceValueType::INT8) {
|
||||||
@@ -131,6 +136,12 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
|
|||||||
FL_(entity_cmd),
|
FL_(entity_cmd),
|
||||||
CommandFlag::ADMIN_ONLY);
|
CommandFlag::ADMIN_ONLY);
|
||||||
}
|
}
|
||||||
|
if (webCustomEntity.customEntityItems.back().ram && doc.containsKey(webCustomEntity.customEntityItems.back().name)
|
||||||
|
&& doc[webCustomEntity.customEntityItems.back().name] != webCustomEntity.customEntityItems.back().value) {
|
||||||
|
char cmd[COMMAND_MAX_LENGTH];
|
||||||
|
snprintf(cmd, sizeof(cmd), "%s/%s", F_(custom), webCustomEntity.customEntityItems.back().name.c_str());
|
||||||
|
EMSESP::webSchedulerService.onChange(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
@@ -144,10 +155,11 @@ bool WebCustomEntityService::command_setvalue(const char * value, const int8_t i
|
|||||||
entityItem.data = value;
|
entityItem.data = value;
|
||||||
} else if (entityItem.value_type == DeviceValueType::STRING) {
|
} else if (entityItem.value_type == DeviceValueType::STRING) {
|
||||||
auto telegram = strdup(value);
|
auto telegram = strdup(value);
|
||||||
uint8_t * data = new uint8_t[(strlen(telegram)) / 3 + 1];
|
uint8_t length = strlen(telegram) / 3 + 1;
|
||||||
|
uint8_t * data = new uint8_t[length];
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
char * p = strtok(telegram, " ,"); // delimiter
|
char * p = strtok(telegram, " ,"); // delimiter
|
||||||
while (p != nullptr) {
|
while (p != nullptr && count < length) {
|
||||||
data[count++] = (uint8_t)strtol(p, 0, 16);
|
data[count++] = (uint8_t)strtol(p, 0, 16);
|
||||||
p = strtok(nullptr, " ,");
|
p = strtok(nullptr, " ,");
|
||||||
}
|
}
|
||||||
@@ -467,7 +479,7 @@ uint8_t WebCustomEntityService::has_commands() {
|
|||||||
|
|
||||||
// send to dashboard, msgpack don't like serialized, use number
|
// send to dashboard, msgpack don't like serialized, use number
|
||||||
void WebCustomEntityService::generate_value_web(JsonObject output) {
|
void WebCustomEntityService::generate_value_web(JsonObject output) {
|
||||||
output["label"] = (std::string) "Custom Entities";
|
// output["label"] = (std::string) "Custom Entities";
|
||||||
JsonArray data = output["data"].to<JsonArray>();
|
JsonArray data = output["data"].to<JsonArray>();
|
||||||
uint8_t index = 0;
|
uint8_t index = 0;
|
||||||
for (const CustomEntityItem & entity : *customEntityItems_) {
|
for (const CustomEntityItem & entity : *customEntityItems_) {
|
||||||
@@ -548,8 +560,8 @@ void WebCustomEntityService::fetch() {
|
|||||||
uint8_t stop = (entity.offset + len[entity.value_type]) % fetchblock;
|
uint8_t stop = (entity.offset + len[entity.value_type]) % fetchblock;
|
||||||
bool is_fetched = start < fetchblock && stop < fetchblock; // make sure the complete value is a a fetched block
|
bool is_fetched = start < fetchblock && stop < fetchblock; // make sure the complete value is a a fetched block
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (entity.value_type != DeviceValueType::STRING && emsdevice->is_device_id(entity.device_id) && emsdevice->is_fetch(entity.type_id)
|
if (emsdevice->is_device_id(entity.device_id) && emsdevice->is_fetch(entity.type_id)
|
||||||
&& is_fetched) {
|
&& (is_fetched || entity.value_type == DeviceValueType::STRING)) {
|
||||||
needFetch = false;
|
needFetch = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -571,20 +583,22 @@ bool WebCustomEntityService::get_value(std::shared_ptr<const Telegram> telegram)
|
|||||||
// read-length of BOOL, INT8, UINT8, INT16, UINT16, UINT24, TIME, UINT32
|
// read-length of BOOL, INT8, UINT8, INT16, UINT16, UINT24, TIME, UINT32
|
||||||
const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3, 4};
|
const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3, 4};
|
||||||
for (auto & entity : *customEntityItems_) {
|
for (auto & entity : *customEntityItems_) {
|
||||||
if (entity.value_type == DeviceValueType::STRING && telegram->type_id == entity.type_id && telegram->src == entity.device_id
|
if (entity.value_type == DeviceValueType::STRING && entity.raw && telegram->type_id == entity.type_id && telegram->src == entity.device_id
|
||||||
&& (telegram->offset >= entity.offset || entity.offset < telegram->offset + telegram->message_length)) {
|
&& (telegram->offset >= entity.offset || entity.offset < telegram->offset + telegram->message_length)) {
|
||||||
auto message_length = telegram->message_length;
|
auto message_length = telegram->message_length;
|
||||||
auto message_data = telegram->message_data;
|
auto message_data = telegram->message_data;
|
||||||
|
auto offset = telegram->offset - entity.offset;
|
||||||
if (telegram->offset < entity.offset) {
|
if (telegram->offset < entity.offset) {
|
||||||
message_data = &telegram->message_data[entity.offset - telegram->offset];
|
message_data = &telegram->message_data[entity.offset - telegram->offset];
|
||||||
message_length -= entity.offset - telegram->offset;
|
message_length -= entity.offset - telegram->offset;
|
||||||
|
offset = 0;
|
||||||
}
|
}
|
||||||
auto length = std::min((int)telegram->offset - entity.offset + telegram->message_length, (int)entity.factor);
|
auto length = std::min(offset + message_length, (int)entity.factor);
|
||||||
auto rest = std::min((int)entity.factor - telegram->offset + entity.offset, (int)message_length);
|
auto rest = std::min((int)entity.factor - offset, (int)message_length);
|
||||||
if (rest > 0) {
|
if (rest > 0) {
|
||||||
memcpy(&entity.raw[telegram->offset - entity.offset], message_data, rest);
|
memcpy(&entity.raw[offset], message_data, rest);
|
||||||
auto data = Helpers::data_to_hex(entity.raw, (uint8_t)length);
|
auto data = Helpers::data_to_hex(entity.raw, (uint8_t)length);
|
||||||
if (entity.data != data) {
|
if (entity.data != data && length == (int)entity.factor) {
|
||||||
entity.data = data;
|
entity.data = data;
|
||||||
if (Mqtt::publish_single()) {
|
if (Mqtt::publish_single()) {
|
||||||
publish_single(entity);
|
publish_single(entity);
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ void WebSchedulerService::begin() {
|
|||||||
snprintf(topic, sizeof(topic), "%s/#", F_(scheduler));
|
snprintf(topic, sizeof(topic), "%s/#", F_(scheduler));
|
||||||
Mqtt::subscribe(EMSdevice::DeviceType::SCHEDULER, topic, nullptr); // use empty function callback
|
Mqtt::subscribe(EMSdevice::DeviceType::SCHEDULER, topic, nullptr); // use empty function callback
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
xTaskCreate((TaskFunction_t)scheduler_task, "scheduler_task", 4096, NULL, 1, NULL);
|
if (EMSESP::system_.PSram()) {
|
||||||
|
xTaskCreate((TaskFunction_t)scheduler_task, "scheduler_task", 4096, NULL, 1, NULL);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,9 +469,9 @@ void WebSchedulerService::loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check conditions every 10 seconds
|
// check conditions every 10 seconds, start after one minute
|
||||||
uint32_t uptime_sec = uuid::get_uptime_sec() / 10;
|
uint32_t uptime_sec = uuid::get_uptime_sec() / 10;
|
||||||
if (last_uptime_sec != uptime_sec) {
|
if (last_uptime_sec != uptime_sec && uptime_sec > 5) {
|
||||||
condition();
|
condition();
|
||||||
last_uptime_sec = uptime_sec;
|
last_uptime_sec = uptime_sec;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,17 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
|
||||||
|
root["has_loader"] = partition != NULL && partition != esp_ota_get_running_partition();
|
||||||
|
partition = esp_ota_get_next_update_partition(nullptr);
|
||||||
|
if (partition) {
|
||||||
|
uint64_t buffer;
|
||||||
|
esp_partition_read(partition, 0, &buffer, 8);
|
||||||
|
root["has_partition"] = (buffer != 0xFFFFFFFFFFFFFFFF);
|
||||||
|
} else {
|
||||||
|
root["has_partition"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
@@ -127,19 +138,6 @@ void WebStatusService::hardwareStatus(AsyncWebServerRequest * request) {
|
|||||||
root["free_psram"] = ESP.getFreePsram() / 1024;
|
root["free_psram"] = ESP.getFreePsram() / 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
|
|
||||||
if (partition != NULL) { // factory partition found
|
|
||||||
root["has_loader"] = true;
|
|
||||||
} else { // check for not empty, smaller OTA partition
|
|
||||||
partition = esp_ota_get_next_update_partition(nullptr);
|
|
||||||
if (partition) {
|
|
||||||
uint64_t buffer;
|
|
||||||
esp_partition_read(partition, 0, &buffer, 8);
|
|
||||||
const esp_partition_t * running = esp_ota_get_running_partition();
|
|
||||||
root["has_loader"] = (buffer != 0xFFFFFFFFFFFFFFFF && running->size != partition->size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root["model"] = EMSESP::system_.getBBQKeesGatewayDetails();
|
root["model"] = EMSESP::system_.getBBQKeesGatewayDetails();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user