Quay về trang chủ
Tài Liệu API
Hướng dẫn kết nối thiết bị phần cứng (ESP32 / IoT) với SmartSac Web Server để truyền nhận dữ liệu và điều khiển thời gian thực.

Giới Thiệu

SmartSac cung cấp hai nhóm API chính:

Base URL: https://hetcuu.com/smartsac

Xác Thực

Mỗi trạm sạc có một Station Token riêng (tạo từ trang Quản Lý Trạm). Gửi token theo một trong ba cách:

CáchVị tríVí dụ
BearerHeader AuthorizationAuthorization: Bearer SK_xxx
X-HeaderHeader tùy chỉnhX-Station-Token: SK_xxx
QueryURL parameter?token=SK_xxx
Không commit Station Token lên GitHub. Lưu trong Preferences hoặc EEPROM trên thiết bị.

Cấu Trúc Response

Mọi response đều là JSON với trường status:

{
  "status": "success" | "error",
  "message": "...",   // mô tả lỗi (khi status=error)
  "data": { ... }     // dữ liệu trả về (khi status=success)
}

Gửi Telemetry

POST /api/station/device/telemetry Gửi dữ liệu cảm biến từ thiết bị lên server

Gọi định kỳ (khuyến nghị 3–5 giây) để cập nhật telemetry. Server lưu vào Redis với TTL 60s.

Headers

HeaderGiá trị
Content-Typeapplication/json
AuthorizationBearer <station_token>

Body (JSON)

TrườngKiểuMô tả
pfloatCông suất (W)
vfloatĐiện áp đầu vào (V)
ifloatDòng điện (A)
dsfloatNhiệt độ DS18B20 — bộ sạc (°C)
mlxfloatNhiệt độ MLX90614 — vỏ bình (°C)
dht_tfloatNhiệt độ môi trường DHT (°C)
dht_hfloatĐộ ẩm môi trường (%)
statestringMã trạng thái sạc (xem bảng bên dưới)
state_textstringMô tả trạng thái tiếng Việt
charge_time_minfloatThời gian đã sạc (phút)
relay_onboolRelay đang bật?
chargingboolĐang sạc?
wifi_rssiintRSSI WiFi (dBm)
energy_session_kwhfloatĐiện năng phiên hiện tại (kWh)
energy_total_kwhfloatTổng điện năng tích lũy (kWh)

Response thành công

HTTP 200
{ "status": "success", "message": "Đã nhận telemetry", "station": 42 }

Nhận Config & Lệnh Điều Khiển

GET /api/station/device/config Lấy cấu hình và lệnh điều khiển từ server

Gọi định kỳ (khuyến nghị 7–10 giây). Server trả về cấu hình mới nhất và lệnh điều khiển (nếu có).

Response (data object)

{
  "status": "success",
  "data": {
    "station_name": "Trạm Sạc 01",
    "config": {
      "wait_time": 60,          // phút chờ trước khi sạc
      "measure_interval": 300,  // giây xác nhận đầy
      "threshold_w": 10.0,      // ngưỡng đầy (W)
      "limit_input_w": 1000,    // công suất tối đa (W)
      "max_temp_charger": 55,   // nhiệt ngắt DS (°C)
      "max_temp_battery": 55,   // nhiệt ngắt MLX (°C)
      "max_temp_env": 45,       // nhiệt ngắt môi trường (°C)
      "max_humidity": 85,       // độ ẩm ngắt (%)
      "max_time_h": 10,         // giới hạn giờ sạc
      "battery_type": "lead",   // loại pin: lead | li-ion
      "capacity_ah": 20,        // dung lượng (Ah)
      "output_a": 3.0           // dòng sạc (A)
    },
    "command": {
      "action": "charge_now"    // charge_now | charge_wait | charge_stop | ""
    },
    "telegram": {
      "enabled": true,
      "token": "123:ABC...",
      "chat_id": "987654321"
    }
  }
}
Sau khi thực hiện lệnh action, thiết bị nên gửi telemetry ngay để server cập nhật trạng thái.

Ví dụ — ESP32 (Arduino / C++)

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* SERVER    = "https://hetcuu.com/smartsac";
const char* TOKEN     = "SK_YOUR_TOKEN_HERE";   // lấy từ trang Quản Lý Trạm

