mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-09 17:29:50 +03:00
Merge branch 'dev11' into dev
This commit is contained in:
@@ -57,17 +57,17 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
||||
|
||||
// this creates the customization file, saving it to the FS
|
||||
void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
||||
// Dallas Sensor customization
|
||||
JsonArray sensorsJson = root.createNestedArray("sensors");
|
||||
// Temperature Sensor customization
|
||||
JsonArray sensorsJson = root.createNestedArray("ts");
|
||||
for (const SensorCustomization & sensor : settings.sensorCustomizations) {
|
||||
JsonObject sensorJson = sensorsJson.createNestedObject();
|
||||
sensorJson["id"] = sensor.id; // is
|
||||
sensorJson["id"] = sensor.id; // ID of chip
|
||||
sensorJson["name"] = sensor.name; // n
|
||||
sensorJson["offset"] = sensor.offset; // o
|
||||
}
|
||||
|
||||
// Analog Sensor customization
|
||||
JsonArray analogJson = root.createNestedArray("analogs");
|
||||
JsonArray analogJson = root.createNestedArray("as");
|
||||
for (const AnalogCustomization & sensor : settings.analogCustomizations) {
|
||||
JsonObject sensorJson = analogJson.createNestedObject();
|
||||
sensorJson["gpio"] = sensor.gpio; // g
|
||||
@@ -98,7 +98,7 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
||||
StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) {
|
||||
#ifdef EMSESP_STANDALONE
|
||||
// invoke some fake data for testing
|
||||
const char * json = "{\"sensors\":[],\"analogs\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom "
|
||||
const char * json = "{\"ts\":[],\"as\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom "
|
||||
"name for heating active\",\"08tapwateractive\"]}]}";
|
||||
|
||||
StaticJsonDocument<500> doc;
|
||||
@@ -111,10 +111,10 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
||||
Serial.println(COLOR_RESET);
|
||||
#endif
|
||||
|
||||
// Dallas Sensor customization
|
||||
// Temperature Sensor customization
|
||||
settings.sensorCustomizations.clear();
|
||||
if (root["sensors"].is<JsonArray>()) {
|
||||
for (const JsonObject sensorJson : root["sensors"].as<JsonArray>()) {
|
||||
if (root["ts"].is<JsonArray>()) {
|
||||
for (const JsonObject sensorJson : root["ts"].as<JsonArray>()) {
|
||||
// create each of the sensor, overwriting any previous settings
|
||||
auto sensor = SensorCustomization();
|
||||
sensor.id = sensorJson["id"].as<std::string>();
|
||||
@@ -126,8 +126,8 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
||||
|
||||
// Analog Sensor customization
|
||||
settings.analogCustomizations.clear();
|
||||
if (root["analogs"].is<JsonArray>()) {
|
||||
for (const JsonObject analogJson : root["analogs"].as<JsonArray>()) {
|
||||
if (root["as"].is<JsonArray>()) {
|
||||
for (const JsonObject analogJson : root["as"].as<JsonArray>()) {
|
||||
// create each of the sensor, overwriting any previous settings
|
||||
auto sensor = AnalogCustomization();
|
||||
sensor.gpio = analogJson["gpio"];
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
// Customization for dallas sensor
|
||||
// Customization for temperature sensor
|
||||
class SensorCustomization {
|
||||
public:
|
||||
std::string id;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -25,12 +25,13 @@ using namespace std::placeholders; // for `_1` etc
|
||||
WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: _device_data_handler(DEVICE_DATA_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::device_data, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED))
|
||||
, _write_value_handler(WRITE_VALUE_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
|
||||
, _write_sensor_handler(WRITE_SENSOR_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_sensor, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
|
||||
, _write_analog_handler(WRITE_ANALOG_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_analog, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
|
||||
, _write_value_handler(WRITE_DEVICE_VALUE_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_device_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
|
||||
, _write_temperature_handler(WRITE_TEMPERATURE_SENSOR_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_temperature_sensor, this, _1, _2),
|
||||
AuthenticationPredicates::IS_ADMIN))
|
||||
, _write_analog_handler(WRITE_ANALOG_SENSOR_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_analog_sensor, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
|
||||
server->on(CORE_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
@@ -51,9 +52,9 @@ WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securi
|
||||
_write_value_handler.setMaxContentLength(256);
|
||||
server->addHandler(&_write_value_handler);
|
||||
|
||||
_write_sensor_handler.setMethod(HTTP_POST);
|
||||
_write_sensor_handler.setMaxContentLength(256);
|
||||
server->addHandler(&_write_sensor_handler);
|
||||
_write_temperature_handler.setMethod(HTTP_POST);
|
||||
_write_temperature_handler.setMaxContentLength(256);
|
||||
server->addHandler(&_write_temperature_handler);
|
||||
|
||||
_write_analog_handler.setMethod(HTTP_POST);
|
||||
_write_analog_handler.setMaxContentLength(256);
|
||||
@@ -75,40 +76,37 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
|
||||
// list is already sorted by device type
|
||||
JsonArray devices = root.createNestedArray("devices");
|
||||
char buffer[3];
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
// ignore controller
|
||||
if (emsdevice && (emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER || emsdevice->count_entities() > 0)) {
|
||||
JsonObject obj = devices.createNestedObject();
|
||||
obj["id"] = Helpers::smallitoa(buffer, emsdevice->unique_id()); // a unique id as a string
|
||||
obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name
|
||||
obj["t"] = emsdevice->device_type(); // device type number
|
||||
obj["b"] = emsdevice->brand_to_char(); // brand
|
||||
obj["n"] = emsdevice->name(); // name
|
||||
obj["d"] = emsdevice->device_id(); // deviceid
|
||||
obj["p"] = emsdevice->product_id(); // productid
|
||||
obj["v"] = emsdevice->version(); // version
|
||||
obj["e"] = emsdevice->count_entities(); // number of entities (device values)
|
||||
obj["id"] = emsdevice->unique_id(); // a unique id
|
||||
obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name
|
||||
obj["t"] = emsdevice->device_type(); // device type number
|
||||
obj["b"] = emsdevice->brand_to_char(); // brand
|
||||
obj["n"] = emsdevice->name(); // name
|
||||
obj["d"] = emsdevice->device_id(); // deviceid
|
||||
obj["p"] = emsdevice->product_id(); // productid
|
||||
obj["v"] = emsdevice->version(); // version
|
||||
obj["e"] = emsdevice->count_entities(); // number of entities (device values)
|
||||
}
|
||||
}
|
||||
|
||||
// add any custom entities
|
||||
if (EMSESP::webEntityService.count_entities()) {
|
||||
JsonObject obj = devices.createNestedObject();
|
||||
obj["id"] = "99"; // the last unique id as a string
|
||||
obj["tn"] = "Custom"; // translated device type name
|
||||
obj["t"] = EMSdevice::DeviceType::CUSTOM; // device type number
|
||||
obj["b"] = 0; // brand
|
||||
obj["n"] = Helpers::translated_word(FL_(custom_device)); // name
|
||||
obj["d"] = 0; // deviceid
|
||||
obj["p"] = 0; // productid
|
||||
obj["v"] = 0; // version
|
||||
obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values)
|
||||
obj["id"] = 99; // the last unique id
|
||||
obj["tn"] = Helpers::translated_word(FL_(custom_device)); // translated device type name
|
||||
obj["t"] = EMSdevice::DeviceType::CUSTOM; // device type number
|
||||
obj["b"] = Helpers::translated_word(FL_(na)); // brand
|
||||
obj["n"] = Helpers::translated_word(FL_(custom_device_name)); // name
|
||||
obj["d"] = 0; // deviceid
|
||||
obj["p"] = 0; // productid
|
||||
obj["v"] = 0; // version
|
||||
obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values)
|
||||
}
|
||||
|
||||
// sensors stuff
|
||||
root["s_n"] = Helpers::translated_word(FL_(sensors_device));
|
||||
root["active_sensors"] = EMSESP::dallassensor_.no_sensors() + (EMSESP::analogsensor_.analog_enabled() ? EMSESP::analogsensor_.no_sensors() : 0);
|
||||
root["analog_enabled"] = EMSESP::analogsensor_.analog_enabled();
|
||||
root["connected"] = EMSESP::bus_status() != 2;
|
||||
root["connected"] = EMSESP::bus_status() != 2;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@@ -116,15 +114,14 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
|
||||
// sensor data - sends back to web
|
||||
// /sensorData endpoint
|
||||
// the "sensors" and "analogs" are arrays and must exist
|
||||
void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// dallas sensors
|
||||
JsonArray sensors = root.createNestedArray("sensors");
|
||||
if (EMSESP::dallassensor_.have_sensors()) {
|
||||
for (const auto & sensor : EMSESP::dallassensor_.sensors()) {
|
||||
// temperature sensors
|
||||
JsonArray sensors = root.createNestedArray("ts");
|
||||
if (EMSESP::temperaturesensor_.have_sensors()) {
|
||||
for (const auto & sensor : EMSESP::temperaturesensor_.sensors()) {
|
||||
JsonObject obj = sensors.createNestedObject();
|
||||
obj["id"] = sensor.id(); // id as string
|
||||
obj["n"] = sensor.name(); // name
|
||||
@@ -145,32 +142,29 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
||||
}
|
||||
|
||||
// analog sensors
|
||||
JsonArray analogs = root.createNestedArray("analogs");
|
||||
JsonArray analogs = root.createNestedArray("as");
|
||||
if (EMSESP::analog_enabled() && EMSESP::analogsensor_.have_sensors()) {
|
||||
uint8_t count = 0;
|
||||
char buffer[3];
|
||||
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
|
||||
// don't send if it's marked for removal
|
||||
if (sensor.type() != AnalogSensor::AnalogType::MARK_DELETED) {
|
||||
count++;
|
||||
JsonObject obj = analogs.createNestedObject();
|
||||
obj["id"] = Helpers::smallitoa(buffer, count); // needed for sorting table
|
||||
obj["g"] = sensor.gpio();
|
||||
obj["n"] = sensor.name();
|
||||
obj["u"] = sensor.uom();
|
||||
obj["o"] = sensor.offset();
|
||||
obj["f"] = sensor.factor();
|
||||
obj["t"] = sensor.type();
|
||||
JsonObject obj = analogs.createNestedObject();
|
||||
obj["id"] = ++count; // needed for sorting table
|
||||
obj["g"] = sensor.gpio();
|
||||
obj["n"] = sensor.name();
|
||||
obj["u"] = sensor.uom();
|
||||
obj["o"] = sensor.offset();
|
||||
obj["f"] = sensor.factor();
|
||||
obj["t"] = sensor.type();
|
||||
|
||||
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) {
|
||||
obj["v"] = Helpers::transformNumFloat(sensor.value(), 0); // is optional and is a float
|
||||
} else {
|
||||
obj["v"] = 0; // must have a value for web sorting to work
|
||||
}
|
||||
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) {
|
||||
obj["v"] = Helpers::transformNumFloat(sensor.value(), 0); // is optional and is a float
|
||||
} else {
|
||||
obj["v"] = 0; // must have a value for web sorting to work
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root["analog_enabled"] = EMSESP::analogsensor_.analog_enabled();
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
@@ -227,7 +221,7 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant &
|
||||
|
||||
// takes a command and its data value from a specific EMS Device, from the Web
|
||||
// assumes the service has been checked for admin authentication
|
||||
void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
if (json.is<JsonObject>()) {
|
||||
JsonObject dv = json["devicevalue"];
|
||||
uint8_t unique_id = json["id"];
|
||||
@@ -314,9 +308,9 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant &
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
// takes a dallas sensor name and optional offset from the WebUI and update the customization settings
|
||||
// via the Dallas service
|
||||
void WebDataService::write_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
// takes a temperaturesensor name and optional offset from the WebUI and update the customization settings
|
||||
// via the temperaturesensor service
|
||||
void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
bool ok = false;
|
||||
if (json.is<JsonObject>()) {
|
||||
JsonObject sensor = json;
|
||||
@@ -330,7 +324,7 @@ void WebDataService::write_sensor(AsyncWebServerRequest * request, JsonVariant &
|
||||
if (EMSESP::system_.fahrenheit()) {
|
||||
offset10 = offset / 0.18;
|
||||
}
|
||||
ok = EMSESP::dallassensor_.update(id, name, offset10);
|
||||
ok = EMSESP::temperaturesensor_.update(id, name, offset10);
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
||||
@@ -338,18 +332,19 @@ void WebDataService::write_sensor(AsyncWebServerRequest * request, JsonVariant &
|
||||
}
|
||||
|
||||
// update the analog record, or create a new one
|
||||
void WebDataService::write_analog(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
void WebDataService::write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
bool ok = false;
|
||||
if (json.is<JsonObject>()) {
|
||||
JsonObject analog = json;
|
||||
|
||||
uint8_t gpio = analog["gpio"]; // this is the unique key, the GPIO
|
||||
std::string name = analog["name"];
|
||||
double factor = analog["factor"];
|
||||
double offset = analog["offset"];
|
||||
uint8_t uom = analog["uom"];
|
||||
int8_t type = analog["type"];
|
||||
ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type);
|
||||
uint8_t gpio = analog["gpio"];
|
||||
std::string name = analog["name"];
|
||||
double factor = analog["factor"];
|
||||
double offset = analog["offset"];
|
||||
uint8_t uom = analog["uom"];
|
||||
int8_t type = analog["type"];
|
||||
bool deleted = analog["deleted"];
|
||||
ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type, deleted);
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -26,9 +26,9 @@
|
||||
#define SENSOR_DATA_SERVICE_PATH "/rest/sensorData"
|
||||
|
||||
// POST
|
||||
#define WRITE_VALUE_SERVICE_PATH "/rest/writeValue"
|
||||
#define WRITE_SENSOR_SERVICE_PATH "/rest/writeSensor"
|
||||
#define WRITE_ANALOG_SERVICE_PATH "/rest/writeAnalog"
|
||||
#define WRITE_DEVICE_VALUE_SERVICE_PATH "/rest/writeDeviceValue"
|
||||
#define WRITE_TEMPERATURE_SENSOR_SERVICE_PATH "/rest/writeTemperatureSensor"
|
||||
#define WRITE_ANALOG_SENSOR_SERVICE_PATH "/rest/writeAnalogSensor"
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
@@ -47,12 +47,12 @@ class WebDataService {
|
||||
|
||||
// POST
|
||||
void device_data(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_value(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_analog(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_device_value(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void scan_devices(AsyncWebServerRequest * request);
|
||||
|
||||
AsyncCallbackJsonWebHandler _device_data_handler, _write_value_handler, _write_sensor_handler, _write_analog_handler;
|
||||
AsyncCallbackJsonWebHandler _device_data_handler, _write_value_handler, _write_temperature_handler, _write_analog_handler;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -33,20 +33,22 @@ void WebEntityService::begin() {
|
||||
EMSESP::logger().info("Starting custom entity service");
|
||||
}
|
||||
|
||||
// this creates the scheduler file, saving it to the FS
|
||||
// and also calls when the Scheduler web page is refreshed
|
||||
// this creates the entity file, saving it to the FS
|
||||
// and also calls when the Entity web page is refreshed
|
||||
void WebEntity::read(WebEntity & webEntity, JsonObject & root) {
|
||||
JsonArray entity = root.createNestedArray("entity");
|
||||
JsonArray entity = root.createNestedArray("entities");
|
||||
uint8_t counter = 0;
|
||||
for (const EntityItem & entityItem : webEntity.entityItems) {
|
||||
JsonObject ei = entity.createNestedObject();
|
||||
ei["device_id"] = Helpers::hextoa(entityItem.device_id, false);
|
||||
ei["type_id"] = Helpers::hextoa(entityItem.type_id, false);
|
||||
ei["offset"] = entityItem.offset;
|
||||
ei["factor"] = entityItem.factor;
|
||||
ei["name"] = entityItem.name;
|
||||
ei["uom"] = entityItem.uom;
|
||||
ei["val_type"] = entityItem.valuetype;
|
||||
ei["write"] = entityItem.writeable;
|
||||
JsonObject ei = entity.createNestedObject();
|
||||
ei["id"] = counter++; // id is only used to render the table and must be unique
|
||||
ei["device_id"] = entityItem.device_id;
|
||||
ei["type_id"] = entityItem.type_id;
|
||||
ei["offset"] = entityItem.offset;
|
||||
ei["factor"] = entityItem.factor;
|
||||
ei["name"] = entityItem.name;
|
||||
ei["uom"] = entityItem.uom;
|
||||
ei["value_type"] = entityItem.value_type;
|
||||
ei["writeable"] = entityItem.writeable;
|
||||
EMSESP::webEntityService.render_value(ei, entityItem, true, true);
|
||||
}
|
||||
}
|
||||
@@ -59,33 +61,34 @@ StateUpdateResult WebEntity::update(JsonObject & root, WebEntity & webEntity) {
|
||||
}
|
||||
webEntity.entityItems.clear();
|
||||
|
||||
if (root["entity"].is<JsonArray>()) {
|
||||
for (const JsonObject ei : root["entity"].as<JsonArray>()) {
|
||||
auto entityItem = EntityItem();
|
||||
entityItem.device_id = Helpers::hextoint(ei["device_id"]);
|
||||
entityItem.type_id = Helpers::hextoint(ei["type_id"]);
|
||||
entityItem.offset = ei["offset"];
|
||||
entityItem.factor = ei["factor"];
|
||||
entityItem.name = ei["name"].as<std::string>();
|
||||
entityItem.uom = ei["uom"];
|
||||
entityItem.valuetype = ei["val_type"];
|
||||
entityItem.writeable = ei["write"];
|
||||
if (root["entities"].is<JsonArray>()) {
|
||||
for (const JsonObject ei : root["entities"].as<JsonArray>()) {
|
||||
auto entityItem = EntityItem();
|
||||
entityItem.device_id = ei["device_id"]; // send as numeric, will be converted to string in web
|
||||
entityItem.type_id = ei["type_id"];
|
||||
entityItem.offset = ei["offset"];
|
||||
entityItem.factor = ei["factor"];
|
||||
entityItem.name = ei["name"].as<std::string>();
|
||||
entityItem.uom = ei["uom"];
|
||||
entityItem.value_type = ei["value_type"];
|
||||
entityItem.writeable = ei["writeable"];
|
||||
|
||||
if (entityItem.valuetype == DeviceValueType::BOOL) {
|
||||
entityItem.val = EMS_VALUE_DEFAULT_BOOL;
|
||||
} else if (entityItem.valuetype == DeviceValueType::INT) {
|
||||
entityItem.val = EMS_VALUE_DEFAULT_INT;
|
||||
} else if (entityItem.valuetype == DeviceValueType::UINT) {
|
||||
entityItem.val = EMS_VALUE_DEFAULT_UINT;
|
||||
} else if (entityItem.valuetype == DeviceValueType::SHORT) {
|
||||
entityItem.val = EMS_VALUE_DEFAULT_SHORT;
|
||||
} else if (entityItem.valuetype == DeviceValueType::USHORT) {
|
||||
entityItem.val = EMS_VALUE_DEFAULT_USHORT;
|
||||
} else { // if (entityItem.valuetype == DeviceValueType::ULONG || entityItem.valuetype == DeviceValueType::TIME) {
|
||||
entityItem.val = EMS_VALUE_DEFAULT_ULONG;
|
||||
if (entityItem.value_type == DeviceValueType::BOOL) {
|
||||
entityItem.value = EMS_VALUE_DEFAULT_BOOL;
|
||||
} else if (entityItem.value_type == DeviceValueType::INT) {
|
||||
entityItem.value = EMS_VALUE_DEFAULT_INT;
|
||||
} else if (entityItem.value_type == DeviceValueType::UINT) {
|
||||
entityItem.value = EMS_VALUE_DEFAULT_UINT;
|
||||
} else if (entityItem.value_type == DeviceValueType::SHORT) {
|
||||
entityItem.value = EMS_VALUE_DEFAULT_SHORT;
|
||||
} else if (entityItem.value_type == DeviceValueType::USHORT) {
|
||||
entityItem.value = EMS_VALUE_DEFAULT_USHORT;
|
||||
} else { // if (entityItem.value_type == DeviceValueType::ULONG || entityItem.valuetype == DeviceValueType::TIME) {
|
||||
entityItem.value = EMS_VALUE_DEFAULT_ULONG;
|
||||
}
|
||||
|
||||
webEntity.entityItems.push_back(entityItem); // add to list
|
||||
|
||||
if (entityItem.writeable) {
|
||||
Command::add(
|
||||
EMSdevice::DeviceType::CUSTOM,
|
||||
@@ -106,7 +109,7 @@ bool WebEntityService::command_setvalue(const char * value, const std::string na
|
||||
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; });
|
||||
for (EntityItem & entityItem : *entityItems) {
|
||||
if (entityItem.name == name) {
|
||||
if (entityItem.valuetype == DeviceValueType::BOOL) {
|
||||
if (entityItem.value_type == DeviceValueType::BOOL) {
|
||||
bool v;
|
||||
if (!Helpers::value2bool(value, v)) {
|
||||
return false;
|
||||
@@ -118,9 +121,9 @@ bool WebEntityService::command_setvalue(const char * value, const std::string na
|
||||
return false;
|
||||
}
|
||||
int v = f / entityItem.factor;
|
||||
if (entityItem.valuetype == DeviceValueType::UINT || entityItem.valuetype == DeviceValueType::INT) {
|
||||
if (entityItem.value_type == DeviceValueType::UINT || entityItem.value_type == DeviceValueType::INT) {
|
||||
EMSESP::send_write_request(entityItem.type_id, entityItem.device_id, entityItem.offset, v, 0);
|
||||
} else if (entityItem.valuetype == DeviceValueType::USHORT || entityItem.valuetype == DeviceValueType::SHORT) {
|
||||
} else if (entityItem.value_type == DeviceValueType::USHORT || entityItem.value_type == DeviceValueType::SHORT) {
|
||||
uint8_t v1[2] = {(uint8_t)(v >> 8), (uint8_t)(v & 0xFF)};
|
||||
EMSESP::send_write_request(entityItem.type_id, entityItem.device_id, entityItem.offset, v1, 2, 0);
|
||||
} else {
|
||||
@@ -128,6 +131,7 @@ bool WebEntityService::command_setvalue(const char * value, const std::string na
|
||||
EMSESP::send_write_request(entityItem.type_id, entityItem.device_id, entityItem.offset, v1, 3, 0);
|
||||
}
|
||||
}
|
||||
|
||||
publish_single(entityItem);
|
||||
if (EMSESP::mqtt_.get_publish_onchange(0)) {
|
||||
publish();
|
||||
@@ -142,44 +146,44 @@ bool WebEntityService::command_setvalue(const char * value, const std::string na
|
||||
void WebEntityService::render_value(JsonObject & output, EntityItem entity, const bool useVal, const bool web) {
|
||||
char payload[12];
|
||||
std::string name = useVal ? "value" : entity.name;
|
||||
switch (entity.valuetype) {
|
||||
switch (entity.value_type) {
|
||||
case DeviceValueType::BOOL:
|
||||
if ((uint8_t)entity.val != EMS_VALUE_BOOL_NOTSET) {
|
||||
if ((uint8_t)entity.value != EMS_VALUE_BOOL_NOTSET) {
|
||||
if (web) {
|
||||
output[name] = Helpers::render_boolean(payload, (uint8_t)entity.val, true);
|
||||
output[name] = Helpers::render_boolean(payload, (uint8_t)entity.value, true);
|
||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||
output[name] = (uint8_t)entity.val ? true : false;
|
||||
output[name] = (uint8_t)entity.value ? true : false;
|
||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||
output[name] = (uint8_t)entity.val ? 1 : 0;
|
||||
output[name] = (uint8_t)entity.value ? 1 : 0;
|
||||
} else {
|
||||
output[name] = Helpers::render_boolean(payload, (uint8_t)entity.val);
|
||||
output[name] = Helpers::render_boolean(payload, (uint8_t)entity.value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::INT:
|
||||
if ((int8_t)entity.val != EMS_VALUE_INT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (int8_t)entity.val, 2));
|
||||
if ((int8_t)entity.value != EMS_VALUE_INT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (int8_t)entity.value, 2));
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::UINT:
|
||||
if ((uint8_t)entity.val != EMS_VALUE_UINT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (uint8_t)entity.val, 2));
|
||||
if ((uint8_t)entity.value != EMS_VALUE_UINT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (uint8_t)entity.value, 2));
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::SHORT:
|
||||
if ((int16_t)entity.val != EMS_VALUE_SHORT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (int16_t)entity.val, 2));
|
||||
if ((int16_t)entity.value != EMS_VALUE_SHORT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (int16_t)entity.value, 2));
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::USHORT:
|
||||
if ((uint16_t)entity.val != EMS_VALUE_USHORT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (uint16_t)entity.val, 2));
|
||||
if ((uint16_t)entity.value != EMS_VALUE_USHORT_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * (uint16_t)entity.value, 2));
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::ULONG:
|
||||
case DeviceValueType::TIME:
|
||||
if (entity.val != EMS_VALUE_ULONG_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * entity.val, 2));
|
||||
if (entity.value != EMS_VALUE_ULONG_NOTSET) {
|
||||
output[name] = serialized(Helpers::render_value(payload, entity.factor * entity.value, 2));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -334,6 +338,7 @@ uint8_t WebEntityService::count_entities() {
|
||||
if (entityItems->size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE);
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
uint8_t count = 0;
|
||||
@@ -347,6 +352,7 @@ uint8_t WebEntityService::count_entities() {
|
||||
// send to dashboard, msgpack don't like serialized, use number
|
||||
void WebEntityService::generate_value_web(JsonObject & output) {
|
||||
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; });
|
||||
|
||||
output["label"] = (std::string) "Custom Entities";
|
||||
JsonArray data = output.createNestedArray("data");
|
||||
uint8_t index = 0;
|
||||
@@ -357,39 +363,40 @@ void WebEntityService::generate_value_web(JsonObject & output) {
|
||||
if (entity.writeable) {
|
||||
obj["c"] = entity.name;
|
||||
}
|
||||
switch (entity.valuetype) {
|
||||
|
||||
switch (entity.value_type) {
|
||||
case DeviceValueType::BOOL: {
|
||||
char s[12];
|
||||
obj["v"] = Helpers::render_boolean(s, (uint8_t)entity.val, true);
|
||||
obj["v"] = Helpers::render_boolean(s, (uint8_t)entity.value, true);
|
||||
JsonArray l = obj.createNestedArray("l");
|
||||
l.add(Helpers::render_boolean(s, false, true));
|
||||
l.add(Helpers::render_boolean(s, true, true));
|
||||
break;
|
||||
}
|
||||
case DeviceValueType::INT:
|
||||
if ((int8_t)entity.val != EMS_VALUE_INT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (int8_t)entity.val, 0);
|
||||
if ((int8_t)entity.value != EMS_VALUE_INT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (int8_t)entity.value, 0);
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::UINT:
|
||||
if ((uint8_t)entity.val != EMS_VALUE_UINT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (uint8_t)entity.val, 0);
|
||||
if ((uint8_t)entity.value != EMS_VALUE_UINT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (uint8_t)entity.value, 0);
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::SHORT:
|
||||
if ((int16_t)entity.val != EMS_VALUE_SHORT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (int16_t)entity.val, 0);
|
||||
if ((int16_t)entity.value != EMS_VALUE_SHORT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (int16_t)entity.value, 0);
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::USHORT:
|
||||
if ((uint16_t)entity.val != EMS_VALUE_USHORT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (uint16_t)entity.val, 0);
|
||||
if ((uint16_t)entity.value != EMS_VALUE_USHORT_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * (uint16_t)entity.value, 0);
|
||||
}
|
||||
break;
|
||||
case DeviceValueType::ULONG:
|
||||
case DeviceValueType::TIME:
|
||||
if (entity.val != EMS_VALUE_ULONG_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * entity.val, 0);
|
||||
if (entity.value != EMS_VALUE_ULONG_NOTSET) {
|
||||
obj["v"] = Helpers::transformNumFloat(entity.factor * entity.value, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -420,13 +427,13 @@ bool WebEntityService::get_value(std::shared_ptr<const Telegram> telegram) {
|
||||
const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3};
|
||||
for (auto & entity : *entityItems) {
|
||||
if (telegram->type_id == entity.type_id && telegram->src == entity.device_id && telegram->offset <= entity.offset
|
||||
&& (telegram->offset + telegram->message_length) >= (entity.offset + len[entity.valuetype])) {
|
||||
uint32_t val = 0;
|
||||
for (uint8_t i = 0; i < len[entity.valuetype]; i++) {
|
||||
val = (val << 8) + telegram->message_data[i + entity.offset - telegram->offset];
|
||||
&& (telegram->offset + telegram->message_length) >= (entity.offset + len[entity.value_type])) {
|
||||
uint32_t value = 0;
|
||||
for (uint8_t i = 0; i < len[entity.value_type]; i++) {
|
||||
value = (value << 8) + telegram->message_data[i + entity.offset - telegram->offset];
|
||||
}
|
||||
if (val != entity.val) {
|
||||
entity.val = val;
|
||||
if (value != entity.value) {
|
||||
entity.value = value;
|
||||
if (Mqtt::publish_single()) {
|
||||
publish_single(entity);
|
||||
} else if (EMSESP::mqtt_.get_publish_onchange(0)) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -21,21 +21,22 @@
|
||||
#define WebEntityService_h
|
||||
|
||||
#define EMSESP_ENTITY_FILE "/config/emsespEntity.json"
|
||||
#define EMSESP_ENTITY_SERVICE_PATH "/rest/entity" // GET and POST
|
||||
#define EMSESP_ENTITY_SERVICE_PATH "/rest/entities" // GET and POST
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
class EntityItem {
|
||||
public:
|
||||
uint8_t id;
|
||||
uint8_t device_id;
|
||||
uint16_t type_id;
|
||||
uint8_t offset;
|
||||
int8_t valuetype;
|
||||
int8_t value_type;
|
||||
uint8_t uom;
|
||||
std::string name;
|
||||
double factor;
|
||||
bool writeable;
|
||||
uint32_t val;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
class WebEntity {
|
||||
@@ -66,7 +67,7 @@ class WebEntityService : public StatefulService<WebEntity> {
|
||||
HttpEndpoint<WebEntity> _httpEndpoint;
|
||||
FSPersistence<WebEntity> _fsPersistence;
|
||||
|
||||
std::list<EntityItem> * entityItems; // pointer to the list of schedule events
|
||||
std::list<EntityItem> * entityItems; // pointer to the list of entity items
|
||||
bool ha_registered_ = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -56,7 +56,7 @@ StateUpdateResult WebScheduler::update(JsonObject & root, WebScheduler & webSche
|
||||
#ifdef EMSESP_STANDALONE
|
||||
// invoke some fake data for testing
|
||||
const char * json =
|
||||
"{[{\"id\":\"01\",\"active\":true,\"flags\":31,\"time\": \"07:30\",\"cmd\": \"hc1/mode\",\"value\": \"day\",\"name\": \"turn on central heating\"}]}";
|
||||
"{[{\"id\":1,\"active\":true,\"flags\":31,\"time\": \"07:30\",\"cmd\": \"hc1/mode\",\"value\": \"day\",\"name\": \"turn on central heating\"}]}";
|
||||
StaticJsonDocument<500> doc;
|
||||
deserializeJson(doc, json);
|
||||
root = doc.as<JsonObject>();
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace emsesp {
|
||||
|
||||
class ScheduleItem {
|
||||
public:
|
||||
std::string id; // unqiue id
|
||||
boolean active;
|
||||
uint8_t flags;
|
||||
uint16_t elapsed_min; // total mins from 00:00
|
||||
|
||||
@@ -176,13 +176,13 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
|
||||
settings.pbutton_gpio = root["pbutton_gpio"] | default_pbutton_gpio;
|
||||
check_flag(prev, settings.pbutton_gpio, ChangeFlags::BUTTON);
|
||||
|
||||
// dallas
|
||||
// temperaturesensor
|
||||
prev = settings.dallas_gpio;
|
||||
settings.dallas_gpio = root["dallas_gpio"] | default_dallas_gpio;
|
||||
check_flag(prev, settings.dallas_gpio, ChangeFlags::DALLAS);
|
||||
check_flag(prev, settings.dallas_gpio, ChangeFlags::SENSOR);
|
||||
prev = settings.dallas_parasite;
|
||||
settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE;
|
||||
check_flag(prev, settings.dallas_parasite, ChangeFlags::DALLAS);
|
||||
check_flag(prev, settings.dallas_parasite, ChangeFlags::SENSOR);
|
||||
|
||||
// shower
|
||||
prev = settings.shower_timer;
|
||||
@@ -301,8 +301,8 @@ void WebSettingsService::onUpdate() {
|
||||
EMSESP::shower_.start();
|
||||
}
|
||||
|
||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::DALLAS)) {
|
||||
EMSESP::dallassensor_.start();
|
||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::SENSOR)) {
|
||||
EMSESP::temperaturesensor_.start();
|
||||
}
|
||||
|
||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::UART)) {
|
||||
|
||||
@@ -79,7 +79,7 @@ class WebSettings {
|
||||
UART = (1 << 0), // 1
|
||||
SYSLOG = (1 << 1), // 2
|
||||
ADC = (1 << 2), // 4 - analog
|
||||
DALLAS = (1 << 3), // 8
|
||||
SENSOR = (1 << 3), // 8
|
||||
SHOWER = (1 << 4), // 16
|
||||
LED = (1 << 5), // 32
|
||||
BUTTON = (1 << 6), // 64
|
||||
|
||||
@@ -124,7 +124,7 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
||||
root["tx_mode"] = EMSESP::txservice_.tx_mode();
|
||||
root["uptime"] = EMSbus::bus_uptime();
|
||||
root["num_devices"] = EMSESP::count_devices(); // excluding Controller
|
||||
root["num_sensors"] = EMSESP::dallassensor_.no_sensors();
|
||||
root["num_sensors"] = EMSESP::temperaturesensor_.no_sensors();
|
||||
root["num_analogs"] = EMSESP::analogsensor_.no_sensors();
|
||||
|
||||
JsonArray statsJson = root.createNestedArray("stats");
|
||||
@@ -148,12 +148,13 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
||||
statJson["f"] = EMSESP::txservice_.telegram_write_fail_count();
|
||||
statJson["q"] = EMSESP::txservice_.write_quality();
|
||||
|
||||
if (EMSESP::dallassensor_.dallas_enabled()) {
|
||||
if (EMSESP::temperaturesensor_.sensor_enabled()) {
|
||||
statJson = statsJson.createNestedObject();
|
||||
statJson["id"] = 3;
|
||||
statJson["s"] = EMSESP::dallassensor_.reads();
|
||||
statJson["f"] = EMSESP::dallassensor_.fails();
|
||||
statJson["q"] = EMSESP::dallassensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::dallassensor_.fails()) / EMSESP::dallassensor_.reads());
|
||||
statJson["s"] = EMSESP::temperaturesensor_.reads();
|
||||
statJson["f"] = EMSESP::temperaturesensor_.fails();
|
||||
statJson["q"] =
|
||||
EMSESP::temperaturesensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::temperaturesensor_.fails()) / EMSESP::temperaturesensor_.reads());
|
||||
}
|
||||
if (EMSESP::analog_enabled()) {
|
||||
statJson = statsJson.createNestedObject();
|
||||
|
||||
Reference in New Issue
Block a user