@jiangtaste/baiwei-sdk
v1.0.2
Published
面向百微智能网关的 SDK
Maintainers
Readme
baiwei-sdk
baiwei-sdk 现在收敛为一个面向百微智能网关的 TCP 长连接通信转换层。
它默认只做几件事:
- 建立和维护 TCP 长连接
- 完成协议编解码
- 关联请求/响应
- 汇总分片消息
- 透传网关
report - 保存登录后的
token
它默认不再做这些事:
- 不维护设备/房间/场景的长期缓存
- 不自动帮业务层同步状态
- 不把 SDK 本身做成状态中心
安装
npm install baiwei-sdk适用场景
这个 SDK 适合放在更上层的库或服务下面,作为“百微网关协议适配层”:
- 在
NestJS服务里做网关接入 - 在
Homebridge/Home Assistant插件里做设备桥接 - 在你自己的
IoT Hub或家庭中台里做设备查询、控制和上报接收 - 在脚本工具里做调试、巡检、排障
如果你的目标是:
- 维持 TCP 长连接
- 请求设备、房间、场景
- 控制设备
- 接收网关
report
那么可以直接使用这个 SDK。
如果你的目标是:
- 做设备缓存
- 做状态中心
- 做自动同步和状态广播
- 做插件平台或业务编排
这些建议放在你自己的上层库里实现,而不是塞进 SDK 本身。
快速开始
1. 管理员登录
import {
BaiweiClient,
BaiweiProductType,
LightState,
MessageResponse,
} from "baiwei-sdk";
async function main() {
const client = new BaiweiClient({
host: "1.2.3.4", // 网关IP
port: 12345, // 网关端口
gatewaySN: "设备序列号", // MAC地址去掉空格
timeoutMs: 5_000,
});
client.on("report", (message) => {
const device = client.controlService.getReportedDeviceState(
message as MessageResponse
);
if (device) {
console.log("device report", device.device_id, device.device_status);
}
});
await client.connect();
await client.userService.login();
const devices = await client.deviceService.getDevicesByType(
BaiweiProductType.ON_OFF_LIGHT
);
const states = await client.controlService.getDeviceStatesByType<LightState>(
BaiweiProductType.ON_OFF_LIGHT
);
console.log("devices", devices.length);
console.log("states", states.device_list?.length ?? 0);
}
main().catch(console.error);2. 普通用户账号密码登录
import { BaiweiClient } from "baiwei-sdk";
async function main() {
const client = new BaiweiClient({
host: "192.168.4.14",
port: 12345,
gatewaySN: "304a2656b37e",
});
await client.connect();
await client.userService.login({
userName: "alice",
userPwd: "123456",
});
const rooms = await client.roomService.listRooms();
console.log("rooms", rooms.length);
}
main().catch(console.error);API 边界
你可以直接把它当作“协议适配器”来用:
client.connect()/client.disconnect()负责连接生命周期client.request()允许你直接发原始协议请求client.on("report", handler)接收网关主动上报userService/deviceService/controlService/roomService/sceneService/gatewayService只保留单次请求封装
当前设计原则
- SDK 只保留通信所需的最小状态:连接、token、pending request、分片组装
- 业务缓存、状态合并、同步策略交给上层网关服务实现
- 如果后续要接 Home Assistant、NestJS、Homebridge,这一层都可以继续复用
其他库如何使用这个 SDK
最推荐的方式是:把它当作底层驱动,不要直接把业务逻辑写进 SDK。
接入思路
通常可以分成三层:
baiwei-sdk只负责 TCP、协议、请求/响应、report。- 你的网关适配层 负责缓存设备目录、维护状态、重连后的重新同步、事件分发。
- 你的业务层 / 插件层 负责 UI、自动化、告警、场景编排、第三方平台桥接。
在服务端项目中使用
如果你在 NestJS、Express、Fastify 之类的服务端项目里接入,建议封装一个长期存活的网关服务:
import {
BaiweiClient,
BaiweiProductType,
MessageResponse,
} from "baiwei-sdk";
export class BaiweiGatewayService {
private readonly client = new BaiweiClient({
host: process.env.BAIWEI_HOST!,
port: Number(process.env.BAIWEI_PORT!),
gatewaySN: process.env.BAIWEI_GATEWAY_SN!,
timeoutMs: 5000,
});
async start() {
this.client.on("report", (message) => {
this.handleReport(message as MessageResponse);
});
await this.client.connect();
await this.client.userService.login({
userName: process.env.BAIWEI_USER_NAME!,
userPwd: process.env.BAIWEI_USER_PWD!,
});
}
async listLights() {
return this.client.deviceService.getDevicesByType(
BaiweiProductType.ON_OFF_LIGHT
);
}
async stop() {
this.client.disconnect();
}
private handleReport(message: MessageResponse) {
const device = this.client.controlService.getReportedDeviceState(message);
if (!device) return;
console.log("device report", device.device_id, device.device_status);
}
}这种模式适合:
- 你的服务要长期在线
- 你要统一管理连接和登录
- 你要把上报转成自己的事件总线
在 Homebridge / Home Assistant 类插件中使用
插件层通常不要让每个 accessory / entity 自己建连接。更合理的方式是:
- 整个插件只维护一个
BaiweiClient - 启动时统一登录
- 用
deviceService拉一次设备目录 - 用
controlService查询状态或发送控制 - 用
report更新插件内部缓存
也就是说,这个 SDK 更适合作为“单网关单连接”的底层驱动,而不是每个设备实例各自使用。
在你自己的领域库中二次封装
如果你准备做一个更高层的库,比如:
baiwei-homebridge-adapterbaiwei-nest-gatewaybaiwei-state-manager
建议在上层封装这些能力:
- 设备缓存:启动后拉取一次
deviceService.listDevices() - 状态缓存:收到
report时合并到内存状态 - 自动重同步:重连后重新登录、重新拉目录、重新拉状态
- 业务事件:对外发出
device-updated、room-updated、scene-triggered - 权限与多租户:如果普通用户和管理员权限不同,这一层做权限隔离
SDK 自己则尽量保持“薄”,避免和你的业务模型耦合。
推荐封装方式
1. 做一个单例 client
不要在每次请求里都 new BaiweiClient();更推荐在进程生命周期内复用一个实例。
2. 登录逻辑集中管理
建议只在一处完成:
client.connect()client.userService.login()
不要让业务层到处散落登录逻辑。
3. 把 report 当事件源,不要当最终状态
report 只是网关主动上报的消息流。上层如果要形成完整状态,仍然建议自己维护缓存和合并策略。
4. 尽量让业务代码依赖你自己的适配层
也就是说,业务代码最好依赖:
gateway.listLights()
gateway.turnOn(deviceId)
gateway.getRoomDevices(roomId)而不是在每个业务模块里直接操作 client.deviceService、client.controlService。
这样你以后换协议、换缓存策略、换权限模型,改动面会小很多。
原始协议请求
如果现成 service 还没覆盖某个接口,可以直接走 client.request():
import { BaiweiClient, MsgClass, MsgName, MsgType } from "baiwei-sdk";
const response = await client.request({
msgClass: MsgClass.CONTROL_MGMT,
msgName: MsgName.DEVICE_STATE_GET,
msgType: MsgType.GET,
payload: {
device: {
type: "On/Off Light",
},
},
});这对你做上层库很有用:即使 SDK 还没补好某个 service,你也能先继续开发。
调试 SDK
仓库里已经带了一个可直接运行的调试入口:examples/debug.ts。
先准备连接参数:
export BAIWEI_HOST=192.168.4.14
export BAIWEI_PORT=12345
export BAIWEI_GATEWAY_SN=304a2656b37e
export BAIWEI_USER_PWD=888888
export BAIWEI_DEBUG=1如果要测试普通用户登录,还可以额外设置:
export BAIWEI_USER_NAME=alice
export BAIWEI_USER_PWD=123456然后可以直接跑这些命令:
npm run debug -- overview
npm run debug -- devices
npm run debug -- devices ON_OFF_LIGHT
npm run debug -- states ON_OFF_LIGHT
npm run debug -- state <deviceId> ON_OFF_LIGHT
npm run debug -- rooms
npm run debug -- scenes
npm run debug -- reports
npm run debug -- permit-join 60
npm run debug -- call-scene 1如果你要直接调原始协议请求,用 raw:
export BAIWEI_MSG_CLASS=CONTROL_MGMT
export BAIWEI_MSG_NAME=DEVICE_STATE_GET
export BAIWEI_MSG_TYPE=GET
export BAIWEI_RAW_PAYLOAD='{"device":{"type":"On/Off Light"}}'
npm run debug -- raw几个调试建议:
- 连通性先看
overview,它会快速验证连接、登录、设备/房间/场景查询。 - 想观察网关主动上报时,用
reports,保持连接直到你按Ctrl+C。 - 想看 SDK 底层收发和报文切包,打开
BAIWEI_DEBUG=1。 state和states在当前无状态设计下都需要显式传设备类型。
小结
一句话概括:baiwei-sdk 更适合作为“百微网关协议驱动层”,而不是最终业务层。
如果你在别的库里使用它,最佳实践通常是:
- 复用单连接
- 集中登录
- 自己做缓存
- 自己做事件模型
- 需要时直接走原始协议请求
