Changes made based on pr feedback.

This commit is contained in:
PhosphorosVR
2025-09-23 01:46:53 +02:00
parent 15641753f0
commit e47735c720
8 changed files with 48 additions and 50 deletions
+16 -6
View File
@@ -124,8 +124,10 @@ Runtime override: If the setup CLI (or a JSON command) provides a new device nam
- Fast WiFi setup: in the CLI, go to “WiFi settings” → “Automatic setup”, then check “status”. - Fast WiFi setup: in the CLI, go to “WiFi settings” → “Automatic setup”, then check “status”.
- Change name/MDNS: set the device name in the CLI, then replug USB — UVC will show the new name. - Change name/MDNS: set the device name in the CLI, then replug USB — UVC will show the new name.
- Adjust brightness/LED: set LED PWM in the CLI. - Adjust brightness/LED: set LED PWM in the CLI.
- Switch to UVC mode over commands: send JSON `{ "cmd": "switch_mode", "mode": "uvc" }` then reboot. - Switch to UVC mode over commands (CDC/serial):
- Read filtered LED current (if enabled): `{ "cmd": "get_led_current" }`. `{"commands":[{"command":"switch_mode","data":{"mode":"uvc"}}]}` then reboot.
- Read filtered LED current (if enabled):
`{"commands":[{"command":"get_led_current"}]}`
--- ---
@@ -143,11 +145,19 @@ When UVC support is compiled in the device enumerates as a composite USB device:
- UVC interface: video streaming (JPEG frames) - UVC interface: video streaming (JPEG frames)
- CDC (virtual COM): command channel accepting newlineterminated JSON objects - CDC (virtual COM): command channel accepting newlineterminated JSON objects
Example newlineterminated JSON commands over CDC: Example newlineterminated JSON commands over CDC (one per line):
``` ```
{"cmd":"ping"}\n {"commands":[{"command":"ping"}]}
{"cmd":"get_info"}\n {"commands":[{"command":"get_who_am_i"}]}
{"cmd":"switch_mode","mode":"wifi"}\n {"commands":[{"command":"switch_mode","data":{"mode":"wifi"}}]}
```
Chained commands in a single request (processed in order):
```
{"commands":[
{"command":"set_mdns","data":{"hostname":"tracker"}},
{"command":"set_wifi","data":{"name":"main","ssid":"your_network","password":"password","channel":0,"power":0}}
]}
``` ```
Responses are JSON blobs flushed immediately. Responses are JSON blobs flushed immediately.
@@ -72,8 +72,8 @@ private:
bool finishedPattern = false; bool finishedPattern = false;
#if defined(CONFIG_LED_EXTERNAL_CONTROL) && defined(CONFIG_LED_EXTERNAL_AS_DEBUG) #if defined(CONFIG_LED_EXTERNAL_CONTROL) && defined(CONFIG_LED_EXTERNAL_AS_DEBUG)
mutable bool hasStoredExternalDuty = false; bool hasStoredExternalDuty = false;
mutable uint32_t storedExternalDuty = 0; // raw 0-255 uint32_t storedExternalDuty = 0; // raw 0-255
#endif #endif
}; };
@@ -1,3 +1,5 @@
#ifndef CURRENT_MONITOR_HPP
#define CURRENT_MONITOR_HPP
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
@@ -43,3 +45,5 @@ private:
size_t sample_idx_ = 0; size_t sample_idx_ = 0;
size_t sample_count_ = 0; size_t sample_count_ = 0;
}; };
#endif
@@ -6,8 +6,6 @@
class MonitoringManager { class MonitoringManager {
public: public:
MonitoringManager() = default;
~MonitoringManager() = default;
void setup(); void setup();
void start(); void start();
+4 -4
View File
@@ -97,10 +97,10 @@ static uvc_fb_t *UVCStreamHelpers::camera_fb_get_cb(void *cb_ctx)
// --- Frame pacing BEFORE grabbing a new camera frame --- // --- Frame pacing BEFORE grabbing a new camera frame ---
static int64_t next_deadline_us = 0; // next permitted capture time static int64_t next_deadline_us = 0; // next permitted capture time
static int rem_acc = 0; // fractional remainder accumulator static int rem_acc = 0; // fractional remainder accumulator
constexpr int target_fps = 60; // desired FPS static const int target_fps = 60; // desired FPS
constexpr int64_t us_per_sec = 1000000; // 1e6 microseconds static const int64_t us_per_sec = 1000000; // 1e6 microseconds
constexpr int base_interval_us = us_per_sec / target_fps; // 16666 static const int base_interval_us = us_per_sec / target_fps; // 16666
constexpr int rem_us = us_per_sec % target_fps; // 40 (distributed) static const int rem_us = us_per_sec % target_fps; // 40 (distributed)
const int64_t now_us = esp_timer_get_time(); const int64_t now_us = esp_timer_get_time();
if (next_deadline_us == 0) if (next_deadline_us == 0)
+11 -11
View File
@@ -5,9 +5,9 @@
#include "freertos/queue.h" #include "freertos/queue.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_timer.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "nvs_flash.h" #include "nvs_flash.h"
#include "esp_wifi.h"
#include <openiris_logo.hpp> #include <openiris_logo.hpp>
#include <wifiManager.hpp> #include <wifiManager.hpp>
@@ -65,7 +65,7 @@ UVCStreamManager uvcStream;
auto ledManager = std::make_shared<LEDManager>(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue, deviceConfig); auto ledManager = std::make_shared<LEDManager>(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue, deviceConfig);
auto *serialManager = new SerialManager(commandManager, &timerHandle, deviceConfig); auto *serialManager = new SerialManager(commandManager, &timerHandle, deviceConfig);
MonitoringManager monitoringManager; std::shared_ptr<MonitoringManager> monitoringManager = std::make_shared<MonitoringManager>();
void startWiFiMode(bool shouldCloseSerialManager); void startWiFiMode(bool shouldCloseSerialManager);
void startWiredMode(bool shouldCloseSerialManager); void startWiredMode(bool shouldCloseSerialManager);
@@ -233,11 +233,11 @@ void startSetupMode()
{ {
// If we're in SETUP mode - Device starts with a 20-second delay before deciding on what to do // If we're in SETUP mode - Device starts with a 20-second delay before deciding on what to do
// during this time we await any commands // during this time we await any commands
const int startup_delay_s = CONFIG_GENERAL_STARTUP_DELAY; const uint64_t startup_delay_s = CONFIG_GENERAL_STARTUP_DELAY;
ESP_LOGI("[MAIN]", "====================================="); ESP_LOGI("[MAIN]", "=====================================");
ESP_LOGI("[MAIN]", "STARTUP: %d-SECOND DELAY MODE ACTIVE", startup_delay_s); ESP_LOGI("[MAIN]", "STARTUP: %llu-SECOND DELAY MODE ACTIVE", (unsigned long long)startup_delay_s);
ESP_LOGI("[MAIN]", "====================================="); ESP_LOGI("[MAIN]", "=====================================");
ESP_LOGI("[MAIN]", "Device will wait %d seconds for commands...", startup_delay_s); ESP_LOGI("[MAIN]", "Device will wait %llu seconds for commands...", (unsigned long long)startup_delay_s);
// Create a one-shot timer for 20 seconds // Create a one-shot timer for 20 seconds
const esp_timer_create_args_t startup_timer_args = { const esp_timer_create_args_t startup_timer_args = {
@@ -248,9 +248,9 @@ void startSetupMode()
.skip_unhandled_events = false}; .skip_unhandled_events = false};
ESP_ERROR_CHECK(esp_timer_create(&startup_timer_args, &timerHandle)); ESP_ERROR_CHECK(esp_timer_create(&startup_timer_args, &timerHandle));
ESP_ERROR_CHECK(esp_timer_start_once(timerHandle, (uint64_t)startup_delay_s * 1000000)); ESP_ERROR_CHECK(esp_timer_start_once(timerHandle, startup_delay_s * 1000000));
ESP_LOGI("[MAIN]", "Started %d-second startup timer", startup_delay_s); ESP_LOGI("[MAIN]", "Started %llu-second startup timer", (unsigned long long)startup_delay_s);
ESP_LOGI("[MAIN]", "Send any command within %d seconds to enter heartbeat mode", startup_delay_s); ESP_LOGI("[MAIN]", "Send any command within %llu seconds to enter heartbeat mode", (unsigned long long)startup_delay_s);
} }
extern "C" void app_main(void) extern "C" void app_main(void)
@@ -262,7 +262,7 @@ extern "C" void app_main(void)
dependencyRegistry->registerService<WiFiManager>(DependencyType::wifi_manager, wifiManager); dependencyRegistry->registerService<WiFiManager>(DependencyType::wifi_manager, wifiManager);
#endif #endif
dependencyRegistry->registerService<LEDManager>(DependencyType::led_manager, ledManager); dependencyRegistry->registerService<LEDManager>(DependencyType::led_manager, ledManager);
dependencyRegistry->registerService<MonitoringManager>(DependencyType::monitoring_manager, std::shared_ptr<MonitoringManager>(&monitoringManager, [](MonitoringManager*){})); dependencyRegistry->registerService<MonitoringManager>(DependencyType::monitoring_manager, monitoringManager);
// add endpoint to check firmware version // add endpoint to check firmware version
// add firmware version somewhere // add firmware version somewhere
@@ -275,8 +275,8 @@ extern "C" void app_main(void)
initNVSStorage(); initNVSStorage();
deviceConfig->load(); deviceConfig->load();
ledManager->setup(); ledManager->setup();
monitoringManager.setup(); monitoringManager->setup();
monitoringManager.start(); monitoringManager->start();
xTaskCreate( xTaskCreate(
HandleStateManagerTask, HandleStateManagerTask,
+7 -9
View File
@@ -1063,10 +1063,9 @@ def get_settings(device: OpenIrisDevice, args=None):
print("🔑 Serial/MAC: unavailable") print("🔑 Serial/MAC: unavailable")
# Advertised Name # Advertised Name
adv = summary.get("AdvertisedName", {}) advertised_name_data = summary.get("AdvertisedName", {})
adv_name = adv.get("advertised_name") if advertised_name := advertised_name_data.get("advertised_name"):
if adv_name: print(f"📛 Name: {advertised_name}")
print(f"📛 Name: {adv_name}")
# Info # Info
info = summary.get("Info", {}) info = summary.get("Info", {})
@@ -1090,12 +1089,11 @@ def get_settings(device: OpenIrisDevice, args=None):
print(f"🎚️ Mode: {mode if mode else 'unknown'}") print(f"🎚️ Mode: {mode if mode else 'unknown'}")
# Current # Current
current = summary.get("Current", {}).get("led_current_ma") current_section = summary.get("Current", {})
if current is not None: if (led_current_ma := current_section.get("led_current_ma")) is not None:
print(f"🔌 LED Current: {current:.3f} mA") print(f"🔌 LED Current: {led_current_ma:.3f} mA")
else: else:
err = summary.get("Current", {}).get("error") if (err := current_section.get("error")):
if err:
print(f"🔌 LED Current: unavailable ({err})") print(f"🔌 LED Current: unavailable ({err})")
else: else:
print("🔌 LED Current: unavailable") print("🔌 LED Current: unavailable")
+4 -16
View File
@@ -1,4 +1,5 @@
import os import os
import difflib
import argparse import argparse
from typing import Dict, Optional, List from typing import Dict, Optional, List
@@ -70,22 +71,9 @@ def _suggest_boards(partial: str) -> List[str]:
contains = [b for b in BOARD_CONFIGS if partial_low in b.lower()] contains = [b for b in BOARD_CONFIGS if partial_low in b.lower()]
if contains: if contains:
return contains[:10] return contains[:10]
# simple levenshtein distance limited (manual lightweight) # fallback to fuzzy matching using difflib
def distance(a: str, b: str) -> int: choices = list(BOARD_CONFIGS.keys())
if len(a) < len(b): return difflib.get_close_matches(partial, choices, n=5, cutoff=0.4)
a, b = b, a
prev = list(range(len(b)+1))
for i, ca in enumerate(a, 1):
cur = [i]
for j, cb in enumerate(b, 1):
ins = cur[j-1] + 1
dele = prev[j] + 1
sub = prev[j-1] + (ca != cb)
cur.append(min(ins, dele, sub))
prev = cur
return prev[-1]
ranked = sorted(BOARD_CONFIGS, key=lambda k: distance(partial_low, k.lower()))
return ranked[:5]
def normalize_board_name(raw: Optional[str]) -> Optional[str]: def normalize_board_name(raw: Optional[str]) -> Optional[str]:
if raw is None: if raw is None: