#include #include "wm_include.h" #include "wm_mem.h" #include "cJSON.h" #include "light/nl_control.h" #include "light/nl_engine.h" #include "net/nl_mdns.h" #include "net/nl_names.h" #include "net/nl_wifi.h" #include "sys/nl_app.h" #include "sys/nl_app_api.h" #include "sys/nl_ota.h" #include "nl_version.h" static void *json_alloc(size_t n) { return tls_mem_alloc(n); } static void json_free(void *p) { tls_mem_free(p); } static void get_state(nl_light_state_t *out) { nl_app_lock(); nl_ctrl_get(out); nl_app_unlock(); } static nl_ctrl_err_t apply(const nl_light_change_t *c) { nl_ctrl_err_t e; nl_app_lock(); e = nl_ctrl_apply(c, nl_app_now_ms()); nl_app_unlock(); return e; } static void get_settings(nl_settings_t *out) { nl_app_lock(); *out = *nl_app_settings(); nl_app_unlock(); } /* The API never changes Wi-Fi credentials through here (that goes through the onboarding test), * so the current ones are kept even if the network task stored new ones meanwhile. */ static int save_settings(const nl_settings_t *s) { nl_settings_t *cur; char name[NL_NAME_LEN]; bool name_changed; nl_app_lock(); cur = nl_app_settings(); name_changed = strcmp(cur->name, s->name) != 0; { nl_settings_t merged = *s; memcpy(merged.wifi_ssid, cur->wifi_ssid, sizeof merged.wifi_ssid); memcpy(merged.wifi_pass, cur->wifi_pass, sizeof merged.wifi_pass); *cur = merged; } nl_ctrl_set_options(cur->fade_in_ms, cur->fade_out_ms, cur->transition_ms, cur->wake_on_change != 0); memcpy(name, cur->name, sizeof name); nl_app_unlock(); if (name_changed) nl_mdns_set_name(name); return nl_app_save_settings(); } static int wifi_configure(const char *ssid, const char *pass) { return nl_wifi_request_onboard(ssid, pass); } static bool open_access(void) { return nl_wifi_open_access(); } static void get_info(nl_sys_info_t *out) { nl_wifi_status_t w; uint8_t mac[6]; memset(out, 0, sizeof *out); nl_wifi_mac(mac); nl_names_mac_str(mac, out->mac); nl_app_lock(); memcpy(out->name, nl_app_settings()->name, sizeof out->name); nl_app_unlock(); nl_wifi_status(&w); out->wifi_mode = w.mode; memcpy(out->ssid, w.ssid, sizeof out->ssid); out->rssi = w.rssi; memcpy(out->ip, w.ip, sizeof out->ip); memcpy(out->sta_ip, w.sta_ip, sizeof out->sta_ip); out->wifi_error = w.error; out->uptime_s = nl_app_now_ms() / 1000u; out->free_heap = tls_mem_get_avail_heapsize(); out->last_ota_error = nl_ota_last_error(); } static void factory_reset(void) { nl_app_request_factory_reset(); } static void ping(void) { nl_app_lock(); nl_engine_blink(3); nl_app_unlock(); } static int fw_update(const char *url) { return nl_ota_start(url); } const nl_api_ctx_t *nl_app_api_ctx(void) { static nl_api_ctx_t ctx; static bool ready; if (!ready) { cJSON_Hooks hooks = {json_alloc, json_free}; cJSON_InitHooks(&hooks); ctx.board = nl_board_get(); ctx.fw_version = NINLIGHT_FW_VERSION; ctx.build_date = NINLIGHT_BUILD_DATE; ctx.get_state = get_state; ctx.apply = apply; ctx.get_settings = get_settings; ctx.save_settings = save_settings; ctx.wifi_configure = wifi_configure; ctx.open_access = open_access; ctx.get_info = get_info; ctx.factory_reset = factory_reset; ctx.ping = ping; ctx.fw_update = fw_update; ready = true; } return &ctx; }