Passa al contenuto

← Comandi terminale | Indice | Avanti: Web API - POST →

8. Web API – Endpoint GET

Version: 1.0.0
Date: 2025-01-15

Documentazione dettagliata degli endpoint GET dell'API REST per il monitoraggio e il recupero delle informazioni di sistema di ACRouter.




Sommario




8.1 Introduzione

L'API REST di ACRouter fornisce un insieme di endpoint GET per:

  • Monitoraggio – recuperare lo stato attuale del router e le metriche di potenza
  • Configurazione – leggere i parametri di sistema
  • Diagnostica – informazioni di sistema, stato WiFi, configurazione hardware

Tutti gli endpoint restituiscono dati in formato JSON.

Implementazione: components/comm/src/WebServerManager.cpp

Avvio rapido: Consultare 07_COMMANDS_EN.md section "REST API Reference" for basic usage examples.




8.2 URL base e autenticazione


8.2.1 URL base

Modalità punto di accesso:

python
http://192.168.4.1/api/

Modalità stazione:

python
http:///api/

Utilizzare il comando seriale wifi-status o GET /api/wifi/status per trovare l'indirizzo IP.


8.2.2 Autenticazione

⚠️ Importante: L'API REST non richiede autenticazione. Tutti gli endpoint sono accessibili senza password.

Security Recommendations:
- Use a separate WiFi network for IoT devices
- Configure firewall rules to restrict access
- Do not expose port 80 to external networks
- Basic authentication is planned for future versions


8.2.3 CORS

Il CORS (Cross-Origin Resource Sharing) è abilitato per tutti gli endpoint.

Header della risposta:

python
Access-Control-Allow-Origin: *

Questo consente le chiamate API da applicazioni web ospitate su altri domini.




8.3 Formato della risposta


8.3.1 Risposta riuscita

Stato HTTP: 200 OK

Content-Type: application/json

Struttura:

json
{
  "field1": "value1",
  "field2": 123,
  "field3": true
}


8.3.2 Risposta di errore

Stato HTTP: 400, 404, 500, 501

Content-Type: application/json

Struttura:

json
{
  "error": "Error message description"
}

Esempio:

json
{
  "error": "Not Found"
}


8.3.3 Codifica

Tutte le risposte utilizzano la codifica UTF-8.




8.4 Endpoint: GET /api/status

Ottenere lo stato completo del router, inclusi modalità operativa, stato del controller, potenza di rete e livello del dimmer.


8.4.1 Richiesta

http
GET /api/status HTTP/1.1
Host: 192.168.4.1

Parametri: Nessuno


8.4.2 Risposta

Stato HTTP: 200 OK

Schema JSON:

json
{
  "mode": "string",              // Router operating mode
  "state": "string",             // Controller state
  "power_grid": 0.0,             // Grid power (W)
  "dimmer": 0,                   // Dimmer level (0-100%)
  "target_level": 0,             // Target level (0-100%)
  "control_gain": 0.0,           // Control gain
  "balance_threshold": 0.0,      // Balance threshold (W)
  "valid": true,                 // Data validity
  "uptime": 0,                   // Uptime (seconds)
  "free_heap": 0                 // Free memory (bytes)
}


8.4.3 Descrizione dei campi

Campo Tipo Descrizione Valori possibili
mode string Modalità operativa del router "off", "auto", "eco", "offgrid", "manual", "boost", "unknown"
state string Stato del controller "idle", "increasing", "decreasing", "at_max", "at_min", "error"
power_grid float Potenza di rete in watt. Positivo = prelievo dalla rete (consumo), Negativo = immissione in rete (surplus) -∞ .. +∞
dimmer integer Livello attuale del dimmer in percentuale 0 .. 100
target_level integer Livello obiettivo del dimmer (per modalità AUTO, ECO, OFFGRID) 0 .. 100
control_gain float Guadagno del circuito di controllo 1.0 .. 1000.0
balance_threshold float Soglia di bilanciamento in watt (per modalità AUTO) 0.0 .. 100.0
valid boolean Validità dei dati di misura. false = sensori non inizializzati o errore true / false
uptime integer Tempo di attività dall'avvio in secondi 0 ..
free_heap integer RAM libera in byte 0 ..


