GemeOpen GSPM1B × Home Assistant × Python/React Demo

把 GemeOpen GSPM1B 智能转换器插座 接入 Home Assistant,实现 通断电控制 与
电压 / 电流 / 功率 / 累计用电量 采集;并附一套 Python(FastAPI) + React(Vite) 的完整自研 Demo。

面向程序员初学者:文档从零讲起,每一步都可直接复制执行。

工程源码下载地址
https://smart-bird-oss.smart-bird.cn/document/2026/09/27/1107261215687071.zip


✨ 能力一览

能力Home Assistant自研 Demo
通断电开关✅ switch✅ Web 开关
实时电压/电流/功率✅ sensor✅ 实时卡片
累计用电量✅ sensor(能源面板)✅ 卡片
历史曲线✅ History graph✅ recharts 折线
实时推送—✅ WebSocket
需要写代码❌ 仅 YAML✅ Python + React

🏗 架构

GSPM1B ──MQTT──► Mosquitto Broker ◄──MQTT── Home Assistant (路径 A, 零代码)
                        ▲
                        └──MQTT── Python 后端 ──REST/WS── React 前端 (路径 B, 自研 Demo)

📁 目录结构

gemeopen-ha-demo/
├── README.md                     # 本文件
├── docker-compose.yml            # 一键启动 Mosquitto + 后端 + 前端
├── docs/                         # 全部中文文档
│   ├── 00-architecture.md        # 架构与接口契约(基准)
│   ├── 01-overview.md            # 方案总览(先读)
│   ├── 02-device-setup.md        # 设备端 MQTT 配置
│   ├── 03-homeassistant.md       # Home Assistant 接入
│   ├── 04-backend.md             # Python 后端说明
│   ├── 05-frontend.md            # React 前端说明
│   ├── 06-deploy-ops.md          # 部署与运维
│   └── 07-troubleshooting.md     # 排错手册
├── homeassistant/                # HA 配置片段
│   ├── mqtt-gspm1b.yaml          # switch + sensor 实体定义
│   └── dashboard.yaml            # Lovelace 仪表盘
├── backend/                      # Python FastAPI 后端
├── frontend/                     # React 前端
├── scripts/                      # 设备配置脚本
│   ├── configure_device.py       # 把设备切到自建 Broker
│   └── device_switch.example.json
└── mosquitto/                    # MQTT Broker 配置
    └── mosquitto.conf

🚀 快速开始

# 1) 启动 Broker + 后端 + 前端
docker compose up -d --build

# 2) 把设备切换到你的 Broker(编辑 scripts/device_switch.json 后执行)
cd scripts && cp device_switch.example.json device_switch.json
python3 configure_device.py --config device_switch.json
#   成功后给设备断电重启

# 3) 开启设备定时上报(示例 15 秒)
mosquitto_pub -h <你的IP> -p 1883 \
  -t 'gemeopen/gspm1b/<MAC>/command' \
  -m '{"messageId":"1","timerEnable":1,"timerInterval":15,"type":"setting"}'

# 4) 打开自研 Demo
#    http://<你的IP>:8080

# 5) 接入 Home Assistant:见 docs/03-homeassistant.md

📖 文档路线(建议顺序)

  1. [01 · 方案总览] docs/01-overview.md
  2. [02 · 设备端配置] docs/02-device-setup.md
  3. 按需选择:
    • Home Assistant 用户 → [03 · HA 接入] docs/03-homeassistant.md
    • 开发者 → [04 · Python 后端] docs/04-backend.md)、[05 · React 前端] 浏览工程包 docs/05-frontend.md
  4. 上线 → [06 · 部署与运维] docs/06-deploy-ops.md
  5. 遇问题 → [07 · 排错手册] docs/07-troubleshooting.md

⚠️ 三个最重要的提醒

  1. 主题语义反直觉:设备 publish 主题是你要订阅的;设备 subcribe 主题是你要发布指令的。
  2. Broker 地址设备要能访问:设备端填的必须是你服务器的局域网 IP / 公网域名,不能是 localhost。
  3. 切换 MQTT 后需重启设备生效。

🔧 环境要求

组件版本
Docker / Docker Compose24+
Python(跑后端/脚本)3.11+
Node(跑前端)18+ / 20+
Home Assistant任意近期版本

📄 说明

  • 本工程为教学示例,生产使用请参考 [06 · 部署与运维] docs/06-deploy-ops.md 的安全清单(密码认证、HTTPS、最小权限等)。
  • 设备型号协议以 GemeOpen 官方开发文档为准。

工程包说明

00-architecture.md

00 · 架构与接口契约(基准文档)

本文是整个工程的基准契约。所有子模块(Home Assistant 配置、Python 后端、React 前端)都必须严格遵守本文件定义的主题名、消息格式与 API 字段名。

1. 总体架构

┌─────────────┐   MQTT    ┌──────────────────┐   MQTT    ┌──────────────────────┐
│  GSPM1B     │ ────────► │  Mosquitto       │ ◄──────── │  Home Assistant      │
│  智能插座    │ ◄──────── │  (自建 Broker)    │ ────────► │  MQTT 集成           │
└─────────────┘           │                  │           │  switch + sensor     │
                          │                  │           └──────────────────────┘
                          │                  │   MQTT    ┌──────────────────────┐
                          │                  │ ◄──────── │  Python 后端 (FastAPI)│
                          │                  │ ────────► │  MQTT ⇄ REST/WebSocket│
                          └──────────────────┘           └──────────┬───────────┘
                                                                    │ HTTP / WS
                                                         ┌──────────▼───────────┐
                                                         │  React 前端 (Vite)    │
                                                         └──────────────────────┘

