← Команды терминала | Содержание | Далее: Web API - POST →
8. Web API — GET-эндпоинты
Version: 1.0.0
Date: 2025-01-15
Детальная документация по REST API GET-эндпоинтам для мониторинга и получения системной информации от ACRouter.
Содержание
- 8.1 Введение
- 8.2 Базовый URL и аутентификация
- 8.3 Формат ответа
- 8.4 Эндпоинт: GET /api/status
- 8.5 Эндпоинт: GET /api/metrics
- 8.6 Эндпоинт: GET /api/config
- 8.7 Эндпоинт: GET /api/info
- 8.8 Эндпоинт: GET /api/wifi/status
- 8.9 Эндпоинт: GET /api/wifi/scan
- 8.10 Эндпоинт: GET /api/hardware/config
- 8.11 Коды ошибок HTTP
- 8.12 Примеры использования
8.1 Введение
REST API ACRouter предоставляет набор GET-эндпоинтов для:
- Мониторинга — получение текущего статуса роутера и метрик мощности
- Конфигурации — чтение системных параметров
- Диагностики — системная информация, статус WiFi, конфигурация железа
Все эндпоинты возвращают данные в формате JSON.
Реализация: components/comm/src/WebServerManager.cpp
Быстрый старт: базовые примеры использования — в разделе «Справочник REST API» файла 07_COMMANDS_RU.md. 8.2 Базовый URL и аутентификация section "REST API Reference" for basic usage examples.
8.2 Базовый URL и аутентификация
python
📋 Copy
http://192.168.4.1/api/
📋 Copy
http:///api/
⚠️ Важно: REST API не требует аутентификации. Все эндпоинты доступны без пароля.
Рекомендации по безопасности: - Используйте отдельную WiFi-сеть для IoT-устройств - Настройте правила брандмауэра для ограничения доступа - Не открывайте порт 80 во внешние сети - Базовая аутентификация запланирована в следующих версиях
8.2.3 CORS
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
Заголовок ответа:
python
📋 Copy
Access-Control-Allow-Origin: *
8.3.1 Успешный ответ
8.3 Формат ответа
Content-Type: application/json
Структура:
json
📋 Copy
{
"field1": "value1",
"field2": 123,
"field3": true
}
Content-Type: application/json
Структура:
json
📋 Copy
{
"error": "Error message description"
}
📋 Copy
{
"error": "Not Found"
}
8.4 Эндпоинт: GET /api/status
Получить полный статус роутера: режим работы, состояние контроллера, мощность сети и уровень диммера.
8.4 Эндпоинт: GET /api/status
http
📋 Copy
GET /api/status HTTP/1.1
Host: 192.168.4.1
HTTP-статус: 200 OK
JSON-схема:
Структура:
📋 Copy
{
"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)
}
Тип
| Описание | Возможные значения | mode |
string |
|---|---|---|---|
| Режим работы роутера | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
state |
string |
| Состояние контроллера | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
power_grid |
float |
| Мощность сети в Ваттах. Положительная = импорт из сети (потребление), отрицательная = экспорт в сеть (избыток) | -∞ .. +∞ |
dimmer |
integer |
| Текущий уровень диммера в процентах | 0 .. 100 |
target_level |
integer |
| Целевой уровень диммера (для режимов AUTO, ECO, OFFGRID) | 0 .. 100 |
control_gain |
integer |
| Коэффициент усиления контура управления | -∞ .. +∞ |
balance_threshold |
float |
| Порог баланса в Ваттах (для режима AUTO) | -∞ .. +∞ |
valid |
boolean |
Корректность данных измерений. false = датчики не инициализированы или ошибка |
true / false |
uptime |
integer |
| Время работы с момента загрузки в секундах | 0 .. 100 |
free_heap |
integer |
| Свободная RAM в байтах | 0 .. 100 |
8.4.4 Пример ответа | integer |
📋 Copy
{
"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
bash
📋 Copy
# Poll every 2 seconds
while true; do
curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer'
sleep 2
done
📋 Copy
curl -s http://192.168.4.1/api/status | jq -r '.mode'
# Output: auto
📋 Copy
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 Эндпоинт: GET /api/metrics
http
📋 Copy
GET /api/metrics HTTP/1.1
Host: 192.168.4.1
HTTP-статус: 200 OK
JSON-схема:
Структура:
📋 Copy
{
"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)
}
Тип
| Описание | Возможные значения | mode |
|---|---|---|
| Мощность сети (Вт). Положительная = импорт, отрицательная = экспорт | -∞ .. +∞ |
integer |
| Текущий уровень диммера (0–100%) | 0 .. 100 |
integer |
| Целевой уровень диммера (0–100%) | 0 .. 100 |
integer |
| Время с момента загрузки в миллисекундах | 0 .. 100 |
json |
📋 Copy
{
"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
bash
📋 Copy
# Poll every second (minimal traffic)
while true; do
curl -s http://192.168.4.1/api/metrics | jq '.metrics'
sleep 1
done
📋 Copy
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);
/api/status
/api/metrics |
Размер ответа | ~250 байт |
|---|---|---|
| ~80 байт | Количество полей | 10 полей |
| 3 поля + timestamp | Применение | Полная информация |
| Мониторинг в реальном времени | Частота опроса | 5–10 секунд |
| 1–2 секунды | 8.6 Эндпоинт: GET /api/config | Получить все параметры конфигурации системы, сохранённые в NVS. |
8.6 Эндпоинт: GET /api/config
http
📋 Copy
GET /api/config HTTP/1.1
Host: 192.168.4.1
HTTP-статус: 200 OK
JSON-схема:
Структура:
📋 Copy
{
"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%)
}
Тип
| Описание | Возможные значения | Описание | control_gain |
mode |
|---|---|---|---|---|
| Коэффициент усиления контура управления | -∞ .. +∞ |
float | balance_threshold |
balance_threshold |
| Порог баланса в Ваттах (для режима AUTO) | -∞ .. +∞ |
boolean | voltage_coef |
float |
0.1 .. 10.0 |
-∞ .. +∞ |
Калибровочный коэффициент напряжения | current_coef |
float |
0.1 .. 100.0 |
-∞ .. +∞ |
Коэффициент преобразования тока (А/В) | current_threshold |
float |
0.01 .. 10.0 |
-∞ .. +∞ |
Порог обнаружения тока (А) | power_threshold |
float |
1.0 .. 1000.0 |
-∞ .. +∞ |
float | router_mode |
integer |
0 .. 5 |
0 .. 100 |
Режим роутера: 0=OFF, 1=AUTO, 2=ECO, 3=OFFGRID, 4=MANUAL, 5=BOOST | manual_level |
integer |
0 .. 100 |
0 .. 100 |
integer | 8.6.4 Пример ответа | json |
📋 Copy
{
"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)
bash
📋 Copy
# 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
📋 Copy
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 Эндпоинт: GET /api/info
http
📋 Copy
GET /api/info HTTP/1.1
Host: 192.168.4.1
HTTP-статус: 200 OK
JSON-схема:
Структура:
📋 Copy
{
"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)
}
Тип
| Описание | Возможные значения | mode |
|---|---|---|
| Версия прошивки ACRouter (формат: «X.Y.Z») | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
ACRouter firmware version (format: "X.Y.Z") |
| Тип микроконтроллера (обычно «ESP32») | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
Microcontroller type (typically "ESP32") |
| Размер Flash-памяти в байтах | 0 .. 100 |
integer |
| Свободная RAM в байтах | 0 .. 100 |
8.4.4 Пример ответа |
| Время работы с момента загрузки в секундах | 0 .. 100 |
integer |
| Время работы с момента загрузки в секундах | 0 .. 100 |
free_heap |
📋 Copy
{
"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)
bash
📋 Copy
# 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
📋 Copy
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)
📋 Copy
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 Эндпоинт: GET /api/wifi/status
http
📋 Copy
GET /api/wifi/status HTTP/1.1
Host: 192.168.4.1
HTTP-статус: 200 OK
JSON-схема:
Структура:
📋 Copy
{
"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
}
Тип
| Описание | Возможные значения | mode |
string |
|---|---|---|---|
| Состояние контроллера | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
ap_active |
boolean |
| Точка доступа активна | true / false |
ap_ssid |
integer |
Имя AP (формат: ACRouter_XXXXXX) |
"off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
ap_ip |
string |
IP-адрес AP (обычно 192.168.4.1) |
"off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
ap_clients |
string |
| Количество клиентов, подключённых к AP | 0 .. 100 |
sta_connected |
boolean |
| Подключено к WiFi-сети как клиент | true / false |
sta_ssid |
integer |
| Имя WiFi-сети | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
sta_ip |
string |
| IP-адрес, полученный от DHCP | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
rssi |
string |
| Уровень сигнала WiFi в дБм | 0 .. 100 |
has_saved_credentials |
boolean |
| Учётные данные сохранены в NVS | true / false |
mac |
integer |
MAC-адрес устройства (формат: XX:XX:XX:XX:XX:XX) |
"off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
hostname |
string |
| Имя хоста устройства | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
Оценка уровня сигнала (RSSI): | string |
Качество
| Описание | от -30 до -50 | mode |
|---|---|---|
| Очень сильный сигнал | от -51 до -70 | Хороший |
| Стабильное соединение | от -71 до -85 | Удовлетворительный |
| Возможны кратковременные обрывы | от -86 до -100 | Плохой |
| Нестабильное соединение | 8.8.4 Пример ответа (AP + STA активны) | json |
📋 Copy
{
"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
📋 Copy
{
"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"
}
bash
📋 Copy
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
📋 Copy
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 Эндпоинт: GET /api/wifi/scan
http
📋 Copy
GET /api/wifi/scan HTTP/1.1
Host: 192.168.4.1
HTTP-статус: 200 OK
HTTP-статус: 200 OK
JSON-схема:
Структура:
📋 Copy
{
"networks": [
{
"ssid": "string", // Network name
"rssi": 0, // Signal strength (dBm)
"encryption": "string", // Encryption type
"channel": 0 // Channel number
}
],
"count": 0 // Number of networks found
}
Тип
| Описание | Возможные значения | mode |
|---|---|---|
| Массив найденных сетей | networks[].ssid |
string |
| Имя WiFi-сети | "off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
sta_ip |
| Уровень сигнала в дБм | 0 .. 100 |
string |
Тип шифрования: "open" или "secured" |
"off", "auto", "eco", "offgrid", "manual", "boost", "unknown" |
integer |
| Номер WiFi-канала (1–14) | 0 .. 100 |
integer |
| Общее количество найденных сетей | 0 .. 100 |
json |
📋 Copy
{
"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
}
📋 Copy
{
"networks": [],
"count": 0
}
bash
📋 Copy
curl -s http://192.168.4.1/api/wifi/scan | jq -r '.networks[] | "\(.ssid): \(.rssi) dBm (\(.encryption))"'
📋 Copy
MyHomeNetwork: -45 dBm (secured)
GuestNetwork: -62 dBm (open)
Neighbor_WiFi: -78 dBm (secured)
📋 Copy
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")
8.10.1 Запрос
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 Эндпоинт: GET /api/hardware/config
8.10.2 Ответ
HTTP-статус: 200 OK
GET /api/hardware/config HTTP/1.1
Host: 192.168.4.1
HTTP-статус: 200 OK
8.10.3 Типы датчиков (SensorType)
Структура:
📋 Copy
{
"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
}
Не используется
| 1 | ZMPT107 |
mode |
|---|---|---|
| 2 | SCT013 |
Датчик тока SCT-013 (трансформатор) |
| 3 | ACS712 |
Датчик тока ACS712 (эффект Холла) |
| 8.10.4 Пример ответа | json | 📋 Copy |
| { "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 } | Интерпретация: - ADC канал 0: GPIO 34, датчик напряжения ZMPT107 - ADC канал 1: GPIO 35, датчик тока SCT013 - ADC канал 2: GPIO 32, датчик тока ACS712 - ADC канал 3: не используется - Диммер 1: GPIO 19 (активен) - Диммер 2: GPIO 23 (отключён) - Zero-cross: GPIO 18 (активен) - Реле 1-2: отключены | 8.11 Коды ошибок HTTP |
Код
{
"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
OK
Успешный запрос
curl -s http://192.168.4.1/api/hardware/config | jq '.'
Неверный формат запроса
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
| 1 | 500 | mode |
Внутренняя ошибка сервера |
|---|---|---|---|
| Ошибка чтения NVS | 501 | Not Implemented | Функция не реализована |
| GET /api/calibrate | Формат ошибки: | json | 📋 Copy |
| { "error": "Описание ошибки" } | 8.12 Примеры использования | 8.12.1 Мониторинг статуса (Python) | python |
| 📋 Copy | 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 — нажмите Ctrl+C для остановки") 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'] power_str = f"{power:+7.1f} Вт" if power > 0: direction = "ИМПОРТ" elif power < 0: direction = "ЭКСПОРТ" else: direction = "БАЛАНС" print(f"[{timestamp}] {mode:8} | {state:11} | {power_str} {direction:7} | Диммер: {dimmer:3}%") time.sleep(interval) except KeyboardInterrupt: print("\nМониторинг остановлен") # Использование monitor = ACRouterMonitor("http://192.168.4.1") monitor.monitor_loop(interval=2) | 8.12.2 Панель управления (JavaScript + HTML) | html |
| 📋 Copy | Not Implemented | 8.12.3 Экспорт в CSV (Bash) | bash |
📋 Copy
{
"error": "Error message description"
}
07_COMMANDS_RU.md — справочник команд
{
"error": "Not Found"
}
{
"error": "Failed to read configuration from NVS"
}
8.12 Примеры использования
← Команды терминала
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)
Далее: Web API - POST →
ACRouter Dashboard
ACRouter Dashboard
Mode
-
Grid Power
-
Dimmer
-
State
-
8.12.3 Export to 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
Related Documentation
- 01_OVERVIEW.md - Project overview
- 03_STRUCTURE.md - Application architecture
- 07_COMMANDS.md - Commands Reference (RU)
- 8.2 Базовый URL и аутентификация - Commands Reference (EN)
- 09_WEB_API_POST.md - Web API POST endpoints (next section)
Firmware Version: 1.0.0
Last Updated: 2025-01-15