Passa al contenuto

← Web API - GET | Indice | Avanti: Calibrazione sensori →

9. Web API - Endpoint POST

Version: 1.0.0
Date: 2025-01-15

Documentazione dettagliata degli endpoint POST dell'API REST per il controllo e la configurazione del sistema ACRouter.




Indice




9.1 Introduzione

Gli endpoint POST dell'API REST di ACRouter sono progettati per:

  • Controllo del router – cambiare modalità operativa, livello del dimmer
  • Configurazione – aggiornare i parametri di sistema
  • Gestione WiFi – connessione/disconnessione dalle reti
  • Configurazione hardware – configurare GPIO, sensori, dimmer
  • Controllo di sistema – riavviare il dispositivo

Tutte le modifiche vengono applicate immediatamente e salvate nel NVS (Non-Volatile Storage).

Implementazione: components/comm/src/WebServerManager.cpp




9.2 Formato delle richieste


9.2.1 Content-Type

Tutte le richieste POST devono utilizzare:

http
Content-Type: application/json


9.2.2 Struttura della richiesta

http
POST /api/endpoint HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "parameter1": "value1",
  "parameter2": 123
}


9.2.3 Formato di risposta positiva

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Operation completed successfully"
}


9.2.4 Formato di risposta errore

Stato HTTP: 400, 500, 501

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



9.3 Endpoint: POST /api/config

Aggiornamento dei parametri di configurazione del sistema. È possibile aggiornare uno o più parametri in un'unica richiesta.


9.3.1 Richiesta

http
POST /api/config HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "voltage_coef": 1.02,
  "current_coef": 30.0,
  "current_threshold": 0.12,
  "power_threshold": 12.0,
  "control_gain": 180.0,
  "balance_threshold": 40.0
}


9.3.2 Parametri (opzionali)

Tutti i parametri sono opzionali. Vengono aggiornati solo i campi specificati.

Parametro Tipo Intervallo Descrizione
voltage_coef float 0.1 .. 10.0 Coefficiente di calibrazione della tensione
current_coef float 0.1 .. 100.0 Coefficiente di conversione della corrente (A/V)
current_threshold float 0.01 .. 10.0 Soglia di rilevamento della corrente (A)
power_threshold float 1.0 .. 1000.0 Soglia di rilevamento della potenza (W)
control_gain float 1.0 .. 1000.0 Guadagno del loop di controllo
balance_threshold float 0.0 .. 100.0 Soglia di bilanciamento per la modalità AUTO (W)


9.3.3 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Configuration updated"
}

Se nessun parametro è stato modificato:

json
{
  "success": true,
  "message": "No changes"
}


9.3.4 Risposta (errore)

Stato HTTP: 400 Bad Request

json
{
  "error": "Missing request body"
}
json
{
  "error": "Invalid JSON"
}


9.3.5 Esempi di utilizzo

Aggiornare un singolo parametro:

bash
curl -X POST http://192.168.4.1/api/config \
  -H "Content-Type: application/json" \
  -d '{"control_gain": 200.0}'

Aggiornare più parametri:

bash
curl -X POST http://192.168.4.1/api/config \
  -H "Content-Type: application/json" \
  -d '{
    "control_gain": 180.0,
    "balance_threshold": 40.0,
    "voltage_coef": 1.02
  }'

Python:

python
import requests

config = {
    "control_gain": 200.0,
    "balance_threshold": 35.0
}

response = requests.post(
    "http://192.168.4.1/api/config",
    json=config
)

print(response.json())
# {'success': True, 'message': 'Configuration updated'}

JavaScript:

javascript
const config = {
  control_gain: 200.0,
  balance_threshold: 35.0
};

fetch('http://192.168.4.1/api/config', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify(config)
})
  .then(r => r.json())
  .then(data => console.log(data));



9.4 Endpoint: POST /api/config/reset

Ripristinare tutti i parametri di configurazione ai valori di fabbrica.


9.4.1 Richiesta

http
POST /api/config/reset HTTP/1.1
Host: 192.168.4.1

Corpo della richiesta: Non richiesto


9.4.2 Valori di fabbrica

cpp
control_gain        = 150.0
balance_threshold   = 50.0 W
voltage_coef        = 1.0
current_coef        = 30.0 A/V
current_threshold   = 0.1 A
power_threshold     = 10.0 W


