e67fb754c2
Session kxkm-ai 25-26 mars 2026 — 98/98 tâches TODO complétées. Hardware: - KiCad 10.0.0 native avec sym/fp-lib-table locales - Nouveau block SPI (gen_spi_header.py), ERC clean - Module partagé hardware/lib/kicad_gen.py (5 générateurs refactorisés) - Pipeline export: tools/hw/hw_export.sh (ERC + SVG + PDF + netlist) - KiBot 1.8.5 installé, .kibot.yaml configuré Firmware: - Fix I2S driver conflict: migration I2sMic vers nouvelle API i2s_channel_* - Fix WDT risk: yield() dans CompletePushToTalk (voice_controller.cpp) - Fix XSS wifi_manager.cpp: innerHTML → createElement/textContent - Fix null check FwIsValidWavHeader - Dead code supprimé: i2s_audio.cpp.bak, i2s_audio.h Simulation MCU: - QEMU ESP32-S3 v9.2.2 installé (tools/sim/) - Script run_qemu_esp32s3.sh — boot OK vérifié - [env:esp32s3_qemu] dans platformio.ini - Wokwi CI: wokwi.toml + diagram.json + scenario.yaml - SPICE bridge POC: tools/sim/spice_bridge.py (ngspice → ADC/brownout) Compliance: - Profil iot_wifi_eu validé (16 standards, 8 evidence) - 4 evidence remplis: risk_assessment, security_architecture, test_plan_radio_emc, supply_chain_declarations - plan.yaml complété avec données produit réelles CI: - Job hardware-export (KiCad 10 ERC + SVG + PDF + netlist) - Job firmware-sim (Wokwi, conditionnel WOKWI_CLI_TOKEN) - evidence_pack.yml enrichi avec exports hardware Docs & RAG: - specs/02_arch.md complet (481 lignes, 4 ADR, diagrammes) - docs/SIMULATION.md (3 niveaux: native, QEMU, Wokwi) - 6 chunks ingérés dans kb-kicad RAG - Dataset HF: tools/generate_hf_dataset.py + datasets/kb_kicad_qa.jsonl - Rapport analyse: docs/plans/ANALYSIS_REPORT_2026-03-25.md - Recherche OSS: docs/research/oss_similar_projects.md Infra: - ZeroClaw 0.1.7 installé (cargo install) - APIFY_API_KEY configurée, smoke OK - Tests: 39/39 firmware + 26/26 Python stable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
2.5 KiB
C++
94 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <functional>
|
|
|
|
/// WiFi connection manager with AP fallback and captive portal.
|
|
///
|
|
/// Flow:
|
|
/// 1. On boot, try saved credentials from NVS
|
|
/// 2. If no credentials or connection fails → start AP mode
|
|
/// 3. AP mode: captive portal web UI for config
|
|
/// 4. Long-press BOOT button (3s) → force AP mode
|
|
///
|
|
/// NVS keys: "wifi_ssid", "wifi_pass", "backend_url"
|
|
class WifiManager {
|
|
public:
|
|
enum class State {
|
|
kIdle,
|
|
kConnecting,
|
|
kConnected,
|
|
kApMode,
|
|
kFailed,
|
|
};
|
|
|
|
struct ScanResult {
|
|
std::string ssid;
|
|
int rssi;
|
|
bool open; // no encryption
|
|
};
|
|
|
|
using OnStateChange = std::function<void(State state, const std::string& info)>;
|
|
|
|
/// AP mode settings.
|
|
void SetApCredentials(const std::string& ssid, const std::string& password);
|
|
|
|
/// Register callback for state changes (for LCD updates).
|
|
void SetOnStateChange(OnStateChange cb) { on_state_change_ = cb; }
|
|
|
|
/// Load saved credentials and try to connect.
|
|
/// Falls back to AP mode if no credentials or connection fails.
|
|
void Begin();
|
|
|
|
/// Call from loop() — handles AP mode web server.
|
|
void Loop();
|
|
|
|
/// Force switch to AP mode (e.g. from long-press).
|
|
void StartApMode();
|
|
|
|
/// Current state.
|
|
State state() const { return state_; }
|
|
bool IsConnected() const { return state_ == State::kConnected; }
|
|
bool IsApMode() const { return state_ == State::kApMode; }
|
|
|
|
/// Connected network info.
|
|
std::string ssid() const { return current_ssid_; }
|
|
std::string ip() const;
|
|
int rssi() const;
|
|
|
|
/// AP mode info.
|
|
std::string apSsid() const { return ap_ssid_; }
|
|
std::string apPassword() const { return ap_password_; }
|
|
std::string apIp() const;
|
|
|
|
/// Saved backend URL.
|
|
std::string backendUrl() const { return backend_url_; }
|
|
|
|
/// Scan available networks (blocking, ~2s).
|
|
std::vector<ScanResult> Scan();
|
|
|
|
private:
|
|
void LoadCredentials();
|
|
void SaveCredentials(const std::string& ssid, const std::string& pass,
|
|
const std::string& backend);
|
|
bool TryConnect(const std::string& ssid, const std::string& pass,
|
|
uint32_t timeout_ms = 12000);
|
|
void SetupApWebServer();
|
|
void StopApWebServer();
|
|
void SetState(State s, const std::string& info = "");
|
|
|
|
State state_ = State::kIdle;
|
|
OnStateChange on_state_change_;
|
|
|
|
std::string saved_ssid_;
|
|
std::string saved_pass_;
|
|
std::string backend_url_ = "http://192.168.1.42:8000";
|
|
std::string current_ssid_;
|
|
|
|
std::string ap_ssid_ = "KillLife-Setup";
|
|
std::string ap_password_ = "killlife";
|
|
|
|
bool server_running_ = false;
|
|
};
|