Se rendre au contenu

← Web API - GET | Sommaire | Suivant : Calibrage des capteurs →

9. Web API - Points de terminaison POST

Version: 1.0.0
Date: 2025-01-15

Documentation détaillée des points de terminaison POST de l'API REST pour le contrôle et la configuration du système ACRouter.




Table des matières




9.1 Introduction

Les points de terminaison POST de l'API REST ACRouter sont conçus pour :

  • Contrôle du routeur – changer le mode de fonctionnement, le niveau du variateur
  • Configuration – mettre à jour les paramètres système
  • Gestion WiFi – connexion/déconnexion aux réseaux
  • Configuration matérielle – configurer les GPIOs, capteurs, variateurs
  • Contrôle système – redémarrer l'appareil

Toutes les modifications sont appliquées immédiatement et sauvegardées dans le NVS (Non-Volatile Storage).

Implémentation : components/comm/src/WebServerManager.cpp




9.2 Format des requêtes


9.2.1 Content-Type

Toutes les requêtes POST doivent utiliser :

http
Content-Type: application/json


9.2.2 Structure de la requête

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

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


9.2.3 Format de réponse en cas de succès

Statut HTTP : 200 OK

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


9.2.4 Format de réponse en cas d'erreur

Statut HTTP : 400, 500, 501

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



9.3 Point de terminaison : POST /api/config

Mise à jour des paramètres de configuration du système. Permet de mettre à jour un ou plusieurs paramètres dans une seule requête.


9.3.1 Requête

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 Paramètres (optionnels)

Tous les paramètres sont optionnels. Seuls les champs spécifiés sont mis à jour.

Paramètre Type Plage Description
voltage_coef float 0.1 .. 10.0 Coefficient de calibrage de la tension
current_coef float 0.1 .. 100.0 Coefficient de conversion du courant (A/V)
current_threshold float 0.01 .. 10.0 Seuil de détection du courant (A)
power_threshold float 1.0 .. 1000.0 Seuil de détection de puissance (W)
control_gain float 1.0 .. 1000.0 Gain de la boucle de régulation
balance_threshold float 0.0 .. 100.0 Seuil d'équilibre pour le mode AUTO (W)


9.3.3 Réponse (succès)

Statut HTTP : 200 OK

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

Si aucun paramètre n'a été modifié :

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


9.3.4 Réponse (erreur)

Statut HTTP : 400 Bad Request

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


9.3.5 Exemples d'utilisation

Mettre à jour un seul paramètre :

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

Mettre à jour plusieurs paramètres :

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 Point de terminaison : POST /api/config/reset

Réinitialiser tous les paramètres de configuration aux valeurs d'usine.


9.4.1 Requête

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

Corps de la requête : Non requis


9.4.2 Valeurs d'usine

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 Réponse (succès)

Statut HTTP : 200 OK

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


9.4.4 Exemples d'utilisation

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

⚠️ Avertissement : Cette opération est irréversible. Tous les paramètres personnalisés seront perdus.




9.5 Point de terminaison : POST /api/mode

Définir le mode de fonctionnement du routeur.


9.5.1 Requête

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

{
  "mode": "auto"
}


9.5.2 Paramètres

Paramètre Type Requis Valeurs valides
mode string Oui "off", "auto", "eco", "offgrid", "manual", "boost"

Description des modes :

Mode Description
"off" Routeur désactivé, variateur 0%
"auto" Routeur solaire – minimiser import/export réseau
"eco" Économique – éviter l'import, permettre l'export
"offgrid" Offgrid – solaire/batterie, utilisation minimale du réseau
"manual" Manuel – niveau de variateur fixe
"boost" Puissance maximale – variateur 100%


9.5.3 Réponse (succès)

Statut HTTP : 200 OK

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


9.5.4 Réponse (erreur)

Statut HTTP : 400 Bad Request

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


9.5.5 Exemples d'utilisation

Activer le mode AUTO (routeur solaire) :

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

Activer le mode ECO :

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

Python – basculer entre les modes :

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 Point de terminaison : POST /api/dimmer