9.4.3 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Configuration reset to defaults"
}


9.4.4 Esempi di utilizzo

Bash:

bash
curl -X POST http://192.168.4.1/api/config/reset

Python:

python
import requests

response = requests.post("http://192.168.4.1/api/config/reset")
print(response.json())
# {'success': True, 'message': 'Configuration reset to defaults'}

⚠️ Avviso: Questa operazione è irreversibile. Tutte le impostazioni personalizzate andranno perse.




9.5 Endpoint: POST /api/mode

Impostare la modalità operativa del router.


9.5.1 Richiesta

http
POST /api/mode HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "mode": "auto"
}


9.5.2 Parametri

Parametro Tipo Obbligatorio Valori validi
mode string "off", "auto", "eco", "offgrid", "manual", "boost"

Descrizione delle modalità:

Modalità Descrizione
"off" Router disattivato, dimmer 0%
"auto" Router solare – minimizzare importazione/esportazione dalla rete
"eco" Economica – evitare importazione, permettere esportazione
"offgrid" Offgrid – solare/batteria, utilizzo minimo della rete
"manual" Manuale – livello dimmer fisso
"boost" Potenza massima – dimmer 100%


9.5.3 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Mode set to AUTO"
}


9.5.4 Risposta (errore)

Stato HTTP: 400 Bad Request

json
{
  "error": "Missing 'mode' field"
}
json
{
  "error": "Invalid mode (use: off, auto, eco, offgrid, manual, boost)"
}


9.5.5 Esempi di utilizzo

Impostare modalità AUTO (router solare):

bash
curl -X POST http://192.168.4.1/api/mode \
  -H "Content-Type: application/json" \
  -d '{"mode": "auto"}'

Impostare modalità ECO:

bash
curl -X POST http://192.168.4.1/api/mode \
  -H "Content-Type: application/json" \
  -d '{"mode": "eco"}'

Python – alternare tra le modalità:

python
import requests
import time

def set_mode(mode):
    response = requests.post(
        "http://192.168.4.1/api/mode",
        json={"mode": mode}
    )
    return response.json()

# Set AUTO mode
print(set_mode("auto"))
time.sleep(60)

# Switch to MANUAL for testing
print(set_mode("manual"))
time.sleep(30)

# Return to AUTO
print(set_mode("auto"))



9.6 Endpoint: POST /api/dimmer

Impostare il livello del dimmer. Passa automaticamente il router in modalità MANUAL.


9.6.1 Richiesta

http
POST /api/dimmer HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "value": 75
}


9.6.2 Parametri

Parametro Tipo Obbligatorio Intervallo Descrizione
value integer 0 .. 100 Livello del dimmer in percentuale


9.6.3 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Dimmer value set"
}

⚠️ Importante: Il router passa automaticamente alla modalità MANUAL quando viene impostato il livello del dimmer.


9.6.4 Risposta (errore)

Stato HTTP: 400 Bad Request

json
{
  "error": "Missing 'value' field"
}
json
{
  "error": "Value must be 0-100"
}


9.6.5 Esempi di utilizzo

Impostare il dimmer al 50%:

bash
curl -X POST http://192.168.4.1/api/dimmer \
  -H "Content-Type: application/json" \
  -d '{"value": 50}'

Python – rampa di potenza graduale:

python
import requests
import time

def set_dimmer(value):
    response = requests.post(
        "http://192.168.4.1/api/dimmer",
        json={"value": value}
    )
    return response.json()

# Gradually increase from 0% to 100%
for level in range(0, 101, 10):
    print(f"Setting dimmer to {level}%")
    set_dimmer(level)
    time.sleep(5)

# Gradually decrease back
for level in range(100, -1, -10):
    print(f"Setting dimmer to {level}%")
    set_dimmer(level)
    time.sleep(5)

JavaScript – controllo tramite slider:

javascript
// HTML: 

const slider = document.getElementById('dimmerSlider');

slider.addEventListener('change', (e) => {
  const value = parseInt(e.target.value);

  fetch('http://192.168.4.1/api/dimmer', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({value: value})
  })
    .then(r => r.json())
    .then(data => console.log(`Dimmer set to ${value}%`));
});



9.7 Endpoint: POST /api/manual

Endpoint alternativo per impostare la modalità manuale con un livello dimmer specificato. Equivalente a POST /api/mode (mode=manual) + POST /api/dimmer.