8.4.4 Esempio di risposta

json
{
  "mode": "auto",
  "state": "increasing",
  "power_grid": 1250.3,
  "dimmer": 45,
  "target_level": 50,
  "control_gain": 150.0,
  "balance_threshold": 50.0,
  "valid": true,
  "uptime": 3625,
  "free_heap": 187456
}

Interpretation:
- Router in AUTO mode (Solar Router)
- State INCREASING (increasing power)
- Grid import: 1250.3 W (consumption exceeds generation)
- Current dimmer: 45%
- Target level: 50% (will increase to 50%)
- Uptime: 3625 sec (≈ 1 hour)
- Free memory: 187 KB


8.4.5 Utilizzo

Monitoraggio in tempo reale:

bash
# Poll every 2 seconds
while true; do
  curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer'
  sleep 2
done

Verificare la modalità operativa:

bash
curl -s http://192.168.4.1/api/status | jq -r '.mode'
# Output: auto

Python – monitoraggio del bilanciamento:

python
import requests
import time

def monitor_balance():
    url = "http://192.168.4.1/api/status"
    while True:
        resp = requests.get(url).json()
        power = resp['power_grid']
        dimmer = resp['dimmer']

        if power > 0:
            print(f"IMPORT: {power:.1f}W | Dimmer: {dimmer}%")
        elif power < 0:
            print(f"EXPORT: {abs(power):.1f}W | Dimmer: {dimmer}%")
        else:
            print(f"BALANCE: 0W | Dimmer: {dimmer}%")

        time.sleep(2)

monitor_balance()



8.5 Endpoint: GET /api/metrics

Ottenere metriche di potenza leggere per interrogazioni frequenti. Restituisce solo dati critici per il monitoraggio, minimizzando la dimensione della risposta.


8.5.1 Richiesta

http
GET /api/metrics HTTP/1.1
Host: 192.168.4.1

Parametri: Nessuno


8.5.2 Risposta

Stato HTTP: 200 OK

Schema JSON:

json
{
  "metrics": {
    "power_grid": 0.0,      // Grid power (W)
    "dimmer": 0,            // Dimmer level (0-100%)
    "target_level": 0       // Target level (0-100%)
  },
  "timestamp": 0            // Time (milliseconds since boot)
}


8.5.3 Descrizione dei campi

Campo Tipo Descrizione
metrics.power_grid float Potenza di rete (W). Positivo = prelievo, negativo = immissione
metrics.dimmer integer Livello attuale del dimmer (0–100 %)
metrics.target_level integer Livello obiettivo del dimmer (0–100 %)
timestamp integer Tempo dall'avvio in millisecondi


8.5.4 Esempio di risposta

json
{
  "metrics": {
    "power_grid": -125.7,
    "dimmer": 80,
    "target_level": 80
  },
  "timestamp": 3625482
}

Interpretation:
- Grid export: 125.7 W (generation exceeds consumption)
- Dimmer: 80% (routing surplus to load)
- Time: 3625 seconds since boot


8.5.5 Utilizzo

Monitoraggio ad alta frequenza:

bash
# Poll every second (minimal traffic)
while true; do
  curl -s http://192.168.4.1/api/metrics | jq '.metrics'
  sleep 1
done

JavaScript – grafico in tempo reale:

javascript
const baseUrl = "http://192.168.4.1/api";
const chartData = {
  labels: [],
  power: [],
  dimmer: []
};

function updateMetrics() {
  fetch(`${baseUrl}/metrics`)
    .then(r => r.json())
    .then(data => {
      const time = new Date().toLocaleTimeString();
      chartData.labels.push(time);
      chartData.power.push(data.metrics.power_grid);
      chartData.dimmer.push(data.metrics.dimmer);

      // Update chart (Chart.js, D3.js, etc.)
      updateChart(chartData);
    });
}

