更新时间:2022-02-17 07:06:03下载pdf
涂鸦蓝牙有三条技术线路,即蓝牙设备与手机一对一相连的蓝牙单点设备、涂鸦自研的蓝牙拓扑通信 涂鸦 Mesh 、蓝牙技术联盟发布的蓝牙拓扑通信 蓝牙 Mesh。本文主要介绍涂鸦 Mesh 相关设备的配网、控制、管理等开发指导。
不同的智能产品适用的蓝牙类型如下所示。
分类 | 产品举例 |
---|---|
蓝牙单点 | 体脂秤、手环、温控器、电动牙刷、门锁等 |
蓝牙 Mesh | 一路、二路、五路等灯泡、插座、传感器等蓝牙 Mesh 子设备 |
涂鸦 Mesh | 与蓝牙 Mesh 产品类似,协议为涂鸦智能自研 |
双模设备 | 蓝牙 Mesh 网关、IPC 设备以及新版多协议 Wi-Fi 设备等 |
除此之外,还有一些多协议设备也会使用到蓝牙技术,例如同时具备 Wi-Fi 能力和蓝牙能力的 双模设备,也可以使用蓝牙进行配网,当然 Wi-Fi 设备原本的配网仍然可用。双模配网的蓝牙配网部分,使用的是蓝牙单点技术为设备配网。详情请参考 蓝牙单点。
开发蓝牙 Mesh 功能前,请先熟悉智能生活 App SDK。Mesh 的所有操作都建立在站点数据已经初始化的基础上。一个站点里可以拥有多个 Mesh,但建议只创建一个 Mesh。
系统要求:蓝牙使用需要安卓 4.3 以及以上版本,智能生活 App SDK 从安卓 4.4 开始支持。
Manifest 权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
使用蓝牙前的权限检测
App 在使用蓝牙连接或者扫描操作前 需要检查 App 定位权限是否被允许。
检查蓝牙状态是否为开启。
该部分检查逻辑,智能生活 SDK 未提供 API,您可自行检测。每次扫描和连接前都要进行检测,否则 App 无法正常使用蓝牙。
Mesh 产品目前分为:
相关名词 | 说明 |
---|---|
NodeId | 表示 Mesh 节点,为 2 字节字段。NodeId 用于区分每个 Mesh 设备在 Mesh 网中的唯一标识,控制某个设备就向 Mesh 网发此设备对应的 NodeId 命令即可。 |
LocalId | 表示 Mesh 群组,为 2 字节字段。LocalId 用于区分每个 Mesh 群组在 Mesh 网中的唯一标识,控制某个群组中的设备就向 Mesh 网发此群组对应的 LocalId 命令即可。 |
多步操作 | 因为设备的操作,例如增删操作、群组操作,都需要本地蓝牙命令执行一次、云端记录一次。所以,向本地 Mesh 网同步操作信息的同时也需要向云端同步操作信息。 |
本地连接 | 指已配网设备通过蓝牙连接,来控制 Mesh 和指令操作 |
网关连接 | 指已配网设备通过网关连接(网关需和设备在一起,距离不能太远),来控制 Mesh 和指令操作 |
接口说明
void createBlueMesh(String meshName, ITuyaResultCallback<BlueMeshBean> callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
meshName | String | Mesh 的名称,不超过 16 字节 |
callback | ITuyaResultCallback | 回调 |
示例代码
TuyaHomeSdk.newHomeInstance("homeId").createBlueMesh("meshName", new ITuyaResultCallback<BlueMeshBean>() {
@Override
public void onError(String errorCode, String errorMsg) {
}
@Override
public void onSuccess(BlueMeshBean blueMeshBean) {
}
});
接口说明
void removeMesh(IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
callback | IResultCallback | 回调 |
示例代码
TuyaHomeSdk.newBlueMeshDeviceInstance(meshId).removeMesh(new IResultCallback() {
@Override
public void onError(String errorCode, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
接口说明
List<BlueMeshBean> getMeshList();
示例代码
ITuyaHome mTuyaHome = TuyaHomeSdk.newHomeInstance("homeId");
if (mTuyaHome.getHomeBean() != null){
List<BlueMeshBean> meshList = mTuyaHome.getHomeBean().getMeshList();
BlueMeshBean meshBean= meshList.get(0);
}
接口说明
List<DeviceBean> getMeshSubDevList();
示例代码
List<DeviceBean> meshSubDevList = TuyaHomeSdk.newBlueMeshDeviceInstance("meshId").getMeshSubDevList();
建议在切换站点时,销毁当前 Mesh,然后重新初始化站点中的 Mesh。
接口调用
//初始化Mesh
TuyaHomeSdk.getTuyaBlueMeshClient().initMesh(String meshId);
//销毁当前Mesh
TuyaHomeSdk.getTuyaBlueMeshClient().destroyMesh();
ITuyaBlueMeshClient
提供开始连接、断开连接、开启扫描、停止扫描等接口。
接口调用
// 开启连接
TuyaHomeSdk.getTuyaBlueMeshClient().startClient(mBlueMeshBean);
//断开连接
TuyaHomeSdk.getTuyaBlueMeshClient().stopClient();
//开启扫描
TuyaHomeSdk.getTuyaBlueMeshClient().startSearch()
//停止扫描
TuyaHomeSdk.getTuyaBlueMeshClient().stopSearch();
startClient()
)时,调用 startSearch()
和 stopSearch()
属于无效操作。startSearch()
和 stopSearch()
也属于无效操作。Mesh 配网主要分为两种:
普通蓝牙 Mesh 设备,又称 Mesh 子设备
Mesh 网关配网
常见的子设备有智能灯、智能插座、低功耗产品等。只要不带 Mesh 网关,都可以等同于普通蓝牙 Mesh设备。
处于重置状态的设备,默认名字为 out_of_mesh
,默认密码为 123456
。重置设备可以通过以下常见方式操作:
产品类型 | 重置操作 | 可配网现象 |
---|---|---|
智能灯 | 连续开关三次 | 灯快闪 |
智能插座 | 长按开关 3s | 插座指示灯快闪 |
网关产品 | 长按开关 3s | 红灯和蓝灯快闪 |
低功耗设备 | 长按开关 3s | 再按一次出现长亮即可配网,且配网需在灯亮期间完成 |
报警器 | 长按开关 3s | 灯快闪 |
扫描前需要检查蓝牙和位置权限,扫描附近的待配网 Mesh 设备。
接口说明
//开启扫描
void startSearch();
//停止扫描
void stopSearch();
示例代码
ITuyaBlueMeshSearchListener iTuyaBlueMeshSearchListener = new ITuyaBlueMeshSearchListener() {
@Override
public void onSearched(SearchDeviceBean deviceBean) {
}
@Override
public void onSearchFinish() {
}
};
SearchBuilder searchBuilder = new SearchBuilder()
//要扫描设备的名称(默认会是out_of_mesh,设备处于配网状态下的名称)
.setMeshName("out_of_mesh")
.setTimeOut(100) //扫描时长 单位秒
.setTuyaBlueMeshSearchListener(iTuyaBlueMeshSearchListener).build();
ITuyaBlueMeshSearch mMeshSearch = TuyaHomeSdk.getTuyaBlueMeshConfig().newTuyaBlueMeshSearch(searchBuilder);
//开启扫描
mMeshSearch.startSearch();
//停止扫描
mMeshSearch.stopSearch();
接口说明
//开启配网
void startActivator();
//停止配网
void stopActivator();
参数说明
参数 | String | 说明 |
---|---|---|
mSearchDeviceBeans | List | 待配网的设备集合 |
timeout | Int | 配网的超时时间设置,默认是 100s. |
ssid | String | 配网之后,设备连接的 Wi-Fi 的名称。(站点网络) |
password | String | 配网之后,设备连接的 Wi-Fi 的密码。(站点网络) |
mMeshBean | MeshBean | MeshBean |
homeId | Long | 设备要加入的 Mesh 网的所属站点 |
version | String | 普通设备配网:1.0 网关配网:2.2 |
代码示例
//普通设备入网
TuyaBlueMeshActivatorBuilder tuyaBlueMeshActivatorBuilder = new TuyaBlueMeshActivatorBuilder()
.setSearchDeviceBeans(foundDevices)
.setVersion("1.0")
.setBlueMeshBean(mMeshBean)
.setTimeOut(timeOut)
.setTuyaBlueMeshActivatorListener(new ITuyaBlueMeshActivatorListener() {
@Override
public void onSuccess(DeviceBean deviceBean) {
}
@Override
public void onError(String errorCode, String errorMsg) {
}
@Override
public void onFinish() {
}});
ITuyaBlueMeshActivator iTuyaBlueMeshActivator = TuyaHomeSdk.getTuyaBlueMeshConfig().newActivator(tuyaBlueMeshActivatorBuilder);
//开始入网
iTuyaBlueMeshActivator.startActivator();
//停止入网
iTuyaBlueMeshActivator.stopActivator();
接口说明
//开启配网
void startActivator();
//停止配网
void stopActivator();
参数说明
参数 | String | 说明 |
---|---|---|
mSearchDeviceBeans | List | 待配网的设备集合 |
timeout | Int | 配网的超时时间设置,默认值:100s |
ssid | String | 配网之后,设备连接的 Wi-Fi 的名称。(站点网络) |
password | String | 配网之后,设备连接的 Wi-Fi 的密码。(站点网络) |
mMeshBean | MeshBean | MeshBean |
homeId | Long | 设备要加入的 Mesh 网的所属站点 |
version | String | 普通设备配网:1.0 网关配网:2.2 |
代码示例
//网关入网
TuyaBlueMeshActivatorBuilder tuyaBlueMeshActivatorBuilder = new TuyaBlueMeshActivatorBuilder()
.setWifiSsid(mSsid)
.setWifiPassword(mPassword)
.setSearchDeviceBeans(foundDevices)
.setVersion("2.2 ")
.setBlueMeshBean(mMeshBean)
.setHomeId("homeId")
.setTuyaBlueMeshActivatorListener(new ITuyaBlueMeshActivatorListener() {
@Override
public void onSuccess(DeviceBean devBean) {
//单个设备配网成功回调
L.d(TAG, "startConfig success");
}
@Override
public void onError(String errorCode, String errorMsg) {
//单个设备配网失败回调
//errorCode 见错误码
L.d(TAG, "errorCode: " + errorCode + " errorMsg: " + errorMsg);
}
@Override
public void onFinish() {
//所有设备配网结束回调
}
});
ITuyaBlueMeshActivator iTuyaBlueMeshActivator = TuyaHomeSdk.getTuyaBlueMeshConfig().newWifiActivator(tuyaBlueMeshActivatorBuilder);
//开始入网
iTuyaBlueMeshActivator.startActivator();
//停止入网
//iTuyaBlueMeshActivator.stopActivator();
错误码 | 说明 |
---|---|
13007 | 登录设备失败 |
13004 | 重置设备地址失败 |
13005 | 设备地址已满 |
13007 | SSID 为空 |
13011 | 配网超时 |
方法接口
DeviceBean deviceBean=TuyaHomeSdk.getDataInstance().getDeviceBean(mDevId);
// 蓝牙 Mesh 设备判断 (子设备+网关)
if(deviceBean.isBlueMesh()){
L.d(TAG, "This device is blue mesh device");
}
// 蓝牙 Mesh 网关设备判断
if(deviceBean.isBlueMeshWifi()){
L.d(TAG, "This device is blue mesh wifi device");
}
接口说明
void renameMeshSubDev(String devId, String name, IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
devId | String | 设备 ID |
name | String | 设备新名称 |
callback | IResultCallback | 回调 |
代码示例
mTuyaBlueMesh.renameMeshSubDev(devBean.getDevId(),"设备名称", new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
示例代码
DeviceBean deviceBean=TuyaHomeSdk.getDataInstance().getDeviceBean(mDevId);
DeviceBean gwBean=TuyaHomeSdk.getDataInstance().getDeviceBean(deviceBean.getParentId());
//综合在线状态 (包括本地在线和网关在线)
boolean online=deviceBean.getIsOnline()
//设备本地蓝牙在线状态
boolean localOnline=deviceBean.getIsLocalOnline()
//设备网关在线状态 (需要网关在线且子设备在线 才认为网关真实在线)
boolean wifiOnline=deviceBean.isCloudOnline() && gwBean.getIsOnline()
接口说明
void removeMeshSubDev(String devId, IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
devId | String | 设备 ID |
pcc | String | 设备大小类 |
callback | IResultCallback | 回调 |
代码示例
mTuyaBlueMesh.removeMeshSubDev(devBean.getDevId(), new IResultCallback(){
@Override
public void onError(String code, String errorMsg) {
Toast.makeText(mContext, "子设备移除失败 "+ errorMsg, Toast.LENGTH_LONG).show();
}
@Override
public void onSuccess() {
Toast.makeText(mContext, "子设备移除成功", Toast.LENGTH_LONG).show();
}
});
云端查询到的 DP 数据可能不是当前设备实时的数据。您可以通过该命令去查询设备的当前数据值,结果通过 IMeshDevListener
的 onDpUpdate
方法返回。
接口说明
void querySubDevStatusByLocal(String pcc, String nodeId, IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
pcc | String | 设备大小类 |
nodeId | String | 设备 NodeId |
callback | IResultCallback | 回调 |
代码示例
mTuyaBlueMeshDevice.querySubDevStatusByLocal(devBean.getCategory(), devBean.getNodeId(), new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
ITuyaGroup
类提供了对 Mesh 群组的操作。
可以通过群组中是否具备 MeshId 来区分 Mesh 群组和普通 Wi-Fi 群组。
代码调用
GroupBean groupBean=TuyaHomeSdk.getDataInstance().getGroupBean("groupId");
if(!TextUtils.isEmpty(groupBean.getMeshId())){
L.d(TAG, "This group is a Bluetooth mesh group");
}
Mesh 网内支持创建 28672 个群组,返回时 ID 范围为 16 进制的 8000 ~ EFFF,由本地进行维护。
接口说明
void addGroup(String name, String pcc, String localId,IAddGroupCallback callback);
参数说明
参数 | 说明 |
---|---|
name | 群组名称 |
pcc | 群组中设备的大小类,支持跨小类创建,FF01 表示覆盖灯大类 |
localId | 群组的 LocalId,范围为 16 进制的 8000 ~ EFFF |
callback | 回调 |
示例代码
mITuyaBlueMesh.addGroup("群组名称","大小类", "8001", new IAddGroupCallback() {
@Override
public void onError(String errorCode, String errorMsg) {
}
@Override
public void onSuccess(long groupId) {
}
});
接口说明
void addDevice(String devId,IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
devId | String | 设备 ID |
callback | IResultCallback | 回调 |
示例代码
ITuyaGroup mGroup = TuyaHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.addDevice("devId", new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
接口说明
void removeDevice(String devId,IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
devId | String | 设备 ID |
callback | IResultCallback | 回调 |
示例代码
ITuyaGroup mGroup = TuyaHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.removeDevice("devId", new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
接口说明
void dismissGroup(IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
callback | IResultCallback | 回调 |
接口说明
ITuyaGroup mGroup = TuyaHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.dismissGroup(new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
接口说明
void renameGroup(String groupName,IResultCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
groupName | String | 重命名名称 |
callback | IResultCallback | 回调 |
示例代码
ITuyaGroup mGroup = TuyaHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.renameGroup("群组名称",new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
ITuyaBlueMeshDevice
类提供了对 Mesh 设备的操作
发送控制指令按照以下格式:
{"(dpId)":"(dpValue)"}
接口说明
void publishDps(String nodeId, String pcc, String dps, IResultCallback callback);
参数说明
参数 | 说明 |
---|---|
nodeId | 子设备本地编号 |
pcc | 设备产品大小类 |
dps | 控制指令 |
callback | 回调 |
示例代码
String dps = {"1":false};
ITuyaBlueMeshDevice mTuyaBlueMeshDevice=TuyaHomeSdk.newBlueMeshDeviceInstance("meshId");
mTuyaBlueMeshDevice.publishDps(devBean.getNodeId(), devBean.getCategory(), dps, new IResultCallback() {
@Override
public void onError(String s, String s1) {
}
@Override
public void onSuccess() {
}
});
控制群组通过发送控制指令来实现,控制指令的格式如下:
{
"(dpId)":"(dpValue)"
}
接口说明
void multicastDps(String localId, String pcc, String dps, IResultCallback callback)
参数说明
参数 | 说明 |
---|---|
localId | 群组本地编号 |
pcc | 设备产品大小类 |
dps | 控制指令 |
callback | 回调 |
示例代码
String dps = {"1":false};
ITuyaBlueMeshDevice mTuyaBlueMeshDevice= TuyaHomeSdk.newBlueMeshDeviceInstance("meshId");
mTuyaBlueMeshDevice.multicastDps(groupBean.getLocalId(), devBean.getCategory(), dps, new IResultCallback() {
@Override
public void onError(String errorCode, String errorMsg) {
}
@Override
public void onSuccess() {
}
});
Mesh 网内相关信息(DP 数据、状态变更、设备名称、设备移除)会实时同步到 IMeshDevListener
。
示例代码
mTuyaBlueMeshDevice.registerMeshDevListener(new IMeshDevListener() {
/**
* 数据更新
* @param nodeId 更新设备的nodeId
* @param dps dp数据
* @param isFromLocal 数据来源 true表示从本地蓝牙 false表示从云端
*/
@Override
public void onDpUpdate(String nodeId, String dps,boolean isFromLocal) {
//可以通过node来找到相对应的DeviceBean
DeviceBean deviceBean = mTuyaBlueMeshDevice.getMeshSubDevBeanByNodeId(nodeId);
}
/**
* 设备状态的上报
* @param online 在线设备列表
* @param offline 离线设备列表
* @param gwId 状态的来源 gwId不为空表示来自云端(gwId是上报数据的网关Id) 为空则表示来自本地蓝牙
*/
@Override
public void onStatusChanged(List<String> online, List<String> offline,String gwId) {
}
/**
* 网络状态变化
* @param devId
* @param status
*/
@Override
public void onNetworkStatusChanged(String devId, boolean status) {
}
/**
* raw类型数据上报
* @param bytes
*/
@Override
public void onRawDataUpdate(byte[] bytes) {
}
/**
* 设备信息变更(名称等)
* @param bytes
*/
@Override
public void onDevInfoUpdate(String devId) {
}
/**
* 设备移除
* @param devId
*/
@Override
public void onRemoved(String devId) {
}
});
涂鸦 Mesh 设备的固件升级与蓝牙 Mesh 逻辑一致,详情请参考 蓝牙 Mesh 固件升级 章节。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