9.7.1 Richiesta

http
POST /api/manual HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "value": 60
}


9.7.2 Parametri

Parametro Tipo Obbligatorio Intervallo Descrizione
value integer 0 .. 100 Livello del dimmer in percentuale


9.7.3 Comportamento

  1. Passa il router in modalità MANUAL
  2. Imposta il livello del dimmer al valore specificato


9.7.4 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Manual control set"
}


9.7.5 Esempi di utilizzo

Bash:

bash
curl -X POST http://192.168.4.1/api/manual \
  -H "Content-Type: application/json" \
  -d '{"value": 60}'

Differenza tra /api/dimmer e /api/manual:

python
import requests

# Option 1: Use /api/dimmer
# Automatically switches to MANUAL
requests.post("http://192.168.4.1/api/dimmer", json={"value": 60})

# Option 2: Use /api/manual
# Explicitly switches to MANUAL and sets level
requests.post("http://192.168.4.1/api/manual", json={"value": 60})

# Result is identical



9.8 Endpoint: POST /api/hardware/voltage/calibrate

Calibrazione automatica del sensore di tensione (disponibile dalla versione 2.0).

Il sistema misura automaticamente l'uscita del sensore (VDC RMS) e calcola il moltiplicatore di calibrazione basandosi sulla tensione di rete misurata.


9.8.1 Richiesta

http
POST /api/hardware/voltage/calibrate HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "measured_vac": 232.5
}


9.8.2 Parametri

Parametro Tipo Obbligatorio Descrizione
measured_vac float Tensione di rete misurata con multimetro (VAC RMS)

Intervallo: 100.0 .. 300.0 (in base allo standard di rete)


9.8.3 Processo di calibrazione

  1. PowerMeterADC misura l'uscita attuale del sensore (VDC RMS)
  2. Calcola il moltiplicatore: multiplier = measured_vac / sensor_vdc
  3. Aggiorna nominal_vdc con il valore effettivamente misurato
  4. La configurazione viene salvata nel NVS
  5. ⚠️ È necessario un riavvio per applicare le modifiche


9.8.4 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Voltage sensor calibrated",
  "sensor_vdc": 0.72,
  "multiplier": 322.92,
  "sensor_type": "ZMPT107"
}

Campi della risposta:

Campo Tipo Descrizione
sensor_vdc float Uscita misurata del sensore (VDC RMS)
multiplier float Moltiplicatore calcolato
sensor_type string Tipo di sensore (ZMPT107, ZMPT101B, CUSTOM)


9.8.5 Risposta (errore)

Stato HTTP: 400 Bad Request

json
{
  "error": "Missing 'measured_vac' field"
}
json
{
  "error": "PowerMeterADC is not running"
}
json
{
  "error": "No voltage sensor configured"
}

Stato HTTP: 500 Internal Server Error

json
{
  "error": "Failed to save calibration to NVS"
}


9.8.6 Esempi di utilizzo

Calibrazione di base:

bash
curl -X POST http://192.168.4.1/api/hardware/voltage/calibrate \
  -H "Content-Type: application/json" \
  -d '{"measured_vac": 232.5}'

Esempio di risposta:

json
{
  "success": true,
  "message": "Voltage sensor calibrated",
  "sensor_vdc": 0.72,
  "multiplier": 322.92,
  "sensor_type": "ZMPT107"
}

Python – procedura di calibrazione completa:

python
import requests
import time