两条并行的消费路径(互不影响):

  • 路径 A(面向最终用户):Home Assistant 直接通过 MQTT 集成接入,无需自研代码。
  • 路径 B(面向二次开发):Python + React Demo,演示如何自建一套 Web 控制台。

2. 设备通信配置(出厂默认 → 自建 Broker)

设备出厂默认连接 GemeOpen 厂家 MQTT 服务器。接入自建 Broker 需在原厂通道下发 setting-mqtt 指令(详见 docs/02-device-setup.md)。

setting-mqtt 指令:

{
  "clientId": "gspm1b-28372fcbbbb8",
  "messageId": "20260520120000001",
  "password": "device-pass",
  "port": "1883",
  "protocol": "mqtt",
  "publish": "gemeopen/gspm1b/28372fcbbbb8/report",
  "server": "192.168.1.10",
  "subcribe": "gemeopen/gspm1b/28372fcbbbb8/command",
  "type": "custom",
  "username": "device"
}

⚠️ 语义(易错,务必按此理解)

  • publish = 设备发布数据的主题 → 服务端订阅它来接收上报(本项目记作 reportTopic)。
  • subcribe = 设备订阅的主题 → 服务端发布指令到它来控制设备(本项目记作 commandTopic)。

3. MQTT 主题约定

名称默认值方向
reportTopicgemeopen/gspm1b/{mac}/report设备 → 服务端(上行,服务端订阅)
commandTopicgemeopen/gspm1b/{mac}/command服务端 → 设备(下行,服务端发布)

HA 与 Python 后端使用同一套主题;两者各自用独立 clientId 连接 Broker。

4. 指令与消息契约(JSON)

4.1 下行指令(服务端 → 设备,发到 commandTopic)

功能payload说明
通断电控制{"key":1,"messageId":"<id>","type":"event"}key=1 通电,key=0 断电
查询实时电量{"messageId":"<id>","type":"statistic"}触发一次实时数据回传
设置上报频率{"messageId":"<id>","timerEnable":1,"timerInterval":15,"type":"setting"}自动上报开关与周期(5~86400 秒)
获取设备信息{"messageId":"<id>","type":"info"}返回固件、IP、信号等
恢复出厂{"messageId":"<id>","system":"reset","type":"setting"}谨慎

4.2 上行消息(设备 → 服务端,来自 reportTopic)

A. 定时自动上报(device-timer-task)

{
  "commandName": "device-timer-task",
  "mac": "28372fcbbbb8",
  "messageId": "",
  "source": "auto",
  "key": 1,
  "voltage": 226.024,
  "current": 0.501,
  "power": 113.4,
  "energy": 25.047
}

B. 指令响应(controller-event / info-statistic / info-all)

{
  "commandName": "info-statistic",
  "mac": "28372fcbbbb8",
  "messageId": "20260520120000001",
  "source": "command",
  "key": 1,
  "voltage": 226.024,
  "current": 0.501,
  "power": 113.4,
  "energy": 25.047
}

字段语义与单位

设备字段含义单位归一化字段(本项目统一命名)
key通断电状态(1 通电 / 0 断电)—relayOn (boolean)
voltage电压VvoltageV
current电流AcurrentA
power有功功率WactivePowerW
energy累计用电量(断电不归零)kW·henergyKwh
signal信号强度dBmsignalDbm
commandName指令名—commandName
source来源 command/auto/button—source

5. Python 后端 API 契约(供 React 前端调用)

Base URL:http://<host>:8000

5.1 GET /api/health

{ "status": "ok", "mqttConnected": true, "deviceOnline": true }

5.2 GET /api/device

返回当前设备状态快照 DeviceState:

{
  "mac": "28372fcbbbb8",
  "online": true,
  "relayOn": true,
  "voltageV": 226.024,
  "currentA": 0.501,
  "activePowerW": 113.4,
  "energyKwh": 25.047,
  "signalDbm": -75,
  "source": "auto",
  "lastUpdate": 1787992225
}

lastUpdate 为秒级 Unix 时间戳;无数据时各数值字段为 null。

5.3 POST /api/device/switch

请求:{ "on": true } → 响应:{ "success": true, "state": <DeviceState> }

5.4 POST /api/device/refresh

触发一轮 info + statistic 查询,响应:{ "success": true }

5.5 GET /api/device/history?limit=200

返回采样历史(时间升序):

[ { "ts": 1787992225, "voltageV": 226.024, "currentA": 0.501, "activePowerW": 113.4, "energyKwh": 25.047, "relayOn": true } ]

5.6 GET /api/config

返回非敏感运行配置:{ "reportTopic": "...", "commandTopic": "...", "mac": "..." }

5.7 WS /ws/telemetry

WebSocket,每次设备状态更新时推送一帧 DeviceState(与 5.2 同结构)。

6. 后端环境变量(.env)

