Merge remote-tracking branch 'origin/v3.4' into dev

This commit is contained in:
proddy
2022-01-23 17:56:52 +01:00
parent 02e2b51814
commit 77e1898512
538 changed files with 32282 additions and 38655 deletions

View File

@@ -23,69 +23,131 @@ namespace emsesp {
using namespace std::placeholders; // for `_1` etc
WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securityManager)
: _device_dataHandler(DEVICE_DATA_SERVICE_PATH,
securityManager->wrapCallback(std::bind(&WebDataService::device_data, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED))
, _writevalue_dataHandler(WRITE_VALUE_SERVICE_PATH,
securityManager->wrapCallback(std::bind(&WebDataService::write_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
, _writesensor_dataHandler(WRITE_SENSOR_SERVICE_PATH,
securityManager->wrapCallback(std::bind(&WebDataService::write_sensor, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
server->on(EMSESP_DATA_SERVICE_PATH,
: _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)) {
server->on(CORE_DATA_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest(std::bind(&WebDataService::all_devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
server->on(SENSOR_DATA_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest(std::bind(&WebDataService::sensor_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
server->on(SCAN_DEVICES_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest(std::bind(&WebDataService::scan_devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
HTTP_POST,
securityManager->wrapRequest(std::bind(&WebDataService::scan_devices, this, _1), AuthenticationPredicates::IS_ADMIN));
_device_dataHandler.setMethod(HTTP_POST);
_device_dataHandler.setMaxContentLength(256);
server->addHandler(&_device_dataHandler);
_device_data_handler.setMethod(HTTP_POST);
_device_data_handler.setMaxContentLength(256);
server->addHandler(&_device_data_handler);
_writevalue_dataHandler.setMethod(HTTP_POST);
_writevalue_dataHandler.setMaxContentLength(256);
server->addHandler(&_writevalue_dataHandler);
_write_value_handler.setMethod(HTTP_POST);
_write_value_handler.setMaxContentLength(256);
server->addHandler(&_write_value_handler);
_writesensor_dataHandler.setMethod(HTTP_POST);
_writesensor_dataHandler.setMaxContentLength(256);
server->addHandler(&_writesensor_dataHandler);
_write_sensor_handler.setMethod(HTTP_POST);
_write_sensor_handler.setMaxContentLength(256);
server->addHandler(&_write_sensor_handler);
_write_analog_handler.setMethod(HTTP_POST);
_write_analog_handler.setMaxContentLength(256);
server->addHandler(&_write_analog_handler);
}
// scan devices service
void WebDataService::scan_devices(AsyncWebServerRequest * request) {
EMSESP::logger().info(F("Scanning devices..."));
EMSESP::scan_devices();
request->send(200);
}
void WebDataService::all_devices(AsyncWebServerRequest * request) {
// this is used in the dashboard and contains all ems device information
// /coreData endpoint
void WebDataService::core_data(AsyncWebServerRequest * request) {
AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN);
JsonObject root = response->getRoot();
// list is already sorted by device type
// Ignore Contoller
JsonArray devices = root.createNestedArray("devices");
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice) {
for (auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice && emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER) {
JsonObject obj = devices.createNestedObject();
obj["i"] = emsdevice->unique_id(); // id
obj["i"] = emsdevice->unique_id(); // a unique id
obj["t"] = emsdevice->device_type_name(); // type
obj["b"] = emsdevice->brand_to_string(); // 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)
}
}
// sensors stuff
root["active_sensors"] = EMSESP::dallassensor_.no_sensors() + (EMSESP::analogsensor_.analog_enabled() ? EMSESP::analogsensor_.no_sensors() : 0);
root["analog_enabled"] = EMSESP::analogsensor_.analog_enabled();
response->setLength();
request->send(response);
}
// sensor data - sends back to web
// /sensorData endpoint
// the "sensors" and "analogs" are arrays and must exist
void WebDataService::sensor_data(AsyncWebServerRequest * request) {
AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN);
JsonObject root = response->getRoot();
// dallas sensors
JsonArray sensors = root.createNestedArray("sensors");
if (EMSESP::have_sensors()) {
uint8_t i = 1;
for (const auto & sensor : EMSESP::sensor_devices()) {
if (EMSESP::dallassensor_.have_sensors()) {
for (const auto & sensor : EMSESP::dallassensor_.sensors()) {
JsonObject obj = sensors.createNestedObject();
obj["n"] = i++; // no
obj["i"] = sensor.to_string(true); // id
obj["t"] = (float)(sensor.temperature_c) / 10; // temp
obj["o"] = (float)(sensor.offset()) / 10; // offset
obj["is"] = sensor.id_str(); // id
obj["n"] = sensor.name(); // name
if (EMSESP::system_.fahrenheit()) {
if (Helpers::hasValue(sensor.temperature_c)) {
obj["t"] = (float)sensor.temperature_c * 0.18 + 32;
}
obj["u"] = DeviceValueUOM::FAHRENHEIT;
obj["o"] = (float)sensor.offset() * 0.18;
} else {
if (Helpers::hasValue(sensor.temperature_c)) {
obj["t"] = (float)sensor.temperature_c / 10;
}
obj["u"] = DeviceValueUOM::DEGREES;
obj["o"] = (float)(sensor.offset()) / 10;
}
}
}
if (EMSESP::system_.analog_enabled()) {
root["analog"] = EMSESP::system_.analog();
// analog sensors
// assume list is already sorted by id
JsonArray analogs = root.createNestedArray("analogs");
if (EMSESP::analog_enabled() && EMSESP::analogsensor_.have_sensors()) {
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
// don't send if it's marked for removal
if (sensor.type() != AnalogSensor::AnalogType::MARK_DELETED) {
JsonObject obj = analogs.createNestedObject();
obj["i"] = sensor.id();
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::round2(sensor.value(), 1); // is optional and is a float
}
}
}
}
response->setLength();
@@ -96,7 +158,7 @@ void WebDataService::all_devices(AsyncWebServerRequest * request) {
// Compresses the JSON using MsgPack https://msgpack.org/index.html
void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant & json) {
if (json.is<JsonObject>()) {
MsgpackAsyncJsonResponse * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN);
MsgpackAsyncJsonResponse * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXXLARGE_DYN);
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice) {
if (emsdevice->unique_id() == json["id"]) {
@@ -106,8 +168,8 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant &
}
EMSESP::wait_validate(0); // reset in case of timeout
#ifndef EMSESP_STANDALONE
JsonObject root = response->getRoot();
emsdevice->generate_values_json_web(root);
JsonObject output = response->getRoot();
emsdevice->generate_values_web(output);
#endif
response->setLength();
request->send(response);
@@ -117,12 +179,13 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant &
}
}
// invalid
// invalid but send ok
AsyncWebServerResponse * response = request->beginResponse(200);
request->send(response);
}
// takes a command and its data value from a specific Device, from the Web
// 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) {
if (json.is<JsonObject>()) {
@@ -180,23 +243,42 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant &
request->send(response);
}
// takes a sensorname and optional offset from the Web
// 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) {
bool ok = false;
if (json.is<JsonObject>()) {
JsonObject sensor = json["sensor"];
JsonObject sensor = json;
// if valid add.
uint8_t no = sensor["no"];
if (no > 0 && no < 100) {
char name[20];
std::string id = sensor["id"];
strlcpy(name, id.c_str(), sizeof(name));
float offset = sensor["offset"]; // this will be a float value. We'll convert it to int and * 10 it
int16_t offset10 = offset * 10;
char idstr[3];
ok = EMSESP::dallassensor_.update(Helpers::itoa(idstr, no, 10), name, offset10);
std::string id_str = sensor["id_str"]; // this is the key
std::string name = sensor["name"];
// calculate offset. We'll convert it to an int and * 10
float offset = sensor["offset"];
int16_t offset10 = offset * 10;
if (EMSESP::system_.fahrenheit()) {
offset10 = offset / 0.18;
}
ok = EMSESP::dallassensor_.update(id_str, name, offset10);
}
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
request->send(response);
}
// update the analog record, or create a new one
void WebDataService::write_analog(AsyncWebServerRequest * request, JsonVariant & json) {
bool ok = false;
if (json.is<JsonObject>()) {
JsonObject analog = json;
uint8_t id = analog["id"]; // this is the unique key
std::string name = analog["name"];
float factor = analog["factor"];
int16_t offset = analog["offset"];
uint8_t uom = analog["uom"];
int8_t type = analog["type"];
ok = EMSESP::analogsensor_.update(id, name, offset, factor, uom, type);
}
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);