Définir le niveau du variateur. Passe automatiquement le routeur en mode MANUAL.


9.6.1 Requête

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

{
  "value": 75
}


9.6.2 Paramètres

Paramètre Type Requis Plage Description
value integer Oui 0 .. 100 Niveau du variateur en pourcentage


9.6.3 Réponse (succès)

Statut HTTP : 200 OK

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

⚠️ Important : Le routeur passe automatiquement en mode MANUAL lorsque le niveau du variateur est défini.


9.6.4 Réponse (erreur)

Statut HTTP : 400 Bad Request

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


9.6.5 Exemples d'utilisation

Régler le variateur à 50% :

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

Python – montée en puissance progressive :

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 – commande par curseur :

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 Point de terminaison : POST /api/manual

Point de terminaison alternatif pour activer le mode manuel avec un niveau de variateur spécifié. Équivalent à POST /api/mode (mode=manual) + POST /api/dimmer.


9.7.1 Requête

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

{
  "value": 60
}


9.7.2 Paramètres

Paramètre Type Requis Plage Description
value integer Oui 0 .. 100 Niveau du variateur en pourcentage


9.7.3 Comportement

  1. Passe le routeur en mode MANUAL
  2. Définit le niveau du variateur à la valeur spécifiée


9.7.4 Réponse (succès)

Statut HTTP : 200 OK

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


9.7.5 Exemples d'utilisation

Bash :

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

Différence entre /api/dimmer et /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 Point de terminaison : POST /api/hardware/voltage/calibrate

Calibrage automatique du capteur de tension (disponible depuis la version 2.0).

Le système mesure automatiquement la sortie du capteur (VDC RMS) et calcule le multiplicateur de calibrage à partir de la tension réseau mesurée.


9.8.1 Requête

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 Paramètres

Paramètre Type Requis Description
measured_vac float Oui Tension réseau mesurée au multimètre (VAC RMS)

Plage : 100.0 .. 300.0 (selon le standard réseau)


9.8.3 Processus de calibrage

  1. PowerMeterADC mesure la sortie actuelle du capteur (VDC RMS)
  2. Calcule le multiplicateur : multiplier = measured_vac / sensor_vdc
  3. Met à jour nominal_vdc avec la valeur réellement mesurée
  4. La configuration est sauvegardée dans le NVS
  5. ⚠️ Un redémarrage est nécessaire pour appliquer les modifications


9.8.4 Réponse (succès)

Statut HTTP : 200 OK

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

Champs de la réponse :

Champ Type Description
sensor_vdc float Sortie mesurée du capteur (VDC RMS)
multiplier float Multiplicateur calculé
sensor_type string Type de capteur (ZMPT107, ZMPT101B, CUSTOM)


9.8.5 Réponse (erreur)

Statut HTTP : 400 Bad Request

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

Statut HTTP : 500 Internal Server Error

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


9.8.6 Exemples d'utilisation

Calibrage simple :

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

Exemple de réponse :

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

Python – procédure de calibrage complète :

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 – calibrage depuis l'interface 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 Remarques importantes

⚠️ Prérequis :

  • PowerMeterADC doit être en cours d'exécution (isRunning() == true)
  • Un capteur de tension doit être configuré (type VOLTAGE_AC)
  • Un redémarrage est nécessaire après le calibrage

Avantages du calibrage automatique :

  • Pas besoin de régler manuellement le potentiomètre du capteur
  • Fonctionne avec n'importe quelle tension de sortie du capteur (0,5 V, 0,7 V, 1,0 V, etc.)
  • Met automatiquement à jour nominal_vdc avec la valeur réellement mesurée
  • Calibrage plus précis et plus rapide

📖 Voir aussi :




9.9 Point de terminaison : POST /api/wifi/connect

Se connecter à un réseau WiFi. Les identifiants sont automatiquement sauvegardés dans le NVS en cas de connexion réussie.


9.9.1 Requête

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

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


9.9.2 Paramètres

Paramètre Type Requis Description
ssid string Oui Nom du réseau WiFi (max. 32 caractères)
password string Non Mot de passe du réseau (vide pour les réseaux ouverts)