变量默认值说明
MQTT_HOST127.0.0.1Broker 地址
MQTT_PORT1883Broker 端口
MQTT_USERNAMEbackend后端连接 Broker 的用户名
MQTT_PASSWORDbackend-pass后端密码
MQTT_CLIENT_IDgemeopen-backend后端 clientId(唯一)
MQTT_REPORT_TOPICgemeopen/gspm1b/+/report订阅(+ 通配单设备)
MQTT_COMMAND_TOPICgemeopen/gspm1b/{mac}/command发布指令
DEVICE_MAC28372fcbbbb8目标设备 MAC
HISTORY_SIZE2000内存中保留的采样条数
CORS_ORIGINS*允许的前端来源

7. 前端约定

  • 构建工具:Vite + React 18
  • 状态来源:REST 轮询(/api/device)+ WebSocket(/ws/telemetry)实时推送
  • API Base:环境变量 VITE_API_BASE(默认 http://localhost:8000)
  • 展示内容:通断电开关、电压/电流/功率实时值、累计用电量、在线状态、简易历史曲线

8. 目录结构

gemeopen-ha-demo/
├── README.md                 # 总览与快速开始
├── docker-compose.yml        # Mosquitto + 后端 + 前端
├── docs/
│   ├── 00-architecture.md    # 本文件(契约)
│   ├── 01-overview.md        # 方案总览(初学者向)
│   ├── 02-device-setup.md    # 设备端 MQTT 配置
│   ├── 03-homeassistant.md   # Home Assistant 接入
│   ├── 04-backend.md         # Python 后端说明
│   ├── 05-frontend.md        # React 前端说明
│   ├── 06-deploy-ops.md      # 部署与运维
│   └── 07-troubleshooting.md # 排错手册
├── homeassistant/            # HA 配置片段
├── backend/                  # Python FastAPI 后端
├── frontend/                 # React 前端
├── scripts/                  # 设备配置脚本
└── mosquitto/                # Broker 配置

01-overview.md

01 · 方案总览(初学者先读这篇)

1. 这个项目要解决什么?

GemeOpen GSPM1B 智能转换器插座支持二次开发(MQTT/TCP)。本工程教你把它接入 Home Assistant,
实现:

  • ✅ 通断电控制(开 / 关)
  • ✅ 实时电压、电流、功率采集
  • ✅ 累计用电量查询
  • ✅(加分)一套 Python 后端 + React 前端的自研 Demo,演示如何自己写控制台

2. 两条接入路径(任选,也可都做)

                 ┌──────────────────────────────────────────┐
   GSPM1B ──MQTT─┤            Mosquitto Broker               │
   (设备)         └───────┬───────────────────────┬───────────┘
                          │ MQTT                  │ MQTT
                 ┌────────▼─────────┐    ┌────────▼──────────────┐
                 │ 路径 A            │    │ 路径 B                 │
                 │ Home Assistant   │    │ Python 后端 (FastAPI)  │
                 │ MQTT 集成        │    │   ⇅ REST / WebSocket   │
                 │ switch + sensor  │    │ React 前端 (Vite)      │
                 └──────────────────┘    └────────────────────────┘
                    无需写代码               适合学习/二次开发
  • 路径 A(Home Assistant):零代码,靠 YAML 配置。日常使用推荐。
  • 路径 B(Python + React):完整可运行 Demo,适合程序员学习 MQTT、FastAPI、React 全栈。

3. 你需要准备什么

准备项说明
硬件1 台 GSPM1B 插座;一个能连 2.4GHz WiFi 的网络
服务器/电脑跑 Mosquitto(和 Home Assistant)的机器,建议 Linux / 树莓派 / NAS
软件Docker(推荐);Node 18+、Python 3.11+(跑 Demo 用)
账号信息设备当前 Broker 的接入信息(见 02 文档)

4. 快速开始(5 步)

# ① 启动 Broker + 后端 + 前端(一条命令)
cd gemeopen-ha-demo
docker compose up -d --build

# ② 把设备切到你的 Broker(改成你的实际参数后执行)
cd scripts && cp device_switch.example.json device_switch.json
python3 configure_device.py --config device_switch.json
# 成功后给设备断电重启

# ③ 让设备定时上报(示例 15 秒)
mosquitto_pub -h <你的IP> -p 1883 -t 'gemeopen/gspm1b/<MAC>/command' \
  -m '{"messageId":"1","timerEnable":1,"timerInterval":15,"type":"setting"}'

# ④ 打开自研 Demo 前端
#    浏览器访问 http://<你的IP>:8080   → 能看数据、能开关

# ⑤ 接入 Home Assistant(详见 docs/03)
#    - MQTT 集成连接同一 Broker
#    - 引入 homeassistant/mqtt-gspm1b.yaml

5. 文档导航

文档内容适合
[02 · 设备端配置] 02-device-setup.md把设备指向自建 Broker必读
[03 · Home Assistant 接入] 03-homeassistant.mdHA 集成 + 实体 + 仪表盘 + 自动化路径 A
[04 · Python 后端] 04-backend.mdFastAPI + MQTT 代码说明路径 B
[05 · React 前端] 05-frontend.md前端组件与运行路径 B
[06 · 部署与运维] 06-deploy-ops.md三种部署方式、备份、监控上线
[07 · 排错手册] 07-troubleshooting.md按症状排查遇问题
[00 · 架构与契约] 00-architecture.md主题/消息/API 契约(基准)开发

6. 关键概念 30 秒速通

  • MQTT:一种轻量发布/订阅消息协议。设备把数据“发布”到某个“主题”,其他程序“订阅”该主题即可收到。
  • Broker(Mosquitto):消息中转站。设备、HA、后端都连它,彼此不直接通信。
  • Topic(主题):类似“频道名”。本项目用 gemeopen/gspm1b/<mac>/report(设备发)与 .../command(设备收)。
  • Home Assistant:开源智能家居平台,通过 MQTT 集成把设备变成可控制的“实体”。

⚠️ 最容易踩的坑:GemeOpen 文档里的 publish / subcribe 与直觉相反——
设备的 publish 主题是你要订阅的,subcribe 主题是你要发布指令的。详见 [02] 02-device-setup.md


02-device-setup.md

02 · 设备端 MQTT 配置(把 GSPM1B 指向自建 Broker)

目标:让 GSPM1B 把数据发到你自己的 MQTT Broker(Mosquitto),这样 Home Assistant 和 Python 后端才能读到数据、发出控制指令。

1. 为什么需要这一步?

GSPM1B 出厂时默认连接 GemeOpen 厂家测试服务器(mqtt.smart-bird.cn:1883),免费供调试。要让 HA 接管,就需要把设备改为连接你自己的 Broker。

设备提供了专门的指令 setting-mqtt(自定义 MQTT 参数)来完成这件事。

2. 准备工作

你需要先知道设备当前所在 Broker 的连接信息,通过设备指令 info-protocol 获取:

字段含义用途
server / port当前 Broker 地址/端口连接它来下发切换指令
username当前 Broker 用户名连接凭据
publish设备发布主题(服务端订阅它收数据)记为 report_topic
subcribe设备订阅主题(服务端向它发指令)记为 command_topic

⚠️ 注意 publish / subcribe(原文拼写)的语义与直觉相反:

  • 设备把数据 publish 到 publish 主题 → 所以你要订阅它。
  • 设备 subscribe 了 subcribe 主题 → 所以你要往它发布指令。

获取方式:

  1. GemeOpen 控制台:登录后在设备详情页查看;
  2. 设备指令:往设备发 {"type":"info","messageId":"..."}(info-protocol 需按其文档说明触发),返回里含上述字段;
  3. 向厂家/销售索取:测试服务器的连接凭据(username/password)通常需要厂家提供。

3. 一键切换脚本

工程提供了脚本 scripts/configure_device.py:

cd scripts
cp device_switch.example.json device_switch.json
# 编辑 device_switch.json,填入 current(当前 Broker)与 target(你的自建 Broker)
pip install paho-mqtt==2.1.0
python3 configure_device.py --config device_switch.json

配置模板关键字段:

{
  "current": {                          // 设备“现在”所在的 Broker
    "server": "mqtt.smart-bird.cn",
    "port": 1883,
    "username": "<平台用户名>",
    "password": "<平台密码>",
    "report_topic": "<info-protocol 的 publish>",
    "command_topic": "<info-protocol 的 subcribe>"
  },
  "target": {                           // 要切换到的“自建” Broker
    "server": "192.168.1.10",           // 必须设备网络可达
    "port": 1883,
    "username": "device",
    "password": "device-pass",
    "client_id": "gspm1b-28372fcbbbb8",
    "publish_topic": "gemeopen/gspm1b/28372fcbbbb8/report",
    "subcribe_topic": "gemeopen/gspm1b/28372fcbbbb8/command"
  }
}

脚本会:连接当前 Broker → 向 command_topic 发布 setting-mqtt → 等待设备回执。

成功后会提示:

✅ 设备已接受新的 MQTT 配置。
   请给设备【断电重启】,或发送 controller-restart 指令,使配置生效。

4. 使配置生效

setting-mqtt 需要重启才生效:

  • 断电重启:拔掉设备再上电(最简单);
  • 软重启:向设备发 {"messageId":"...","system":"restart","type":"setting"}(controller-restart)。

5. 验证设备已切换

在你的 Broker 上用任意 MQTT 客户端订阅:

mosquitto_sub -h 192.168.1.10 -p 1883 -u device -P device-pass \
  -t 'gemeopen/gspm1b/28372fcbbbb8/report' -v

若设备按上报周期持续吐出 JSON(含 voltage/current/power/energy/key),说明切换成功 🎉。

6. 没有厂家凭据怎么办?

  • 方案 A(推荐):联系 GemeOpen 获取测试服务器凭据,用脚本切换;
  • 方案 B:设备支持内网 HTTP 控制(固件 2.0.0+),可在设备所在局域网内直接配置(具体接口以设备文档为准);
  • 方案 C:先用厂家默认服务器调试,跑通 scripts/ 与后端逻辑后,再切换。

7. 主题与设备 MAC 的对应关系

建议按设备 MAC 规划主题,便于多设备管理:

gemeopen/gspm1b/<mac>/report     # 设备上报(你订阅)
gemeopen/gspm1b/<mac>/command    # 设备指令(你发布)

后端的 MQTT_REPORT_TOPIC 默认用通配符 gemeopen/gspm1b/+/report,可同时接收多台设备。


03-homeassistant.md

03 · Home Assistant 接入

面向初学者,从零把 GSPM1B 接入 Home Assistant,实现通断电控制 + 实时电流/电压/功率采集 + 累计用电量。

1. 整体思路(先看这张图)

GSPM1B ──MQTT──► Mosquitto Broker ◄──MQTT── Home Assistant
   (设备)          (你的服务器)               (MQTT 集成)

Home Assistant 通过 MQTT 集成连接你的 Mosquitto,再用一份 YAML 把设备消息映射成实体:

  • switch(开关)→ 控制通断电
  • sensor(传感器)→ 电压 / 电流 / 功率 / 累计用电量 / 信号

2. 前置条件

项要求
Home Assistant任意安装方式(HAOS / Docker / Supervised / Core)
MQTT BrokerMosquitto(本工程 mosquitto/ + docker-compose.yml 已提供)
设备GSPM1B 已按 [02 · 设备端配置] 02-device-setup.md 指向你的 Broker
设备 MAC后面配置中所有 <MAC> 都要替换成它

3. 步骤一:准备 Mosquitto Broker

3.1 用本工程一键启动(推荐)

cd gemeopen-ha-demo
docker compose up -d mosquitto

3.2 或使用 Home Assistant OS 的官方 Add-on

设置 → 加载项 → 搜索 Mosquitto broker → 安装 → 启动。

用哪种都行,只要设备、HA 都连同一个 Broker。

4. 步骤二:在 HA 中添加 MQTT 集成

  1. 设置 → 设备与服务 → 添加集成 → 搜索 MQTT;
  2. Broker 填 mosquitto 的地址(Docker 场景填宿主机 IP,如 192.168.1.10)、端口 1883;
  3. 填入 Mosquitto 的用户名/密码(见 mosquitto/mosquitto.conf 与 docker-compose.yml);
  4. 提交,集成显示“已连接”。

5. 步骤三:添加实体配置

  1. 把本工程的 homeassistant/mqtt-gspm1b.yaml 复制到 HA 配置目录(与 configuration.yaml 同级);
  2. 编辑 mqtt-gspm1b.yaml,把 所有 <MAC> 替换为你的设备 MAC(小写,例如 28372fcbbbb8);
  3. 在 configuration.yaml 中加入一行:
mqtt: !include mqtt-gspm1b.yaml
  1. 开发者工具 → YAML → 检查配置 → 重启 HA。

如果你更熟悉 UI:也可在设置 → 设备与服务 → MQTT → 通过“添加实体”逐个添加,参数与 YAML 一致。

6. 步骤四:验证实体

重启后,设置 → 设备与服务 → 实体,应能看到:

实体 ID类型说明
switch.gspm1b_switchswitch通断电开关
sensor.gspm1b_voltagesensor电压 (V)
sensor.gspm1b_currentsensor电流 (A)
sensor.gspm1b_powersensor功率 (W)
sensor.gspm1b_energysensor累计用电量 (kWh)
sensor.gspm1b_signalsensor信号强度 (dBm)

测试:

  • 点 switch.gspm1b_switch 开/关,观察实物插座继电器是否动作;
  • 若传感器数值为“未知”,说明设备还没上报——检查:
    1. 设备是否已切换到该 Broker(见 02 文档);
    2. 是否已开启定时上报(见下节)。

7. 步骤五:开启设备定时上报(让传感器持续更新)

设备默认可能不主动汇报。给它下发一次“设置上报频率”指令即可(示例间隔 15 秒):

mosquitto_pub -h 192.168.1.10 -p 1883 -u device -P device-pass \
  -t 'gemeopen/gspm1b/28372fcbbbb8/command' \
  -m '{"messageId":"1","timerEnable":1,"timerInterval":15,"type":"setting"}'

之后 report 主题会每 15 秒收到一条 device-timer-task,HA 传感器随之更新。

8. 步骤六:添加仪表盘

  1. 设置 → 仪表盘 → 新建仪表盘(标题如“智能插座”);
  2. 打开它 → 右上角编辑 → 添加卡片,按 homeassistant/dashboard.yaml 的内容添加:
    • 开关:Entities 卡片 → switch.gspm1b_switch
    • 电压/电流:Gauge 卡片
    • 功率/电量:Sensor 卡片(带迷你曲线)
    • 历史:History graph 卡片

也可直接把 dashboard.yaml 的内容粘贴到“原始配置编辑器”。

9. 步骤七(加分项):能源面板与自动化

能源面板:累计用电量已设 device_class: energy + state_class: total_increasing,会自动出现在
设置 → 仪表盘 → 能源 → 添加用电设备。

自动化示例:功率超过 2000W 时通知(configuration.yaml 或 UI 自动化):

automation:
  - alias: "GSPM1B 功率过高提醒"
    trigger:
      - platform: numeric_state
        entity_id: sensor.gspm1b_power
        above: 2000
        for: "00:01:00"
    action:
      - service: persistent_notification.create
        data:
          title: "插座功率过高"
          message: "当前功率 {{ states('sensor.gspm1b_power') }} W"

定时断电示例:

  - alias: "每天 23:30 自动断电"
    trigger:
      - platform: time
        at: "23:30:00"
    action:
      - service: switch.turn_off
        target:
          entity_id: switch.gspm1b_switch

10. 常见问题速查

现象排查
switch 显示不可用command_topic/state_topic 里的 <MAC> 是否替换正确;MQTT 集成是否连接
开关能点但实物无反应设备是否已切到该 Broker;command_topic 是否为设备的 subcribe
传感器一直“未知”未开启定时上报;或设备未上报;用 mosquitto_sub 抓包确认
数值不变上报间隔过大;或本地缓存未触发上报
能源面板不显示确认 state_class: total_increasing 已生效并已产生数据

更多排错见 [07 · 排错手册] 07-troubleshooting.md


04-backend.md

04 · Python 后端(FastAPI + MQTT)

路径 B 的后端:订阅设备 MQTT 消息 → 归一化 → 通过 REST / WebSocket 提供给 React 前端。

1. 文件结构

backend/
├── requirements.txt        # 依赖
├── .env.example            # 环境变量模板
├── Dockerfile              # 镜像构建
├── README.md               # 简版运行说明
└── app/
    ├── __init__.py
    ├── config.py           # 读取环境变量(pydantic-settings)
    ├── models.py           # DeviceState / Sample / SwitchRequest 数据模型
    ├── store.py            # 线程安全状态 + 历史环形缓冲
    ├── mqtt_client.py      # MQTT 连接、订阅、解析、下发指令
    └── main.py             # FastAPI 应用与路由(含 WebSocket)

2. 运行

本地

cd backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env          # 修改 MQTT_HOST、DEVICE_MAC 等
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Docker

docker build -t gemeopen-backend ./backend
docker run -d --name gemeopen-backend -p 8000:8000 \
  -e MQTT_HOST=192.168.1.10 -e DEVICE_MAC=28372fcbbbb8 \
  gemeopen-backend

会自动生成交互式 API 文档:http://localhost:8000/docs

3. API 一览

方法路径说明
GET/api/health健康检查:服务/Broker/设备在线状态
GET/api/device当前设备状态快照
POST/api/device/switch通断电控制,body {"on": true}
POST/api/device/refresh主动触发一次 info + statistic 查询
GET/api/device/history?limit=200采样历史(用于绘图)
GET/api/config非敏感运行配置(主题、MAC)
WS/ws/telemetry实时状态推送(每帧一个 DeviceState)

响应字段定义见 [00 · 架构与契约] 00-architecture.md 第 5 节。

4. 代码导读(重点看这三处)

4.1 mqtt_client.py:怎么把回调桥接到 Web 服务

MQTT 的回调运行在独立线程,而 FastAPI 是 asyncio 事件循环。若直接在回调里操作 WebSocket 会出错。
正确做法是把事件“递交”到事件循环:

# 伪代码
loop = asyncio.get_event_loop()          # 主线程里保存
...
def on_message(client, userdata, msg):    # 运行在 MQTT 线程
    payload = json.loads(msg.payload)
    state = normalize(payload)            # key→relayOn, voltage→voltageV ...
    store.update(state)
    asyncio.run_coroutine_threadsafe(broadcast(state), loop)   # 线程安全地广播

4.2 store.py:为什么用 deque

历史采样用 collections.deque(maxlen=HISTORY_SIZE) 做环形缓冲——满了自动丢最旧的一条,
不会无限占内存,非常适合“只看最近 N 条”的场景。

4.3 main.py:启动/关闭生命周期

@asynccontextmanager
async def lifespan(app):
    client.connect()      # 启动时连 Broker 并订阅
    yield
    client.disconnect()   # 关闭时释放

5. 字段归一化对照

设备原始字段归一化字段类型
key (0/1)relayOnboolean
voltagevoltageVfloat
currentcurrentAfloat
poweractivePowerWfloat
energyenergyKwhfloat
signalsignalDbmint

6. 二次开发建议

  1. 接入数据库:把 store.py 的内存历史换成 InfluxDB/PostgreSQL;
  2. 多设备:MQTT_REPORT_TOPIC 已用 + 通配,可扩展为按 MAC 管理多台;
  3. 鉴权:生产环境下在前端与后端之间加 Token 鉴权;
  4. 告警:复用前面温湿度工程的阈值引擎思路,对功率/电量做越限告警。

05-frontend.md

05 · React 前端(Vite)

路径 B 的前端:展示实时电压/电流/功率/累计电量,并提供通断电开关。

1. 文件结构

frontend/
├── package.json            # 依赖与脚本(vite / react / recharts)
├── vite.config.js          # 开发代理 /api、/ws → localhost:8000
├── index.html
├── .env.example            # VITE_API_BASE
├── nginx.conf              # 生产用 Nginx(托管 + 反向代理)
├── Dockerfile              # 多阶段构建 → Nginx
├── README.md
└── src/
    ├── main.jsx            # 入口
    ├── App.jsx             # 根组件(布局 + 状态汇总)
    ├── api.js              # REST 封装
    ├── useTelemetry.js     # 数据 Hook:REST 初拉 + WS 实时 + 降级轮询
    ├── styles.css
    └── components/
        ├── SwitchControl.jsx    # 通断电开关
        ├── RealtimeMetrics.jsx  # 电压/电流/功率/信号 卡片
        ├── EnergyTotal.jsx      # 累计用电量
        └── HistoryChart.jsx     # 历史曲线(recharts)

2. 运行

cd frontend
npm install
npm run dev        # http://localhost:5173
npm run build      # 产物在 dist/
npm run preview    # 本地预览构建产物

3. 数据来源与更新机制

useTelemetry.js 是核心:

  1. 首屏 GET /api/device 拿一次快照;
  2. 建立 WebSocket /ws/telemetry,后端每次状态更新即推一帧,界面实时刷新;
  3. 断线后指数退避自动重连;
  4. 若 WebSocket 不可用,自动降级为 5 秒轮询,保证界面仍可用。

4. 配置

前端通过环境变量 VITE_API_BASE 指定后端地址(默认 http://localhost:8000):

cp .env.example .env
# .env
VITE_API_BASE=http://192.168.1.10:8000
  • 开发模式:Vite 已配置代理,保持默认即可;
  • 生产模式(Docker/Nginx):容器内 nginx.conf 会把 /api、/ws 反代到后端,可保持默认值。

5. 界面构成

区域组件内容
顶部App标题、在线/连接状态徽标、刷新、最后更新时间
控制SwitchControl通电/断电开关(带请求中状态、离线禁用)
指标RealtimeMetrics电压 V / 电流 A / 功率 W / 信号 dBm
电量EnergyTotal累计用电量 kWh
趋势HistoryChart电压/功率历史折线(双 Y 轴)

6. 构建与部署

# 本地构建
npm run build

# 或 Docker(由仓库根 docker-compose.yml 统一编排)
docker build -t gemeopen-frontend ./frontend
docker run -d -p 8080:80 gemeopen-frontend

7. 二次开发建议

  1. 换 UI 库:可平滑替换为 Ant Design / MUI;
  2. 加认证:登录页 + Token 注入 api.js 请求头;
  3. 多设备切换:顶部加设备选择器,按 MAC 切换 API 参数;
  4. 告警展示:接入后端告警接口,做 Toast/声音提醒。

06-deploy-ops.md

06 · 部署与运维

面向初学者,覆盖 本地开发 → Docker 部署 → 生产建议,以及日常运维操作。

1. 部署方式总览

方式适用场景难度说明
A. 本地开发学习/调试★手动起 Mosquitto + 后端 + 前端
B. Docker Compose快速上线★★一条命令起全套(推荐)
C. 生产部署长期运行★★★密码认证 + HTTPS + 自动启动 + 备份

2. 方式 A:本地开发

2.1 启动 MQTT Broker

# 有 Docker:直接用仓库内的配置
docker compose up -d mosquitto

# 或本机安装 mosquitto 后
mosquitto -c mosquitto/mosquitto.conf -v

2.2 启动 Python 后端

cd backend
python3 -m venv .venv && source .venv/bin/activate     # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env         # 按需修改(尤其 MQTT_HOST、DEVICE_MAC)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

打开 http://localhost:8000/docs 可看到自动生成的 API 文档。

2.3 启动 React 前端

cd frontend
npm install
npm run dev        # 默认 http://localhost:5173

开发时 Vite 已把 /api、/ws 代理到 localhost:8000,一般无需额外配置。


3. 方式 B:Docker Compose(推荐)

3.1 前置

  • 安装 Docker 与 Docker Compose 插件;
  • 修改 docker-compose.yml 中 DEVICE_MAC 为你的设备 MAC。

3.2 启动

cd gemeopen-ha-demo
docker compose up -d --build
docker compose ps

启动后:

服务地址
Mosquittomqtt://<宿主机IP>:1883
后端 APIhttp://localhost:8000/docs
前端界面http://localhost:8080

3.3 关键:让设备能访问到 Broker

docker-compose.yml 里 devices 的目标 Broker 地址应填 宿主机局域网 IP(如 192.168.1.10),
不能用 localhost / mosquitto(那是容器内部的地址,设备访问不到)。

同时确认防火墙放行 1883 端口。


4. 方式 C:生产环境建议

4.1 启用 Broker 密码认证

按 mosquitto/mosquitto.conf 文件末尾的说明生成 passwd 并开启认证,然后:

  • 设备 setting-mqtt 里填 username/password;
  • HA 的 MQTT 集成里填同样的凭据;
  • 后端 .env 里填 MQTT_USERNAME / MQTT_PASSWORD。

4.2 安全清单

  • 关闭匿名访问;为设备/HA/后端分配独立账号
  • MQTT 端口不直接暴露公网;远程访问用 VPN 或 TLS(8883)
  • 前端对外访问用 HTTPS(Nginx/Caddy 反代 + 证书)
  • 后端 CORS_ORIGINS 由 * 收紧为你的域名
  • 敏感信息用环境变量/密钥管理,不写进代码

4.3 开机自启

  • Docker:restart: unless-stopped 已配置,Docker 服务开机自启即可;
  • 裸机后端可用 systemd:
# /etc/systemd/system/gemeopen-backend.service
[Unit]
Description=GemeOpen Backend
After=network.target mosquitto.service
[Service]
WorkingDirectory=/opt/gemeopen-ha-demo/backend
ExecStart=/opt/gemeopen-ha-demo/backend/.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now gemeopen-backend

5. 日常运维

5.1 看日志

docker compose logs -f backend      # 后端日志
docker compose logs -f mosquitto    # Broker 日志
docker compose logs -f frontend     # 前端日志

5.2 健康检查

curl http://localhost:8000/api/health
# {"status":"ok","mqttConnected":true,"deviceOnline":true}

5.3 更新

git pull                 # 或替换为新版本文件
docker compose up -d --build

5.4 备份

  • Broker 数据:mosquitto-data 卷(docker compose down 后备份该卷即可);
  • 历史数据:当前 Demo 存于内存,重启即清空。生产建议改接 InfluxDB / TimescaleDB / PostgreSQL 持久化。

5.5 监控建议

指标方式
后端存活/api/health 加 Uptime Kuma / 定时 curl
MQTT 连接数mosquitto_sub -t '$SYS/broker/clients/connected'
设备在线后端 online 字段(可加 HA 自动化告警)
磁盘/内存cAdvisor / node_exporter + Prometheus + Grafana

5.6 容量与性能

  • 单设备 15 秒上报 → 每天约 5760 条,压力很小;
  • 多设备/高频上报时,HISTORY_SIZE 与前端刷新频率需相应调整;
  • 历史落库后再做长期趋势与统计。

6. 配置速查(后端环境变量)

见 [00 · 架构与接口契约] 00-architecture.md 第 6 节,或 backend/.env.example。


07-troubleshooting.md

07 · 排错手册

按“症状”查“原因/解决”。建议随身备好两条抓包命令:

# 看设备是否在发数据(订阅设备上报主题)
mosquitto_sub -h 192.168.1.10 -p 1883 -u device -P device-pass -t 'gemeopen/gspm1b/+/report' -v

# 看是否有人给设备发指令(订阅设备指令主题)
mosquitto_sub -h 192.168.1.10 -p 1883 -u device -P device-pass -t 'gemeopen/gspm1b/+/command' -v

一、设备侧

症状可能原因解决
设备不上报未切换到自建 Broker用 scripts/configure_device.py 执行 setting-mqtt,再断电重启
切换后彻底没数据目标 Broker 地址设备不可达目标地址必须是局域网 IP/公网域名,且防火墙放行 1883
上报间隔很长电池供电 + 缓存条数大用 device-timer-interval 把 timerInterval 调小(如 15s)
通电后数据不刷新未开启定时上报发 {"timerEnable":1,"timerInterval":15,"type":"setting"}
想恢复出厂配置错了发 {"system":"reset","type":"setting"}(会清空配网,谨慎)
改了参数不生效部分设置需重启断电重启或发 {"system":"restart","type":"setting"}

二、MQTT Broker

症状可能原因解决
客户端连不上端口未放行 / 地址错检查防火墙、docker compose ps、mosquitto -v 日志
Connection Refused: not authorised开了密码认证但凭据错核对 passwd 中的账号,或临时改回 allow_anonymous true 验证
订阅收不到消息主题拼写错误用 + 通配符测试:gemeopen/gspm1b/+/report
容器起不来配置文件语法错docker compose logs mosquitto,检查 mosquitto.conf

三、Home Assistant

症状可能原因解决
MQTT 集成添加失败Broker 地址/凭据错Docker 场景用宿主机 IP;核对账号密码
switch 实体“不可用”state_topic 无数据先确保设备在报数据;检查 <MAC> 是否替换
点开关没反应command_topic 错(填成了 report)必须是设备的 subcribe 主题(.../command)
开关状态不同步上报里没有 key确认上报 JSON 含 key;模板为 {{ value_json.key }}
传感器一直“未知”未开启定时上报 / 未收到该字段开启上报;抓包确认字段名 voltage/current/power/energy
能源面板无数据缺 state_class确认 energy 传感器 state_class: total_increasing
改了 YAML 没生效未重载/重启开发者工具 → YAML → 检查配置 → 重启 HA

四、Python 后端

症状可能原因解决
启动报 ImportError依赖没装pip install -r requirements.txt
/api/health 里 mqttConnected:false连不上 Broker检查 MQTT_HOST/PORT/USERNAME/PASSWORD
/api/device 全为 null没收到设备上报用 mosquitto_sub 验证设备是否在发
开关接口返回失败MQTT_COMMAND_TOPIC 的 {mac} 未替换检查 .env 的 DEVICE_MAC 与 topic 模板
端口被占用8000 已占用换端口:uvicorn ... --port 8001,并同步前端 VITE_API_BASE

五、React 前端

症状可能原因解决
页面一直“离线”后端未启动 / 地址错打开 http://localhost:8000/docs 确认后端在跑;检查 VITE_API_BASE
有数据但不刷新WebSocket 被代理拦截开发用 Vite 代理;生产用 Nginx 的 /ws 段(已提供 frontend/nginx.conf)
跨域报错(CORS)后端未允许前端来源后端 CORS_ORIGINS 设为前端地址
图表为空/api/device/history 无数据需先有若干条上报采样
构建失败Node 版本过低使用 Node 18+/20+

六、网络连通性自查(万能四连)

# 1) 设备 → Broker 是否通(在能访问设备的网络内)
mosquitto_pub -h 192.168.1.10 -p 1883 -t test -m hello

# 2) 后端 → Broker
docker compose exec backend python -c "import os;print(os.getenv('MQTT_HOST'))"

# 3) 浏览器 → 后端
curl http://192.168.1.10:8000/api/health

# 4) HA → Broker(HA 的 MQTT 集成页面看“已连接”)

绝大多数问题都能通过“确认数据是否到达 Broker”这一步快速定位到是设备侧、Broker 侧还是应用侧。


Logo

一站式 AI 云服务平台

更多推荐