四博 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 控制 Tasmota
AI 硬件选型表中,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 1
Tasmota 命令支持 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 8
Tasmota 命令文档也说明,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 --old
8. 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 1
12. 远程管理平台设计
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}/ota
12.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_FAIL
16. 推荐版本
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 音箱或客户云平台负责编排流程、记录校准结果和接入业务系统。