def calibrate_voltage_sensor(measured_vac, base_url="http://192.168.4.1"):
    """
    Automatic voltage sensor calibration

    Args:
        measured_vac: Grid voltage measured with multimeter (VAC)
        base_url: Router URL

    Returns:
        bool: True if calibration successful
    """

    print(f"Starting voltage sensor calibration...")
    print(f"Measured grid voltage: {measured_vac} VAC")

    # 1. Send calibration request
    response = requests.post(
        f"{base_url}/api/hardware/voltage/calibrate",
        json={"measured_vac": measured_vac},
        timeout=10
    )

    if response.status_code != 200:
        error = response.json().get('error', 'Unknown error')
        print(f"✗ Calibration failed: {error}")
        return False

    # 2. Get results
    result = response.json()

    if not result.get('success'):
        print(f"✗ Calibration failed")
        return False

    print(f"✓ Calibration successful:")
    print(f"  Sensor VDC: {result['sensor_vdc']:.3f} V")
    print(f"  Multiplier: {result['multiplier']:.2f}")
    print(f"  Sensor type: {result['sensor_type']}")

    # 3. Reboot device
    print("\nRebooting device to apply calibration...")
    requests.post(f"{base_url}/api/system/reboot")

    # 4. Wait for reboot
    time.sleep(15)

    # 5. Verify result
    print("Verifying calibration...")
    for attempt in range(10):
        try:
            status = requests.get(f"{base_url}/api/status", timeout=2).json()
            voltage = status.get('voltage', 0)

            # Check voltage is close to measured value
            if abs(voltage - measured_vac) < 5.0:
                print(f"✓ Calibration verified: {voltage:.1f} V")
                return True
            else:
                print(f"  Current reading: {voltage:.1f} V (expected {measured_vac:.1f} V)")
        except:
            pass

        time.sleep(2)

    print("⚠ Could not verify calibration (device may still be rebooting)")
    return False

# Usage
calibrate_voltage_sensor(232.5)

JavaScript – calibrazione dall'interfaccia web:

javascript
async function calibrateVoltageSensor(measuredVAC) {
    try {
        // 1. Send calibration request
        const response = await fetch('http://192.168.4.1/api/hardware/voltage/calibrate', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({measured_vac: measuredVAC})
        });

        const result = await response.json();

        if (!result.success) {
            alert(`Calibration failed: ${result.error || 'Unknown error'}`);
            return false;
        }

        // 2. Show results
        alert(`Calibration successful!\n` +
              `Sensor VDC: ${result.sensor_vdc.toFixed(3)} V\n` +
              `Multiplier: ${result.multiplier.toFixed(2)}\n` +
              `Sensor: ${result.sensor_type}\n\n` +
              `Device will reboot now...`);

        // 3. Reboot device
        await fetch('http://192.168.4.1/api/system/reboot', {method: 'POST'});

        return true;
    } catch (error) {
        alert(`Error: ${error.message}`);
        return false;
    }
}

// Usage in HTML form
// 
// 


9.8.7 Note importanti

⚠️ Requisiti:

  • PowerMeterADC deve essere in esecuzione (isRunning() == true)
  • Un sensore di tensione deve essere configurato (tipo VOLTAGE_AC)
  • È necessario un riavvio dopo la calibrazione

Vantaggi della calibrazione automatica:

  • Non è necessario regolare manualmente il potenziometro del sensore
  • Funziona con qualsiasi tensione di uscita del sensore (0,5 V, 0,7 V, 1,0 V, ecc.)
  • Aggiorna automaticamente nominal_vdc con il valore effettivamente misurato
  • Calibrazione più precisa e veloce

📖 Vedi anche:




9.9 Endpoint: POST /api/wifi/connect

Connessione a una rete WiFi. Le credenziali vengono salvate automaticamente nel NVS in caso di connessione riuscita.


9.9.1 Richiesta

http
POST /api/wifi/connect HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "ssid": "MyHomeNetwork",
  "password": "MySecurePassword123"
}


9.9.2 Parametri

Parametro Tipo Obbligatorio Descrizione
ssid string Nome della rete WiFi (max 32 caratteri)
password string No Password della rete (vuoto per reti aperte)


9.9.3 Comportamento

  1. Si disconnette dalla rete STA attuale (se connesso)
  2. Tenta la connessione alla nuova rete
  3. In caso di successo:
  4. Le credenziali vengono salvate automaticamente nel NVS
  5. Ottiene un indirizzo IP tramite DHCP
  6. Inizializza NTP (sincronizzazione dell'orario)
  7. La modalità AP rimane attiva (modalità AP+STA)
  8. Al prossimo avvio, il router si connetterà automaticamente a questa rete


9.9.4 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Connecting to WiFi... Credentials will be saved on success",
  "ssid": "MyHomeNetwork"
}

⚠️ Importante: La risposta viene inviata immediatamente dopo l'avvio della connessione. La connessione effettiva richiede 5–10 secondi.


9.9.5 Risposta (errore)

Stato HTTP: 400 Bad Request

json
{
  "error": "Missing 'ssid' field"
}

Stato HTTP: 500 Internal Server Error

json
{
  "error": "Failed to initiate WiFi connection"
}


9.9.6 Verificare la connessione

