ztUtil SDK(端侧设备通信)
ztUtil(app-lightsmart-ztutil)是轻享智能的端侧设备通信 SDK,封装了 BLE 配网、MQTT 通信、设备控制等底层功能,是应用与硬件设备之间的唯一通信桥梁。
除纯 HTTP 接口(用户登录、家庭管理、设备列表拉取)外,所有涉及"与设备交互"的功能全部依赖本模块。
通过平台适配层支持微信小程序、浏览器、Node.js 等多种运行环境,业务代码无需关心平台差异。
支持的平台
| 平台 | MQTT 远程控制 | BLE 蓝牙 | 本地存储 | HTTP 请求 |
|---|---|---|---|---|
| 微信小程序 / uni-app | ✅ | ✅ 完整 | ✅ | ✅ |
| 浏览器 | ✅ | ⚠️ 有限(Web Bluetooth) | ✅ | ✅ |
| Node.js | ✅ | ⚠️ 需安装 noble | ✅ | ✅ |
BLE 蓝牙的完整功能(配网、Mesh、外设模式)仅在微信小程序中可用。浏览器和 Node.js 适合使用 MQTT 远程控制模式。
安装与配置
微信小程序 / uni-app
// package.json
{
"dependencies": {
"app-lightsmart-ztutil": "file:../app-lightsmart-ztutil"
}
}// vite.config.js
import { ztUtilPolyfill } from 'app-lightsmart-ztutil/vite-plugin'
export default defineConfig({
plugins: [
uni(),
ztUtilPolyfill(), // 注入 Buffer/process polyfill + 修复 mqtt wx transport
],
})可选参数:
ztUtilPolyfill({ platform: 'mp-weixin' }) // 指定目标平台产物路径(默认 mp-weixin)
ztUtilPolyfill({ platform: 'mp-alipay' }) // 支付宝小程序
ztUtilPolyfill({ enabled: false }) // 禁用插件浏览器 / Node.js
直接 import 使用,不需要 Vite 和 vite-plugin。平台适配器在模块加载时自动检测运行环境。
npm install app-lightsmart-ztutil单文件构建
如需将 SDK 打包为单文件发给别人(如嵌入 HTML 页面、无 npm 环境使用),可编译为自包含的单文件产物:
cd app-lightsmart-ztutil
npm run build:bundle产物在 dist/ 目录下,零外部依赖:
| 文件 | 格式 | 用途 |
|---|---|---|
ztutil.bundle.js | UMD(minified) | <script> 引入 / require() |
ztutil.bundle.esm.js | ESM | import 引入 |
浏览器使用:
<script src="ztutil.bundle.js"></script>
<script>
const { ztUtil, MODE_MQTT } = ztUtil;
ztUtil.setMode(MODE_MQTT);
ztUtil.connectMqtt({ /* ... */ });
</script>Node.js 使用:
const { ztUtil } = require('./ztutil.bundle.js');导入
// npm 包引入
import { ztUtil as ysUtil } from 'app-lightsmart-ztutil'
// ztUtil === ysUtil(同一个 ZtUtil 实例)
// 单文件引入
import { ztUtil as ysUtil } from './ztutil.bundle.esm.js'通信模式
| 模式 | 常量 | 触发条件 | 典型用途 |
|---|---|---|---|
| MQTT 远程 | MODE_MQTT = 4 | 网关在线时自动选择 | 设备控制/状态查询/场景执行(最常用) |
| BLE 蓝牙 | MODE_BLE = 2 | 网关不在线时回退 | 近场设备控制/配网/扫描添加 |
| YiMesh | MODE_YIMESH = 1 | 特定设备类型 | Mesh 设备配网(旧协议) |
模式选择逻辑
- 查当前家庭是否有网关设备(
type === "wangguanchazuo") - 有网关 →
MODE_MQTT(通过connectMqtt远程连接网关) - 无网关但蓝牙可用 →
MODE_BLE(通过connectBle直连设备代理) - 都不可用 → 抛出"没有合适的连接方式"
API 分类
网络连接与初始化
| 方法 | 参数 | 返回 | 说明 |
|---|---|---|---|
init(params) | { companyCode, roomPrivateKey, verifyCode, connectMode, callback } | {code, msg} | 初始化 SDK,校验秘钥 |
register(callback) | callback(res) | — | 注册状态推送回调 |
unregister() | — | — | 注销回调 |
setMode(mode) | MODE_BLE | MODE_MQTT | — | 切换通信模式 |
bleIsOk() | — | boolean | 检查蓝牙是否可用 |
register 回调 code
| code | 含义 | data 字段 |
|---|---|---|
1000 | 蓝牙连接成功 | — |
2000 | 设备状态推送 | naddr, status |
2001 | OTA 升级进度 | mac, status, percent |
-2000 | 设备离线状态 | naddr, offline |
-1001 | 蓝牙连接断开 | type: 'active' | 'non_active' |
蓝牙连接 (MODE_BLE)
| 方法 | 参数 | 说明 |
|---|---|---|
connectBle(params, callback) | { deviceMacList, gatewayMacList, checkPrivateKey } | BLE 连接网关/设备代理 |
closeBLEConnection() | — | 断开蓝牙连接 |
connectGatewayBle(params, callback) | { gatewayMac } | 连接指定网关 BLE |
MQTT 连接 (MODE_MQTT)
| 方法 | 参数 | 说明 |
|---|---|---|
connectMqtt(params) | { serverUrl, username, password, serverId, mqId, callback, receiveMsgCallback } | MQTT 远程连接网关 |
closeMqtt() | — | 断开 MQTT 连接 |
systemPublish(data) | { module_sn, mstype, timestamp, data } | 通过 MQTT 发送系统命令 |
网关管理
| 方法 | 参数 | 返回 | 说明 |
|---|---|---|---|
addGateway(params, callback) | { gateway } | callback({code, data}) | 添加新网关 |
configWifi(params) | { ssid, psk, gatewayMac } | {code, msg} | 给网关配置 WiFi |
getGatewaySn() | — | {code, data} | 获取网关 SN |
getGatewayRSSI() | — | {code, data} | 获取网关信号强度 |
getGatewayIp() | — | {code, data} | 获取网关 IP |
restoreGateway() | — | {code} | 网关恢复出厂 |
startScanGateway(params) | { callback } | — | 扫描网关 |
stopScanGateway() | — | — | 停止扫描网关 |
设备扫描与添加
| 方法 | 参数 | 说明 |
|---|---|---|
startScanDevices(params) | { deviceMacList, containGateway, callback } | 扫描 BLE/MQTT 设备 |
stopScanDevices() | — | 停止扫描 |
enableDeviceConfigState(params) | { mac, timeDelay, cb } | 使设备进入配网状态 |
addDevice(params) | { item, naddr, callback } | 添加单个设备 |
addDeviceList(params) | { deviceList, callback } | 批量添加设备 |
resetParams(naddr) | naddr | 重置设备参数 |
设备控制
| 方法 | 参数 | 说明 |
|---|---|---|
controlDevice(params, callback) | { action, device, payload } | 控制设备开关/亮度/色温/窗帘 |
controlGroupDevice(params) | { action, groupType, groupId, payload } | 群组控制(灯组) |
getDeviceStatus(params, callback) | { device, action } | 查询设备状态 |
getCurtainPosition(params) | { naddr } | 查询窗帘位置 |
controlDevice action 列表
| action | 适用设备 type | payload | 说明 |
|---|---|---|---|
turn_on / turn_off | 1/2/12/41/42(开关) | { index } | 开关控制 |
turn_on / turn_off | 4/24(灯) | { index } | 灯控制 |
turn_on_all / turn_off_all | 1/2/12/4/5 | — | 全开/全关 |
set_brightness | 4/24 | { brightness } | 设置亮度 |
set_colour_temperature | 4/24 | { value } | 设置色温 |
open_curtain / close_curtain / stop_curtain | 5 | — | 窗帘控制 |
position_curtain | 5 | { position } | 窗帘到位 |
set_back_light_on / set_back_light_off | 1/2/12 | — | 背光控制 |
场景管理
| 方法 | 参数 | 说明 |
|---|---|---|
execScene(params, callback) | { sceneId } | 执行场景 |
configSceneSwitch(params, callback) | { sceneId, keyList, device } | 配置开关场景 |
configSceneCurtain(params) | { sceneId, naddr, action, position } | 配置窗帘场景 |
configSceneLight(params, callback) | { sceneId, naddr, action, ... } | 配置智能灯场景 |
deleteDeviceScene(params, callback) | { naddr, sceneId } | 删除设备场景 |
开关按键配置
| 方法 | 参数 | 说明 |
|---|---|---|
configSwitchKeyFunc(params, callback) | { naddr, keyList } | 配置按键功能 |
setSwitchKeySceneCmd(params, callback) | { naddr, ... } | 设置按键场景命令 |
setSwitchKeyPub(params) | { naddr, pubList } | 设置按键广播 |
设备维护
| 方法 | 参数 | 说明 |
|---|---|---|
restoreFactory(params, callback) | { naddr } | 设备恢复出厂 |
readVersion(naddr) | naddr | 读取固件版本 |
setDeviceToGroup(params) | { naddr, groupIds } | 设备加入群组 |
configCurtainRemote(params) | { naddr, rcuMac } | 配置窗帘遥控器 |
使用示例
1. 初始化 + 连接网关(MQTT 远程)
import { ztUtil as ysUtil } from 'app-lightsmart-ztutil'
await ysUtil.init({
companyCode: '5192a5a4',
roomPrivateKey: project.private_key,
verifyCode: sha256(private_key + '5192a5a4' + '37b08e2b975e6fd153874381f091762b').substr(0, 16),
connectMode: ysUtil.MODE_MQTT,
})
ysUtil.register(callback => {
if (callback.code === 2000) {
// 设备状态推送:callback.data.naddr + callback.data.status
}
if (callback.code === -1001) {
// 蓝牙断开
}
})
ysUtil.setMode(ysUtil.MODE_MQTT)
await ysUtil.connectMqtt({
serverUrl: 'wxs://hotel.chintiot.com/mqtt',
username: mq_id,
password: mq_pass,
serverId,
mqId,
callback: res => {
if (res.code === 0) console.log('MQTT 连接成功')
},
})
serverUrl中的wxs://协议前缀会被平台适配器自动转换:微信保持wxs://,浏览器转为wss://,Node.js 转为mqtts://。业务代码无需关心平台差异。
2. 控制设备
ysUtil.controlDevice({
action: 'turn_on',
device: { naddr: 0x0001, type: 1, subNum: 1 },
payload: { index: 0 }
}, res => {
if (res.code === 0) console.log('控制成功')
})3. 执行场景
ysUtil.execScene({ sceneId: 5 }, res => {
if (res.code === 0) console.log('场景执行成功')
})4. 蓝牙配网
ysUtil.setMode(ysUtil.MODE_BLE)
ysUtil.connectBle({ gatewayMacList: ['AABBCCDDEEFF'] }, res => {
if (res.code === 0) {
ysUtil.configWifi({
ssid: 'MyWiFi',
psk: 'password',
gatewayMac: 'AABBCCDDEEFF'
})
}
})configWifi 工作方式
通过蓝牙发送 AT 命令 AT+CWJAP="ssid","psk" 给网关,不下发服务器地址。网关连上 WiFi 后,固件自行调用 hapi module/login 获取 MQTT 地址(hapi 地址硬编码在固件中)。
平台适配层
ztUtil 通过平台适配层实现跨平台能力。业务代码不直接访问 wx/uni/window 等平台全局对象,而是通过适配器统一调用。适配器在模块加载时自动检测运行环境并选择对应实现。
自动检测优先级
| 优先级 | 检测条件 | 选择的适配器 |
|---|---|---|
| 1 | typeof uni !== 'undefined' | 微信小程序(uni-app 环境) |
| 2 | typeof wx !== 'undefined' | 微信小程序(原生) |
| 3 | typeof window !== 'undefined' | 浏览器 |
| 4 | process.versions.node 存在 | Node.js |
| 5 | 兜底 | 微信小程序(globalThis 回退) |
手动指定平台
import { setPlatform, BrowserPlatform } from 'app-lightsmart-ztutil'
// 强制使用浏览器适配器(如测试环境)
setPlatform(new BrowserPlatform())新增平台
新增平台只需在 src/platform/ 目录下添加适配器文件并继承 BasePlatform,无需修改任何业务代码。
内部架构
ztUtil (ZtUtil 主类, 58 方法)
├── ble (BleLayer + GatewayCommander, 68 方法)
│ ├── 设备发现: discoverBleDevice / startBlePair / startScanGateway
│ ├── 连接管理: commonConnectBleDevice / closeBLEConnection
│ ├── 指令收发: commonSendCommandV2 / processBleCommand
│ └── GatewayCommander: configSceneSwitch / restoreFactory / readVersion / ...
├── mqttManager (MqttLayer, 3 方法)
│ ├── initMqtt / closeMqtt / systemPublish
│ └── mqtt@4.3.8 + readable-stream@2.3.8(锁版本兼容)
└── protocol (协议编解码)
├── buildCommand(command, params) → hex 指令
├── parseStatusData(hex) → 状态对象
└── matchCommand(sent, received) → 响应匹配BLE 服务 UUID
| Service UUID | 用途 |
|---|---|
FFE0 | 网关 BLE 服务(配网/AT 命令) |
1827 | 设备代理服务(未连接网关时直连设备) |
1828 | Mesh 设备服务(已连接网关时代理发现) |
BLE 指令帧格式
53 <msgType> <cmdLen> <naddr_le> <opcode> <data> <xor>与 hapi → 网关的 ble_in 格式完全一致(同一套协议),区别在于传输通道:hapi 走 MQTT,ztUtil BLE 模式走微信 BLE API 直连。
影响的小程序功能
| 功能域 | 涉及页面 | 使用的核心方法 |
|---|---|---|
| 首页/智能 | index、zhineng、mine | init、register、connectMqtt、getGatewayRSSI、controlDevice、execScene |
| 设备控制 | control、info、kaiguan/*、curtainmotor/*、dimmingcontroller/*、tiaoguang2/* | controlDevice、controlGroupDevice、getDeviceStatus、getCurtainPosition、readVersion |
| 网关管理 | gateway/list、wangguanchazuo/info、wangguanchazuo/voice-auth | connectMqtt、getGatewayRSSI、getGatewayIp、getGatewaySn、restoreGateway、systemPublish |
| 设备添加/配网 | dev_add/index、dev_add/conn_wifi | configWifi、addDevice、addDeviceList、addGateway、startScanDevices、stopScanDevices |
| 场景管理 | scene/config、scene_add/* | configSceneSwitch、configSceneLight、configSceneCurtain、execScene、deleteDeviceScene |
| 设备配置 | kaiguan/config、curtainmotor/config、dimmingcontroller/config、upgrade | configSwitchKeyFunc、configCurtainRemote、setDeviceToGroup、resetParams、restoreFactory |
| 家庭/房间 | house、house_edit、house_transfer、room、room_detail | UQRCode、closeBLEConnection、closeMqtt、systemPublish |
| 登录/账户 | login/index、login/use_mobile、account_delete、account_secure | init、register、closeMqtt、closeBLEConnection |
| 配置恢复 | config_recovery/list | restoreFactory、systemPublish |
共计影响 53 个页面(3 个直接调用 + 50 个通过设备状态管理间接依赖)。
