← 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
- 8.2 Basis-URL und Authentifizierung
- 8.3 Antwortformat
- 8.4 Endpunkt: GET /api/status
- 8.5 Endpunkt: GET /api/metrics
- 8.6 Endpunkt: GET /api/config
- 8.7 Endpunkt: GET /api/info
- 8.8 Endpunkt: GET /api/wifi/status
- 8.9 Endpunkt: GET /api/wifi/scan
- 8.10 Endpunkt: GET /api/hardware/config
- 8.11 HTTP-Fehlercodes
- 8.12 Anwendungsbeispiele
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:
http://192.168.4.1/api/
Station-Modus:
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:
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:
{
"field1": "value1",
"field2": 123,
"field3": true
}
8.3.2 Fehlerantwort
HTTP-Status: 400, 404, 500, 501
Content-Type: application/json
Struktur:
{
"error": "Error message description"
}
Beispiel:
{
"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
GET /api/status HTTP/1.1
Host: 192.168.4.1
Parameter: Keine
8.4.2 Antwort
HTTP-Status: 200 OK
JSON-Schema:
{
"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
{
"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:
# 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:
curl -s http://192.168.4.1/api/status | jq -r '.mode'
# Output: auto
Python – Balance-Überwachung:
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
GET /api/metrics HTTP/1.1
Host: 192.168.4.1
Parameter: Keine
8.5.2 Antwort
HTTP-Status: 200 OK
JSON-Schema:
{
"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
{
"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:
# 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:
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
GET /api/config HTTP/1.1
Host: 192.168.4.1
Parameter: Keine
8.6.2 Antwort
HTTP-Status: 200 OK
JSON-Schema:
{
"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
{
"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:
# 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:
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
GET /api/info HTTP/1.1
Host: 192.168.4.1
Parameter: Keine
8.7.2 Antwort
HTTP-Status: 200 OK
JSON-Schema:
{
"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
{
"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:
# 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:
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:
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
GET /api/wifi/status HTTP/1.1
Host: 192.168.4.1
Parameter: Keine
8.8.2 Antwort
HTTP-Status: 200 OK
JSON-Schema:
{
"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)
{
"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)
{
"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:
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:
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
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:
{
"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
{
"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)
{
"networks": [],
"count": 0
}
8.9.6 Verwendung
Bash – verfügbare Netzwerke auflisten:
curl -s http://192.168.4.1/api/wifi/scan | jq -r '.networks[] | "\(.ssid): \(.rssi) dBm (\(.encryption))"'
Ausgabe:
MyHomeNetwork: -45 dBm (secured)
GuestNetwork: -62 dBm (open)
Neighbor_WiFi: -78 dBm (secured)
Python – bestes Netzwerk finden:
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:
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
GET /api/hardware/config HTTP/1.1
Host: 192.168.4.1
Parameter: Keine
8.10.2 Antwort
HTTP-Status: 200 OK
JSON-Schema:
{
"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
{
"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:
curl -s http://192.168.4.1/api/hardware/config | jq '.'
Python – GPIO-Konflikte prüfen:
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:
{
"error": "Error message description"
}
Beispiele:
{
"error": "Not Found"
}
{
"error": "Failed to read configuration from NVS"
}
8.12 Anwendungsbeispiele
8.12.1 Statusüberwachung (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)
ACRouter Dashboard
ACRouter Dashboard
Mode
-
Grid Power
-
Dimmer
-
State
-
8.12.3 Export nach CSV (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
Verwandte Dokumentation
- 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 →