9.9.3 Comportement

  1. Se déconnecte du réseau STA actuel (si connecté)
  2. Tente de se connecter au nouveau réseau
  3. En cas de succès :
  4. Les identifiants sont automatiquement sauvegardés dans le NVS
  5. Obtient une adresse IP via DHCP
  6. Initialise NTP (synchronisation de l'heure)
  7. Le mode AP reste actif (mode AP+STA)
  8. Au prochain démarrage, le routeur se connectera automatiquement à ce réseau


9.9.4 Réponse (succès)

Statut HTTP : 200 OK

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

⚠️ Important : La réponse est envoyée immédiatement après l'initiation de la connexion. La connexion effective prend 5 à 10 secondes.


9.9.5 Réponse (erreur)

Statut HTTP : 400 Bad Request

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

Statut HTTP : 500 Internal Server Error

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


9.9.6 Vérifier la connexion

Après 10 à 15 secondes, vérifier le statut :

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


9.9.7 Exemples d'utilisation

Se connecter à un réseau sécurisé :

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

Se connecter à un réseau ouvert :

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

Python – connexion avec vérification :

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")

⚠️ Sécurité : Le mot de passe est transmis en clair. À utiliser uniquement via une connexion AP directe.




9.10 Point de terminaison : POST /api/wifi/disconnect

Se déconnecter du réseau WiFi (mode STA). Le point d'accès (AP) reste actif.


9.10.1 Requête

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

Corps de la requête : Non requis


9.10.2 Comportement

  • Se déconnecte du réseau STA
  • Passe en mode AP_ONLY
  • Les identifiants sauvegardés restent dans le NVS (pour la connexion automatique au redémarrage)


9.10.3 Réponse (succès)

Statut HTTP : 200 OK

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


9.10.4 Exemples d'utilisation

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 Point de terminaison : POST /api/wifi/forget

Effacer les identifiants WiFi sauvegardés du NVS.


9.11.1 Requête

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

Corps de la requête : Non requis


9.11.2 Comportement

  • Efface les identifiants WiFi du NVS
  • La connexion active est maintenue (si connecté)
  • Au prochain démarrage, le routeur NE se connectera PAS automatiquement
  • Restera en mode AP_ONLY


9.11.3 Réponse (succès)

Statut HTTP : 200 OK

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


9.11.4 Réponse (erreur)

Statut HTTP : 500 Internal Server Error

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


9.11.5 Exemples d'utilisation

Bash :

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

Python – réinitialisation complète du 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()

Scénario d'utilisation courant :

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 Point de terminaison : POST /api/hardware/config

Mettre à jour la configuration matérielle : canaux ADC, variateurs, passage par zéro, relais, LEDs.

⚠️ Important : Les modifications ne sont appliquées qu'après le redémarrage de l'appareil.


9.12.1 Requête

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 Paramètres

Canaux ADC (tableau de 4 éléments) :

Paramètre Type Requis Description Plage recommandée
gpio integer Oui Broche GPIO 32–39 (ADC1 uniquement !)
type integer Oui Type de capteur 0=NONE, 1=VOLTAGE_AC, 2=CURRENT_LOAD, 3=CURRENT_GRID, 4=CURRENT_SOLAR
multiplier float Non Coefficient de calibrage Auto : 328,57 (tension 230 V), 30,0 (courant). Voir Calibrage des capteurs. Plage : 0,1–1000,0
offset float Non Décalage de calibrage Par défaut : 0,0. Plage : -100,0 à +100,0
enabled boolean Oui Activé true/false

Remarques :

  • GPIO : ADC1 uniquement (32–39). ADC2 n'est pas pris en charge en mode de lecture continue !
  • Multiplicateur : Sélectionné automatiquement en fonction du type de capteur si non spécifié :
  • VOLTAGE_AC → 230,0 (ZMPT107)
  • CURRENT_* → 30,0 (SCT013-030)
  • Décalage : Utilisé pour compenser l'erreur systématique du capteur

Variateurs :

Paramètre Type Description
dimmer_ch1.gpio integer Broche GPIO pour le variateur 1
dimmer_ch1.enabled boolean Variateur 1 activé
dimmer_ch2.gpio integer Broche GPIO pour le variateur 2
dimmer_ch2.enabled boolean Variateur 2 activé

Détecteur de passage par zéro :

Paramètre Type Description
zerocross_gpio integer Broche GPIO
zerocross_enabled boolean Activé

Relais :

Paramètre Type Description
relay_ch1.gpio integer Broche GPIO pour le relais 1
relay_ch1.active_high boolean Logique : true = actif à l'état HAUT
relay_ch1.enabled boolean Relais 1 activé
relay_ch2.* ... Identique pour le relais 2

Indicateurs LED :

Paramètre Type Description
led_status_gpio integer GPIO pour la LED de statut
led_load_gpio integer GPIO pour la LED de charge


9.12.3 Validation

La configuration est automatiquement validée avant la sauvegarde :

  • Vérification des conflits GPIO (un GPIO ne peut pas être utilisé deux fois)
  • Vérification des broches GPIO valides (0–39)
  • Vérification des types de capteurs


9.12.4 Réponse (succès)

Statut HTTP : 200 OK

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

⚠️ Important : Un redémarrage est nécessaire pour appliquer les modifications !


9.12.5 Réponse (erreur de validation)

Statut HTTP : 400 Bad Request

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


9.12.6 Exemples d'utilisation

Mettre à jour les canaux 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 – changer le GPIO du variateur :

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 Point de terminaison : POST /api/hardware/validate

Valider la configuration matérielle sans la sauvegarder. Utile pour vérifier avant d'appliquer.


9.13.1 Requête

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 Réponse (configuration valide)

Statut HTTP : 200 OK

json
{
  "valid": true
}


9.13.3 Réponse (configuration invalide)

Statut HTTP : 200 OK

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


9.13.4 Exemples d'utilisation

Python – valider avant d'appliquer :

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 Point de terminaison : POST /api/system/reboot

Redémarrer l'appareil.


9.14.1 Requête

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

Corps de la requête : Non requis


9.14.2 Comportement

  1. Envoie la réponse au client
  2. Attend 500 ms (pour transmettre la réponse)
  3. Attend 3 secondes supplémentaires
  4. Exécute le redémarrage via ESP.restart()

⚠️ Important : Les tâches critiques doivent être arrêtées avant le redémarrage (prévu pour les versions futures).


9.14.3 Réponse

Statut HTTP : 200 OK

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


9.14.4 Exemples d'utilisation

Bash :

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

Python – redémarrer et attendre :

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 Gestion des erreurs


9.15.1 Codes d'erreur HTTP

Code Statut Description
400 Bad Request Format de requête invalide, champs manquants, valeurs invalides
500 Internal Server Error Erreur interne du serveur (erreur NVS, etc.)
501 Not Implemented Fonctionnalité non implémentée


9.15.2 Exemples d'erreurs

Corps de requête manquant :

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

JSON invalide :

json
{
  "error": "Invalid JSON"
}

Champ requis manquant :

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

Valeur invalide :

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

Erreur de validation :

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


9.15.3 Gestion des erreurs dans le code

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 Exemples d'utilisation


9.16.1 Configuration complète du routeur (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 Surveillance et correction automatique (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 Panneau de contrôle web (HTML + JavaScript)

html



    ACRouter Control Panel
    


    

ACRouter Control Panel

Mode Control

Dimmer Control

0%

Quick Actions




  • 07_COMMANDS.md – Référence des commandes (RU)
  • 07_COMMANDS_EN.md – Référence des commandes (EN)
  • 08_WEB_API_GET.md – Points de terminaison Web API GET (RU)
  • 08_WEB_API_GET_EN.md – Points de terminaison Web API GET (EN)
  • 09_WEB_API_POST.md – Points de terminaison Web API POST (RU)
  • 10_WEB_INTERFACE.md – Navigation de l'interface web (section suivante)

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

← Web API - GET | Sommaire | Suivant : Calibrage des capteurs →