// Update every 2 seconds
setInterval(updateMetrics, 2000);

Confronto con /api/status:

Criterio /api/status /api/metrics
Dimensione risposta ~250 byte ~80 byte
Campi 10 campi 3 campi + timestamp
Caso d'uso Informazioni complete Monitoraggio in tempo reale
Frequenza di interrogazione 5–10 secondi 1–2 secondi



8.6 Endpoint: GET /api/config

Ottenere tutti i parametri di configurazione del sistema salvati nel NVS.


8.6.1 Richiesta

http
GET /api/config HTTP/1.1
Host: 192.168.4.1

Parametri: Nessuno


8.6.2 Risposta

Stato HTTP: 200 OK

Schema JSON:

json
{
  "control_gain": 0.0,          // Control gain
  "balance_threshold": 0.0,     // Balance threshold (W)
  "voltage_coef": 0.0,          // Voltage coefficient
  "current_coef": 0.0,          // Current coefficient (A/V)
  "current_threshold": 0.0,     // Current detection threshold (A)
  "power_threshold": 0.0,       // Power detection threshold (W)
  "router_mode": 0,             // Router mode (number)
  "manual_level": 0             // Manual mode level (0-100%)
}


8.6.3 Descrizione dei campi

Campo Tipo Intervallo Predefinito Descrizione
control_gain float 1.0 .. 1000.0 150.0 Guadagno del circuito di controllo
balance_threshold float 0.0 .. 100.0 50.0 Soglia di bilanciamento per modalità AUTO (W)
voltage_coef float 0.1 .. 10.0 1.0 Coefficiente di calibrazione della tensione
current_coef float 0.1 .. 100.0 30.0 Coefficiente di conversione della corrente (A/V)
current_threshold float 0.01 .. 10.0 0.1 Soglia di rilevamento della corrente (A)
power_threshold float 1.0 .. 1000.0 10.0 Soglia di rilevamento della potenza attiva (W)
router_mode integer 0 .. 5 1 Modalità del router: 0=OFF, 1=AUTO, 2=ECO, 3=OFFGRID, 4=MANUAL, 5=BOOST
manual_level integer 0 .. 100 0 Livello del dimmer per modalità manuale (%)


8.6.4 Esempio di risposta

json
{
  "control_gain": 180.0,
  "balance_threshold": 40.0,
  "voltage_coef": 1.02,
  "current_coef": 30.0,
  "current_threshold": 0.12,
  "power_threshold": 12.0,
  "router_mode": 1,
  "manual_level": 50
}

Interpretation:
- Gain increased to 180 (faster response)
- Balance threshold reduced to ±40 W (tighter balancing)
- Voltage corrected by +2% (sensor calibration)
- Mode: 1 (AUTO - Solar Router)
- Manual level: 50% (when switching to MANUAL)


8.6.5 Utilizzo

Backup della configurazione:

bash
# Save configuration to file
curl -s http://192.168.4.1/api/config > acrouter_config_backup.json

# Restore later via POST /api/config
curl -X POST http://192.168.4.1/api/config \
  -H "Content-Type: application/json" \
  -d @acrouter_config_backup.json

Python – confrontare le configurazioni:

python
import requests
import json

def compare_configs(url1, url2):
    config1 = requests.get(f"{url1}/api/config").json()
    config2 = requests.get(f"{url2}/api/config").json()

    differences = {}
    for key in config1:
        if config1[key] != config2.get(key):
            differences[key] = {
                'device1': config1[key],
                'device2': config2.get(key)
            }

    return differences

# Compare two routers
diffs = compare_configs("http://192.168.4.1", "http://192.168.4.2")
print(json.dumps(diffs, indent=2))



8.7 Endpoint: GET /api/info

Ottenere le informazioni di sistema: versione del firmware, tipo di chip, dimensione del flash, memoria libera, tempo di attività.


8.7.1 Richiesta

