Zum Inhalt springen

← Terminalbefehle | Inhaltsverzeichnis | Weiter: Web API - POST →

8. Web API – GET-Endpunkte

Version: 1.0.0
Date: 2025-01-15

Ausführliche Dokumentation der REST API GET-Endpunkte zur Überwachung und zum Abruf von Systeminformationen des ACRouter.




Inhaltsverzeichnis




8.1 Einleitung

Die ACRouter REST API stellt eine Reihe von GET-Endpunkten bereit für:

  • Überwachung – aktuellen Router-Status und Leistung abrufen
  • Konfiguration – Systemparameter auslesen
  • Diagnose – Systeminformationen, WiFi-Status, Hardware-Konfiguration

Alle Endpunkte liefern Daten im JSON-Format.

Implementierung: components/comm/src/WebServerManager.cpp

Schnellstart: Siehe 07_COMMANDS_EN.md section "REST API Reference" for basic usage examples.




8.2 Basis-URL und Authentifizierung


8.2.1 Basis-URL

Access-Point-Modus:

python
http://192.168.4.1/api/

Station-Modus:

python
http:///api/

Verwenden Sie den seriellen Befehl wifi-status oder GET /api/wifi/status, um die IP-Adresse zu ermitteln.


8.2.2 Authentifizierung

⚠️ Wichtig: Die REST API erfordert keine Authentifizierung. Alle Endpunkte sind ohne Passwort zugänglich.

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

CORS (Cross-Origin Resource Sharing) ist für alle Endpunkte aktiviert.

Antwort-Header:

python
Access-Control-Allow-Origin: *

Dies ermöglicht API-Aufrufe von Webanwendungen, die auf anderen Domains gehostet werden.




8.3 Antwortformat


8.3.1 Erfolgreiche Antwort

HTTP-Status: 200 OK

Content-Type: application/json

Struktur:

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


8.3.2 Fehlerantwort

HTTP-Status: 400, 404, 500, 501

Content-Type: application/json

Struktur:

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

Beispiel:

json
{
  "error": "Not Found"
}


8.3.3 Zeichenkodierung

Alle Antworten verwenden die UTF-8-Kodierung.




8.4 Endpunkt: GET /api/status

Vollständigen Router-Status abrufen, einschließlich Betriebsmodus, Controller-Zustand, Netzleistung und Dimmer-Stufe.


8.4.1 Anfrage

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

Parameter: Keine


8.4.2 Antwort

HTTP-Status: 200 OK

JSON-Schema:

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 Feldbeschreibungen

Feld Typ Beschreibung Mögliche Werte
mode string Betriebsmodus des Routers "off", "auto", "eco", "offgrid", "manual", "boost", "unknown"
state string Controller-Zustand "idle", "increasing", "decreasing", "at_max", "at_min", "error"
power_grid float Netzleistung in Watt. Positiv = Netzbezug (Verbrauch), Negativ = Netzeinspeisung (Überschuss) -∞ .. +∞
dimmer integer Aktuelle Dimmer-Stufe in Prozent 0 .. 100
target_level integer Ziel-Dimmer-Stufe (für AUTO-, ECO-, OFFGRID-Modi) 0 .. 100
control_gain float Verstärkung des Regelkreises 1.0 .. 1000.0
balance_threshold float Schwellenwert für Balance in Watt (für AUTO-Modus) 0.0 .. 100.0
valid boolean Gültigkeit der Messdaten. false = Sensoren nicht initialisiert oder Fehler true / false
uptime integer Betriebszeit seit dem Start in Sekunden 0 ..
free_heap integer Freier RAM-Speicher in Bytes 0 ..


8.4.4 Beispielantwort

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 Verwendung

Echtzeitüberwachung:

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

Betriebsmodus prüfen:

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

Python – Balance-Überwachung:

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 Endpunkt: GET /api/metrics

Leichtgewichtige Leistungsmetriken für häufiges Polling abrufen. Liefert nur kritische Daten für die Überwachung bei minimaler Antwortgröße.


8.5.1 Anfrage

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

Parameter: Keine


8.5.2 Antwort

HTTP-Status: 200 OK

