From 79d7142e5f8f0fd3c8158a3439684e900089bfd9 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 18:27:58 +0100 Subject: [PATCH] add test data --- src/test/test.cpp | 63 +++++++++++++++------ src/test/test.h | 3 +- src/web/WebCustomEntityService.cpp | 90 +++++++++++++++++++++++------- src/web/WebCustomEntityService.h | 6 +- src/web/WebSchedulerService.cpp | 41 +++++++++----- src/web/WebSchedulerService.h | 4 ++ 6 files changed, 155 insertions(+), 52 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 48af75f6f..ad7015780 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -307,13 +307,19 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const } if (command == "general") { - shell.printfln("Testing adding a boiler, thermostat and sensors..."); + shell.printfln("Testing adding a boiler, thermostat, all sensors, scheduler and custom entities..."); test("general"); - // add sensors + // add analog and temperatire sensors emsesp::EMSESP::analogsensor_.test(); emsesp::EMSESP::temperaturesensor_.test(); + // scheduler + EMSESP::webSchedulerService.test(); + + // custom entities + EMSESP::webCustomEntityService.test(); + // shell.invoke_command("show devices"); // shell.invoke_command("show values"); shell.invoke_command("call system allvalues"); @@ -331,16 +337,40 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const } if (command == "custom_entities") { - shell.printfln("custom entities..."); - test("general"); + shell.printfln("Adding custom entities..."); + + // add some dummy entities + EMSESP::webCustomEntityService.test(); #ifdef EMSESP_STANDALONE AsyncWebServerRequest request; request.method(HTTP_GET); request.url("/api/custom"); - request.url("/api/custom/boiler_flowtemp"); - request.url("/api/custom/boiler_flowtemp2"); EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/custom/test_custom"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/custom/test_read_only"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/custom/test_ram"); + EMSESP::webAPIService.webAPIService_get(&request); + shell.invoke_command("call custom info"); + +#endif + ok = true; + } + + if (command == "scheduler") { + shell.printfln("Adding Scheduler items..."); + + // add some dummy entities + EMSESP::webSchedulerService.test(); + +#ifdef EMSESP_STANDALONE + AsyncWebServerRequest request; + request.method(HTTP_GET); + request.url("/api/scheduler"); + EMSESP::webAPIService.webAPIService_get(&request); + shell.invoke_command("call scheduler info"); #endif ok = true; } @@ -574,7 +604,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const test("boiler"); test("thermostat"); - JsonDocument doc; // some absurd high number + JsonDocument doc; for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice) { doc.clear(); @@ -784,25 +814,26 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const ok = true; } - if (command == "custom") { - shell.printfln("Testing custom entities"); + if (command == "customization") { + shell.printfln("Testing customization renaming entity"); Mqtt::ha_enabled(true); // Mqtt::send_response(false); test("thermostat"); + // before // shell.invoke_command("call thermostat seltemp"); // shell.invoke_command("call system publish"); - // toggle mode + // find thermostat for (const auto & emsdevice : EMSESP::emsdevices) { - Serial.print("Custom: "); - Serial.print(emsdevice->device_type_name()); - Serial.print(" uniqueid="); - Serial.println(emsdevice->unique_id()); - - if (emsdevice->unique_id() == 1) { // thermostat + if (emsdevice->unique_id() == 1) { + Serial.println(); + Serial.print("Custom: "); + Serial.print(emsdevice->device_type_name()); + Serial.print(" uniqueid="); + Serial.println(emsdevice->unique_id()); std::string a = "00hc1/seltemp|new name>5<52"; emsdevice->setCustomizationEntity(a); break; diff --git a/src/test/test.h b/src/test/test.h index 83caa6e84..fbfad38b9 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -52,11 +52,12 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "api_values" // #define EMSESP_DEBUG_DEFAULT "mqtt_post" // #define EMSESP_DEBUG_DEFAULT "api_wwmode" -// #define EMSESP_DEBUG_DEFAULT "custom" +// #define EMSESP_DEBUG_DEFAULT "customization" // #define EMSESP_DEBUG_DEFAULT "entity_dump" // #define EMSESP_DEBUG_DEFAULT "memory" // #define EMSESP_DEBUG_DEFAULT "coldshot" // #define EMSESP_DEBUG_DEFAULT "custom_entities" +// #define EMSESP_DEBUG_DEFAULT "scheduler" // #define EMSESP_DEBUG_DEFAULT "heat_exchange" class Test { diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index ea0b5ae55..d488ef435 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -36,7 +36,7 @@ WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs, // load the settings when the service starts void WebCustomEntityService::begin() { _fsPersistence.readFromFS(); - EMSESP::logger().info("Starting Custom entity service"); + EMSESP::logger().info("Starting Custom Entity service"); Mqtt::subscribe(EMSdevice::DeviceType::CUSTOM, "custom/#", nullptr); // use empty function callback } @@ -61,31 +61,17 @@ void WebCustomEntity::read(WebCustomEntity & webEntity, JsonObject root) { } } -// call on initialization and also when the Entity web page is updated +// call on initialization and also when the Entity web page is updated/saved // this loads the data into the internal class StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & webCustomEntity) { -#ifdef EMSESP_STANDALONE - // invoke some fake data for testing - // clang-format off - /* prettier-ignore */ - const char * json = - "{\"entities\": [{\"id\":0,\"device_id\":8,\"type_id\":24,\"offset\":0,\"factor\":1,\"name\":\"boiler_flowtemp\",\"uom\":1,\"value_type\":1,\"writeable\":true}]}"; - // clang-format on - JsonDocument doc; - deserializeJson(doc, json); - root = doc.as(); - Serial.print(COLOR_BRIGHT_MAGENTA); - Serial.print(" Using fake custom entity file: "); - serializeJson(root, Serial); - Serial.println(COLOR_RESET); -#endif - + // reset everything to start fresh for (CustomEntityItem & entityItem : webCustomEntity.customEntityItems) { Command::erase_command(EMSdevice::DeviceType::CUSTOM, entityItem.name.c_str()); } webCustomEntity.customEntityItems.clear(); EMSESP::webCustomEntityService.ha_reset(); + // rebuild the list if (root["entities"].is()) { for (const JsonObject ei : root["entities"].as()) { auto entityItem = CustomEntityItem(); @@ -120,10 +106,13 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web } else if (entityItem.value_type == DeviceValueType::ULONG || entityItem.value_type == DeviceValueType::TIME) { entityItem.value = EMS_VALUE_DEFAULT_ULONG; } + if (entityItem.factor == 0) { entityItem.factor = 1; } + webCustomEntity.customEntityItems.push_back(entityItem); // add to list + if (entityItem.writeable) { Command::add( EMSdevice::DeviceType::CUSTOM, @@ -262,15 +251,16 @@ void WebCustomEntityService::show_values(JsonObject output) { } } - // process json output for info/commands and value_info bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) { EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; }); + + // if it's commands... if (Helpers::toLower(cmd) == F_(commands)) { output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); for (const auto & entity : *customEntityItems) { - output[entity.name] = "custom entitiy"; + output[entity.name] = "custom entity"; } return true; } @@ -281,6 +271,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) return true; } + // if it's info or values... if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) { // list all names for (const CustomEntityItem & entity : *customEntityItems) { @@ -350,12 +341,14 @@ void WebCustomEntityService::publish_single(const CustomEntityItem & entity) { if (!Mqtt::enabled() || !Mqtt::publish_single()) { return; } + char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; if (Mqtt::publish_single2cmd()) { snprintf(topic, sizeof(topic), "%s/%s", "custom", entity.name.c_str()); } else { snprintf(topic, sizeof(topic), "%s/%s", "custom_data", entity.name.c_str()); } + JsonDocument doc; JsonObject output = doc.to(); render_value(output, entity, true); @@ -473,6 +466,7 @@ uint8_t WebCustomEntityService::count_entities() { render_value(output, entity); count += (output.containsKey(entity.name) || entity.writeable) ? 1 : 0; } + return count; } @@ -482,6 +476,7 @@ uint8_t WebCustomEntityService::has_commands() { for (const CustomEntityItem & entity : *customEntityItems) { count += entity.writeable ? 1 : 0; } + return count; } @@ -547,6 +542,7 @@ void WebCustomEntityService::generate_value_web(JsonObject output) { default: break; } + // show only entities with value or command if (!obj.containsKey("v") && !obj.containsKey("c")) { data.remove(index); @@ -560,6 +556,7 @@ void WebCustomEntityService::generate_value_web(JsonObject output) { void WebCustomEntityService::fetch() { EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; }); const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3}; + for (auto & entity : *customEntityItems) { if (entity.device_id > 0 && entity.type_id > 0) { // ths excludes also RAM type bool needFetch = true; @@ -615,11 +612,64 @@ bool WebCustomEntityService::get_value(std::shared_ptr telegram) // EMSESP::logger().debug("custom entity %s received with value %d", entity.name.c_str(), (int)entity.val); } } + if (has_change) { publish(); return true; } + return false; } +// hard coded tests +#ifdef EMSESP_TEST +void WebCustomEntityService::test() { + update( + [&](WebCustomEntity & webCustomEntity) { + // test 1 + auto entityItem = CustomEntityItem(); + entityItem.ram = 0; + entityItem.device_id = 8; + entityItem.type_id = 24; + entityItem.offset = 0; + entityItem.factor = 1; + entityItem.name = "test_custom"; + entityItem.uom = 1; + entityItem.value_type = 1; + entityItem.writeable = true; + entityItem.data = "70"; + webCustomEntity.customEntityItems.push_back(entityItem); + + // test 2 + entityItem.ram = 0; + entityItem.device_id = 8; + entityItem.type_id = 18; + entityItem.offset = 0; + entityItem.factor = 1; + entityItem.name = "test_read_only"; + entityItem.uom = 3; + entityItem.value_type = 2; + entityItem.writeable = false; + entityItem.data = "12"; + webCustomEntity.customEntityItems.push_back(entityItem); + + // test 2 + entityItem.ram = 1; + entityItem.device_id = 0; + entityItem.type_id = 0; + entityItem.offset = 0; + entityItem.factor = 1; + entityItem.name = "test_ram"; + entityItem.uom = 0; + entityItem.value_type = 8; + entityItem.writeable = true; + entityItem.data = "14"; + webCustomEntity.customEntityItems.push_back(entityItem); + + return StateUpdateResult::CHANGED; // persist the changes + }, + "local"); +} +#endif + } // namespace emsesp diff --git a/src/web/WebCustomEntityService.h b/src/web/WebCustomEntityService.h index 228cd95c6..ab2cef9ba 100644 --- a/src/web/WebCustomEntityService.h +++ b/src/web/WebCustomEntityService.h @@ -38,7 +38,7 @@ class CustomEntityItem { bool writeable; uint32_t value; std::string data; - uint8_t ram; + uint8_t ram; }; class WebCustomEntity { @@ -70,6 +70,10 @@ class WebCustomEntityService : public StatefulService { ha_registered_ = false; } +#if defined(EMSESP_TEST) + void test(); +#endif + private: HttpEndpoint _httpEndpoint; FSPersistence _fsPersistence; diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index b7fd19d74..80b01d806 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -54,26 +54,15 @@ void WebScheduler::read(WebScheduler & webScheduler, JsonObject root) { // call on initialization and also when the Schedule web page is saved // this loads the data into the internal class StateUpdateResult WebScheduler::update(JsonObject root, WebScheduler & webScheduler) { -#ifdef EMSESP_STANDALONE - // invoke some fake data for testing - const char * json = - "{\"schedule\": [{\"id\":1,\"active\":true,\"flags\":31,\"time\": \"07:30\",\"cmd\": \"hc1mode\",\"value\": \"day\",\"name\": \"turn on " - "central heating\"}]}"; - JsonDocument doc; - deserializeJson(doc, json); - root = doc.as(); - Serial.print(COLOR_BRIGHT_MAGENTA); - Serial.print(" Using fake scheduler file: "); - serializeJson(root, Serial); - Serial.println(COLOR_RESET); -#endif - for (ScheduleItem & scheduleItem : webScheduler.scheduleItems) { Command::erase_command(EMSdevice::DeviceType::SCHEDULER, scheduleItem.name.c_str()); } + + // reset the list webScheduler.scheduleItems.clear(); EMSESP::webSchedulerService.ha_reset(); + // build up the list of schedule items if (root["schedule"].is()) { for (const JsonObject schedule : root["schedule"].as()) { // create each schedule item, overwriting any previous settings @@ -425,4 +414,28 @@ void WebSchedulerService::loop() { } } +// hard coded tests +#if defined(EMSESP_TEST) +void WebSchedulerService::test() { + update( + [&](WebScheduler & webScheduler) { + // test 1 + auto si = ScheduleItem(); + si.active = true; + si.flags = 1; + si.time = "12:00"; + si.cmd = "test"; + si.value = "10"; + si.name = "test_scheduler"; + si.elapsed_min = 0; + si.retry_cnt = 0xFF; // no startup retries + + webScheduler.scheduleItems.push_back(si); + + return StateUpdateResult::CHANGED; // persist the changes + }, + "local"); +} +#endif + } // namespace emsesp diff --git a/src/web/WebSchedulerService.h b/src/web/WebSchedulerService.h index d5496a9e1..cb48c58b4 100644 --- a/src/web/WebSchedulerService.h +++ b/src/web/WebSchedulerService.h @@ -62,6 +62,10 @@ class WebSchedulerService : public StatefulService { ha_registered_ = false; } +#if defined(EMSESP_TEST) + void test(); +#endif + // make all functions public so we can test in the debug and standalone mode #ifndef EMSESP_STANDALONE private: