Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
 
root / src / web / w-private.h
Author[]Andy Green <andy@warmcat.com> 2026-04-25 07:51 UTC
Committer[]Andy Green <andy@warmcat.com> 2026-04-25 13:06 UTC
Treeef0c7e93d78837dd9a33906bfb23bc93f49ff9e2   Raw Patch
 
sai-power: self-assemble pcon info from builders
sai-power: self-assemble pcon info from builders
diff --git a/CMakeLists.txt b/CMakeLists.txt index dab131b..ea5acde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,8 +118,15 @@ if (LWS_OPENSSL_INCLUDE_DIRS) set(CMAKE_C_FLAGS "-I\"${LWS_OPENSSL_INCLUDE_DIRS}\" ${CMAKE_C_FLAGS}") endif() - -set(CMAKE_C_FLAGS "-DBUILD_INFO=\\\"${LWS_BUILD_HASH}\\\" ${CMAKE_C_FLAGS}") +include_directories(${CMAKE_BINARY_DIR}) +add_custom_target(sai_git_hash ALL + COMMAND ${CMAKE_COMMAND} + -DCMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR} + -DCPACK_PACKAGE_VERSION=${CPACK_PACKAGE_VERSION} + -DOUTPUT_FILE=${CMAKE_BINARY_DIR}/sai-git-hash.h + -P ${CMAKE_SOURCE_DIR}/cmake/GetGitHash.cmake + BYPRODUCTS ${CMAKE_BINARY_DIR}/sai-git-hash.h +) CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(LWS_HAVE_LIBCAP)\n return diff --git a/src/builder/CMakeLists.txt b/src/builder/CMakeLists.txt index ee680f4..f27d026 100644 --- a/src/builder/CMakeLists.txt +++ b/src/builder/CMakeLists.txt @@ -29,6 +29,7 @@ require_lws_config(LWS_WITH_DIR 1 requirements) if (requirements) add_executable(${SUB} ${SRCS}) +add_dependencies(${SUB} sai_git_hash) if (APPLE) set_property(TARGET ${SUB} PROPERTY MACOSX_RPATH YES) set(CMAKE_MACOSX_RPATH 1) diff --git a/src/builder/b-conf.c b/src/builder/b-conf.c index ce0d34a..1839dc9 100644 --- a/src/builder/b-conf.c +++ b/src/builder/b-conf.c @@ -25,6 +25,7 @@ #include <time.h> #include <fcntl.h> +#include "sai-git-hash.h" #include "b-private.h" /* global part */ @@ -43,6 +44,7 @@ static const char * const paths_global[] = { "power-on.mac", "power-off.type", "power-off.url", + "power-monitor.url", "rebuild_script_user", "rebuild_script_root" }; @@ -61,6 +63,7 @@ enum enum_paths_global { LEJPM_POWER_ON_MAC, LEJPM_POWER_OFF_TYPE, LEJPM_POWER_OFF_URL, + LEJPM_POWER_MONITOR_URL, LEJPM_REBUILD_SCRIPT_USER, LEJPM_REBUILD_SCRIPT_ROOT }; @@ -115,7 +118,7 @@ saib_conf_cb(struct lejp_ctx *ctx, char reason) if (!a->sai_plat) return -1; - lws_strncpy(a->sai_plat->sai_hash, BUILD_INFO, + lws_strncpy(a->sai_plat->sai_hash, SAI_BUILD_INFO, sizeof(a->sai_plat->sai_hash)); lws_strncpy(a->sai_plat->lws_hash, LWS_BUILD_HASH, sizeof(a->sai_plat->lws_hash)); @@ -311,6 +314,9 @@ saib_conf_global_cb(struct lejp_ctx *ctx, char reason) case LEJPM_POWER_OFF_URL: pp = &a->builder->power_off_url; break; + case LEJPM_POWER_MONITOR_URL: + pp = &a->builder->power_monitor_url; + break; case LEJPM_REBUILD_SCRIPT_USER: pp = &a->builder->rebuild_script_user; diff --git a/src/builder/b-power.c b/src/builder/b-power.c index 37f14d1..1422fec 100644 --- a/src/builder/b-power.c +++ b/src/builder/b-power.c @@ -75,6 +75,14 @@ saib_power_client_state(void *userobj, void *sh, lws_ss_constate_t state, (unsigned int)ack); switch (state) { + case LWSSSCS_CREATING: + lwsl_notice("%s: CREATING sai-power client connection to %s\n", __func__, builder.url_sai_power); + if (lws_ss_set_metadata((struct lws_ss_handle *)sh, "url", + builder.url_sai_power, + strlen(builder.url_sai_power))) + lwsl_err("%s: failed to set metadata\n", __func__); + break; + case LWSSSCS_CONNECTED: lwsl_notice("%s: Connected to sai-power, sending registration: '%s' '%s'\n", __func__, builder.host, builder.power_controller_name); @@ -87,6 +95,19 @@ saib_power_client_state(void *userobj, void *sh, lws_ss_constate_t state, else lws_strncpy(r.power_controller_name, "unknown", sizeof(r.power_controller_name)); + if (builder.power_on_type) + lws_strncpy(r.power_on_type, builder.power_on_type, sizeof(r.power_on_type)); + if (builder.power_on_url) + lws_strncpy(r.power_on_url, builder.power_on_url, sizeof(r.power_on_url)); + if (builder.power_on_mac) + lws_strncpy(r.power_on_mac, builder.power_on_mac, sizeof(r.power_on_mac)); + if (builder.power_off_type) + lws_strncpy(r.power_off_type, builder.power_off_type, sizeof(r.power_off_type)); + if (builder.power_off_url) + lws_strncpy(r.power_off_url, builder.power_off_url, sizeof(r.power_off_url)); + if (builder.power_monitor_url) + lws_strncpy(r.power_monitor_url, builder.power_monitor_url, sizeof(r.power_monitor_url)); + /* Add platforms */ lws_start_foreach_dll(struct lws_dll2 *, d, builder.sai_plat_owner.head) { sai_plat_t *sp = lws_container_of(d, sai_plat_t, sai_plat_list); @@ -112,6 +133,10 @@ saib_power_client_state(void *userobj, void *sh, lws_ss_constate_t state, lws_buflist_destroy_all_segments(&g->bl_tx); break; + case LWSSSCS_ALL_RETRIES_FAILED: + lwsl_err("%s: Failed to connect to sai-power\n", __func__); + break; + default: break; } diff --git a/src/builder/b-private.h b/src/builder/b-private.h index f61c09b..5b1ac65 100644 --- a/src/builder/b-private.h +++ b/src/builder/b-private.h @@ -136,6 +136,7 @@ struct sai_builder { const char *power_on_type; const char *power_on_url; const char *power_on_mac; + const char *power_monitor_url; const char *home; /* home dir, usually /sai/home */ const char *perms; /* user:group */ diff --git a/src/builder/b-task.c b/src/builder/b-task.c index cde9996..43f0e5f 100644 --- a/src/builder/b-task.c +++ b/src/builder/b-task.c @@ -25,6 +25,7 @@ #include <fcntl.h> #include <errno.h> +#include "sai-git-hash.h" #include "b-private.h" const char *git_helper_sh = @@ -910,7 +911,7 @@ saib_consider_allocating_task(struct sai_plat_server *spm, lws_struct_args_t *a, ml = lws_snprintf(mb, sizeof(mb), ">saib> Sai Builder Version: %s, lws: %s\n", - BUILD_INFO, LWS_BUILD_HASH); + SAI_BUILD_INFO, LWS_BUILD_HASH); saib_log_chunk_create(ns, mb, (unsigned int)ml, 3); } diff --git a/src/common/c-sqlite3.c b/src/common/c-sqlite3.c index bf91b12..e007d33 100644 --- a/src/common/c-sqlite3.c +++ b/src/common/c-sqlite3.c @@ -20,6 +20,7 @@ */ #include <libwebsockets.h> +#include <sqlite3.h> #include <assert.h> diff --git a/src/common/include/private.h b/src/common/include/private.h index eb4f709..abe9970 100644 --- a/src/common/include/private.h +++ b/src/common/include/private.h @@ -622,6 +622,12 @@ typedef struct sai_power_controller { char name[64]; char type[32]; char depends_on[64]; + char power_on_type[16]; + char power_on_url[128]; + char power_on_mac[24]; + char power_off_type[16]; + char power_off_url[128]; + char power_monitor_url[128]; unsigned int on; unsigned int manual_on; } sai_power_controller_t; @@ -658,6 +664,12 @@ typedef struct sai_builder_registration { lws_dll2_owner_t platforms_owner; /* sai_builder_platform_t */ char builder_name[64]; char power_controller_name[64]; + char power_on_type[16]; + char power_on_url[128]; + char power_on_mac[24]; + char power_off_type[16]; + char power_off_url[128]; + char power_monitor_url[128]; } sai_builder_registration_t; typedef struct tasmota_data { @@ -703,7 +715,7 @@ extern const lws_struct_map_t lsm_power_managed_builder[2], lsm_power_managed_builders_list[2], lsm_schema_power_managed_builders[1], - lsm_power_controller[6], + lsm_power_controller[12], lsm_schema_json_map_task[], lsm_schema_sq3_map_task[], lsm_schema_sq3_map_event[], @@ -739,10 +751,11 @@ extern const lws_struct_map_t lsm_build_metric[14], lsm_plat[14], /* +1 for pcon */ lsm_builder_platform[1], - lsm_builder_registration[3], + lsm_builder_registration[9], lsm_schema_sq3_map_power_controller[1], lsm_schema_sq3_map_controlled_builder[1], lsm_schema_builder_registration[1], + lsm_schema_sq3_map_builder_registration[1], lsm_pcon_energy_report[1], lsm_schema_pcon_energy[1], lsm_pcon_control[2], diff --git a/src/common/struct-metadata.c b/src/common/struct-metadata.c index a310e10..ddb98af 100644 --- a/src/common/struct-metadata.c +++ b/src/common/struct-metadata.c @@ -326,6 +326,12 @@ const lws_struct_map_t lsm_power_controller[] = { LSM_CARRAY(sai_power_controller_t, name, "name"), LSM_CARRAY(sai_power_controller_t, type, "type"), LSM_CARRAY(sai_power_controller_t, depends_on, "depends_on"), + LSM_CARRAY(sai_power_controller_t, power_on_type, "power_on_type"), + LSM_CARRAY(sai_power_controller_t, power_on_url, "power_on_url"), + LSM_CARRAY(sai_power_controller_t, power_on_mac, "power_on_mac"), + LSM_CARRAY(sai_power_controller_t, power_off_type, "power_off_type"), + LSM_CARRAY(sai_power_controller_t, power_off_url, "power_off_url"), + LSM_CARRAY(sai_power_controller_t, power_monitor_url, "power_monitor_url"), LSM_UNSIGNED(sai_power_controller_t, on, "on"), LSM_UNSIGNED(sai_power_controller_t, manual_on, "manual_on"), LSM_LIST(sai_power_controller_t, controlled_builders_owner, @@ -338,6 +344,12 @@ const lws_struct_map_t lsm_sq3_power_controller[] = { LSM_CARRAY(sai_power_controller_t, name, "name"), LSM_CARRAY(sai_power_controller_t, type, "type"), LSM_CARRAY(sai_power_controller_t, depends_on, "depends_on"), + LSM_CARRAY(sai_power_controller_t, power_on_type, "power_on_type"), + LSM_CARRAY(sai_power_controller_t, power_on_url, "power_on_url"), + LSM_CARRAY(sai_power_controller_t, power_on_mac, "power_on_mac"), + LSM_CARRAY(sai_power_controller_t, power_off_type, "power_off_type"), + LSM_CARRAY(sai_power_controller_t, power_off_url, "power_off_url"), + LSM_CARRAY(sai_power_controller_t, power_monitor_url, "power_monitor_url"), LSM_UNSIGNED(sai_power_controller_t, on, "state"), }; @@ -391,6 +403,12 @@ const lws_struct_map_t lsm_builder_registration[] = { lsm_builder_platform, "platforms"), LSM_CARRAY(sai_builder_registration_t, builder_name, "builder_name"), LSM_CARRAY(sai_builder_registration_t, power_controller_name, "power_controller_name"), + LSM_CARRAY(sai_builder_registration_t, power_on_type, "power_on_type"), + LSM_CARRAY(sai_builder_registration_t, power_on_url, "power_on_url"), + LSM_CARRAY(sai_builder_registration_t, power_on_mac, "power_on_mac"), + LSM_CARRAY(sai_builder_registration_t, power_off_type, "power_off_type"), + LSM_CARRAY(sai_builder_registration_t, power_off_url, "power_off_url"), + LSM_CARRAY(sai_builder_registration_t, power_monitor_url, "power_monitor_url"), }; const lws_struct_map_t lsm_schema_builder_registration[] = { @@ -399,6 +417,22 @@ const lws_struct_map_t lsm_schema_builder_registration[] = { "com.warmcat.sai.builder_registration"), }; +const lws_struct_map_t lsm_sq3_builder_registration[] = { + LSM_CARRAY(sai_builder_registration_t, builder_name, "builder_name"), + LSM_CARRAY(sai_builder_registration_t, power_controller_name, "power_controller_name"), + LSM_CARRAY(sai_builder_registration_t, power_on_type, "power_on_type"), + LSM_CARRAY(sai_builder_registration_t, power_on_url, "power_on_url"), + LSM_CARRAY(sai_builder_registration_t, power_on_mac, "power_on_mac"), + LSM_CARRAY(sai_builder_registration_t, power_off_type, "power_off_type"), + LSM_CARRAY(sai_builder_registration_t, power_off_url, "power_off_url"), + LSM_CARRAY(sai_builder_registration_t, power_monitor_url, "power_monitor_url"), +}; + +const lws_struct_map_t lsm_schema_sq3_map_builder_registration[] = { + LSM_SCHEMA_DLL2(sai_builder_registration_t, list, NULL, + lsm_sq3_builder_registration, "builder_registrations"), +}; + static const lws_struct_map_t lsm_pcon_energy_item[] = { LSM_CARRAY (sai_pcon_energy_report_item_t, name, "name"), LSM_UNSIGNED (sai_pcon_energy_report_item_t, data.voltage_v, "voltage_v"), diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index a69acb2..9142373 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -17,6 +17,7 @@ require_lws_config(LWS_WITH_DIR 1 requirements) if (requirements) add_executable("sai-device" ${SRCS}) +add_dependencies("sai-device" sai_git_hash) if (APPLE) set_property(TARGET sai-device PROPERTY MACOSX_RPATH YES) endif() diff --git a/src/expect/CMakeLists.txt b/src/expect/CMakeLists.txt index 84dc913..0386ac9 100644 --- a/src/expect/CMakeLists.txt +++ b/src/expect/CMakeLists.txt @@ -24,6 +24,7 @@ if (requirements AND NOT MSVC) endif() add_executable("sai-expect" ${SRCS}) +add_dependencies("sai-expect" sai_git_hash) if (APPLE) set_property(TARGET sai-expect PROPERTY MACOSX_RPATH YES) endif() diff --git a/src/jig/CMakeLists.txt b/src/jig/CMakeLists.txt index c007c9b..0305956 100644 --- a/src/jig/CMakeLists.txt +++ b/src/jig/CMakeLists.txt @@ -24,6 +24,7 @@ if (requirements) include_directories(BEFORE "${GPIOD_INC_PATH}") add_executable("sai-jig" ${SRCS}) +add_dependencies("sai-jig" sai_git_hash) target_link_libraries("sai-jig" ${GPIOD_LIB_PATH}) if (APPLE) diff --git a/src/power/CMakeLists.txt b/src/power/CMakeLists.txt index ac91e4a..6c312e0 100644 --- a/src/power/CMakeLists.txt +++ b/src/power/CMakeLists.txt @@ -11,6 +11,7 @@ set(SRCS p-tasmota-monitor.c ../common/c-utils.c ../common/struct-metadata.c + ../common/c-sqlite3.c ) set(requirements 1) @@ -20,10 +21,12 @@ require_lws_config(LWS_WITH_STRUCT_JSON 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_DIR 1 requirements) require_lws_config(LWS_WITH_WOL 1 requirements) +require_lws_config(LWS_WITH_STRUCT_SQLITE3 1 requirements) if (requirements) add_executable(${SUB} ${SRCS}) +add_dependencies(${SUB} sai_git_hash) if (APPLE) set_property(TARGET ${SUB} PROPERTY MACOSX_RPATH YES) endif() @@ -36,7 +39,7 @@ if (requirements) find_library(CAP_LIB_PATH NAMES "cap") endif() - target_link_libraries(${SUB} websockets ${SAI_LWS_LIB_PATH}) + target_link_libraries(${SUB} websockets sqlite3 ${SAI_LWS_LIB_PATH}) message("LWS_OPENSSL_LIBRARIES ${SUB} '${LWS_OPENSSL_LIBRARIES}'") if (LWS_OPENSSL_LIBRARIES) diff --git a/src/power/p-conf.c b/src/power/p-conf.c index 0e8da54..a5dddc4 100644 --- a/src/power/p-conf.c +++ b/src/power/p-conf.c @@ -32,38 +32,16 @@ static const char * const paths_global[] = { "perms", "wol-if", + "database", "servers[].url", - "servers[].power_controllers[].name", - "servers[].power_controllers[].type", - "servers[].power_controllers[].url", - "servers[].power_controllers[].mac", - "servers[].power_controllers[].depends_on", - "servers[].power_controllers[]", - "power_controllers[].name", - "power_controllers[].type", - "power_controllers[].url", - "power_controllers[].mac", - "power_controllers[].depends_on", - "power_controllers[]", "servers[]" }; enum enum_paths_global { LEJPM_PERMS, LEJPM_WOL_IF, + LEJPM_DATABASE, LEJPM_SERVERS_URL, - LEJPM_SRV_PCON_NAME, - LEJPM_SRV_PCON_TYPE, - LEJPM_SRV_PCON_URL, - LEJPM_SRV_PCON_MAC, - LEJPM_SRV_PCON_DEPENDS_ON, - LEJPM_SRV_PCON, - LEJPM_PCON_NAME, - LEJPM_PCON_TYPE, - LEJPM_PCON_URL, - LEJPM_PCON_MAC, - LEJPM_PCON_DEPENDS_ON, - LEJPM_PCON, LEJPM_SERVERS }; @@ -93,21 +71,6 @@ saip_conf_global_cb(struct lejp_ctx *ctx, char reason) &a->power->sai_server_owner); break; - case LEJPM_PCON: - case LEJPM_SRV_PCON: - /* - * Create the saip_pcon_t object - */ - a->sai_pcon = lwsac_use_zero(&a->power->ac_conf_head, - sizeof(*a->sai_pcon), 4096); - if (!a->sai_pcon) - return -1; - - /* We will link dependencies later */ - lws_dll2_add_tail(&a->sai_pcon->list, - &a->power->sai_pcon_owner); - break; - default: return 0; } @@ -132,29 +95,8 @@ saip_conf_global_cb(struct lejp_ctx *ctx, char reason) pp = &a->power->wol_if; break; - case LEJPM_PCON_NAME: - case LEJPM_SRV_PCON_NAME: - pp = &a->sai_pcon->name; - break; - - case LEJPM_PCON_TYPE: - case LEJPM_SRV_PCON_TYPE: - pp = &a->sai_pcon->type; - break; - - case LEJPM_PCON_URL: - case LEJPM_SRV_PCON_URL: - pp = &a->sai_pcon->url; - break; - - case LEJPM_PCON_MAC: - case LEJPM_SRV_PCON_MAC: - pp = &a->sai_pcon->mac; - break; - - case LEJPM_PCON_DEPENDS_ON: - case LEJPM_SRV_PCON_DEPENDS_ON: - pp = &a->sai_pcon->depends_on; + case LEJPM_DATABASE: + pp = &a->power->database; break; case LEJPM_SERVERS_URL: diff --git a/src/power/p-http-api.c b/src/power/p-http-api.c index 45d70ee..30d27d3 100644 --- a/src/power/p-http-api.c +++ b/src/power/p-http-api.c @@ -97,8 +97,8 @@ saip_builder_bringup(saip_server_t *sps, saip_pcon_t *pc) { saip_notify_server_power_state(pc->name, 1, 0); - if (pc->type && !strcmp(pc->type, "wol")) { - if (pc->mac) { + if (pc->type[0] && !strcmp(pc->type, "wol")) { + if (pc->mac[0]) { lwsl_notice("%s: triggering WOL for %s\n", __func__, pc->name); #if defined(LWS_WITH_SPAWN) write(lws_spawn_get_fd_stdxxx(lsp_wol, 0), @@ -301,6 +301,42 @@ local_srv_rx(void *userobj, const uint8_t *buf, size_t len, int flags) } if (pc) { + /* update dynamic info */ + if (r->power_on_type[0]) + lws_strncpy(pc->type, r->power_on_type, sizeof(pc->type)); + if (r->power_on_url[0]) + lws_strncpy(pc->url_on, r->power_on_url, sizeof(pc->url_on)); + if (r->power_on_mac[0]) + lws_strncpy(pc->mac, r->power_on_mac, sizeof(pc->mac)); + if (r->power_off_url[0]) + lws_strncpy(pc->url_off, r->power_off_url, sizeof(pc->url_off)); + if (r->power_monitor_url[0]) + lws_strncpy(pc->url_monitor, r->power_monitor_url, sizeof(pc->url_monitor)); + + saip_ss_create_pcon_streams(pc); + +#if defined(LWS_WITH_STRUCT_SQLITE3) + if (power.pdb) { + char q[256], esc[128]; + struct lws_dll2_owner o; + + lws_dll2_owner_clear(&o); + lws_dll2_add_tail(&r->list, &o); + + lws_sql_purify(esc, r->builder_name, sizeof(esc)); + lws_snprintf(q, sizeof(q), "DELETE FROM builder_registrations WHERE builder_name='%s'", esc); + sai_sqlite3_statement(power.pdb, q, "delete sticky reg"); + + if (lws_struct_sq3_serialize(power.pdb, lsm_schema_sq3_map_builder_registration, &o, 0)) + lwsl_err("%s: Failed to serialize sticky reg\n", __func__); + else + lwsl_notice("%s: Successfully serialized sticky reg for %s\n", __func__, r->builder_name); + + lws_dll2_remove(&r->list); + } +#endif + + /* Check if builder already exists */ int found = 0; lws_start_foreach_dll(struct lws_dll2 *, b_node, pc->registered_builders_owner.head) { @@ -456,7 +492,7 @@ local_srv_state(void *userobj, void *sh, lws_ss_constate_t state, saip_notify_server_power_state(pc->name, 1, 0); - if (pc->mac) { + if (pc->mac[0]) { #if defined(LWS_WITH_SPAWN) if (write(lws_spawn_get_fd_stdxxx(lsp_wol, 0), pc->mac, strlen(pc->mac)) != diff --git a/src/power/p-private.h b/src/power/p-private.h index 0c56d0d..fe50aeb 100644 --- a/src/power/p-private.h +++ b/src/power/p-private.h @@ -64,9 +64,9 @@ typedef struct saip_pcon { const char *depends_on; /* name from config */ const char *name; - const char *type; - const char *url; - const char *mac; /* For WOL */ + char type[32]; + char url[128]; + char mac[24]; /* For WOL */ char url_on[128]; char url_off[128]; @@ -142,6 +142,9 @@ struct sai_power { const char *power_off; const char *wol_if; + const char *database; + + struct sqlite3 *pdb; const char *bind; /* listen socket binding */ const char *perms; /* user:group */ @@ -200,7 +203,7 @@ int saip_parse_tasmota_status(tasmota_parse_t *tp); void -saip_ss_create_tasmota(void); +saip_ss_create_pcon_streams(saip_pcon_t *pc); void saip_pcon_start_check(void); diff --git a/src/power/p-sai.c b/src/power/p-sai.c index de7c4a5..fba4a73 100644 --- a/src/power/p-sai.c +++ b/src/power/p-sai.c @@ -286,7 +286,7 @@ sul_broadcast_energy_cb(lws_sorted_usec_list_t *sul) } lws_end_foreach_dll(p); if (!polled) - lwsl_notice("%s: No PCONs polled\n", __func__); + lwsl_info("%s: No PCONs polled\n", __func__); /* 2. Queue energy report to server (sends whatever latest data we have) */ /* We iterate servers, though usually only one */ @@ -536,7 +536,47 @@ int main(int argc, const char **argv) goto bail; } - saip_ss_create_tasmota(); + if (power.database) { + if (lws_struct_sq3_open(power.context, power.database, 1, &power.pdb)) { + lwsl_err("%s: Failed to open sqlite3 db %s\n", __func__, power.database); + } else { + if (lws_struct_sq3_create_table(power.pdb, lsm_schema_sq3_map_builder_registration)) { + lwsl_err("%s: Failed to create builder_registrations table\n", __func__); + } else { + /* deserialize existing sticky registrations */ + struct lws_dll2_owner temp_owner; + struct lwsac *ac = NULL; + + lws_dll2_owner_clear(&temp_owner); + if (lws_struct_sq3_deserialize(power.pdb, "", + NULL, lsm_schema_sq3_map_builder_registration, + &temp_owner, &ac, 0, 100) >= 0) { + /* Create PCONs for them */ + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, temp_owner.head) { + sai_builder_registration_t *r = lws_container_of(p, sai_builder_registration_t, list); + + lwsl_notice("%s: Sticky registration found for PCON %s\n", __func__, r->power_controller_name); + saip_pcon_t *pc = saip_pcon_create(&power, r->power_controller_name); + if (pc) { + if (r->power_on_type[0]) + lws_strncpy(pc->type, r->power_on_type, sizeof(pc->type)); + if (r->power_on_url[0]) + lws_strncpy(pc->url_on, r->power_on_url, sizeof(pc->url_on)); + if (r->power_on_mac[0]) + lws_strncpy(pc->mac, r->power_on_mac, sizeof(pc->mac)); + if (r->power_off_url[0]) + lws_strncpy(pc->url_off, r->power_off_url, sizeof(pc->url_off)); + if (r->power_monitor_url[0]) + lws_strncpy(pc->url_monitor, r->power_monitor_url, sizeof(pc->url_monitor)); + + saip_ss_create_pcon_streams(pc); + } + } lws_end_foreach_dll_safe(p, p1); + } + lwsac_free(&ac); + } + } + } #if defined(LWS_WITH_SPAWN) { diff --git a/src/power/p-smartplug.c b/src/power/p-smartplug.c index f2265aa..1b0b49f 100644 --- a/src/power/p-smartplug.c +++ b/src/power/p-smartplug.c @@ -132,40 +132,31 @@ LWS_SS_INFO("sai_power_smartplug", saip_smartplug_t) }; void -saip_ss_create_tasmota() +saip_ss_create_pcon_streams(saip_pcon_t *pc) { - /* let's create any needed tasmota ss */ - - lws_start_foreach_dll(struct lws_dll2 *, px, power.sai_pcon_owner.head) { - saip_pcon_t *pc = lws_container_of(px, saip_pcon_t, list); - - if (pc->type && !strcmp(pc->type, "tasmota") && pc->url) { - lws_snprintf(pc->url_on, sizeof(pc->url_on), - "%s/cm?cmnd=Power%%20On", pc->url); - if (lws_ss_create(power.context, 0, &ssi_saip_smartplug_t, - (void *)pc, - &pc->ss_tasmota_on, NULL, NULL)) - lwsl_err("%s: %s: failed to create ON smartplug secure stream %s\n", - __func__, pc->name, pc->url_on); - - lws_snprintf(pc->url_off, sizeof(pc->url_off), - "%s/cm?cmnd=Power%%20Off", pc->url); - if (lws_ss_create(power.context, 0, &ssi_saip_smartplug_t, - (void *)pc, - &pc->ss_tasmota_off, NULL, NULL)) - lwsl_err("%s: %s: failed to create OFF smartplug secure stream %s\n", - __func__, pc->name, pc->url_off); - - lws_snprintf(pc->url_monitor, sizeof(pc->url_monitor), - "%s/?m=1", pc->url); - if (lws_ss_create(power.context, 0, &ssi_saip_smartplug_t, - (void *)pc, - &pc->ss_tasmota_monitor, NULL, NULL)) - lwsl_err("%s: %s: failed to create MONITOR smartplug secure stream %s\n", - __func__, pc->name, pc->url_monitor); - else - lwsl_ss_warn(pc->ss_tasmota_monitor, "============================ creating monitor SS for %s", pc->url_monitor); - } + /* let's create any needed smartplug ss */ + + if (pc->url_on[0] && !pc->ss_tasmota_on) { + if (lws_ss_create(power.context, 0, &ssi_saip_smartplug_t, + (void *)pc, + &pc->ss_tasmota_on, NULL, NULL)) + lwsl_err("%s: %s: failed to create ON smartplug secure stream %s\n", + __func__, pc->name, pc->url_on); + } - } lws_end_foreach_dll(px); + if (pc->url_off[0] && !pc->ss_tasmota_off) { + if (lws_ss_create(power.context, 0, &ssi_saip_smartplug_t, + (void *)pc, + &pc->ss_tasmota_off, NULL, NULL)) + lwsl_err("%s: %s: failed to create OFF smartplug secure stream %s\n", + __func__, pc->name, pc->url_off); + } + + if (pc->url_monitor[0] && !pc->ss_tasmota_monitor) { + if (lws_ss_create(power.context, 0, &ssi_saip_smartplug_t, + (void *)pc, + &pc->ss_tasmota_monitor, NULL, NULL)) + lwsl_err("%s: %s: failed to create MONITOR smartplug secure stream %s\n", + __func__, pc->name, pc->url_monitor); + } } diff --git a/src/power/p-utils.c b/src/power/p-utils.c index 4d64b7a..e239343 100644 --- a/src/power/p-utils.c +++ b/src/power/p-utils.c @@ -66,7 +66,8 @@ saip_switch(saip_pcon_t *pc, int on) struct lws_ss_handle *h = on ? pc->ss_tasmota_on : pc->ss_tasmota_off; int wol_fired = 0; - if (on && pc->mac) { + if (on && pc->mac[0]) { +#if defined(LWS_WITH_SPAWN) char buf[64]; size_t n = (size_t)lws_snprintf(buf, sizeof(buf), "%s\n", pc->mac); @@ -79,12 +80,15 @@ saip_switch(saip_pcon_t *pc, int on) __func__, pc->name); wol_fired = 1; } +#else + lwsl_notice("%s: WOL needed but LWS_WITH_SPAWN disabled\n", __func__); +#endif } if (!h) { if (!wol_fired) { - if (pc->type && !strcmp(pc->type, "wol")) { - if (on && !pc->mac) + if (pc->type[0] && !strcmp(pc->type, "wol")) { + if (on && !pc->mac[0]) lwsl_err("%s: %s: WOL type but no MAC configured\n", __func__, pc->name); else @@ -94,8 +98,8 @@ saip_switch(saip_pcon_t *pc, int on) } else { lwsl_err("%s: %s: no ss handle for %s (type: %s, mac: %s)\n", __func__, pc->name, on ? "ON" : "OFF", - pc->type ? pc->type : "null", - pc->mac ? pc->mac : "null"); + pc->type[0] ? pc->type : "null", + pc->mac[0] ? pc->mac : "null"); } } return; diff --git a/src/power/p-ws-server.c b/src/power/p-ws-server.c index 99f69e3..c1282b0 100644 --- a/src/power/p-ws-server.c +++ b/src/power/p-ws-server.c @@ -147,13 +147,13 @@ saip_queue_stay_info(saip_server_t *sps) saip_pcon_t *pc = lws_container_of(p, saip_pcon_t, list); sai_power_controller_t *pc1 = lwsac_use_zero(&ac, sizeof(*pc1), 2048); - if (pc1 && pc->name) { + if (pc1 && pc->name[0]) { lws_strncpy(pc1->name, pc->name, sizeof(pc1->name)); pc1->on = (unsigned int)pc->on; pc1->manual_on = !!(pc->flags & SAIP_PCON_F_MANUAL_STAY); - if (pc->depends_on) + if (pc->depends_on[0]) lws_strncpy(pc1->depends_on, pc->depends_on, sizeof(pc1->depends_on)); - if (pc->type) + if (pc->type[0]) lws_strncpy(pc1->type, pc->type, sizeof(pc1->type)); lws_dll2_add_tail(&pc1->list, &pmb.power_controllers); diff --git a/src/resource/CMakeLists.txt b/src/resource/CMakeLists.txt index 5eb6cb6..f22f908 100644 --- a/src/resource/CMakeLists.txt +++ b/src/resource/CMakeLists.txt @@ -16,6 +16,7 @@ require_lws_config(LWS_WITH_DIR 1 requirements) if (requirements AND NOT MSVC) add_executable(${SUB} ${SRCS}) +add_dependencies(${SUB} sai_git_hash) if (APPLE) set_property(TARGET sai-resource PROPERTY MACOSX_RPATH YES) endif() diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 8595ed7..ee66246 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -39,6 +39,7 @@ require_lws_config(LWS_WITH_STRUCT_SQLITE3 1 requirements) if (requirements) add_executable(${SUB} ${SRCS}) +add_dependencies(${SUB} sai_git_hash) if (APPLE) set_property(TARGET sai-server PROPERTY MACOSX_RPATH YES) endif() diff --git a/src/server/s-ws-web.c b/src/server/s-ws-web.c index 5311f09..c8d4f6e 100644 --- a/src/server/s-ws-web.c +++ b/src/server/s-ws-web.c @@ -458,7 +458,7 @@ websrvss_ws_rx(void *userobj, const uint8_t *buf, size_t len, int flags) sai_db_result_t r; int n; - lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_info("%s: len %d, flags: %d\n", __func__, (int)len, flags); lwsl_hexdump_info(buf, len); memset(&a, 0, sizeof(a)); diff --git a/src/web/CMakeLists.txt b/src/web/CMakeLists.txt index 0f413fc..8ee5585 100644 --- a/src/web/CMakeLists.txt +++ b/src/web/CMakeLists.txt @@ -22,6 +22,7 @@ require_lws_config(LWS_WITH_UNIX_SOCK 1 requirements) if (requirements) add_executable(${SUB} ${SRCS}) +add_dependencies(${SUB} sai_git_hash) if (APPLE) set_property(TARGET sai-web PROPERTY MACOSX_RPATH YES) endif() diff --git a/src/web/w-comms.c b/src/web/w-comms.c index c156d0f..7cde616 100644 --- a/src/web/w-comms.c +++ b/src/web/w-comms.c @@ -465,7 +465,7 @@ http_resp: lws_hdr_copy(wsi, (char *)buf, sizeof(buf), WSI_TOKEN_X_FORWARDED_FOR); - lwsl_wsi_warn(wsi, "ESTABLISHED: %s %s", (char *)buf, pss->alang); + lwsl_wsi_info(wsi, "ESTABLISHED: %s %s", (char *)buf, pss->alang); if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) { if (lws_hdr_copy(wsi, (char *)start, 64, @@ -559,7 +559,7 @@ http_resp: case LWS_CALLBACK_CLOSED: - lwsl_wsi_err(wsi, "CLOSED browse conn"); + lwsl_wsi_info(wsi, "CLOSED browse conn"); lws_buflist_destroy_all_segments(&pss->raw_tx); saiw_browser_state_changed(pss, 0); lws_dll2_remove(&pss->subs_list); diff --git a/src/web/w-ws-browser.c b/src/web/w-ws-browser.c index 417a07c..33f4bc5 100644 --- a/src/web/w-ws-browser.c +++ b/src/web/w-ws-browser.c @@ -556,8 +556,8 @@ saiw_ws_json_rx_browser(struct vhd *vhd, struct pss *pss, uint8_t *buf, sai_cancel_t *can; int m, ret = -1; - lwsl_notice("%s: len %d, flags: %d\n", __func__, (int)bl, ss_flags); - /* lwsl_hexdump_notice(buf, bl); */ + lwsl_info("%s: len %d, flags: %d\n", __func__, (int)bl, ss_flags); + /* lwsl_hexdump_info(buf, bl); */ memset(&a, 0, sizeof(a)); /*
Page fetched 0s ago, creation time: 36ms (vhost etag hits: 0%, cache hits: 0%)