Files
Kill_LIFE/firmware/include/wifi_manager.h
T
root e67fb754c2 feat: KiCad 10 native, QEMU simulation, compliance EU, firmware fixes
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>
2026-03-26 09:52:00 +01:00

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;
};