/ firmware / src / programs / shell / commands.cpp
commands.cpp
  1  #include "commands.h"
  2  #include <boot/system.h>
  3  #include <networking/wifi.h>
  4  #include "power/sleep.h"
  5  #include "services/data_logger.h"
  6  #include "../ssh/ssh_server.h"
  7  
  8  #include <Arduino.h>
  9  #include <Console.h>
 10  #include <Esp.h>
 11  #include <freertos/FreeRTOS.h>
 12  #include <freertos/task.h>
 13  #include <stdio.h>
 14  
 15  static int cmd_reboot(int argc, char **argv) {
 16    (void)argc; (void)argv;
 17    printf("rebooting...\n");
 18    delay(100);
 19    ESP.restart();
 20    return 0;
 21  }
 22  
 23  static int cmd_wifi_set(int argc, char **argv) {
 24    if (argc != 3) {
 25      printf("usage: wifi-set <ssid> <password>\n");
 26      return 1;
 27    }
 28    WifiSavedConfig config = {};
 29    strlcpy(config.ssid, argv[1], sizeof(config.ssid));
 30    strlcpy(config.password, argv[2], sizeof(config.password));
 31    if (networking::wifi::storeConfig(&config))
 32      printf("saved. use wifi-connect to connect.\n");
 33    else
 34      printf("failed to save config.\n");
 35    return 0;
 36  }
 37  
 38  static int cmd_wifi_connect(int argc, char **argv) {
 39    (void)argc; (void)argv;
 40    printf("connecting...\n");
 41    if (networking::wifi::sta::connect()) {
 42      printf("connected, starting services...\n");
 43      boot::system::startServices();
 44    } else {
 45      printf("failed\n");
 46    }
 47    return 0;
 48  }
 49  
 50  static int cmd_ps(int argc, char **argv) {
 51    (void)argc; (void)argv;
 52  
 53    uint32_t count = uxTaskGetNumberOfTasks();
 54    TaskStatus_t *tasks = (TaskStatus_t *)malloc(count * sizeof(TaskStatus_t));
 55    if (!tasks) { printf("out of memory\n"); return 1; }
 56  
 57    uint32_t total_runtime = 0;
 58    uint32_t filled = uxTaskGetSystemState(tasks, count, &total_runtime);
 59  
 60    static const char *states[] = {"Run", "Rdy", "Blk", "Sus", "Del", "Inv"};
 61  
 62    printf("%-16s %4s %4s %5s %4s\n", "NAME", "STAT", "PRI", "STACK", "CORE");
 63  
 64    for (uint32_t i = 0; i < filled; i++) {
 65      int state = (int)tasks[i].eCurrentState;
 66      if (state > 5) state = 5;
 67      int core = (int)tasks[i].xCoreID;
 68  
 69      printf("%-16s %4s %4lu %5lu %4s\n",
 70             tasks[i].pcTaskName, states[state],
 71             (unsigned long)tasks[i].uxCurrentPriority,
 72             (unsigned long)tasks[i].usStackHighWaterMark,
 73             core == tskNO_AFFINITY ? "*" : (core == 0 ? "0" : "1"));
 74    }
 75  
 76    ::free(tasks);
 77    return 0;
 78  }
 79  
 80  static int cmd_cpu(int argc, char **argv) {
 81    if (argc == 2) {
 82      uint32_t mhz = atoi(argv[1]);
 83      if (mhz != 80 && mhz != 160 && mhz != 240) {
 84        printf("usage: cpu [80|160|240]\n");
 85        return 1;
 86      }
 87      setCpuFrequencyMhz(mhz);
 88      printf("CPU set to %lu MHz\n", (unsigned long)mhz);
 89      return 0;
 90    }
 91    printf("%lu MHz\n", (unsigned long)ESP.getCpuFreqMHz());
 92    return 0;
 93  }
 94  
 95  static int cmd_sleep(int argc, char **argv) {
 96    if (argc != 1 && argc != 2) {
 97      printf("usage: sleep [seconds]\n");
 98      return 1;
 99    }
100  
101    SleepCommand command = {};
102    bool ok = false;
103    if (argc == 2) {
104      command.duration_seconds = static_cast<uint32_t>(atoi(argv[1]));
105      ok = power::sleep::request(&command);
106    } else {
107      ok = power::sleep::requestConfigured(&command);
108    }
109  
110    if (ok)
111      printf("sleeping in %lu second(s)...\n", (unsigned long)command.duration_seconds);
112    else
113      printf("invalid or disabled sleep configuration\n");
114    return ok ? 0 : 1;
115  }
116  
117  static int cmd_wakecause(int argc, char **argv) {
118    (void)argv;
119    if (argc != 1) { printf("usage: wakecause\n"); return 1; }
120    printf("%s\n", power::sleep::accessWakeCause());
121    return 0;
122  }
123  
124  static int cmd_sleep_status(int argc, char **argv) {
125    (void)argv;
126    if (argc != 1) { printf("usage: sleep-status\n"); return 1; }
127  
128    SleepStatusSnapshot snapshot = {};
129    power::sleep::accessStatus(&snapshot);
130    printf("pending=%s\n"
131           "requested_duration_seconds=%lu\n"
132           "wake_cause=%s\n"
133           "timer_wakeup_enabled=%s\n"
134           "timer_wakeup_us=%llu\n"
135           "config_enabled=%s\n"
136           "default_duration_seconds=%lu\n",
137           snapshot.pending ? "true" : "false",
138           (unsigned long)snapshot.requested_duration_seconds,
139           snapshot.wake_cause,
140           snapshot.timer_wakeup_enabled ? "true" : "false",
141           (unsigned long long)snapshot.timer_wakeup_us,
142           snapshot.config_enabled ? "true" : "false",
143           (unsigned long)snapshot.default_duration_seconds);
144    return 0;
145  }
146  
147  static int cmd_sleep_config(int argc, char **argv) {
148    (void)argv;
149    if (argc != 1) { printf("usage: sleep-config\n"); return 1; }
150  
151    SleepConfig config = {};
152    if (!power::sleep::accessConfig(&config)) {
153      printf("sleep config unavailable\n");
154      return 1;
155    }
156    printf("enabled=%s\nduration_seconds=%lu\n",
157           config.enabled ? "true" : "false",
158           (unsigned long)config.duration_seconds);
159    return 0;
160  }
161  
162  static int cmd_sleep_enable(int argc, char **argv) {
163    (void)argv;
164    if (argc != 1) { printf("usage: sleep-enable\n"); return 1; }
165    SleepConfig config = {};
166    if (!power::sleep::accessConfig(&config)) { printf("sleep config unavailable\n"); return 1; }
167    config.enabled = true;
168    if (power::sleep::storeConfig(&config))
169      printf("sleep config enabled\n");
170    else
171      printf("failed to save sleep config\n");
172    return 0;
173  }
174  
175  static int cmd_sleep_disable(int argc, char **argv) {
176    (void)argv;
177    if (argc != 1) { printf("usage: sleep-disable\n"); return 1; }
178    SleepConfig config = {};
179    if (!power::sleep::accessConfig(&config)) { printf("sleep config unavailable\n"); return 1; }
180    config.enabled = false;
181    power::sleep::abortPending();
182    if (power::sleep::storeConfig(&config))
183      printf("sleep config disabled\n");
184    else
185      printf("failed to save sleep config\n");
186    return 0;
187  }
188  
189  static int cmd_sleep_duration(int argc, char **argv) {
190    if (argc != 2) { printf("usage: sleep-duration <seconds>\n"); return 1; }
191    SleepConfig config = {};
192    if (!power::sleep::accessConfig(&config)) { printf("sleep config unavailable\n"); return 1; }
193    config.duration_seconds = static_cast<uint32_t>(atoi(argv[1]));
194    if (power::sleep::storeConfig(&config))
195      printf("default sleep duration set to %lu second(s)\n", (unsigned long)config.duration_seconds);
196    else
197      printf("invalid sleep duration\n");
198    return 0;
199  }
200  
201  static int cmd_log_status(int argc, char **argv) {
202    (void)argv;
203    if (argc != 1) { printf("usage: log-status\n"); return 1; }
204  
205    DataLoggerStatusSnapshot snapshot = {};
206    services::data_logger::accessStatus(&snapshot);
207    printf("initialized=%s\n"
208           "sd_ready=%s\n"
209           "header_written=%s\n"
210           "interval_ms=%lu\n"
211           "last_log_ms=%lu\n"
212           "path=%s\n",
213           snapshot.initialized ? "true" : "false",
214           snapshot.sd_ready ? "true" : "false",
215           snapshot.header_written ? "true" : "false",
216           (unsigned long)snapshot.interval_ms,
217           (unsigned long)snapshot.last_log_ms,
218           snapshot.path);
219    return 0;
220  }
221  
222  void programs::shell::commands::registerAll() {
223    Console.addCmd("reboot",            "reboot the device",                    cmd_reboot);
224    Console.addCmd("wifi-set",          "save WiFi credentials to NVS",        "<ssid> <password>", cmd_wifi_set);
225    Console.addCmd("wifi-connect",      "connect to saved WiFi network",       cmd_wifi_connect);
226    Console.addCmd("ps",                "list running tasks",                   cmd_ps);
227    Console.addCmd("cpufreq",           "read or set CPU frequency",           "[80|160|240]", cmd_cpu);
228    Console.addCmd("deepsleep",         "enter deep sleep for N seconds",      "[seconds]", cmd_sleep);
229    Console.addCmd("deepsleep-config",  "show persisted deep sleep config",    cmd_sleep_config);
230    Console.addCmd("deepsleep-enable",  "enable persisted deep sleep config",  cmd_sleep_enable);
231    Console.addCmd("deepsleep-disable", "disable persisted deep sleep config", cmd_sleep_disable);
232    Console.addCmd("deepsleep-duration","set persisted deep sleep duration",   "<seconds>", cmd_sleep_duration);
233    Console.addCmd("wakecause",         "show the last wake cause",            cmd_wakecause);
234    Console.addCmd("sleep-status",      "show deep sleep status",              cmd_sleep_status);
235    Console.addCmd("log-status",        "show CSV logger status",              cmd_log_status);
236  }