-
Notifications
You must be signed in to change notification settings - Fork 184
如何开发一个新驱动
当前涂鸦仅支持 部分 PBT 类别 产品接入 Homebridge。 你可以基于自身的业务需求,结合涂鸦提供的标准指令集文档,通过以下的流程,开发 Tuya Homebridge 插件的单品硬件驱动,实现通过 Homebridge 控制更多的 PTB 设备。
即使部分 PBT 品类的设备未接入 Homebridge,但是我们还是可以通过运行 Tuya Homebridge 插件的方式,在日志中获取该设备状态信息,例如设备在涂鸦产品体系中的分类,即品类 catagory
。
-
开启调试模式,查看调试日志。
说明: 调试模式下查看日志的方法参见 如何获取日志。
-
在日志中通过 您的设备名称 获取设备信息的日志。
说明: 以 "active_time" 开始, 以 "uuid" 结束。例如,从日志中搜
"Living room switch"
,能获取到该设备的信息,示例代码如下。{ "active_time": 1623229189, "biz_type": 18, "category": "cz", "create_time": 1560491945, "icon": "smart/product_icon/cz.png", "id": "xxxxxxxxxxxxxxx", "ip": "xxxxxxxxxxxxxxx", "lat": "30.30286857361191", "local_key": "xxxxxxxx", "lon": "120.0639743842656", "model": "", "name": "Living room switch", "online": false, "owner_id": "34794909", "product_id": "yfemiswbgjhddhcf", "product_name": "Switch Product", "status": [ { "code": "switch", "value": false }, { "code": "countdown_1", "value": 0 }, { "code": "cur_current", "value": 0 }, { "code": "cur_power", "value": 0 }, { "code": "cur_voltage", "value": 2343 } ], "sub": false, "time_zone": "+08:00", "uid": "ay1622097934070h5Mpi", "update_time": 1625101929, "uuid": "65015854bcddc21a9073" }
获取了品类信息后,你可以在涂鸦开发者平台的文档中心,通过 category
(例如,cz)获取标准指令集和标准状态集的参数说明,为后续驱动开发做准备。
-
获取品类的指令集和状态集参数说明。
-
从日志中的
"category": "cz"
获知,本示例中的设备 "Living room switch" 在涂鸦定义的品类为cz
。 -
在 涂鸦开发者文档中心 的左侧目录搜索栏,搜索品类值(例如
cz
)对应云端指令集和状态集。
-
-
获取品类的 Homebirdge 服务模板。 在 HomeBridge API 中查找相对接近的 Service 模型,方便后续的驱动开发。本示例中, 插座比较接近 Outlet,因此选择 Outlet Service。
-
根据选择的 Outlet Service,在
tuya-homebridge
项目中新建outlet_accessory.js
文件。 -
添加品类。 需要支持的设备为
cz
,所以在index.js
文件中的addAccessory()
方法中添加cz
,代码如下。case 'cz': deviceAccessory = new OutletAccessory(this, homebridgeAccessory, device); this.accessories.set(uuid, deviceAccessory.homebridgeAccessory); this.deviceAccessories.set(uuid, deviceAccessory); break;
-
开发插件。
在
outlet_accessory.js
文件中开发插件,代码示例参见 outlet_accessory.js。-
设置 Characteristics,并且设置该属性的 Get 和 Set 回调。
说明: Characteristics 是 HomeBridge API 中 Outlet 类型对应 Service 的属性,Outlet 的 Service 的 Characteristics 参数为 on。
-
get
:将设备的状态返回 HomeBridge,用于 Home App 上的展示。 -
set
:在 Home App 触发开、关动作时,通过该回调下发对应的指令给设备。
if (this.isRefresh) { service .getCharacteristic(Characteristic.On) .updateValue(value); } else { this.getAccessoryCharacteristic(service, Characteristic.On); }
getAccessoryCharacteristic(service, name) { //set Accessory service Characteristic service.getCharacteristic(name) .on('get', callback => { if (this.hasValidCache()) { callback(null, this.getCachedState(service.displayName)); } }) .on('set', (value, callback) => { var param = this.getSendParam(service.displayName, value) this.platform.tuyaOpenApi.sendCommand(this.deviceId, param).then(() => { this.setCachedState(service.displayName, value); callback(); }).catch((error) => { this.log.error('[SET][%s] Characteristic.Brightness Error: %s', this.homebridgeAccessory.displayName, error); this.invalidateCache(); callback(error); }); }); }
-
-
在 get 回调中将 DP Code ("switch") 对应的值("false")回调给 Homebridge Service,在 set 回调中将 "switch" 作为 dp code 与对应的 value 下发至设备。
"status": [ { "code": "switch", "value": false }, { "code": "countdown_1", "value": 0 }, ]
code
和value
的对应关系你可以在标准指令集和标准状态集说明中获取。以下为开启灯光的指令。
{ "code": "switch", "value": true }
-
新增品类后,你可以再次运行 Tuya Homebridge 插件,成功连接 Homekit 后,在 HomeKit 上控制 PBT 设备。
当你启动插件的时候,入口文件 index.js
会去调用 TuyaSHOpenAPI().getDevices()
获取当前关联 App 账号下的设备,获取到设备后,会遍历调用 this.addAccessory(device);
来将对应的 PBT 设备创建对应的 Accessory
实例然后注册到 PlatformAccessories
中。
Accessory、Service 的创建实现在 base_accessory.js
中,不需要开发者独立开发。
//Accessory
if (this.homebridgeAccessory) {
this.homebridgeAccessory.controller = this;
if (!this.homebridgeAccessory.context.deviceId) {
this.homebridgeAccessory.context.deviceId = this.deviceConfig.id;
}
this.log.log(`Existing Accessory found ${homebridgeAccessory.displayName} ${homebridgeAccessory.context.deviceId} ${homebridgeAccessory.UUID}`);
this.homebridgeAccessory.displayName = this.deviceConfig.name;
}
else {
// Create new Accessory
this.log.log(`Creating New Accessory ${this.deviceConfig.id}`);
this.homebridgeAccessory = new PlatformAccessory(
this.deviceConfig.name,
UUIDGen.generate(this.deviceConfig.id),
categoryType);
this.homebridgeAccessory.context.deviceId = this.deviceConfig.id;
this.homebridgeAccessory.controller = this;
this.platform.registerPlatformAccessory(this.homebridgeAccessory);
}
// Service
if (this.subServices.length == 0) {
// Service
this.service = this.homebridgeAccessory.getService(this.serviceType);
if (this.service) {
this.service.setCharacteristic(Characteristic.Name, this.deviceConfig.name);
}
else {
// add new service
this.service = this.homebridgeAccessory.addService(this.serviceType, this.deviceConfig.name);
}
} else {
// SubService
for (const subService of this.subServices) {
var service = this.homebridgeAccessory.getService(subService);
if (service) {
service.setCharacteristic(Characteristic.Name, subService);
} else {
// add new subService
this.homebridgeAccessory.addService(this.serviceType, subService, subService);
}
}
}
-
index.js
:添加你需要的品类至addAccessory()
function, 然后创建对应的****_accessy.js
文件。 -
****_accessory.js
:遍历设备信息的 Code ,创建对应的Characteristic
。 -
tuyaopenapi.js
:包含设备相关的 APIs -
tuyamqttapi.js
:包含 MQTT 服务相关配置
更多关于 Homebridge 安装的信息参见Homebridge Common Issues。
-
login(username, password)
: 登录涂鸦 IoT 平台 -
getDeviceList()
: 获取资产下所有设备的信息 -
get_assets()
: 获取可用资产 -
getDeviceIDList(assetID)
: 获取指定资产下设备 ID -
getDeviceFunctions(deviceID)
: 获取设备支持的指令集 -
getDeviceInfo(deviceID)
: 获取单个设备详细信息 -
getDeviceListInfo(devIds = [])
: 获取多个设备的详细信息 -
getDeviceStatus(deviceID)
: 获取单个设备的状态 -
getDeviceListStatus(devIds = [])
: 获取多个设备的状态 -
sendCommand(deviceID, params)
: 对设备发送指令
更多信息参见 Tuya Open API docs。
-
start()
: 启动 MQTT -
stop()
: 中断 MQTT -
addMessageListener(listener)
: 添加回调 -
removeMessageListener(listener)
: 删除回调