JSON-Schema:

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 Feldbeschreibungen

Feld Typ Beschreibung
metrics.power_grid float Netzleistung (W). Positiv = Bezug, negativ = Einspeisung
metrics.dimmer integer Aktuelle Dimmer-Stufe (0–100 %)
metrics.target_level integer Ziel-Dimmer-Stufe (0–100 %)
timestamp integer Zeit seit dem Start in Millisekunden


8.5.4 Beispielantwort

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 Verwendung

Hochfrequente Überwachung:

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

JavaScript – Echtzeit-Diagramm:

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

Vergleich mit /api/status:

Kriterium /api/status /api/metrics
Antwortgröße ~250 Bytes ~80 Bytes
Felder 10 Felder 3 Felder + Zeitstempel
Anwendungsfall Vollständige Informationen Echtzeitüberwachung
Abfragefrequenz 5–10 Sekunden 1–2 Sekunden



8.6 Endpunkt: GET /api/config

Alle in NVS gespeicherten Systemkonfigurationsparameter abrufen.


8.6.1 Anfrage

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

Parameter: Keine


8.6.2 Antwort

HTTP-Status: 200 OK

JSON-Schema:

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 Feldbeschreibungen

Feld Typ Bereich Standard Beschreibung
control_gain float 1.0 .. 1000.0 150.0 Verstärkung des Regelkreises
balance_threshold float 0.0 .. 100.0 50.0 Schwellenwert für Balance im AUTO-Modus (W)
voltage_coef float 0.1 .. 10.0 1.0 Kalibrierungskoeffizient für Spannung
current_coef float 0.1 .. 100.0 30.0 Umrechnungskoeffizient für Strom (A/V)
current_threshold float 0.01 .. 10.0 0.1 Schwelle für Stromerkennung (A)
power_threshold float 1.0 .. 1000.0 10.0 Schwelle für Wirkleistungserkennung (W)
router_mode integer 0 .. 5 1 Router-Modus: 0=OFF, 1=AUTO, 2=ECO, 3=OFFGRID, 4=MANUAL, 5=BOOST
manual_level integer 0 .. 100 0 Dimmer-Stufe für manuellen Modus (%)


8.6.4 Beispielantwort

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 Verwendung

Konfigurationssicherung:

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 – Konfigurationen vergleichen:

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 Endpunkt: GET /api/info

Systeminformationen abrufen: Firmware-Version, Chiptyp, Flash-Größe, freier Speicher, Betriebszeit.


8.7.1 Anfrage

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

Parameter: Keine


8.7.2 Antwort

HTTP-Status: 200 OK

JSON-Schema:

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 Feldbeschreibungen

Feld Typ Beschreibung
version string ACRouter firmware version (format: "X.Y.Z")
chip string Microcontroller type (typically "ESP32")
flash_size integer Flash-Speichergröße in Bytes
free_heap integer Freier RAM-Speicher in Bytes
uptime integer [VERALTET] Betriebszeit in Sekunden (verwenden Sie uptime_sec)
uptime_sec integer Betriebszeit seit dem Start in Sekunden


8.7.4 Beispielantwort

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 Verwendung

Speicherüberwachung:

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 – Warnung bei niedrigem Speicher:

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)

Betriebszeit formatieren:

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 Endpunkt: GET /api/wifi/status

Detaillierten WiFi-Verbindungsstatus abrufen: AP/STA-Modus, IP-Adressen, SSID, Signalstärke, MAC-Adresse, gespeicherte Zugangsdaten.


8.8.1 Anfrage

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

Parameter: Keine


8.8.2 Antwort

HTTP-Status: 200 OK

JSON-Schema:

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 Feldbeschreibungen