Dopo 10–15 secondi, controllare lo stato:

bash
curl -s http://192.168.4.1/api/wifi/status | jq '.sta_connected, .sta_ip'


9.9.7 Esempi di utilizzo

Connessione a rete protetta:

bash
curl -X POST http://192.168.4.1/api/wifi/connect \
  -H "Content-Type: application/json" \
  -d '{
    "ssid": "MyHomeNetwork",
    "password": "SecurePass2024"
  }'

Connessione a rete aperta:

bash
curl -X POST http://192.168.4.1/api/wifi/connect \
  -H "Content-Type: application/json" \
  -d '{"ssid": "PublicWiFi"}'

Python – connessione con verifica:

python
import requests
import time

def connect_wifi(ssid, password=None):
    """Connect to WiFi and wait for result"""

    # Send connection request
    payload = {"ssid": ssid}
    if password:
        payload["password"] = password

    response = requests.post(
        "http://192.168.4.1/api/wifi/connect",
        json=payload
    )

    if response.status_code != 200:
        print(f"Failed to initiate connection: {response.json()}")
        return False

    print(f"Connecting to {ssid}...")

    # Wait 10 seconds
    time.sleep(10)

    # Check result
    status = requests.get("http://192.168.4.1/api/wifi/status").json()

    if status['sta_connected'] and status['sta_ssid'] == ssid:
        print(f"✓ Connected to {ssid}")
        print(f"  IP: {status['sta_ip']}")
        print(f"  RSSI: {status['rssi']} dBm")
        return True
    else:
        print(f"✗ Failed to connect to {ssid}")
        return False

# Usage
connect_wifi("MyHomeNetwork", "MyPassword123")

⚠️ Sicurezza: La password viene trasmessa in chiaro. Utilizzare solo tramite connessione AP diretta.




9.10 Endpoint: POST /api/wifi/disconnect

Disconnessione dalla rete WiFi (modalità STA). L'Access Point (AP) rimane attivo.


9.10.1 Richiesta

http
POST /api/wifi/disconnect HTTP/1.1
Host: 192.168.4.1

Corpo della richiesta: Non richiesto


9.10.2 Comportamento

  • Si disconnette dalla rete STA
  • Passa alla modalità AP_ONLY
  • Le credenziali salvate rimangono nel NVS (per la connessione automatica al riavvio)


9.10.3 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Disconnected from WiFi network"
}


9.10.4 Esempi di utilizzo

Bash:

bash
curl -X POST http://192.168.4.1/api/wifi/disconnect

Python:

python
import requests

response = requests.post("http://192.168.4.1/api/wifi/disconnect")
print(response.json())
# {'success': True, 'message': 'Disconnected from WiFi network'}

# Check status
status = requests.get("http://192.168.4.1/api/wifi/status").json()
print(f"State: {status['state']}")  # AP_ONLY
print(f"Saved credentials: {status['has_saved_credentials']}")  # True (remain in NVS)



9.11 Endpoint: POST /api/wifi/forget

Cancellare le credenziali WiFi salvate dal NVS.


9.11.1 Richiesta

http
POST /api/wifi/forget HTTP/1.1
Host: 192.168.4.1

Corpo della richiesta: Non richiesto


9.11.2 Comportamento

  • Cancella le credenziali WiFi dal NVS
  • La connessione attuale rimane attiva (se connesso)
  • Al prossimo avvio, il router NON si connetterà automaticamente
  • Rimarrà in modalità AP_ONLY


9.11.3 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "WiFi credentials cleared from NVS"
}


9.11.4 Risposta (errore)

Stato HTTP: 500 Internal Server Error

json
{
  "error": "Failed to clear WiFi credentials"
}


9.11.5 Esempi di utilizzo

Bash:

bash
curl -X POST http://192.168.4.1/api/wifi/forget

Python – reset completo del WiFi:

python
import requests

def reset_wifi():
    """Complete WiFi reset"""

    # 1. Disconnect from network
    print("Disconnecting from WiFi...")
    requests.post("http://192.168.4.1/api/wifi/disconnect")

    # 2. Clear saved credentials
    print("Clearing saved credentials...")
    response = requests.post("http://192.168.4.1/api/wifi/forget")

    if response.json()['success']:
        print("✓ WiFi reset complete")
        print("  Router will be in AP-only mode after reboot")
    else:
        print("✗ Failed to clear credentials")

