#include #include #include "wm_include.h" #include "wm_watchdog.h" #include "light/nl_control.h" #include "light/nl_engine.h" #include "net/nl_wifi.h" #include "sys/nl_app.h" #include "sys/nl_console.h" #include "sys/nl_console_cmd.h" #define NL_CONSOLE_PRIO 45 static u32 s_stack[768]; static void print_state(void) { nl_light_state_t s; nl_settings_t *cfg = nl_app_settings(); nl_app_lock(); nl_ctrl_get(&s); nl_app_unlock(); printf("state: %s bri=%u mode=%s rgb=%u,%u,%u ct=%u | pob=%u fade=%u/%u\r\n", s.on ? "on" : "off", s.brightness, s.mode == NL_MODE_COLOR ? "color" : "white", s.r, s.g, s.b, s.ct, cfg->power_on_behaviour, cfg->fade_in_ms, cfg->fade_out_ms); } static void set_transition(nl_light_change_t *ch, const nl_cmd_t *c, uint8_t index) { if (c->argc > index) { ch->has_transition = true; ch->transition_ms = (uint32_t)c->arg[index]; } } static void exec(const nl_cmd_t *c) { nl_light_change_t ch; nl_ctrl_err_t err; nl_settings_t *cfg = nl_app_settings(); memset(&ch, 0, sizeof ch); switch (c->type) { case NL_CMD_NONE: return; case NL_CMD_ON: case NL_CMD_OFF: ch.has_on = true; ch.on = c->type == NL_CMD_ON; set_transition(&ch, c, 0); break; case NL_CMD_BRI: ch.has_brightness = true; ch.brightness = (uint8_t)c->arg[0]; set_transition(&ch, c, 1); break; case NL_CMD_RGB: ch.has_color = true; ch.r = (uint8_t)c->arg[0]; ch.g = (uint8_t)c->arg[1]; ch.b = (uint8_t)c->arg[2]; set_transition(&ch, c, 3); break; case NL_CMD_CT: ch.has_ct = true; ch.ct = (uint16_t)c->arg[0]; set_transition(&ch, c, 1); break; case NL_CMD_POB: nl_app_lock(); cfg->power_on_behaviour = (uint8_t)c->arg[0]; nl_app_unlock(); printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n"); print_state(); return; case NL_CMD_FADE: nl_app_lock(); cfg->fade_in_ms = (uint16_t)c->arg[0]; cfg->fade_out_ms = (uint16_t)c->arg[1]; nl_ctrl_set_fades(cfg->fade_in_ms, cfg->fade_out_ms); nl_app_unlock(); printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n"); print_state(); return; case NL_CMD_STATE: print_state(); return; case NL_CMD_BLINK: nl_app_lock(); nl_engine_blink((uint8_t)c->arg[0]); nl_app_unlock(); return; case NL_CMD_PULSE: nl_app_lock(); nl_engine_pulse(c->arg[0] != 0); nl_app_unlock(); return; case NL_CMD_FACTORY: nl_app_request_factory_reset(); return; case NL_CMD_REBOOT: nl_app_reboot(); return; case NL_CMD_NET: { nl_wifi_status_t w; nl_wifi_status(&w); printf("net: mode=%s ssid=%s ip=%s sta_ip=%s rssi=%d error=%s host=%s\r\n", w.mode, w.ssid, w.ip, w.sta_ip[0] ? w.sta_ip : "-", w.rssi, w.error ? w.error : "-", nl_wifi_hostname()); return; } case NL_CMD_WDTEST: printf("wdtest: holding app lock forever\r\n"); nl_app_lock(); /* deliberately never released: light_task and app_task stall on it, * so only the watchdog reset can recover the chip */ return; case NL_CMD_HELP: printf("%s", nl_console_help); return; default: printf("error: unknown command or bad argument (try help)\r\n"); return; } nl_app_lock(); err = nl_ctrl_apply(&ch, nl_app_now_ms()); nl_app_unlock(); if (err == NL_CTRL_OK) printf("ok\r\n"); else printf("error %d\r\n", (int)err); print_state(); } static void console_task(void *arg) { char line[64]; int len = 0; u8 buf[16]; (void)arg; printf("console ready, type help\r\n"); for (;;) { int n = tls_uart_read(TLS_UART_0, buf, sizeof buf); for (int i = 0; i < n; i++) { char c = (char)buf[i]; if (c == '\r' || c == '\n') { if (len) { nl_cmd_t cmd; line[len] = '\0'; cmd = nl_console_parse(line); exec(&cmd); len = 0; } } else if (len < (int)sizeof(line) - 1) { line[len++] = c; } } tls_os_time_delay(HZ / 50); /* 20 ms */ } } void nl_console_start(void) { tls_uart_port_init(TLS_UART_0, NULL, 0); tls_os_task_create(NULL, "nl_con", console_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_CONSOLE_PRIO, 0); }