http
GET /api/info HTTP/1.1
Host: 192.168.4.1

Parametri: Nessuno


8.7.2 Risposta

Stato HTTP: 200 OK

Schema JSON:

json
{
  "version": "string",          // Firmware version
  "chip": "string",             // Chip type
  "flash_size": 0,              // Flash size (bytes)
  "free_heap": 0,               // Free memory (bytes)
  "uptime": 0,                  // [DEPRECATED] Uptime (sec)
  "uptime_sec": 0               // Uptime (seconds)
}


8.7.3 Descrizione dei campi

Campo Tipo Descrizione
version string ACRouter firmware version (format: "X.Y.Z")
chip string Microcontroller type (typically "ESP32")
flash_size integer Dimensione della memoria flash in byte
free_heap integer RAM libera in byte
uptime integer [OBSOLETO] Tempo di attività in secondi (utilizzare uptime_sec)
uptime_sec integer Tempo di attività dall'avvio in secondi


8.7.4 Esempio di risposta

json
{
  "version": "1.0.0",
  "chip": "ESP32",
  "flash_size": 4194304,
  "free_heap": 189328,
  "uptime": 7234,
  "uptime_sec": 7234
}

Interpretation:
- Firmware version: 1.0.0
- Chip: ESP32
- Flash: 4 MB (4194304 bytes)
- Free RAM: 184 KB (189328 bytes)
- Uptime: 7234 sec (≈ 2 hours 34 seconds)


8.7.5 Utilizzo

Monitoraggio della memoria:

bash
# Check for memory leaks
while true; do
  free_heap=$(curl -s http://192.168.4.1/api/info | jq '.free_heap')
  echo "$(date +%T) Free heap: $free_heap bytes"
  sleep 60
done

Python – avviso di memoria insufficiente:

python
import requests
import time

def monitor_memory(url, threshold_kb=100):
    while True:
        info = requests.get(f"{url}/api/info").json()
        free_kb = info['free_heap'] / 1024

        if free_kb < threshold_kb:
            print(f"⚠️ WARNING: Low memory! {free_kb:.1f} KB free")
            # Send notification (email, Telegram, etc.)
        else:
            print(f"✓ Memory OK: {free_kb:.1f} KB free")

        time.sleep(300)  # Check every 5 minutes

monitor_memory("http://192.168.4.1", threshold_kb=150)

Formattare il tempo di attività:

python
def format_uptime(seconds):
    days = seconds // 86400
    hours = (seconds % 86400) // 3600
    minutes = (seconds % 3600) // 60
    secs = seconds % 60

    return f"{days}d {hours}h {minutes}m {secs}s"

info = requests.get("http://192.168.4.1/api/info").json()
print(f"Uptime: {format_uptime(info['uptime_sec'])}")
# Output: Uptime: 0d 2h 34m 18s



8.8 Endpoint: GET /api/wifi/status

Ottenere lo stato dettagliato della connessione WiFi: modalità AP/STA, indirizzi IP, SSID, potenza del segnale, indirizzo MAC, credenziali salvate.


8.8.1 Richiesta

http
GET /api/wifi/status HTTP/1.1
Host: 192.168.4.1

Parametri: Nessuno


8.8.2 Risposta

Stato HTTP: 200 OK

Schema JSON:

json
{
  "state": "string",              // WiFi state
  "ap_active": false,             // AP active
  "ap_ssid": "string",            // AP SSID
  "ap_ip": "string",              // AP IP address
  "ap_clients": 0,                // Connected clients
  "sta_connected": false,         // STA connected
  "sta_ssid": "string",           // STA SSID
  "sta_ip": "string",             // STA IP address
  "rssi": 0,                      // Signal strength (dBm)
  "has_saved_credentials": false, // Credentials saved in NVS
  "mac": "string",                // MAC address
  "hostname": "string"            // Hostname
}


8.8.3 Descrizione dei campi

Campo Tipo Descrizione Valori possibili
state string Stato WiFi "IDLE", "AP_ONLY", "STA_CONNECTING", "STA_CONNECTED", "AP_STA", "STA_FAILED"
ap_active boolean Punto di accesso attivo true / false
ap_ssid string Nome dell'AP (formato: ACRouter_XXXXXX) -
ap_ip string Indirizzo IP dell'AP (solitamente 192.168.4.1) -
ap_clients integer Numero di client connessi all'AP 0 .. 4
sta_connected boolean Connesso alla rete WiFi come client true / false
sta_ssid string Nome della rete WiFi -
sta_ip string Indirizzo IP ottenuto tramite DHCP -
rssi integer Potenza del segnale WiFi in dBm -100 .. -30
has_saved_credentials boolean Credenziali salvate nel NVS true / false
mac string Indirizzo MAC del dispositivo (formato: XX:XX:XX:XX:XX:XX) -
hostname string Nome host del dispositivo -

Valutazione della potenza del segnale (RSSI):

RSSI (dBm) Qualità Descrizione
da -30 a -50 Eccellente Segnale molto forte
da -51 a -70 Buona Connessione stabile
da -71 a -85 Discreta Possibili disconnessioni occasionali
da -86 a -100 Scarsa Connessione instabile


8.8.4 Esempio di risposta (AP + STA attivi)

json
{
  "state": "AP_STA",
  "ap_active": true,
  "ap_ssid": "ACRouter_A1B2C3",
  "ap_ip": "192.168.4.1",
  "ap_clients": 2,
  "sta_connected": true,
  "sta_ssid": "MyHomeNetwork",
  "sta_ip": "192.168.1.150",
  "rssi": -58,
  "has_saved_credentials": true,
  "mac": "24:6F:28:A1:B2:C3",
  "hostname": "acrouter"
}

Interpretation:
- Mode: AP_STA (simultaneous access point and client)
- AP active: ACRouter_A1B2C3 at 192.168.4.1
- 2 clients connected to AP
- STA connected to MyHomeNetwork with IP 192.168.1.150
- Signal strength: -58 dBm (good quality)
- Credentials saved in NVS


8.8.5 Esempio di risposta (solo AP)

json
{
  "state": "AP_ONLY",
  "ap_active": true,
  "ap_ssid": "ACRouter_A1B2C3",
  "ap_ip": "192.168.4.1",
  "ap_clients": 1,
  "sta_connected": false,
  "has_saved_credentials": false,
  "mac": "24:6F:28:A1:B2:C3",
  "hostname": "acrouter"
}


8.8.6 Utilizzo

Verificare la connessione di rete:

bash
sta_connected=$(curl -s http://192.168.4.1/api/wifi/status | jq -r '.sta_connected')

if [ "$sta_connected" = "true" ]; then
  echo "✓ Connected to WiFi"
else
  echo "✗ Not connected to WiFi"
fi

Python – monitoraggio della potenza del segnale:

python
import requests
import time

def monitor_wifi_signal(url):
    while True:
        status = requests.get(f"{url}/api/wifi/status").json()

        if not status['sta_connected']:
            print("⚠️ Not connected to WiFi")
            time.sleep(10)
            continue

        rssi = status['rssi']
        ssid = status['sta_ssid']

        if rssi >= -50:
            quality = "Excellent"
        elif rssi >= -70:
            quality = "Good"
        elif rssi >= -85:
            quality = "Fair"
        else:
            quality = "Poor"

        print(f"{ssid}: {rssi} dBm ({quality})")
        time.sleep(30)

monitor_wifi_signal("http://192.168.4.1")



8.9 Endpoint: GET /api/wifi/scan

Scansione delle reti WiFi disponibili nel raggio d'azione.


8.9.1 Richiesta

http
GET /api/wifi/scan HTTP/1.1
Host: 192.168.4.1

Parametri: Nessuno

⚠️ Avviso: La scansione richiede 2–3 secondi. La connessione STA potrebbe disconnettersi brevemente durante la scansione.


8.9.2 Risposta

Stato HTTP: 200 OK

Schema JSON:

json
{
  "networks": [
    {
      "ssid": "string",         // Network name
      "rssi": 0,                // Signal strength (dBm)
      "encryption": "string",   // Encryption type
      "channel": 0              // Channel number
    }
  ],
  "count": 0                    // Number of networks found
}


8.9.3 Descrizione dei campi

Campo Tipo Descrizione
networks array Array delle reti trovate
networks[].ssid string Nome della rete WiFi
networks[].rssi integer Potenza del segnale in dBm
networks[].encryption string Tipo di crittografia: "open" o "secured"
networks[].channel integer Numero del canale WiFi (1–14)
count integer Numero totale di reti trovate


8.9.4 Esempio di risposta

json
{
  "networks": [
    {
      "ssid": "MyHomeNetwork",
      "rssi": -45,
      "encryption": "secured",
      "channel": 6
    },
    {
      "ssid": "GuestNetwork",
      "rssi": -62,
      "encryption": "open",
      "channel": 11
    },
    {
      "ssid": "Neighbor_WiFi",
      "rssi": -78,
      "encryption": "secured",
      "channel": 1
    }
  ],
  "count": 3
}


8.9.5 Esempio di risposta (nessuna rete)

json
{
  "networks": [],
  "count": 0
}


8.9.6 Utilizzo

Bash – elencare le reti disponibili:

bash
curl -s http://192.168.4.1/api/wifi/scan | jq -r '.networks[] | "\(.ssid): \(.rssi) dBm (\(.encryption))"'

Output:

python
MyHomeNetwork: -45 dBm (secured)
GuestNetwork: -62 dBm (open)
Neighbor_WiFi: -78 dBm (secured)

Python – trovare la rete migliore:

python
import requests

def find_best_network(url, preferred_ssids):
    """Find best network from preferred list"""
    scan_result = requests.get(f"{url}/api/wifi/scan").json()

    best_network = None
    best_rssi = -100

    for network in scan_result['networks']:
        if network['ssid'] in preferred_ssids:
            if network['rssi'] > best_rssi:
                best_rssi = network['rssi']
                best_network = network

    return best_network

# Usage
preferred = ["HomeNetwork_2.4GHz", "HomeNetwork_5GHz", "GuestNetwork"]
best = find_best_network("http://192.168.4.1", preferred)

if best:
    print(f"Best network: {best['ssid']} ({best['rssi']} dBm)")
else:
    print("No preferred networks found")

JavaScript – visualizzare l'elenco delle reti:

javascript
fetch('http://192.168.4.1/api/wifi/scan')
  .then(r => r.json())
  .then(data => {
    const networkList = data.networks.map(net => {
      const signal = net.rssi >= -50 ? '▂▄▆█' :
                     net.rssi >= -70 ? '▂▄▆_' :
                     net.rssi >= -85 ? '▂▄__' : '▂___';

      const lock = net.encryption === 'secured' ? '🔒' : '🔓';

      return `${lock} ${net.ssid} ${signal} (Channel ${net.channel})`;
    });

    console.log(`Found ${data.count} networks:\n${networkList.join('\n')}`);
  });



8.10 Endpoint: GET /api/hardware/config

Ottenere la configurazione dei componenti hardware: canali ADC, dimmer, passaggio per lo zero, relè, LED.


8.10.1 Richiesta

http
GET /api/hardware/config HTTP/1.1
Host: 192.168.4.1

Parametri: Nessuno


8.10.2 Risposta

Stato HTTP: 200 OK

Schema JSON:

json
{
  "adc_channels": [
    {
      "gpio": 0,                // GPIO pin
      "type": 0,                // Sensor type (number)
      "type_name": "string",    // Sensor type name
      "multiplier": 0.0,        // Multiplier
      "offset": 0.0,            // Offset
      "enabled": false          // Enabled
    }
  ],
  "dimmer_ch1": {
    "gpio": 0,                  // GPIO pin
    "enabled": false            // Enabled
  },
  "dimmer_ch2": {
    "gpio": 0,
    "enabled": false
  },
  "zerocross_gpio": 0,          // Zero-cross detector GPIO
  "zerocross_enabled": false,   // Zero-cross enabled
  "relay_ch1": {
    "gpio": 0,
    "active_high": false,       // Logic: true=HIGH active
    "enabled": false
  },
  "relay_ch2": {
    "gpio": 0,
    "active_high": false,
    "enabled": false
  },
  "led_status_gpio": 0,         // Status LED GPIO
  "led_load_gpio": 0            // Load LED GPIO
}


8.10.3 Tipi di sensore (SensorType)

Codice Nome Descrizione
0 NONE Non utilizzato
1 ZMPT107 Sensore di tensione ZMPT107
2 SCT013 Sensore di corrente SCT-013 (trasformatore)
3 ACS712 Sensore di corrente ACS712 (effetto Hall)


8.10.4 Esempio di risposta

json
{
  "adc_channels": [
    {
      "gpio": 34,
      "type": 1,
      "type_name": "ZMPT107",
      "multiplier": 320.0,
      "offset": 0.0,
      "enabled": true
    },
    {
      "gpio": 35,
      "type": 2,
      "type_name": "SCT013",
      "multiplier": 30.0,
      "offset": 0.0,
      "enabled": true
    },
    {
      "gpio": 32,
      "type": 3,
      "type_name": "ACS712",
      "multiplier": 30.0,
      "offset": 0.0,
      "enabled": true
    },
    {
      "gpio": 33,
      "type": 0,
      "type_name": "NONE",
      "multiplier": 1.0,
      "offset": 0.0,
      "enabled": false
    }
  ],
  "dimmer_ch1": {
    "gpio": 19,
    "enabled": true
  },
  "dimmer_ch2": {
    "gpio": 23,
    "enabled": false
  },
  "zerocross_gpio": 18,
  "zerocross_enabled": true,
  "relay_ch1": {
    "gpio": 15,
    "active_high": true,
    "enabled": false
  },
  "relay_ch2": {
    "gpio": 2,
    "active_high": true,
    "enabled": false
  },
  "led_status_gpio": 17,
  "led_load_gpio": 5
}

Interpretation:
- ADC channel 0: GPIO 34, ZMPT107 voltage sensor
- ADC channel 1: GPIO 35, SCT013 current sensor
- ADC channel 2: GPIO 32, ACS712 current sensor
- ADC channel 3: Not used
- Dimmer 1: GPIO 19 (active)
- Dimmer 2: GPIO 23 (disabled)
- Zero-cross: GPIO 18 (active)
- Relays 1-2: Disabled
- Status LED: GPIO 17
- Load LED: GPIO 5


8.10.5 Utilizzo

Diagnostica della configurazione hardware:

bash
curl -s http://192.168.4.1/api/hardware/config | jq '.'

Python – verificare conflitti GPIO:

python
import requests

def check_gpio_conflicts(url):
    config = requests.get(f"{url}/api/hardware/config").json()

    gpio_usage = {}
    conflicts = []

    # Collect all used GPIOs
    for i, ch in enumerate(config['adc_channels']):
        if ch['enabled']:
            gpio = ch['gpio']
            if gpio in gpio_usage:
                conflicts.append(f"GPIO {gpio}: {gpio_usage[gpio]} and ADC channel {i}")
            else:
                gpio_usage[gpio] = f"ADC channel {i}"

    if config['dimmer_ch1']['enabled']:
        gpio = config['dimmer_ch1']['gpio']
        if gpio in gpio_usage:
            conflicts.append(f"GPIO {gpio}: {gpio_usage[gpio]} and Dimmer 1")
        else:
            gpio_usage[gpio] = "Dimmer 1"

    # ... check all other GPIOs

    if conflicts:
        print("⚠️ GPIO conflicts detected:")
        for conflict in conflicts:
            print(f"  - {conflict}")
    else:
        print("✓ No GPIO conflicts")

check_gpio_conflicts("http://192.168.4.1")



8.11 Codici di errore HTTP

Codice Stato Descrizione Esempio
200 OK Richiesta riuscita Tutti gli endpoint GET in caso di successo
400 Bad Request Formato della richiesta non valido Parametro non valido
404 Not Found Endpoint non trovato GET /api/unknown
500 Internal Server Error Errore interno del server Errore nella lettura del NVS
501 Not Implemented Funzionalità non implementata GET /api/calibrate

Formato dell'errore:

json
{
  "error": "Error message description"
}

Esempi:

json
{
  "error": "Not Found"
}
json
{
  "error": "Failed to read configuration from NVS"
}



8.12 Esempi di utilizzo


8.12.1 Monitoraggio dello stato (Python)

python
import requests
import time
from datetime import datetime

class ACRouterMonitor:
    def __init__(self, base_url):
        self.base_url = base_url

    def get_status(self):
        return requests.get(f"{self.base_url}/api/status").json()

    def get_metrics(self):
        return requests.get(f"{self.base_url}/api/metrics").json()

    def get_config(self):
        return requests.get(f"{self.base_url}/api/config").json()

    def monitor_loop(self, interval=2):
        print("ACRouter Monitor - Press Ctrl+C to stop")
        print("-" * 60)

        try:
            while True:
                status = self.get_status()

                timestamp = datetime.now().strftime("%H:%M:%S")
                mode = status['mode'].upper()
                state = status['state']
                power = status['power_grid']
                dimmer = status['dimmer']

                # Format output
                power_str = f"{power:+7.1f}W"
                if power > 0:
                    direction = "IMPORT"
                elif power < 0:
                    direction = "EXPORT"
                else:
                    direction = "BALANCE"

                print(f"[{timestamp}] {mode:8} | {state:11} | {power_str} {direction:7} | Dimmer: {dimmer:3}%")

                time.sleep(interval)

        except KeyboardInterrupt:
            print("\nMonitoring stopped")

# Usage
monitor = ACRouterMonitor("http://192.168.4.1")
monitor.monitor_loop(interval=2)


8.12.2 Dashboard (JavaScript + HTML)

html



    ACRouter Dashboard
    


    

ACRouter Dashboard

Mode
-
Grid Power
-
Dimmer
-
State
-


8.12.3 Esportazione in CSV (Bash)

bash
#!/bin/bash

API_URL="http://192.168.4.1/api"
CSV_FILE="acrouter_metrics_$(date +%Y%m%d_%H%M%S).csv"

# CSV header
echo "timestamp,mode,state,power_grid,dimmer,target_level,free_heap" > "$CSV_FILE"

echo "Logging metrics to $CSV_FILE (Press Ctrl+C to stop)"

while true; do
    # Get data
    status=$(curl -s "$API_URL/status")

    # Extract fields
    timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    mode=$(echo "$status" | jq -r '.mode')
    state=$(echo "$status" | jq -r '.state')
    power=$(echo "$status" | jq -r '.power_grid')
    dimmer=$(echo "$status" | jq -r '.dimmer')
    target=$(echo "$status" | jq -r '.target_level')
    heap=$(echo "$status" | jq -r '.free_heap')

    # Write to CSV
    echo "$timestamp,$mode,$state,$power,$dimmer,$target,$heap" >> "$CSV_FILE"

    # Display
    echo "[$(date +%H:%M:%S)] Logged: Power=${power}W, Dimmer=${dimmer}%"

    sleep 5
done



  • 01_OVERVIEW.md – Panoramica del progetto
  • 03_STRUCTURE.md – Architettura dell'applicazione
  • 07_COMMANDS.md – Riferimento comandi (RU)
  • 07_COMMANDS_EN.md – Riferimento comandi (EN)
  • 09_WEB_API_POST.md – Endpoint POST dell'API Web (sezione successiva)

Firmware Version: 1.0.0
Last Updated: 2025-01-15

← Comandi terminale | Indice | Avanti: Web API - POST →