// ── Gửi telemetry ──────────────────────────────────────────
bool postTelemetry(float p, float v, float i, float ds,
                   float mlx, float dht_t, float dht_h,
                   const char* state, bool charging) {
    HTTPClient http;
    http.begin(String(SERVER) + "/api/station/device/telemetry");
    http.setTimeout(5000);
    http.addHeader("Content-Type",  "application/json");
    http.addHeader("Authorization", String("Bearer ") + TOKEN);

    StaticJsonDocument<512> doc;
    doc["p"] = p; doc["v"] = v; doc["i"] = i;
    doc["ds"] = ds; doc["mlx"] = mlx;
    doc["dht_t"] = dht_t; doc["dht_h"] = dht_h;
    doc["state"] = state;
    doc["charging"] = charging;

    String body; serializeJson(doc, body);
    int code = http.POST(body);
    http.end();
    return code == 200;
}

// ── Lấy config & lệnh điều khiển ──────────────────────────
String fetchCommand() {
    HTTPClient http;
    http.begin(String(SERVER) + "/api/station/device/config");
    http.setTimeout(5000);
    http.addHeader("Authorization", String("Bearer ") + TOKEN);

    int code = http.GET();
    if (code != 200) { http.end(); return ""; }

    String body = http.getString();
    http.end();

    StaticJsonDocument<2048> doc;
    if (deserializeJson(doc, body)) return "";

    return doc["data"]["command"]["action"] | "";
}

// ── Loop ───────────────────────────────────────────────────
unsigned long lastTelemetryMs = 0, lastConfigMs = 0;

void loop() {
    unsigned long now = millis();

    if (now - lastTelemetryMs >= 3000) {
        postTelemetry(readPower(), readVoltage(), readCurrent(),
                      readTempDS(), readTempMLX(), readTempDHT(),
                      readHumDHT(), currentStateCode(), isCharging);
        lastTelemetryMs = now;
    }

    if (now - lastConfigMs >= 7000) {
        String cmd = fetchCommand();
        if      (cmd == "charge_now")  startChargingNow();
        else if (cmd == "charge_wait") setWaitMode();
        else if (cmd == "charge_stop") stopAll();
        lastConfigMs = now;
    }
}

Ví dụ — Python

import requests, time

SERVER = "https://hetcuu.com/smartsac"
TOKEN  = "SK_YOUR_TOKEN_HERE"
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}

def post_telemetry(data: dict):
    r = requests.post(f"{SERVER}/api/station/device/telemetry",
                      json=data, headers=HEADERS, timeout=5)
    return r.json()

def get_command() -> str:
    r = requests.get(f"{SERVER}/api/station/device/config",
                     headers=HEADERS, timeout=5)
    return r.json().get("data", {}).get("command", {}).get("action", "")

# Ví dụ vòng lặp
while True:
    post_telemetry({"p": 150, "v": 220, "i": 0.68,
                    "ds": 38.5, "mlx": 35.2,
                    "dht_t": 30, "dht_h": 65,
                    "state": "DANG_SAC", "charging": True})
    cmd = get_command()
    if cmd: print("Lệnh từ server:", cmd)
    time.sleep(3)

Ví dụ — cURL

# Gửi telemetry
curl -X POST https://hetcuu.com/smartsac/api/station/device/telemetry \
  -H "Authorization: Bearer SK_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"p":120,"v":220,"i":0.55,"ds":36,"mlx":33,"dht_t":28,"dht_h":70,"state":"DANG_SAC","charging":true}'

# Lấy config và lệnh
curl https://hetcuu.com/smartsac/api/station/device/config \
  -H "Authorization: Bearer SK_YOUR_TOKEN"

Mã Trạng Thái Sạc

Mã (state)Ý nghĩaRelay
DANG_SACĐang sạc bình thườngON
DANG_DOĐang đo công suất (probe)ON
SAC_CHOChờ sạc (auto, đếm ngược)OFF
FULLNgắt: pin đầyOFF
NGAT_NHIETNgắt: quá nhiệtOFF
NGAT_DO_AMNgắt: độ ẩm quá caoOFF
NGAT_QUA_GIONgắt: quá thời gian giới hạnOFF
NGAT_QUA_CONG_SUATNgắt: công suất vượt ngưỡngOFF
LOI_CAM_BIENLỗi cảm biến (DS/MLX/PZEM)OFF
MAT_KET_NOIThiết bị mất kết nối >60s

HTTP Status Codes

CodeÝ nghĩa
200Thành công
400Dữ liệu gửi lên thiếu hoặc sai định dạng
401Thiếu token hoặc token không hợp lệ
404Không tìm thấy trạm ứng với token này
503Tính năng tạm tắt (ví dụ: AI đang bảo trì)
500Lỗi server nội bộ