reset_wifi()

Scenario di utilizzo comune:

python
# Change WiFi network

# 1. Clear old credentials
requests.post("http://192.168.4.1/api/wifi/forget")

# 2. Connect to new network
requests.post("http://192.168.4.1/api/wifi/connect", json={
    "ssid": "NewNetwork",
    "password": "NewPassword"
})



9.12 Endpoint: POST /api/hardware/config

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

⚠️ Importante: Le modifiche vengono applicate solo dopo il riavvio del dispositivo.


9.12.1 Richiesta

http
POST /api/hardware/config HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "adc_channels": [
    {
      "gpio": 34,
      "type": 1,
      "multiplier": 320.0,
      "offset": 0.0,
      "enabled": true
    },
    ...
  ],
  "dimmer_ch1": {
    "gpio": 19,
    "enabled": true
  },
  "zerocross_gpio": 18,
  "zerocross_enabled": true,
  ...
}


9.12.2 Parametri

Canali ADC (array di 4 elementi):

Parametro Tipo Obbligatorio Descrizione Intervallo consigliato
gpio integer Pin GPIO 32–39 (solo ADC1!)
type integer Tipo di sensore 0=NONE, 1=VOLTAGE_AC, 2=CURRENT_LOAD, 3=CURRENT_GRID, 4=CURRENT_SOLAR
multiplier float No Coefficiente di calibrazione Auto: 328,57 (tensione 230V), 30,0 (corrente). Vedere Calibrazione sensori. Intervallo: 0,1–1000,0
offset float No Offset di calibrazione Predefinito: 0,0. Intervallo: -100,0 a +100,0
enabled boolean Abilitato true/false

Note:

  • GPIO: Solo ADC1 (32–39). ADC2 non è supportato in modalità di lettura continua!
  • Moltiplicatore: Selezionato automaticamente in base al tipo di sensore se non specificato:
  • VOLTAGE_AC → 230,0 (ZMPT107)
  • CURRENT_* → 30,0 (SCT013-030)
  • Offset: Utilizzato per compensare l'errore sistematico del sensore

Dimmer:

Parametro Tipo Descrizione
dimmer_ch1.gpio integer Pin GPIO per il dimmer 1
dimmer_ch1.enabled boolean Dimmer 1 abilitato
dimmer_ch2.gpio integer Pin GPIO per il dimmer 2
dimmer_ch2.enabled boolean Dimmer 2 abilitato

Rilevatore di passaggio per lo zero:

Parametro Tipo Descrizione
zerocross_gpio integer Pin GPIO
zerocross_enabled boolean Abilitato

Relè:

Parametro Tipo Descrizione
relay_ch1.gpio integer Pin GPIO per il relè 1
relay_ch1.active_high boolean Logica: true = attivo a livello ALTO
relay_ch1.enabled boolean Relè 1 abilitato
relay_ch2.* ... Uguale per il relè 2

Indicatori LED:

Parametro Tipo Descrizione
led_status_gpio integer GPIO per LED di stato
led_load_gpio integer GPIO per LED di carico


9.12.3 Validazione

La configurazione viene validata automaticamente prima del salvataggio:

  • Verifica dei conflitti GPIO (un GPIO non può essere usato due volte)
  • Verifica dei pin GPIO validi (0–39)
  • Verifica dei tipi di sensore


9.12.4 Risposta (successo)

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Configuration saved to NVS (reboot required)"
}

⚠️ Importante: È necessario un riavvio per applicare le modifiche!


9.12.5 Risposta (errore di validazione)

Stato HTTP: 400 Bad Request

json
{
  "success": false,
  "error": "GPIO 19 conflict: used by Dimmer 1 and ADC channel 0"
}


9.12.6 Esempi di utilizzo

Aggiornare i canali ADC:

bash
curl -X POST http://192.168.4.1/api/hardware/config \
  -H "Content-Type: application/json" \
  -d '{
    "adc_channels": [
      {
        "gpio": 34,
        "type": 1,
        "multiplier": 320.0,
        "offset": 0.0,
        "enabled": true
      },
      {
        "gpio": 35,
        "type": 2,
        "multiplier": 30.0,
        "offset": 0.0,
        "enabled": true
      }
    ]
  }'

Python – cambiare GPIO del dimmer:

python
import requests

