Перейти к содержимому

← Команды терминала | Содержание | Далее: Web API - POST →

8. Web API — GET-эндпоинты

Version: 1.0.0
Date: 2025-01-15

Детальная документация по REST API GET-эндпоинтам для мониторинга и получения системной информации от ACRouter.




Содержание




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/
http://192.168.4.1/api/

📋 Copy

http://192.168.4.1/api/
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

http://192.168.4.1/api/
Access-Control-Allow-Origin: *

8.3.1 Успешный ответ




8.3 Формат ответа


Content-Type: application/json

Структура:

json

📋 Copy

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


Content-Type: application/json

Структура:

json

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "error": "Error message description"
}

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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
GET /api/status HTTP/1.1
Host: 192.168.4.1

HTTP-статус: 200 OK


JSON-схема:

Структура:

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
# Poll every 2 seconds
while true; do
  curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer'
  sleep 2
done

📋 Copy

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
curl -s http://192.168.4.1/api/status | jq -r '.mode'
# Output: auto

📋 Copy

http://192.168.4.1/api/
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/status HTTP/1.1 Host: 192.168.4.1
GET /api/metrics HTTP/1.1
Host: 192.168.4.1

HTTP-статус: 200 OK


JSON-схема:

Структура:

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
# 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); // Обновить график (Chart.js, D3.js и т.д.) updateChart(chartData); }); } // Обновление каждые 2 секунды setInterval(updateMetrics, 2000);
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/status HTTP/1.1 Host: 192.168.4.1
GET /api/config HTTP/1.1
Host: 192.168.4.1

HTTP-статус: 200 OK


JSON-схема:

Структура:

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
# 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

http://192.168.4.1/api/
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/status HTTP/1.1 Host: 192.168.4.1
GET /api/info HTTP/1.1
Host: 192.168.4.1

HTTP-статус: 200 OK


JSON-схема:

Структура:

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
# 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

http://192.168.4.1/api/
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

http://192.168.4.1/api/
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/status HTTP/1.1 Host: 192.168.4.1
GET /api/wifi/status HTTP/1.1
Host: 192.168.4.1

HTTP-статус: 200 OK


JSON-схема:

Структура:

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
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

http://192.168.4.1/api/
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/status HTTP/1.1 Host: 192.168.4.1
GET /api/wifi/scan HTTP/1.1
Host: 192.168.4.1

HTTP-статус: 200 OK

HTTP-статус: 200 OK


JSON-схема:

Структура:

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "networks": [],
  "count": 0
}


bash

📋 Copy

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
curl -s http://192.168.4.1/api/wifi/scan | jq -r '.networks[] | "\(.ssid): \(.rssi) dBm (\(.encryption))"'

📋 Copy

http://192.168.4.1/api/
MyHomeNetwork: -45 dBm (secured)
GuestNetwork: -62 dBm (open)
Neighbor_WiFi: -78 dBm (secured)

📋 Copy

http://192.168.4.1/api/
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 Запрос

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); // Обновить график (Chart.js, D3.js и т.д.) updateChart(chartData); }); } // Обновление каждые 2 секунды setInterval(updateMetrics, 2000);
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/status HTTP/1.1 Host: 192.168.4.1
GET /api/hardware/config HTTP/1.1
Host: 192.168.4.1

HTTP-статус: 200 OK


8.10.3 Типы датчиков (SensorType)

Структура:

📋 Copy

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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


Код

{ "field1": "value1", "field2": 123, "field3": true }
{
  "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

Успешный запрос

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
curl -s http://192.168.4.1/api/hardware/config | jq '.'

Неверный формат запроса

http://192.168.4.1/api/
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

{ "field1": "value1", "field2": 123, "field3": true }
{
  "error": "Error message description"
}

07_COMMANDS_RU.md — справочник команд

{ "field1": "value1", "field2": 123, "field3": true }
{
  "error": "Not Found"
}
{ "field1": "value1", "field2": 123, "field3": true }
{
  "error": "Failed to read configuration from NVS"
}



8.12 Примеры использования


← Команды терминала

http://192.168.4.1/api/
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 →

html



    ACRouter Dashboard
    


    

ACRouter Dashboard

Mode
-
Grid Power
-
Dimmer
-
State
-


8.12.3 Export to CSV (Bash)

# Опрос каждые 2 секунды while true; do curl -s http://192.168.4.1/api/status | jq '.power_grid, .dimmer' sleep 2 done
#!/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




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

← Команды терминала | Содержание | Далее: Web API - POST →