四博 AI 智能音箱 + ESPC3 Tasmota 计量通断器方案
1. 方案定位
本方案面向:
1. 智能插座 / 计量通断器 2. 智能空开 / 智能继电器 3. 电工照明类计量开关 4. 酒店 / 公寓 / 门店能耗管控 5. AI 音箱语音控制家电 6. 客户自有云平台 / 私有化系统接入推荐架构:
┌──────────────────────────────────────────────────────────────┐ │ 四博 AI 智能音箱 / AI 中控 │ │ ESP32-S3 / AI-C3 / AI-02 + VB6824 │ │ - 语音唤醒 / AI 对话 │ │ - AT+MCP 语义控制 │ │ - MQTT / HTTP / WebSocket │ │ - 客户系统 API 接入 │ │ - 远程运维 / OTA / 日志 │ └───────────────┬──────────────────────────────────────────────┘ │ MQTT / HTTP / 局域网 / 云平台 ▼ ┌──────────────────────────────────────────────────────────────┐ │ ESPC3 Tasmota 计量通断器节点 │ │ ESPC3-02 / ESPC3-05 / ESPC3-12 / ESPC3-20 / ESPC3-32 │ │ - Relay 通断控制 │ │ - 电压 / 电流 / 功率 / 电量采集 │ │ - Tasmota Web UI / MQTT / HTTP / Rule │ │ - 自动校准 │ │ - 过载 / 欠压 / 过压 / 漏电外部保护扩展 │ └──────────────────────────────────────────────────────────────┘ESPC3 系列适合这类电工产品:四博资料中,ESPC3-02 是 15×17.3 mm 金手指封装,定位电工类应用;ESPC3-05 是 16×20 mm 照明类应用,内置高温 Flash;ESPC3-12 / 12E、ESPC3-20 / 20E 和 ESPC3-32 / 32E 则分别面向通用模组、兼容 ESP32-C3-WROOM-02 / WROOM-32 等形态。
Tasmota 侧建议使用 ESP32-C3 对应的tasmota32c3-固件;Tasmota 官方文档说明 ESP32-C3 是单核 Wi-Fi + Bluetooth 5 LE、RISC-V 架构芯片,并要求 C3 系列使用tasmota32c3-binaries。(Tasmota)
2. 为什么不是“单颗 ESPC3 同时做 AI 音箱 + Tasmota 通断器”
ESPC3 可以做 Wi-Fi、BLE、Tasmota、继电器和计量,但它不是最适合做大模型音箱的主控。更推荐两种落地方式:
方案 A:双设备架构,最稳
AI 音箱: ESP32-S3 / AI-C3 / AI-02 负责语音、大模型、客户系统、MCP、远程管理 通断器: ESPC3 + Tasmota 负责电工控制、计量、校准、MQTT / HTTP优点是开发快、风险低、Tasmota 生态完整、客户系统容易接入。
方案 B:单设备通断器 AI 化,低成本
ESPC3 + Tasmota 仅做通断器、计量、远程管理 AI 能力放在云端或音箱端: 语音指令 → 云端 / 音箱 → MQTT / HTTP → Tasmota适合低成本量产,不在通断器本体上跑复杂语音模型。
方案 C:AI-C3 / AI-02 直接做小型语音开关
四博 AI-C3 / AI-02 是 ESP32-C3 + VB6824 组合,开发宝典中描述其支持 2.4 GHz Wi-Fi、Bluetooth 5 LE、400K SRAM、最大 16MB 片外 Flash,并且 VB6824 负责离线语音识别、降噪、更远距离唤醒、更低误唤醒、更强抗噪和免联网离线识别。
这个版本可以做“带语音的电工面板”,但计量和 Tasmota 生态需要另外移植或改固件,不如 Tasmota 节点方案成熟。
3. 硬件方案
3.1 ESPC3 计量通断器节点
推荐硬件框图:
AC L / N 输入 │ ├── AC-DC 隔离电源 3.3V │ ↓ │ ESPC3 模组 │ ├── Relay GPIO │ ├── Button GPIO │ ├── LED GPIO │ ├── Metering IC UART / CF / CF1 / SEL │ └── NTC / 温度 / 过零检测,可选 │ ├── 继电器 / 磁保持继电器 │ ↓ │ AC L 输出 │ └── 计量芯片 ├── 电压采样 ├── 电流采样:锰铜 / CT └── 功率 / 电量计算推荐器件:
主控: ESPC3-02:金手指电工类模组,适合替换 WB2S / ESP8685-WROOM-03 类产品 ESPC3-05:照明类产品,白色耐高温,适合墙开 / 灯控 ESPC3-12 / 20:通用型,适合插座 / 通断器 ESPC3-32:IO 更宽裕,适合多路继电器 / 多功能面板 计量芯片: BL0937 / HLW8012:成本低,脉冲计量 BL0942 / CSE7766:UART 计量,数据读取方便 外部参考表:产测自动校准使用 继电器: 普通继电器:成本低 磁保持继电器:低功耗、适合长期通断器 安全: 保险丝 / 压敏 / TVS / RC 吸收 AC-DC 隔离电源 继电器触点爬电距离 强弱电隔离槽 产测夹具隔离强电设备调试必须使用隔离电源、封闭夹具和合规产测流程,不能在裸板带电时连接 USB 串口或触碰 GPIO。Tasmota 模板社区中也经常提醒部分计量开关的数字地可能与市电 L 端相连,GPIO 在工作时可能带电,这类设计必须按强电安全处理。(Tasmota 设备库)
3.2 AI 音箱 / 语音中控端
推荐两种:
高端版:ESP32-S3 + VB6824
ESP32-S3R8 + 16M Flash + 8M PSRAM VB6824 语音前端 麦克风 + 喇叭 1.3 / 1.54 / 2.0 寸屏幕 Wi-Fi + BLE BluFi WebSocket AI 后端 MQTT / HTTP 控制 TasmotaAI 硬件选型表中,AI-S3 相关方案采用 ESP32S3R8 + 16M Flash + VB6824,可选小智、豆包、ChatGPT 等主流大模型,并且全开源、支持二次开发,适合品牌 B 端客户或方案商客户。
中低成本版:AI-C3 / AI-02
ESP32-C3 + VB6824 1.28 寸屏,可选 麦克风 + 喇叭 BluFi 配网 小智 / Coze 智能体 MQTT / HTTP 控制 Tasmota开发宝典中 AI-C3 提到:AI-C3 集成 BluFi 蓝牙配网,可通过微信小程序给芯片联网,并支持“小智小助理”微信小程序切换多家 AI 服务;同时 AI-C3 已实现 Coze / 扣子智能体硬件化分身,适合接入客户自己的 Agent 流程。
4. Tasmota 固件与基础配置
Tasmota 官方文档说明,它是面向 ESP 设备的开源固件,支持 Web UI、OTA、规则 / 定时器自动化,并可通过 MQTT、HTTP、串口或 KNX 做本地控制。(Tasmota)
4.1 烧录建议
芯片:ESP32-C3 / ESP8685 固件:tasmota32c3.factory.bin 或项目定制编译版本 烧录方式: 1. Tasmota Web Installer 2. esptool.py 3. 量产烧录治具Tasmota ESP32 文档说明,ESP32 设备可以通过 Web Installer 烧录,也可以使用esptool.py write_flash 0x0 tasmota32.factory.bin方式写入固件;ESP32-C3 使用tasmota32c3-系列 binaries。(Tasmota)
4.2 Tasmota 模板示例
GPIO 必须按最终 PCB 修改。下面只是示例结构:
{ "NAME": "SIBO-ESPC3-Meter-Relay", "GPIO": [ 1, 1, 1, 1, 32, // Relay1 224, // Button1 288, // Led1i 1, 2720, // BL0937 CF / or metering input 2656, // BL0937 CF1 2624, // BL0937 SEL 1, 1, 1, 1, 1 ], "FLAG": 0, "BASE": 1 }实际项目中建议做三套模板:
Template A:BL0937 / HLW8012 脉冲计量版 Template B:BL0942 UART 计量版 Template C:双路继电器 + 单路计量版Tasmota 配置命令示例:
Backlog Module 0; Template {"NAME":"SIBO-ESPC3-Meter-Relay","GPIO":[1,1,1,1,32,224,288,1,2720,2656,2624,1,1,1,1,1],"FLAG":0,"BASE":1}; Restart 1然后配置 MQTT 与远程管理参数:
Backlog MqttHost 192.168.1.10; MqttPort 1883; MqttUser sibo; MqttPassword 123456; Topic sibo_meter_001; TelePeriod 10; PowerRetain 1; SensorRetain 1Tasmota 命令支持 MQTT、HTTP Web Request、WebUI Console 和串口;MQTT 命令主题形态为cmnd/%topic%/<command>,HTTP 则可以通过/cm?cmnd=Power%20On这类 URL 执行命令。(GitHub)
5. 计量自动校准方案
5.1 先说明一个关键点
“自动校准”不能凭空完成。通断器必须拿到一个可信参考值,来源可以是:
1. 产测夹具上的标准功率计; 2. 标准电压 + 标准阻性负载; 3. 上位机手动录入的功率 / 电压 / 电流; 4. Modbus / 串口参考表实时读取; 5. 已校准的基准通断器作为对照。也就是说,自动校准的本质是:
参考仪表读数 ↓ 校准服务器计算目标值 ↓ 通过 Tasmota HTTP / MQTT 下发 VoltageSet / PowerSet / CurrentSet ↓ 读取 Tasmota Status 8 / Telemetry ↓ 判断误差 ↓ 写入 SN、校准结果和批次记录Tasmota 官方功率监控校准文档明确要求使用支持功率监控的 Tasmota 设备、正确模板、AC 校准万用表,以及功率因数尽量接近 1 的已知阻性负载;文档也提示不要使用开关电源类负载、LED 灯、电脑、电机等感性 / 容性负载做校准。(Tasmota)
5.2 Tasmota v14.2.0.1+ 推荐校准流程
官方文档中,Tasmota v14.2.0.1 及以上版本推荐流程是:
1. VoltageSet <voltage> 2. PowerSet <watts>, <voltage> 3. 检查 Power Factor 接近 1.00其中VoltageSet <value>用目标电压校准电压读数,PowerSet <value>,<voltage>可同时按目标功率和电压校准功率与电流。(Tasmota)
示例:
VoltRes 1 WattRes 2 VoltageSet 230.0 PowerSet 60.0,230.0 Status 8Tasmota 命令文档也说明,PowerSet的<value>,<voltage>参数可同时校准功率和基于电压 / 负载计算出的电流,VoltageSet用于把电压校准到目标 V 值,Status 8用于显示用电量 / 传感信息。(GitHub)
5.3 旧版兼容流程
如果使用旧版本 Tasmota,流程如下:
PowerSet 60.0 VoltageSet 230.0 CurrentSet 260.87电流计算:
I(mA) = 1000 × P(W) / V(V) 例如: P = 60 W V = 230 V I = 1000 × 60 / 230 = 260.87 mA官方旧流程文档也给出PowerSet、VoltageSet、CurrentSet的校准顺序,并说明 CurrentSet 使用毫安值。(Tasmota)
6. 产测自动校准流程
6.1 工装结构
PC / 工控机 ├── Python 校准程序 ├── MQTT Broker ├── 标准功率计 Modbus / Serial └── 工装扫码枪 标准 AC 输入 ↓ 安全隔离 / 漏保 / 急停 ↓ 待测 ESPC3 Tasmota 通断器 ↓ 标准阻性负载,例如 60W / 100W 白炽灯或电阻箱6.2 自动校准步骤
1. 扫描设备 SN / MAC。 2. 工装连接待测设备 Wi-Fi 或设备连接工厂路由器。 3. 校准程序发现设备 IP。 4. 下发 Tasmota Template / MQTT / TelePeriod。 5. 打开 Relay。 6. 等待电压、功率、电流稳定。 7. 从标准功率计读取 V / W / A。 8. 下发 VoltageSet。 9. 下发 PowerSet W,V。 10. 读取 Status 8。 11. 判断误差: 电压误差 ≤ ±1% 功率误差 ≤ ±2% 电流误差 ≤ ±2% 12. 写入生产数据库。 13. 打印合格标签。7. Python 自动校准程序
下面代码通过 Tasmota HTTP API 对 ESPC3 通断器进行自动校准。Tasmota 官方文档给出的 HTTP 命令方式是/cm?cmnd=Power%20On这类格式,空格和特殊字符需要 URL 编码。(GitHub)
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ ESPC3 Tasmota 计量通断器自动校准工具 功能: 1. 打开继电器; 2. 等待负载稳定; 3. 下发 VoltageSet; 4. 下发 PowerSet W,V; 5. 读取 Status 8; 6. 判断电压 / 功率 / 电流误差; 7. 输出校准结果。 依赖: pip install requests """ import time import json import math import argparse import urllib.parse from dataclasses import dataclass from typing import Any, Dict, Optional import requests @dataclass class RefMeterValue: voltage_v: float power_w: float current_a: Optional[float] = None @dataclass class TasmotaReading: voltage_v: float power_w: float current_a: float factor: Optional[float] = None class TasmotaClient: def __init__(self, ip: str, username: str = "", password: str = "", timeout: float = 5.0): self.ip = ip self.username = username self.password = password self.timeout = timeout def command(self, cmd: str) -> Dict[str, Any]: params = {"cmnd": cmd} if self.username: params["user"] = self.username params["password"] = self.password url = f"http://{self.ip}/cm" resp = requests.get(url, params=params, timeout=self.timeout) resp.raise_for_status() return resp.json() def backlog(self, commands: list[str]) -> Dict[str, Any]: return self.command("Backlog " + "; ".join(commands)) def power_on(self): return self.command("Power On") def power_off(self): return self.command("Power Off") def status8(self) -> Dict[str, Any]: return self.command("Status 8") def voltage_set(self, voltage: float): return self.command(f"VoltageSet {voltage:.2f}") def power_set_new(self, power: float, voltage: float): """ Tasmota v14.2.0.1+ 推荐方式: PowerSet <watts>,<voltage> """ return self.command(f"PowerSet {power:.2f},{voltage:.2f}") def current_set_old(self, current_ma: float): """ 旧版兼容方式: CurrentSet <mA> """ return self.command(f"CurrentSet {current_ma:.2f}") def extract_energy_reading(status_json: Dict[str, Any]) -> TasmotaReading: """ 常见 Status 8 返回里会有 StatusSNS -> ENERGY。 不同 Tasmota 版本 / 计量驱动字段略有差异,此处做容错解析。 """ energy = None if "StatusSNS" in status_json: sns = status_json["StatusSNS"] if "ENERGY" in sns: energy = sns["ENERGY"] if energy is None and "ENERGY" in status_json: energy = status_json["ENERGY"] if energy is None: raise RuntimeError(f"Cannot find ENERGY in response: {json.dumps(status_json, ensure_ascii=False)}") voltage = float(energy.get("Voltage", 0)) power = float(energy.get("Power", 0)) current = float(energy.get("Current", 0)) factor = energy.get("Factor") return TasmotaReading( voltage_v=voltage, power_w=power, current_a=current, factor=float(factor) if factor is not None else None, ) def percent_error(actual: float, target: float) -> float: if target == 0: return 999.0 return abs(actual - target) * 100.0 / abs(target) def wait_stable_reading(client: TasmotaClient, samples: int = 5, interval: float = 1.0) -> TasmotaReading: readings: list[TasmotaReading] = [] for _ in range(samples): status = client.status8() reading = extract_energy_reading(status) readings.append(reading) time.sleep(interval) avg_voltage = sum(r.voltage_v for r in readings) / len(readings) avg_power = sum(r.power_w for r in readings) / len(readings) avg_current = sum(r.current_a for r in readings) / len(readings) factor_values = [r.factor for r in readings if r.factor is not None] avg_factor = sum(factor_values) / len(factor_values) if factor_values else None return TasmotaReading(avg_voltage, avg_power, avg_current, avg_factor) def calibrate( client: TasmotaClient, ref: RefMeterValue, use_new_method: bool = True, voltage_tolerance_pct: float = 1.0, power_tolerance_pct: float = 2.0, current_tolerance_pct: float = 2.0, ) -> bool: print("[1] Configure resolution and telemetry") client.backlog([ "VoltRes 2", "WattRes 2", "TelePeriod 10", ]) print("[2] Turn relay on") client.power_on() time.sleep(5) print("[3] Before calibration") before = wait_stable_reading(client) print(before) print("[4] Apply calibration") client.voltage_set(ref.voltage_v) time.sleep(2) if use_new_method: client.power_set_new(ref.power_w, ref.voltage_v) else: current_ma = 1000.0 * ref.power_w / ref.voltage_v client.command(f"PowerSet {ref.power_w:.2f}") time.sleep(1) client.current_set_old(current_ma) time.sleep(5) print("[5] After calibration") after = wait_stable_reading(client) print(after) target_current_a = ref.current_a if ref.current_a is not None else ref.power_w / ref.voltage_v v_err = percent_error(after.voltage_v, ref.voltage_v) p_err = percent_error(after.power_w, ref.power_w) i_err = percent_error(after.current_a, target_current_a) print(f"[6] Error voltage={v_err:.2f}% power={p_err:.2f}% current={i_err:.2f}% factor={after.factor}") ok = ( v_err <= voltage_tolerance_pct and p_err <= power_tolerance_pct and i_err <= current_tolerance_pct ) if after.factor is not None and after.factor < 0.95: print("[WARN] Power factor is not close to 1.00. Check load type and wiring.") print("[7] Calibration result:", "PASS" if ok else "FAIL") return ok def main(): parser = argparse.ArgumentParser() parser.add_argument("--ip", required=True, help="Tasmota device IP") parser.add_argument("--voltage", type=float, required=True, help="Reference voltage, V") parser.add_argument("--power", type=float, required=True, help="Reference power, W") parser.add_argument("--current", type=float, default=None, help="Reference current, A") parser.add_argument("--user", default="") parser.add_argument("--password", default="") parser.add_argument("--old", action="store_true", help="Use old PowerSet + VoltageSet + CurrentSet flow") args = parser.parse_args() client = TasmotaClient(args.ip, args.user, args.password) ref = RefMeterValue( voltage_v=args.voltage, power_w=args.power, current_a=args.current, ) ok = calibrate(client, ref, use_new_method=not args.old) raise SystemExit(0 if ok else 2) if __name__ == "__main__": main()运行示例:
python calibrate_tasmota.py --ip 192.168.1.88 --voltage 230.4 --power 60.2旧版 Tasmota 兼容:
python calibrate_tasmota.py --ip 192.168.1.88 --voltage 230.4 --power 60.2 --old8. AI 音箱到 Tasmota 的控制协议
8.1 语音指令设计
用户可以这样说:
“小博,打开客厅插座” “小博,关闭热水器通断器” “小博,查看空调插座功率” “小博,今天用了多少电” “小博,把这个插座校准到 230 伏、60 瓦” “小博,超过 1500 瓦自动断电” “小博,把门店所有插座断开”AI 音箱 / AI 中控需要把自然语言解析成标准动作:
{ "device_id": "sibo_meter_001", "action": "power_on" }{ "device_id": "sibo_meter_001", "action": "calibrate", "voltage": 230.0, "power": 60.0 }{ "device_id": "sibo_meter_001", "action": "set_power_limit", "power_high": 1500 }8.2 使用开发宝典 AT+MCP 做语义到控制
开发宝典中的 AT+MCP 非常适合这类“AI 音箱控制通断器”的场景。文档说明,AT+MCP 使用标准 UART,默认115200, 8N1,所有指令以回车换行结束,合法指令统一回复 OK;通过AT+ADDMCP可以把“人话”映射为 MCU 可执行的二进制控制帧;模块还会上报开机、配网、联网、监听、说话、升级、激活等状态。
协议帧格式:
AI 模组 -> MCU: 0x55 0xAA LEN CMD DATA... 0xAA 0x55开发宝典还说明,当 MCU 收到55 AA 01 FC AA 55时,需要重启 AI 模组并重新发送 MCP 映射;AT+RESTORE可清空 Wi-Fi,AT+CONNECT可一键回连或进入配网。
9. AI 音箱端 MCP 注册代码
下面代码用于音箱端或中控端:启动后向 AI 模组注册“控制 Tasmota 通断器”的 MCP 能力。
/* * ai_mcp_tasmota_register.c * * 功能: * 1. 注册 Tasmota 通断器控制能力; * 2. 将语音指令映射为二进制帧; * 3. 后续由 mcp_rx_task 解析帧并转 MQTT / HTTP。 */ static void mcp_send_line(const char *line) { uart_write_bytes(AI_UART, line, strlen(line)); uart_write_bytes(AI_UART, "\r\n", 2); } static void register_tasmota_mcp_tools(void) { mcp_send_line("AT"); mcp_send_line("AT+WIFICFG=0"); mcp_send_line("AT+CONNECT"); /* * 用户:“打开客厅插座” * AI -> MCU: 55 AA 03 F1 device_id 01 AA 55 */ mcp_send_line( "AT+ADDMCP=1,tasmota_power_control,控制Tasmota通断器开关,F1,2,device_id,power" ); /* * 用户:“查看插座功率” * AI -> MCU: 55 AA 02 F2 device_id AA 55 */ mcp_send_line( "AT+ADDMCP=1,tasmota_query_energy,查询Tasmota通断器电压电流功率,F2,1,device_id" ); /* * 用户:“把插座校准到230伏60瓦” * AI -> MCU: 55 AA 05 F3 device_id voltage_hi voltage_lo power_hi power_lo AA 55 * 为节省字节,这里 voltage/power 可以按 0.1 单位传输。 */ mcp_send_line( "AT+ADDMCP=1,tasmota_calibrate,校准Tasmota通断器计量,F3,5,device_id,voltage_hi,voltage_lo,power_hi,power_lo" ); /* * 用户:“超过1500瓦自动断电” */ mcp_send_line( "AT+ADDMCP=1,tasmota_set_power_limit,设置通断器过载断电阈值,F4,3,device_id,power_hi,power_lo" ); /* * 用户:“同步通断器状态到客户系统” */ mcp_send_line( "AT+ADDMCP=1,customer_sync_meter,同步计量数据到客户系统,F5,1,device_id" ); }10. AI 音箱端:MCP 帧转 MQTT 控制 Tasmota
#include <stdio.h> #include <string.h> #include <stdint.h> #include "esp_log.h" #include "mqtt_client.h" #define TAG "MCP_TASMOTA" #define CMD_TASMOTA_POWER 0xF1 #define CMD_TASMOTA_QUERY 0xF2 #define CMD_TASMOTA_CALIBRATE 0xF3 #define CMD_TASMOTA_LIMIT 0xF4 #define CMD_CUSTOMER_SYNC 0xF5 #define CMD_STATUS 0xFF #define CMD_RECOVER 0xFC static esp_mqtt_client_handle_t s_mqtt = NULL; static const char *device_id_to_topic(uint8_t device_id) { /* * 量产时建议从 NVS / 云端配置中读取: * device_id -> Tasmota Topic 映射。 */ switch (device_id) { case 1: return "sibo_meter_001"; case 2: return "sibo_meter_002"; case 3: return "sibo_meter_003"; default: return "sibo_meter_unknown"; } } static void mqtt_publish_cmd(const char *topic, const char *cmd) { char mqtt_topic[128]; snprintf(mqtt_topic, sizeof(mqtt_topic), "cmnd/%s/%s", topic, cmd); /* * 对于 Power 这类命令,Tasmota 标准格式是: * topic: cmnd/<Topic>/Power * payload: On / Off / Toggle * * 为了通用,这里支持 cmd 里不带 payload 的模式; * 更严谨的实现可拆 command 和 payload。 */ } static void tasmota_mqtt_command(const char *device_topic, const char *command, const char *payload) { char topic[128]; snprintf(topic, sizeof(topic), "cmnd/%s/%s", device_topic, command); ESP_LOGI(TAG, "MQTT publish topic=%s payload=%s", topic, payload); esp_mqtt_client_publish( s_mqtt, topic, payload, 0, 1, 0 ); } static void tasmota_power_control(uint8_t device_id, uint8_t power) { const char *topic = device_id_to_topic(device_id); if (power) { tasmota_mqtt_command(topic, "Power", "On"); } else { tasmota_mqtt_command(topic, "Power", "Off"); } } static void tasmota_query_energy(uint8_t device_id) { const char *topic = device_id_to_topic(device_id); /* * Status 8 用于查询功率 / 传感信息。 */ tasmota_mqtt_command(topic, "Status", "8"); } static void tasmota_calibrate(uint8_t device_id, uint16_t voltage_x10, uint16_t power_x10) { const char *topic = device_id_to_topic(device_id); float voltage = voltage_x10 / 10.0f; float power = power_x10 / 10.0f; char payload[64]; /* * 新版本 Tasmota 推荐: * VoltageSet <voltage> * PowerSet <power>,<voltage> */ snprintf(payload, sizeof(payload), "%.1f", voltage); tasmota_mqtt_command(topic, "VoltageSet", payload); snprintf(payload, sizeof(payload), "%.1f,%.1f", power, voltage); tasmota_mqtt_command(topic, "PowerSet", payload); } static void tasmota_set_power_limit(uint8_t device_id, uint16_t power_w) { const char *topic = device_id_to_topic(device_id); char payload[32]; snprintf(payload, sizeof(payload), "%u", power_w); /* * PowerHigh 可设置功率高阈值。 * 后续配合 Rule 可实现超功率断电。 */ tasmota_mqtt_command(topic, "PowerHigh", payload); } static void customer_sync_meter(uint8_t device_id) { /* * TODO: * 1. 从缓存的 Tasmota telemetry 中取电压 / 电流 / 功率 / 电量; * 2. HTTP / MQTT 上报到客户平台; * 3. 支持客户 project_id / product_id / device_id。 */ ESP_LOGI(TAG, "sync meter data to customer system, device_id=%u", device_id); } static void handle_mcp_frame(uint8_t cmd, const uint8_t *data, uint8_t len) { switch (cmd) { case CMD_TASMOTA_POWER: if (len >= 2) { tasmota_power_control(data[0], data[1]); } break; case CMD_TASMOTA_QUERY: if (len >= 1) { tasmota_query_energy(data[0]); } break; case CMD_TASMOTA_CALIBRATE: if (len >= 5) { uint8_t device_id = data[0]; uint16_t voltage_x10 = ((uint16_t)data[1] << 8) | data[2]; uint16_t power_x10 = ((uint16_t)data[3] << 8) | data[4]; tasmota_calibrate(device_id, voltage_x10, power_x10); } break; case CMD_TASMOTA_LIMIT: if (len >= 3) { uint8_t device_id = data[0]; uint16_t power_w = ((uint16_t)data[1] << 8) | data[2]; tasmota_set_power_limit(device_id, power_w); } break; case CMD_CUSTOMER_SYNC: if (len >= 1) { customer_sync_meter(data[0]); } break; default: ESP_LOGW(TAG, "unknown MCP cmd=0x%02X len=%u", cmd, len); break; } }11. Tasmota Rule:过载自动断电
Tasmota 可以直接在节点侧做本地保护,不依赖云端。
示例逻辑:
当功率超过 1500W: 1. 关闭继电器; 2. 发布过载事件; 3. 点亮告警灯; 4. 需要人工或远程复位。Tasmota Console 示例:
Backlog PowerHigh 1500; Rule1 ON ENERGY#Power>1500 DO Backlog Power Off; Publish stat/%topic%/ALARM OVER_POWER ENDON; Rule1 1也可以用 AI 音箱设置:
“小博,把热水器通断器过载保护设为 1800 瓦”音箱端转成:
cmnd/sibo_meter_001/PowerHigh 1800 cmnd/sibo_meter_001/Rule1 ON ENERGY#Power>1800 DO Backlog Power Off; Publish stat/%topic%/ALARM OVER_POWER ENDON cmnd/sibo_meter_001/Rule1 112. 远程管理平台设计
12.1 设备 Topic 设计
Tasmota 原生: cmnd/sibo_meter_001/Power cmnd/sibo_meter_001/Status stat/sibo_meter_001/RESULT tele/sibo_meter_001/SENSOR 客户平台统一: customer/{project_id}/{device_id}/cmd customer/{project_id}/{device_id}/state customer/{project_id}/{device_id}/event customer/{project_id}/{device_id}/ota12.2 远程管理功能
1. 设备绑定: SN、MAC、Tasmota Topic、客户 device_id 绑定。 2. 实时状态: 开关状态、电压、电流、功率、今日电量、总电量、RSSI、固件版本。 3. 远程控制: 开 / 关 / 定时 / 倒计时 / 场景联动。 4. 远程校准: 下发参考电压、参考功率、参考电流,执行自动校准。 5. 阈值保护: 过压、欠压、过载、过温、过流。 6. OTA: Tasmota 固件 OTA; AI 音箱固件 OTA; 配置模板 OTA。 7. 日志: 校准记录、继电器动作、异常断电、客户系统调用记录。Tasmota 原生支持 MQTT、Web UI、HTTP、serial 等控制方式,因此客户平台既可以直接管理 Tasmota,也可以通过四博 AI 音箱中控做一层网关和权限管理。(Tasmota)
13. 客户系统 HTTP 接入示例
音箱端收到 Tasmota 的 telemetry 后,可以上报客户平台:
#include "esp_http_client.h" #include "esp_log.h" #define TAG "CUSTOMER_API" typedef struct { const char *device_id; float voltage; float current; float power; float energy_today; float energy_total; int relay_on; } meter_state_t; esp_err_t customer_upload_meter_state(const meter_state_t *s) { char body[256]; snprintf(body, sizeof(body), "{" "\"device_id\":\"%s\"," "\"voltage\":%.2f," "\"current\":%.3f," "\"power\":%.2f," "\"energy_today\":%.3f," "\"energy_total\":%.3f," "\"relay_on\":%d" "}", s->device_id, s->voltage, s->current, s->power, s->energy_today, s->energy_total, s->relay_on ); esp_http_client_config_t config = { .url = "https://customer.example.com/api/v1/meter/state", .method = HTTP_METHOD_POST, .timeout_ms = 8000, }; esp_http_client_handle_t client = esp_http_client_init(&config); esp_http_client_set_header(client, "Content-Type", "application/json"); esp_http_client_set_header(client, "Authorization", "Bearer ${token}"); esp_http_client_set_post_field(client, body, strlen(body)); esp_err_t err = esp_http_client_perform(client); int status = esp_http_client_get_status_code(client); ESP_LOGI(TAG, "upload status=%d err=%s", status, esp_err_to_name(err)); esp_http_client_cleanup(client); return err; }14. 后端服务建议
结合开发宝典的小智后端思路,可以部署一个统一后端:
Nginx / Caddy ├── AI WebSocket Gateway ├── OTA Server ├── MQTT Broker ├── Tasmota Device Manager ├── Calibration Service ├── Customer API Gateway ├── Rule Engine └── Web Admin开发宝典中说明,设备默认可连接官方小智服务,也可以运行开源后端服务,把设备连接到自己的后端;后端包含 OTA 接口和 WebSocket 接口,并可配置 LLM、TTS、人设等参数。
推荐后端数据表:
CREATE TABLE device_meter ( id BIGINT PRIMARY KEY AUTO_INCREMENT, device_id VARCHAR(64) NOT NULL, tasmota_topic VARCHAR(64) NOT NULL, mac VARCHAR(32), sn VARCHAR(64), product_id VARCHAR(64), project_id VARCHAR(64), firmware_version VARCHAR(32), calibration_version INT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE meter_calibration_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, device_id VARCHAR(64) NOT NULL, ref_voltage DECIMAL(10,3), ref_power DECIMAL(10,3), ref_current DECIMAL(10,4), read_voltage DECIMAL(10,3), read_power DECIMAL(10,3), read_current DECIMAL(10,4), voltage_error DECIMAL(8,3), power_error DECIMAL(8,3), current_error DECIMAL(8,3), result VARCHAR(16), operator_id VARCHAR(64), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );15. 量产测试方案
15.1 工厂测试项
ESPC3: - Flash 读写 - Wi-Fi MAC - RSSI - Tasmota 固件版本 - Template 是否正确 - MQTT 是否在线 继电器: - 开 / 关动作 - 触点粘连检测 - 上电默认状态 - 断电恢复状态 计量: - 空载功率 - 标准电压 - 标准负载功率 - 电流读数 - 功率因数 - 电量累计 校准: - VoltageSet - PowerSet W,V - Status 8 验证 - 误差判定 - 结果写数据库 安全: - 高压测试 - 绝缘测试 - 老化测试 - 过载断电测试 AI 音箱联动: - 语音开关 - 查询功率 - 设置过载阈值 - 远程校准 - 客户系统上报15.2 产测串口 / 平台命令
FACTORY_SCAN FACTORY_BIND_SN=SBOMETER20260001 FACTORY_SET_TEMPLATE FACTORY_MQTT_CONFIG FACTORY_RELAY_ON FACTORY_RELAY_OFF FACTORY_READ_STATUS8 FACTORY_CALIBRATE=230.0,60.0 FACTORY_CHECK_ERROR FACTORY_SET_POWER_LIMIT=1500 FACTORY_UPLOAD_RESULT FACTORY_PASS FACTORY_FAIL16. 推荐版本
16.1 ESPC3 基础计量通断器
ESPC3-02 / ESPC3-05 1 路继电器 BL0937 / HLW8012 Tasmota32-C3 MQTT / HTTP 手动校准 / 产测自动校准适合低成本智能插座、墙开、灯控。
16.2 ESPC3 高精度计量通断器
ESPC3-12 / ESPC3-20 1 路继电器或磁保持继电器 BL0942 / CSE7766 UART 计量 Tasmota32-C3 定制固件 远程自动校准 过载 / 过压 / 欠压保护 客户云平台适合能耗管理、酒店、公寓、门店。
16.3 AI 音箱 + 通断器套装
AI 音箱: ESP32-S3 + VB6824 屏幕 + 麦克风 + 喇叭 小智 / Coze / 客户 LLM AT+MCP 通断器: ESPC3 + Tasmota Relay + 计量芯片 MQTT / HTTP 能力: 语音控制 语音查询功率 远程管理 自动校准 客户系统接入17. 方案总结
这套方案建议采用“四博 AI 智能音箱作为语音与客户系统入口,ESPC3 Tasmota 计量通断器作为电工执行节点”的架构。ESPC3 负责继电器通断、功率计量、Tasmota Web UI / MQTT / HTTP、自动校准和本地保护;AI 音箱端基于四博 AI 开发宝典的 DOIT_AI、AI-C3 / AI-S3、VB6824、BluFi 和 AT+MCP 能力,把“打开插座、查询功率、校准计量、设置过载保护”等自然语言转成 Tasmota 命令;客户平台通过 MQTT / HTTP 接收数据和下发策略,实现远程管理、批量 OTA、产测自动校准和私有化系统集成。
关键落地点是:自动校准必须有参考仪表或标准负载,Tasmota 负责执行 VoltageSet / PowerSet / CurrentSet,四博 AI 音箱或客户云平台负责编排流程、记录校准结果和接入业务系统。