config = {
    "dimmer_ch1": {
        "gpio": 21,  # Change from 19 to 21
        "enabled": True
    }
}

response = requests.post(
    "http://192.168.4.1/api/hardware/config",
    json=config
)

if response.json()['success']:
    print("Configuration saved. Rebooting device...")
    # Reboot device
    requests.post("http://192.168.4.1/api/system/reboot")



9.13 Endpoint: POST /api/hardware/validate

Validare la configurazione hardware senza salvarla. Utile per verificare prima di applicare.


9.13.1 Richiesta

http
POST /api/hardware/validate HTTP/1.1
Host: 192.168.4.1
Content-Type: application/json

{
  "dimmer_ch1": {
    "gpio": 34,
    "enabled": true
  }
}


9.13.2 Risposta (configurazione valida)

Stato HTTP: 200 OK

json
{
  "valid": true
}


9.13.3 Risposta (configurazione non valida)

Stato HTTP: 200 OK

json
{
  "valid": false,
  "error": "GPIO 34 conflict: already used by ADC channel 0"
}


9.13.4 Esempi di utilizzo

Python – validare prima di applicare:

python
import requests

new_config = {
    "dimmer_ch1": {"gpio": 21, "enabled": True},
    "zerocross_gpio": 18
}

# 1. Validate first
validate_response = requests.post(
    "http://192.168.4.1/api/hardware/validate",
    json=new_config
)

if validate_response.json()['valid']:
    print("✓ Configuration valid, applying...")

    # 2. Apply configuration
    apply_response = requests.post(
        "http://192.168.4.1/api/hardware/config",
        json=new_config
    )

    if apply_response.json()['success']:
        print("✓ Configuration saved, rebooting...")
        requests.post("http://192.168.4.1/api/system/reboot")
else:
    print(f"✗ Invalid configuration: {validate_response.json()['error']}")



9.14 Endpoint: POST /api/system/reboot

Riavviare il dispositivo.


9.14.1 Richiesta

http
POST /api/system/reboot HTTP/1.1
Host: 192.168.4.1

Corpo della richiesta: Non richiesto


9.14.2 Comportamento

  1. Invia la risposta al client
  2. Attende 500 ms (per trasmettere la risposta)
  3. Attende ulteriori 3 secondi
  4. Esegue il riavvio tramite ESP.restart()

⚠️ Importante: Le attività critiche dovrebbero essere interrotte prima del riavvio (previsto per le versioni future).


9.14.3 Risposta

Stato HTTP: 200 OK

json
{
  "success": true,
  "message": "Rebooting in 3 seconds..."
}


9.14.4 Esempi di utilizzo

Bash:

bash
curl -X POST http://192.168.4.1/api/system/reboot

Python – riavviare e attendere:

python
import requests
import time

def reboot_and_wait(url="http://192.168.4.1"):
    """Reboot device and wait for it to come back online"""

    print("Rebooting device...")
    try:
        requests.post(f"{url}/api/system/reboot", timeout=5)
    except requests.exceptions.RequestException:
        pass  # Connection may be dropped

    print("Waiting for device to reboot...")
    time.sleep(10)  # Wait 10 seconds

    # Wait until device comes back online
    for attempt in range(30):
        try:
            response = requests.get(f"{url}/api/info", timeout=2)
            if response.status_code == 200:
                info = response.json()
                print(f"✓ Device online (uptime: {info['uptime_sec']}s)")
                return True
        except requests.exceptions.RequestException:
            pass

        print(f"  Attempt {attempt + 1}/30...")
        time.sleep(2)

    print("✗ Device did not come back online")
    return False

# Usage
reboot_and_wait()



9.15 Gestione degli errori


9.15.1 Codici di errore HTTP

Codice Stato Descrizione
400 Bad Request Formato della richiesta non valido, campi mancanti, valori non validi
500 Internal Server Error Errore interno del server (errore NVS, ecc.)
501 Not Implemented Funzionalità non implementata


9.15.2 Esempi di errori

Corpo della richiesta mancante:

json
{
  "error": "Missing request body"
}

JSON non valido:

json
{
  "error": "Invalid JSON"
}

Campo obbligatorio mancante:

json
{
  "error": "Missing 'mode' field"
}

Valore non valido:

json
{
  "error": "Value must be 0-100"
}

Errore di validazione:

json
{
  "error": "GPIO 19 conflict: used by Dimmer 1 and ADC channel 0"
}


