Android 设备 SDK 是一套融合了网关、日志系统、语音功能以及 ota 升级等功能的开发套件,开发者可以基于该 sdk 实现入网、语音控制、固件和 apk 升级等操作。
应用场景
本方案适用于 对 传统带屏的 Android 设备 的智能化改造。在传统的带屏 Android 设备基础上,通过在原有 ROM 内集成 Tuya 的开发包,并增加 Tuya 的硬件通信模块,实现对网关、设备、语音等的控制能力。
目标领域
如 带屏场景面板、可视对讲、带屏音箱、电视等;
适用范围
- 产品基于 Android 系统
- 带屏的 Android 设备
- 需要在屏上显示设备、操作设备
- 有一定底层驱动开发能力及上层交互开发能力
Android 设备 SDK 主要提供:
能力 | 功能 |
---|---|
网关 | 如网关的启动、入网、获取设备虚拟 id、DP 点 下发/上报 功能。 |
日志系统 | 日志的获取保存等 |
测试套件 | zigBee 测试库 |
语音功能 | |
OTA 功能 |
其他能力:如用户管理、家庭管理、场景等操作需要基于 Tuya Home SDK 完成。
-
配置 build.gradle 文件 app 的 build.gradle 文件dependencies 里添加依赖库。
implementation 'com.tuya.smart:tuyasmart-libgateway:1.0.8-hrs' implementation 'com.tuya.smart:tuyasmart-libtestsuit:1.0.1'
-
根目录下 build.gradle 文件添加源:
jcenter()
网关控制实现了启动、入网、获取设备虚拟 id、DP 点 下发/上报 功能。
接口说明
mIotGateway = TuyaIotGateway.getInstance();
创建TuyaIotGateway.GatewayListener
对象, 调用 TuyaIotGateway
的 setGatewayListener
函数注册。回调函数的实现参考回调函数中说明。
接口说明
mIotGateway.setGatewayListener(new TuyaIotGateway.GatewayListener() {
@Override
public void onStatusChanged(int status) {
}
@Override
public void onReset(int type) {
}
@Override
public void onReboot() {
}
@Override
public void onDataPointCommand(int type, int dttType, String cid, String groupid, TuyaIotGateway.DataPoint[] dataPoint) {
}
@Override
public void onNetworkStatus(int status) {
}
@Override
public void onCloudMedia(TuyaIotGateway.MediaAttribute[] mediaAttributes) {
}
@Override
public void onCloudCustom(String type, String msgJson) {}
@Override
public String onGetIP() {
return null;
}
@Override
public void onStartSuccess() {
}
@Override
public void onStartFailure(int err) {
}
@Override
public String onGetLogFile() {
return null;
}
@Override
public String onGetMacAddress() {
return null;
}
});
接口说明
void tuyaIotStart(Context context, Config config);
参数说明
参数 | 说明 |
---|---|
Context | 上下文 |
Config | 网关配置,参看 TuyaIotGateway.Config |
TuyaIotGateway.Config
成员 | 说明 |
---|---|
mPath | 存储路径,该目录要在app中创建 |
mFirmwareKey | 固件key或者pid,向涂鸦申请,产品唯一。 和mIsOEM配合使用: mIsOEM为true时,mFirmwareKey为固件key mIsOEM为false时,mFirmwareKey为pid |
mUUID | 设备唯一,成对出现 |
mAuthKey | authkey,向涂鸦申请,设备唯一,和mUUID成对出现 |
mVersion | 版本号,用于标识app 版本,而不是网关版本 |
mSerialPort | 串口终端 |
mTempDir | 临时文件目录,该目录要在app中创建 |
mBinDir | bin文件目录,该文件夹下不要存放其他文件,该目录要在app中创建 |
mIsCTS | 是否带流控 |
mIsOEM | 是否是oem产品,和mFirmwareKey配合使用。 |
返回值说明
tuyaIotStart 是异步调用,其结果通过回调函数返回,启动成功回调函数 onStartSuccess,失败调用回调函数onStartFailure,参考 网关启动结果回调 中的说明。
启动网关成功之后,才可以入网。
接口说明
public int tuyaIotBindToken(String token);
参数说明
参数 | 说明 |
---|---|
token | 入网 token , 需要登录涂鸦账号之后调用 Tuya Smart Android Home SDK 中的接口获取。 详情请参考 Tuya Smart Android Home SDK - 设备配网 - 获取配网 token 的接口说明。 |
返回值说明
返回值 | 说明 |
---|---|
0 | 调用成功,请注意,调用成功不代表已经入网成功,入网结果通过 onNetworkStatus 通知。 |
非 0 值 | 调用失败,没有入网。 |
入网成功后,可以获取设备虚拟 ID。
接口说明
public String tuyaIotGetId();
接口说明
同步上传透传型 DP 点数据。
public int tuyaIotReportDataPointJsonAsync(String devId, DataPoint[] dataPoint);
参数说明
参数 | 说明 |
---|---|
devId | 如果是主设备,devId 是自设备 id;如果是网关 /soc/mcu,则 devId 为 null |
dataPoint | dp 点信息,参考 TuyaIotGateway.DataPoint |
TuyaIotGateway.DataPoint
成员 | 说明 |
---|---|
mId | 在涂鸦 IoT 平台上定义的功能点编号 |
mType | 功能点的数据类型,支持的数据类型请参见涂鸦文档中心的功能点定义,参考自定义功能: TYPE_BOOL:布尔型 TYPE_VALUE:数值型 TYPE_STRING:字符串型 TYPE_ENUM:枚举型 TYPE_BITMAP:故障型 |
mData | 功能点的值,数据类型由 mType 指定。 |
mTimeStamp | 时间戳,值为 0 时采用当前的时间。 |
接口说明
public int tuyaIotReportDataPointRawSync(String devId, int dataPointId, byte[] data, int timeout);
参数说明
返回值 | 含义 |
---|---|
devId | 如果是主设备,devId 是自设备 id;如果是网关 /soc/mcu,则 devId 为 null |
dataPointId | 在涂鸦 IoT 平台上定义的功能点编号 |
data | 透传型 dp 点数据 |
timeout | 函数阻塞超时时间,以秒为单位 |
在调用 tuyaIotStart 之前应该注册 TuyaIotGateway.GatewayListener 回调函数,以接收处理结果。
接口说明
接收云端下发多媒体数据结构体,获取音频需要通过地址和参数请求音频数据流。
void onCloudMedia(TuyaIotGateway.MediaAttribute[] mediaAttributes);
class TuyaIotGateway.MediaAttribute {
public int mMediaType; //MEDIA_TYPE_MEDIA = 0 多媒体类型; MEDIA_TYPE_TTS = 1 TTS类型;MEDIA_TYPE_INVALD = 2 无效类型;
public String mUrl; //音频数据请求地址
public String mRequestBody; //音频数据请求参数
}
参数说明
返回值 | 含义 |
---|---|
mediaAttributes | 多媒体结构体 |
接口说明
客户定制501透传接口函数,具体协议内容由云端与客户制定,并提供说明。
void onCloudCustom(String type, String msgJson);
参数说明
返回值 | 含义 |
---|---|
type | 接口类型 |
msgJson | 数据json |
接口说明
网关状态更新时回调。
void onStatusChanged(int status);
参数说明
返回值 | 含义 |
---|---|
status | 状态更改通知回调函数: STATUS_RESET:网关被重置 STATUS_ACTIVATED:网关被激活 STATUS_FIRST_START:网关第一次启动 STATUS_NORMAL:网关激活而且已经启动 |
接口说明
网关被重置后回调,app 需要根据 type 的值做相应的操作。
void onReset(int type);
参数说明
返回值 | 含义 |
---|---|
type | 重置类型: RESET_TYPE_LOCAL_RESET_FACTORY:本地恢复工厂设置 RESET_TYPE_REMOTE_UNACTIVE:远端网关重置,即为通过 APP 取消与账号绑定 RESET_TYPE_LOCAL_UNACTIVE:本地网关重置,取消与账号绑定 RESET_TYPE_REMOTE_RESET_FACTORY:远端恢复工厂设置 RESET_TYPE_RESET_DATA_FACTORY:恢复数据工厂设置 |
接口说明
网关请求重启设备。
void onReboot();
接口说明
网关已经被重置,app 需要根据 type 的值做相应的操作。
void onNetworkStatus(int status);
参数说明
返回值 | 含义 |
---|---|
type | 网络状态: NETWORK_STATUS_LAN_UNCONNECTED:联网失败 NETWORK_STATUS_LAN_CONNECTED:本地网络连接成功 NETWORK_STATUS_CLOUD_CONNECTED:云端连接成功,设备已经激活 |
接口说明
DP 点下发。
void onDataPointCommand(int type, int dttType, String cid, String groupid, DataPoint[] dataPoint);
参数说明
返回值 | 含义 |
---|---|
type | 指令类型: DATAPOINT_CMD_LAN:LAN 触发 DATAPOINT_CMD_MQ:MQTT 触发 DATAPOINT_CMD_TIMER:本地定时触发 DATAPOINT_CMD_SCENE_LINKAGE:场景联动触发 DATAPOINT_CMD_RELIABLE_TRANSFER:重发 |
dttType | 传输方式: DATAPOINT_DTT_SCT_UNC:LAN 触发 DATAPOINT_DTT_SCT_BNC:MQTT 触发 DATAPOINT_DTT_SCT_MNC:本地定时触发 DATAPOINT_DTT_SCT_SCENE:场景联动触发 |
cid | cid == NULL 表示控制的网关的功能点;cid != NULL 表示控制的网关子设备的功能点,其中 cid 是子设备的唯一 ID |
groupid | 群组 ID,只有当 dtt_tp = 2 时,该字段才有效。 |
dataPoint | dp点数据,DataPoint类型参考DP点异步上报中的说明。 |
接口说明
获取设备IP。
String onGetIP();
接口说明
获取设备 MAC 地址。
String onGetMacAddress();
接口说明
tuyaIotStart 成功时调用 onStartSuccess 回调。
void onStartSuccess();
接口说明
tuyaIotStart 失败时调用 onStartFailure 回调。
void onStartFailure(int err);
参数说明
返回值 | 含义 |
---|---|
type | 错误码,为 GatewayError 中定义的值之一,常见错误: ERROR_COM_ERROR:网络连接错误 ERROR_INVALID_PARM:参数错误 ERROR_INVALID_STATUS:状态错误 |
接口说明
获取日志文件,如果启用了日志系统,通过 LogDaemon 的 getZippedLogFile() 方法获取日志文件。
String onGetLogFile();
示例代码
@Override
public String onGetLogFile() {
Log.d(TAG, "onGetLogFile");
if(mLogDaemon != null) {
return mLogDaemon.getZippedLogFile();
}
return null;
}
participant APP
participant Gateway
APP->Gateway:getInstance
APP->Gateway:setGatewayListener
APP->Gateway:tuyaIotStart
Gateway-->APP:onStartSuccess
APP->Gateway:tuyaIotBindToken
Gateway-->APP:onStatusChanged
Gateway-->APP:onNetworkStatus
Gateway-->APP:onReboot
APP->APP:reboot
Gateway-->APP:onReset
Note right of APP:如果 onReset 回调非RESET_TYPE_RESET_DATA_FACTORY,则reboot
APP->APP:reboot
接口说明
public LogDaemon(String logDir, int maxfileCount, int fileSizeKB, String prefixName);
参数说明
参数 | 说明 |
---|---|
logDir | 日志路径,如果路径没有创建,日志系统会创建该目录。 |
maxfileCount | 备份的日志文件个数,不包括当前写的文件。 |
fileSizeKB | 文件大小,当日志文件达到 fileSizeKB 指定大小时,会备份当前文件,如果备份的文件个数达到 maxfileCount 指定的值,则删除最老的一个文件。 |
prefixName | 日志文件名,最终生成日志文件 logDir/prefixName.log,备份文件为logDir/prefixName.log.1, logDir/prefixName.log.2... |
示例代码
String filePath = getFilesDir().getAbsolutePath();
String logPath = filePath + File.separator + "log";
//logPath/gateawy.log
mLogDaemon = new LogDaemon(logPath, 10,3*1024, "gateway");
接口说明
public void setExpectation(int pid, String tags, boolean seperate)
参数说明
参数 | 说明 |
---|---|
pid | -1:不按照进程抓取日志;正值:要抓取的进程id。 |
tags | 设置要抓取的 tag,多个 tag 用英文逗号分开,例如 “TuyaIotGateway,LogDaemon”,抓取Android LOG TAG 为 TuyaIotGateway 和 LogDaemon 的日志。 |
seperate | 如果要通过 pid 和 tag 抓取日志,seperate 指定是否分开抓取,如果分开抓取,pid 一份 log,tag 一份 log;否则抓取 pid 中指定的 tag 日志。只有 pid 和 tag 同时有效时,该参数才有意义。 |
示例代码
-
收集指定进程的全部日志
抓取本进程的所有日志:
mLogDaemon.setExpectation(android.os.Process.myPid(), null, false); mLogDaemon.start();
-
收集指定进程中符合 tag 的日志
抓取本进程中 tag 为 TuyaIotGateway 和 LogDaemon 的日志:
mLogDaemon.setExpectation(android.os.Process.myPid(), "TuyaIotGateway,LogDaemon", false); mLogDaemon.start();
-
收集指定 tag 的日志
抓取 tag 为 TuyaIotGateway和 LogDaemon 的日志:
mLogDaemon.setExpectation(-1, "TuyaIotGateway,LogDaemon", false); mLogDaemon.start();
-
收集指定 pid 的日志和指定 tag 的日志,输出两份日志
分别抓取本进程所有日志以及 tag 为 TuyaIotGateway 和 LogDaemon 的日志的日志。
mLogDaemon.setExpectation(android.os.Process.myPid(), "TuyaIotGateway,LogDaemon", true); mLogDaemon.start();
接口说明
public boolean start();
接口说明
设备退出或者重启 app 进程时,请务必也退出日志系统,因为日志系统内部起了 logcat 进程。
public void stop();
接口说明
该接口会将日志目录下的所有日志文件打包为一个 zip 文件。
public String getZippedLogFile();
participant APP
participant LogDaemon as Log
APP->Log:new
APP->Log:setExpectation
APP->Log:start
APP->Log:getZippedLogFile
APP->Log:stop
libtestsuit 是封装的 zigBee 测试库,主要给产测工具用,调用方法:
- 创建 ZigbeeTestSuit.Config 对象,并按说明配置参数。这个 config 和 TuyaIotGateway.Config 基本一致。
- 注册回调函数 ZigbeeTestSuit.OnTestCompletion
- 调用 tuyaZigbeeTest 开始测试
- 在回调函数中检测测试结果,ZigbeeTestSuit.TEST_OK 为测试通过,其它为错误值 ZigbeeTestSuit.TEST_* 之一。
参考 demo ./app/src/main/java/com/tuya/smart/android/demo/test/ZigbeeTest.java中的调用方式。
TuyaIotGateway.VoiceControl.VOICE_MIC_OPEN = 1, //麦克风开启
TuyaIotGateway.VoiceControl.VOICE_MIC_CLOSE = 2, //麦克风关闭
TuyaIotGateway.VoiceControl.VOICE_PLAY = 3, //播放
TuyaIotGateway.VoiceControl.VOICE_PAUSE = 4, //暂停
TuyaIotGateway.VoiceControl.VOICE_BT_PLAY_OPEN = 5, //打开蓝牙
TuyaIotGateway.VoiceControl.VOICE_BT_PLAY_CLOSE = 6,//关闭蓝牙
TuyaIotGateway.VoiceControl.VOICE_PLAY_NEXT = 7, //下一首
TuyaIotGateway.VoiceControl.VOICE_PLAY_PREV = 8, //上一首
接口说明
void setVoiceCapableCallback(VoiceCapableCallback callback)
参数说明
参数 | 说明 |
---|---|
callback | 语音能力回调 |
示例代码
TuyaIotGateway.getInstance().setVoiceCapableCallback(new VoiceCapableCallback() {
void onVolume(int volume) {
TODO("音量变化回调:volume 音量")
}
void onControl(int control) {
TODO("媒体控制回调: control 媒体控制状态")
}
void onAlarm(String alarm) {
TODO("闹钟回调: alarm 闹钟名称")
}
}
)
接口说明
DP上报音量值,在音量改变的情况下,调用此接口。
int voiceCapableReportVol(int volume)
参数
参数名 | 描述 |
---|---|
volume | 音量值 |
返回值
0 : 成功; 其他:失败错误码
示例代码
TuyaIotGateway.getInstance().voiceCapableReportVol(0)
接口说明
DP上报媒体控制状态,在媒体控制状态改变的情况下,调用此接口。
int voiceCapableReportCtl(int control)
参数
参数名 | 描述 |
---|---|
control | 媒体控制状态 |
返回值
0 : 成功; 其他:失败错误码
示例代码
TuyaIotGateway.getInstance().voiceCapableReportCtl(TuyaIotGateway.VoiceControl.VOICE_PLAY);
接口说明
设备端上报语音数据,依次调用开启、上传、结束接口。
示例代码
//开启上传;返回值:0(成功);其他(失败错误码)
TuyaIotGateway.getInstance().tuyaIotUploadMediaStart();
//上传语音数据;参数buffer 音频数据;返回值:0(成功);其他(失败错误码)
TuyaIotGateway.getInstance().tuyaIotUploadMedia(byte[] buffer);
//结束上传;返回值:0(成功);其他(失败错误码)
TuyaIotGateway.getInstance().tuyaIotUploadMediaStop();
接口说明
设置多媒体数据以及定制数据接收回调,参考 回调函数 中的说明。
示例代码
TuyaIotGateway.getInstance().setGatewayListener(new TuyaIotGateway.GatewayListener() {
···
void onCloudMedia(TuyaIotGateway.MediaAttribute[] medias) {
TODO("接收云端下发tts报文。")
}
void onCloudCustom(String type, String msgJson) {
TODO("客户定制501透传接口函数,具体协议内容由云端与客户制定,并提供说明。")
}
}
)
接口说明
ATopResponse atopPost(String api, String version, String postData);
参数说明
参数 | 说明 |
---|---|
api | 接口名 |
version | 接口版本 |
postData | 上报云端的数据json字符串 |
返回值 | 含义 |
---|---|
ATopResponse | 包含errCode(错误码)和result(请求结果)两个字段。请求正常返回时errCode为0 |
示例代码
ATopResponse response = TuyaIotGateway.getInstance().atopPost("tuya.xx.xx", "1.0", "");
if (response.errCode == 0) {
Log.d(TAG, "result: " + response.result);
}
接口说明
通过 TuyaIotGateway 单例设置回调实现
void setUpgradeCallback(UpgradeEventCallback upgradeCallback);
参数说明
参数 | 说明 |
---|---|
upgradeCallback | OTA 事件回调 |
回调说明
public interface UpgradeEventCallback {
/**
* sdk 接收到后端的升级推送的时候,会触发此接口 附带升级信息
* @param version
*/
void onUpgradeInfo(String version);
/**
* 升级文件开始下载
*/
void onUpgradeDownloadStart();
/**
* 升级文件下载进度
*/
void onUpgradeDownloadUpdate(int progress);
/**
* sdk 下载升级文件下载完成触发此接口
*/
void upgradeFileDownloadFinished(boolean success);
/**
* 升级失败
* @param msg 错误信息
*/
void onUpgradeFail(String msg);
}
-
准备 ROM 升级文件 update.zip(非必须)
-
打升级包 app.apk(必须)
-
准备版本文件 version.json,内容为:
{ "apkVersion": "1.2.0", // apk版本号 "romVersion": "1565694425", // 系统升级文件版本,升级压缩包的/META-INF/com/android/metadata `post-timestamp` }
-
将上面三个(或两个)文件压缩为
标识名_OTA_版本号.bin
,例:test_acs_rk3399-all_OTA_1.0.2.bin
-
在固件及版本管理后台上传
-
在固件升级管理后台添加升级