microfetch.cpp
1 #include "microfetch.h" 2 #include <config.h> 3 #include "console/icons.h" 4 #include <storage.h> 5 #include <i2c.h> 6 #include <networking/wifi.h> 7 #include <manager.h> 8 #include <identity.h> 9 #include <services/system.h> 10 11 #include <Arduino.h> 12 #include <Console.h> 13 14 static char fetch_buf[2048]; 15 16 static int fetch_pos; 17 static int fetch_remaining; 18 19 static void row(const char *color, const char *icon, const char *label, const char *fmt, ...) { 20 int space = fetch_remaining; 21 if (space <= 0) return; 22 23 int n = snprintf(fetch_buf + fetch_pos, space, 24 " \x1b[1;%sm%s %-14s\x1b[0m ", color, icon, label); 25 if (n > 0 && n < space) { fetch_pos += n; fetch_remaining -= n; } 26 27 va_list args; 28 va_start(args, fmt); 29 n = vsnprintf(fetch_buf + fetch_pos, fetch_remaining, fmt, args); 30 va_end(args); 31 if (n > 0 && n < fetch_remaining) { fetch_pos += n; fetch_remaining -= n; } 32 33 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, "\r\n"); 34 if (n > 0 && n < fetch_remaining) { fetch_pos += n; fetch_remaining -= n; } 35 } 36 37 const char *programs::shell::microfetch::generate(const char *transport) { 38 fetch_pos = 0; 39 fetch_remaining = sizeof(fetch_buf) - 1; 40 41 SystemQuery system_query = { 42 .preferred_storage = StorageKind::LittleFS, 43 .snapshot = {}, 44 }; 45 services::system::accessSnapshot(&system_query); 46 const SystemSnapshot &snapshot = system_query.snapshot; 47 SensorInventorySnapshot inventory = {}; 48 sensors::manager::accessInventory(&inventory); 49 uint32_t heap_pct = snapshot.heap_total > 0 50 ? ((snapshot.heap_total - snapshot.heap_free) * 100) / snapshot.heap_total 51 : 0; 52 53 int n; 54 55 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, "\r\n"); 56 fetch_pos += n; fetch_remaining -= n; 57 58 const char *hostname = services::identity::access_hostname(); 59 60 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, 61 " \x1b[1;32m%s\x1b[0m\x1b[2m@\x1b[0m\x1b[1;36m%s\x1b[0m\r\n", 62 CONFIG_SSH_USER, hostname); 63 fetch_pos += n; fetch_remaining -= n; 64 65 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, " \x1b[2m"); 66 fetch_pos += n; fetch_remaining -= n; 67 size_t sep_len = strlen(CONFIG_SSH_USER) + 1 + strlen(hostname); 68 for (size_t i = 0; i < sep_len && fetch_remaining > 1; i++) { 69 fetch_buf[fetch_pos++] = '-'; 70 fetch_remaining--; 71 } 72 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, "\x1b[0m\r\n"); 73 fetch_pos += n; fetch_remaining -= n; 74 75 row("33", NF_FA_MICROCHIP, "OS", "\x1b[1mceratina\x1b[0m (%s)", config::PLATFORM); 76 row("35", NF_FA_DESKTOP, "Host", "\x1b[1m%s\x1b[0m (rev %d)", snapshot.chip_model, snapshot.chip_revision); 77 row("36", NF_FA_COG, "Kernel", "\x1b[1mArduino\x1b[0m / ESP-IDF %s", snapshot.sdk_version); 78 79 uint32_t d = snapshot.uptime_seconds / 86400, h = (snapshot.uptime_seconds % 86400) / 3600; 80 uint32_t m = (snapshot.uptime_seconds % 3600) / 60, s = snapshot.uptime_seconds % 60; 81 if (d > 0) row("34", NF_FA_CLOCK, "Uptime", "\x1b[1m%u\x1b[0md %uh %um %us", d, h, m, s); 82 else if (h > 0) row("34", NF_FA_CLOCK, "Uptime", "\x1b[1m%u\x1b[0mh %um %us", h, m, s); 83 else row("34", NF_FA_CLOCK, "Uptime", "\x1b[1m%u\x1b[0mm %us", m, s); 84 85 row("32", NF_FA_TERMINAL, "Shell", "\x1b[1mMicroshell\x1b[0m (%s)", transport); 86 row("31", NF_FA_MICROCHIP, "CPU", "\x1b[1mXtensa LX7\x1b[0m (%d) @ \x1b[1m%u MHz\x1b[0m", 87 snapshot.chip_cores, (unsigned)snapshot.cpu_mhz); 88 row("36", NF_FA_MEMORY, "RAM", "\x1b[1m%u/%u KiB\x1b[0m (\x1b[1;32m%u%%\x1b[0m)", 89 (snapshot.heap_total - snapshot.heap_free) / 1024, snapshot.heap_total / 1024, heap_pct); 90 91 StorageQuery sd_query = { 92 .kind = StorageKind::SD, 93 .snapshot = {}, 94 }; 95 if (hardware::storage::accessSnapshot(&sd_query)) 96 row("32", NF_FA_HDD, "Disk (SD)", "\x1b[1m%llu MiB\x1b[0m", sd_query.snapshot.total_bytes / (1024*1024)); 97 else 98 row("32", NF_FA_HDD, "Disk (SD)", "\x1b[2mnot detected\x1b[0m"); 99 100 if (snapshot.storage.mounted) 101 row("32", NF_FA_DATABASE, "Disk (LFS)", "\x1b[1m%u/%u KiB\x1b[0m", 102 (unsigned)(snapshot.storage.used_bytes/1024), (unsigned)(snapshot.storage.total_bytes/1024)); 103 104 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, "\r\n"); 105 fetch_pos += n; fetch_remaining -= n; 106 107 if (snapshot.network.connected) { 108 row("33", NF_FA_WIFI, "WiFi", "\x1b[1m%s\x1b[0m (%ld dBm)", snapshot.network.ssid, snapshot.network.rssi); 109 row("33", NF_FA_GLOBE, "Local IP", "\x1b[1m%s\x1b[0m", snapshot.network.ip); 110 } else if (snapshot.network.ap.active) { 111 row("33", NF_FA_WIFI, "WiFi", "\x1b[1mAP mode\x1b[0m (%u clients)", snapshot.network.ap.clients); 112 row("33", NF_FA_GLOBE, "AP IP", "\x1b[1m%s\x1b[0m", snapshot.network.ap.ip); 113 } else { 114 row("33", NF_FA_WIFI, "WiFi", "\x1b[2mnot connected\x1b[0m"); 115 } 116 117 row("35", NF_FA_SERVER, "Hostname", "\x1b[1m%s\x1b[0m.local", hostname); 118 row("34", NF_FA_GLOBE, "NTP", "\x1b[1m%s\x1b[0m", config::sntp::SERVER_1); 119 row("36", NF_FA_PLUG, "Ports", "SSH:\x1b[1m%d\x1b[0m HTTP:\x1b[1m%d\x1b[0m", config::ssh::PORT, config::http::PORT); 120 121 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, "\r\n"); 122 fetch_pos += n; fetch_remaining -= n; 123 124 row("36", NF_FA_SITEMAP, "I2C Mux", "\x1b[1mTCA9548A\x1b[0m @ 0x%02X", config::i2c::MUX_ADDR); 125 126 if (inventory.temperature_humidity_count > 0) 127 row("35", NF_FA_THERMOMETER, "Temp/Hum", "\x1b[1mI2C sensors\x1b[0m x%d", 128 inventory.temperature_humidity_count); 129 130 131 row("35", NF_FA_SIGNAL, "Voltage", "\x1b[1mADS1115\x1b[0m @ 0x%02X", config::voltage::I2C_ADDR); 132 133 n = snprintf(fetch_buf + fetch_pos, fetch_remaining, "\r\n"); 134 fetch_pos += n; fetch_remaining -= n; 135 136 fetch_buf[fetch_pos] = '\0'; 137 return fetch_buf; 138 } 139 140 static int cmd_microfetch(int argc, char **argv) { 141 (void)argc; (void)argv; 142 printf("%s", programs::shell::microfetch::generate()); 143 return 0; 144 } 145 146 void programs::shell::microfetch::registerCmd() { 147 Console.addCmd("microfetch", "system info summary", cmd_microfetch); 148 }