9.15.3 Gestione degli errori nel codice

Python:

python
import requests

def safe_post(url, json_data):
    """Safe POST request with error handling"""
    try:
        response = requests.post(url, json=json_data, timeout=10)

        if response.status_code == 200:
            return response.json()
        else:
            error_msg = response.json().get('error', 'Unknown error')
            print(f"Error {response.status_code}: {error_msg}")
            return None

    except requests.exceptions.Timeout:
        print("Request timeout")
        return None

    except requests.exceptions.ConnectionError:
        print("Connection error")
        return None

    except Exception as e:
        print(f"Unexpected error: {e}")
        return None

# Usage
result = safe_post(
    "http://192.168.4.1/api/mode",
    {"mode": "auto"}
)

if result and result.get('success'):
    print("Success!")
else:
    print("Failed to set mode")



9.16 Esempi di utilizzo


9.16.1 Configurazione completa del router (Python)

python
import requests
import time

class ACRouterConfig:
    def __init__(self, base_url="http://192.168.4.1"):
        self.base_url = base_url

    def set_mode(self, mode):
        """Set operating mode"""
        return requests.post(
            f"{self.base_url}/api/mode",
            json={"mode": mode}
        ).json()

    def set_dimmer(self, value):
        """Set dimmer level"""
        return requests.post(
            f"{self.base_url}/api/dimmer",
            json={"value": value}
        ).json()

    def update_config(self, **params):
        """Update configuration parameters"""
        return requests.post(
            f"{self.base_url}/api/config",
            json=params
        ).json()

    def connect_wifi(self, ssid, password=None):
        """Connect to WiFi"""
        payload = {"ssid": ssid}
        if password:
            payload["password"] = password

        response = requests.post(
            f"{self.base_url}/api/wifi/connect",
            json=payload
        ).json()

        if response['success']:
            time.sleep(10)  # Wait for connection
            status = requests.get(f"{self.base_url}/api/wifi/status").json()
            return status['sta_connected']

        return False

    def setup_solar_router(self):
        """Complete Solar Router setup"""

        # 1. Configure control parameters
        print("Configuring control parameters...")
        self.update_config(
            control_gain=180.0,
            balance_threshold=40.0
        )

        # 2. Set AUTO mode
        print("Setting AUTO mode...")
        self.set_mode("auto")

        # 3. Check status
        status = requests.get(f"{self.base_url}/api/status").json()
        print(f"Mode: {status['mode']}")
        print(f"Dimmer: {status['dimmer']}%")
        print(f"Power: {status['power_grid']}W")

# Usage
router = ACRouterConfig()
router.setup_solar_router()


9.16.2 Monitoraggio e correzione automatica (Python)

python
import requests
import time

def monitor_and_adjust():
    """Monitor power and automatically adjust mode"""

    base_url = "http://192.168.4.1"

    while True:
        # Get current status
        status = requests.get(f"{base_url}/api/status").json()

        power = status['power_grid']
        mode = status['mode']

        print(f"[{time.strftime('%H:%M:%S')}] Power: {power:+7.1f}W | Mode: {mode}")

        # If high import from grid in AUTO mode
        if mode == 'auto' and power > 500:
            print("  High import detected, increasing gain...")
            requests.post(f"{base_url}/api/config", json={"control_gain": 250.0})

        # If high export to grid
        elif mode == 'auto' and power < -500:
            print("  High export detected, switching to BOOST mode...")
            requests.post(f"{base_url}/api/mode", json={"mode": "boost"})

        time.sleep(10)

monitor_and_adjust()


9.16.3 Pannello di controllo web (HTML + JavaScript)

html



    ACRouter Control Panel
    


    

ACRouter Control Panel

Mode Control

Dimmer Control

0%

Quick Actions




  • 07_COMMANDS.md – Riferimento comandi (RU)
  • 07_COMMANDS_EN.md – Riferimento comandi (EN)
  • 08_WEB_API_GET.md – Endpoint Web API GET (RU)
  • 08_WEB_API_GET_EN.md – Endpoint Web API GET (EN)
  • 09_WEB_API_POST.md – Endpoint Web API POST (RU)
  • 10_WEB_INTERFACE.md – Navigazione dell'interfaccia web (sezione successiva)

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

← Web API - GET | Indice | Avanti: Calibrazione sensori →