Feld Typ Beschreibung Mögliche Werte
state string WiFi-Zustand "IDLE", "AP_ONLY", "STA_CONNECTING", "STA_CONNECTED", "AP_STA", "STA_FAILED"
ap_active boolean Access Point aktiv true / false
ap_ssid string AP-Name (Format: ACRouter_XXXXXX) -
ap_ip string AP-IP-Adresse (normalerweise 192.168.4.1) -
ap_clients integer Anzahl der mit dem AP verbundenen Clients 0 .. 4
sta_connected boolean Als Client mit WiFi-Netzwerk verbunden true / false
sta_ssid string Name des WiFi-Netzwerks -
sta_ip string Per DHCP erhaltene IP-Adresse -
rssi integer WiFi-Signalstärke in dBm -100 .. -30
has_saved_credentials boolean Zugangsdaten in NVS gespeichert true / false
mac string MAC-Adresse des Geräts (Format: XX:XX:XX:XX:XX:XX) -
hostname string Hostname des Geräts -

Bewertung der Signalstärke (RSSI):

RSSI (dBm) Qualität Beschreibung
-30 bis -50 Ausgezeichnet Sehr starkes Signal
-51 bis -70 Gut Stabile Verbindung
-71 bis -85 Befriedigend Gelegentliche Abbrüche möglich
-86 bis -100 Schlecht Instabile Verbindung


8.8.4 Beispielantwort (AP + STA aktiv)

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 Beispielantwort (nur 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 Verwendung

Netzwerkverbindung prüfen:

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 – Signalstärke überwachen:

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 Endpunkt: GET /api/wifi/scan

Verfügbare WiFi-Netzwerke in Reichweite scannen.


8.9.1 Anfrage

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

Parameter: Keine

⚠️ Warnung: Der Scan dauert 2–3 Sekunden. Die STA-Verbindung kann während des Scans kurzzeitig unterbrochen werden.


8.9.2 Antwort

HTTP-Status: 200 OK

JSON-Schema:

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 Feldbeschreibungen

Feld Typ Beschreibung
networks array Array der gefundenen Netzwerke
networks[].ssid string Name des WiFi-Netzwerks
networks[].rssi integer Signalstärke in dBm
networks[].encryption string Verschlüsselungstyp: "open" oder "secured"
networks[].channel integer WiFi-Kanalnummer (1–14)
count integer Gesamtzahl der gefundenen Netzwerke


8.9.4 Beispielantwort

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 Beispielantwort (keine Netzwerke)

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


8.9.6 Verwendung

Bash – verfügbare Netzwerke auflisten:

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

Ausgabe:

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

Python – bestes Netzwerk finden:

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 – Netzwerkliste anzeigen:

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 Endpunkt: GET /api/hardware/config

Hardware-Komponentenkonfiguration abrufen: ADC-Kanäle, Dimmer, Nulldurchgang, Relais, LEDs.


8.10.1 Anfrage

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

Parameter: Keine


8.10.2 Antwort

HTTP-Status: 200 OK

JSON-Schema:

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 Sensortypen (SensorType)

Code Name Beschreibung
0 NONE Nicht verwendet
1 ZMPT107 ZMPT107 Spannungssensor
2 SCT013 SCT-013 Stromsensor (Transformator)
3 ACS712 ACS712 Stromsensor (Hall-Effekt)


8.10.4 Beispielantwort

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 Verwendung

Diagnose der Hardwarekonfiguration:

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

Python – GPIO-Konflikte prüfen:

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 HTTP-Fehlercodes

Code Status Beschreibung Beispiel
200 OK Erfolgreiche Anfrage Alle GET-Endpunkte bei Erfolg
400 Bad Request Ungültiges Anfrageformat Ungültiger Parameter
404 Not Found Endpunkt nicht gefunden GET /api/unknown
500 Internal Server Error Interner Serverfehler Fehler beim Lesen von NVS
501 Not Implemented Funktion nicht implementiert GET /api/calibrate

Fehlerformat:

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

Beispiele:

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



8.12 Anwendungsbeispiele


8.12.1 Statusüberwachung (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 Export nach 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 – Projektübersicht
  • 03_STRUCTURE.md – Anwendungsarchitektur
  • 07_COMMANDS.md – Befehlsreferenz (RU)
  • 07_COMMANDS_EN.md – Befehlsreferenz (EN)
  • 09_WEB_API_POST.md – Web API POST-Endpunkte (nächster Abschnitt)

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

← Terminalbefehle | Inhaltsverzeichnis | Weiter: Web API - POST →