对于如今上班打工族来讲,当你带着惺忪的双眼,背着沉重的电脑包,爬着长长的楼梯,回到租的房屋,一开门,乌七八黑,顿时片刻的孤独席卷而来,奈何还须要用手沿着冰冷的墙壁,去摸索着开关。一开灯,刺眼的光芒射进眼球里,原本就沉重的心,又浇了一壶冰水。时光机日后拨一下,当你晚上回家,打开门的时候,一束温暖的灯光,伴随着门的打开流露出来,有点像小学课本里,游子在家门不远处看到母亲打着灯笼的光若隐若散。时光机回到如今,对于新世纪的程序员,咱们艰巨着改变世界的重任,实现一款智能灯APP,改变你们对灯的认识是很是重要的。好比早上起床,伴随着闹钟,冷光灯亮起,走到厨房,自动启动照明,晚上回家,暖光在开门前就已经亮起。html
那么如何实现一款智能灯APP呢?首先先了解下智能灯的基础功能android
前往 涂鸦智能开发平台 注册开发者帐号、建立产品、建立功能点等,具体流程请参考接入流程c++
在涂鸦 IoT 平台中 “App 工做台” 中点击 “App SDK”,点击“建立 App”。git
填写 App 相关信息,点击确认。程序员
您能够根据实际需求选择须要的选择方案,支持多选,而后根据 Podfile 和 Gradle 进行 SDK 的集成。github
点击获取密码,获取 SDK 的 AppKey,AppSecret,安全图片等信息。json
在 Android Studio 中新建工程。api
build.gradle 文件里添加集成准备中下载的 dependencies 依赖库。安全
android { defaultConfig { ndk { abiFilters "armeabi-v7a", "arm64-v8a" } } packagingOptions { pickFirst 'lib/*/libc++_shared.so' // 多个aar存在此so,须要选择第一个 } } dependencies { implementation 'com.alibaba:fastjson:1.1.67.android' implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.14.9' // Tuya Home 最新稳定版: implementation 'com.tuya.smart:tuyasmart:3.20.0' }
在根目录的 build.gradle 文件中增长 jcenter() 仓库网络
repositories { jcenter() }
[!TIP]
- 涂鸦智能 3.10.0 以前的版本的 sdk 默认只支持 armeabi-v7a,
- 3.11.0 版本后已经将 armeabi-v7a、arm64-v8a 集成进 sdk,请将本地手动放入的 sdk 的相关 so 库移除,使用 sdk 中提供的。
- 若是集成新版本 so 库。请移除以前老版本手动集成的库,防止冲突或者代码版本不一致致使的问题
- 若有其余平台须要可前往 GitHub 获取。
点击 "下载安全图片" ——"安全图片下载" 下载安全图片。
在集成准备中点击“下载安全图片”。将下载的安全图片命名为 “t_s.bmp”,放置到工程目录的 assets 文件夹下。
在 AndroidManifest.xml 文件里配置 appkey 和 appSecret,在配置相应的权限等
<meta-data android:name="TUYA_SMART_APPKEY" android:value="应用 Appkey" /> <meta-data android:name="TUYA_SMART_SECRET" android:value="应用密钥 AppSecret" />
在 proguard-rules.pro 文件配置相应混淆配置
#fastJson -keep class com.alibaba.fastjson.**{*;} -dontwarn com.alibaba.fastjson.** #mqtt -keep class com.tuya.smart.mqttclient.mqttv3.** { *; } -dontwarn com.tuya.smart.mqttclient.mqttv3.** #OkHttp3 -keep class okhttp3.** { *; } -keep interface okhttp3.** { *; } -dontwarn okhttp3.** -keep class okio.** { *; } -dontwarn okio.** -keep class com.tuya.**{*;} -dontwarn com.tuya.**
描述
用于初始化 SDK,请在 Application 中初始化 SDK,确保全部进程都能初始化。
示例代码
public class TuyaSmartApp extends Application { @Override public void onCreate() { super.onCreate(); TuyaHomeSdk.init(this); } }
appId 和 appSecret 须要配置 AndroidManifest.xml 文件里,也能够在初始化代码里初始化。
TuyaHomeSdk.init(Application application, String appkey, String appSerect)
在退出应用的时候调用如下接口注销掉。
TuyaHomeSdk.onDestroy();
在 debug 模式下能够开启 SDK 的日志开关,查看更多的日志信息,帮助快速定位问题。在 release 模式下建议关闭日志开关。
TuyaHomeSdk.setDebugMode(true);
在接入 照明控制 SDK 以前,您能够先了解一下 照明灯的DEMO,须要把DEMO跑起来,登录成功以后,在进行下列操做,照明控制 SDK 须要依赖 Home SDK 其中的一部分,下面的文档也会介绍到依赖的这一部分。
// homesdk 依赖,注意,必须使用大于等于此版本的SDK implementation 'com.tuya.smart:tuyasmart:3.20.0' // 控制SDK依赖 implementation 'com.tuya.smart:tuyasmart-centralcontrol:1.0.2'
须要注意的是,tuyasmart-centralcontrol使用了kotlin编译,须要引入kotlin库确保其正常使用。
项目中已引入kotlin的可忽略下面的配置。
kotlin接入
在根目录的build.gradle中引入kotlin插件的依赖:
buildscript { ext.kotlin_version = '1.3.72' dependencies { ... classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }
在app的build.gradle中引入kotlin插件和kotlin包:
apply plugin: 'kotlin-android' dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" }
未使用标准控制指令时,设备控制 通常使用这种方式:
ITuyaDevice mDevice = TuyaHomeSdk.newDeviceInstance(String devId); // 监听控制结果 mDevice.registerDevListener(new IDevListener() { @Override public void onDpUpdate(String devId, String dpStr) { } @Override public void onRemoved(String devId) { } @Override public void onStatusChanged(String devId, boolean online) { } @Override public void onNetworkStatusChanged(String devId, boolean status) { } @Override public void onDevInfoUpdate(String devId) { } }); mDevice.publishDps("{\"101\": true}", new IResultCallback() { @Override public void onError(String code, String error) { Toast.makeText(mContext, "开灯失败", Toast.LENGTH_SHORT).show(); } @Override public void onSuccess() { Toast.makeText(mContext, "开灯成功", Toast.LENGTH_SHORT).show(); } });
这种方式控制时,会发送dpId,如10一、102之类的给设备来控制。其中101就是这个设备定义的开关dpId。
这么作的缺点是,若是另外一个设备也有开关功能,可是不是101控制开关,你就须要传入不一样的参数来控制。而当n个设备都有开关功能,可是却dpId都不一样,就要写很是多的适配逻辑。
为了解决同一个功能定义的id不一样的问题,引入了标准指令的概念。
根据产品 id 判断当前产品是否支持标准指令。
使用标准指令须要判断当前设备是否支持标准指令控制,不支持的设备不可使用该控制方式,只能使用以前的接口控制。
示例代码:
boolean isStandard = TuyaHomeSdk.getDataInstance().isStandardProduct("your_product_id");
其中的 productId 是产品 id,可从 DeviceBean
中获取。
什么是标准指令?
标准指令就是特定功能的标准编号。如照明类设备的开灯功能,其标准指令必定是"switch_led"。发送控制指令switch_led,必定能够控制照明设备的开关。
在集成了此SDK以后,调用方式变化以下:
ITuyaDevice mDevice = TuyaHomeSdk.newDeviceInstance(String devId); // 注意:这里方法是registerDeviceListener,注册的 Listener 是 IDeviceListener tuyaDevice.registerDeviceListener(new IDeviceListener() { @Override public void onDpUpdate(String devId, Map<String, Object> dpCodeMap) { } @Override public void onRemoved(String devId) { } @Override public void onStatusChanged(String devId, boolean online) { } @Override public void onNetworkStatusChanged(String devId, boolean status) { } @Override public void onDevInfoUpdate(String devId) { } }); HashMap<String, Object> dpCodeMap = new HashMap<>(); dpCodeMap.put("switch_led", true); // 发送标准指令 tuyaDevice.publishCommands(dpCodeMap, new IResultCallback() { @Override public void onError(String code, String error) { Toast.makeText(mContext, "开灯失败", Toast.LENGTH_SHORT).show(); } @Override public void onSuccess() { Toast.makeText(mContext, "开灯成功", Toast.LENGTH_SHORT).show(); } });
注意:标准指令使用方法registerDeviceListener
注册监听, 非标准是registerDevListener
值得注意的是,目前不是全部设备都支持标准指令控制,后文会说明如何判断该设备是否支持标准指令控制。
若是不支持的设备,而又必须使用标准控制,须要联系涂鸦适配。
全部标准指令均可以在涂鸦智能平台查找到:
等等。
有了tuyaDevice.publishCommands
方法和上面的指令,就能够发送标准指令来控制设备。
涂鸦 iot 平台上有不少品类的iot设备,不一样的品类在涂鸦平台上都有固定的编号(category)。
开发者文档上体如今每一个品类指令集的标题上,如 灯具(dj) 标准指令集 中dj
,dj
就是灯具的category值。
使用 category 字段能够判断当前设备是什么产品,来展现不一样的面板。
此表格包含大多数支持的品类,具体可参见 iot 平台。
经过产品 id 获取产品的品类值。
示例代码:
String category = TuyaHomeSdk.getDataInstance().getStandardProductConfig("your_product_id").category;
涂鸦照明设备同时存在v1和v2新旧两种固件,即便使用了标准指令,也须要开发两套控制逻辑。
所以对照明设备功能进行封装,封装了灯具设备的开关、工做模式切换、亮度控制、冷暖控制、彩光控制和四种情景模式的控制。
首先,建立ITuyaLightDevice对象,灯相关的方法均封装在此方法中。
ITuyaLightDevice lightDevice = new TuyaLightDevice(String devId);
该对象封装了灯的全部dp点,包括控制指令的下发和上报。
这里提供几个简单的调用示例:
// 建立lightDevice ITuyaLightDevice lightDevice = new TuyaLightDevice("vdevo159793004250542"); // 注册监听 lightDevice.registerLightListener(new ILightListener() { @Override public void onDpUpdate(LightDataPoint dataPoint) { // 返回LightDataPoint,包含灯全部功能点的值 Log.i("test_light", "onDpUpdate:" + dataPoint); } @Override public void onRemoved() { Log.i("test_light", "onRemoved"); } @Override public void onStatusChanged(boolean status) { Log.i("test_light", "onDpUpdate:" + status); } @Override public void onNetworkStatusChanged(boolean status) { Log.i("test_light", "onDpUpdate:" + status); } @Override public void onDevInfoUpdate() { Log.i("test_light", "onDevInfoUpdate:"); } }); // 开灯 lightDevice.powerSwitch(true, new IResultCallback() { @Override public void onError(String code, String error) { Log.i("test_light", "powerSwitch onError:" + code + error); } @Override public void onSuccess() { Log.i("test_light", "powerSwitch onSuccess:"); } }); // 晚安场景 lightDevice.scene(LightScene.SCENE_GOODNIGHT, new IResultCallback() { @Override public void onError(String code, String error) { Log.i("test_light", "scene onError:" + code + error); } @Override public void onSuccess() { Log.i("test_light", "scene onSuccess:"); } }); // 设置颜色 lightDevice.colorHSV(100, 100, 100, new IResultCallback() { @Override public void onError(String code, String error) { Log.i("test_light", "colorHSV onError:" + code + error); } @Override public void onSuccess() { Log.i("test_light", "colorHSV onSuccess:"); } });
更多API请参考下面的文档。
方法说明
/** * 注册监听 */ void registerLightListener(ILightListener listener);
其中,ILightListener回调以下:
public interface ILightListener { /** * 监听照明设备dp点变化 * * @param dataPoint 该灯具全部dp点的状态 */ void onDpUpdate(LightDataPoint dataPoint); /** * 设备移除 */ void onRemoved(); /** * 设备上下线 */ void onStatusChanged(boolean online); /** * 网络状态 */ void onNetworkStatusChanged(boolean status); /** * 设备信息更新例如name之类的 */ void onDevInfoUpdate(); }
参数说明
值得说明的是LightDataPoint
对象,该对象封装了当前设备全部功能点。当功能点发生变化时,将会回调。每次回调的都会是完整的对象。
如下是该对象参数的具体含义:
public class LightDataPoint { /** * 开关 */ public boolean powerSwitch; /** * 工做模式。 * <p> * MODE_WHITE为白光模式; * MODE_COLOUR为彩光模式; * MODE_SCENE为情景模式; */ public LightMode workMode; /** * 亮度百分比,从0到100 */ public int brightness; /** * 色温百分比,从0到100 */ public int colorTemperature; /** * 颜色值,HSV色彩空间. * <p> * 其中H为色调,取值范围0-360; * 其中S为饱和度,取值范围0-100; * 其中V为明度,取值范围0-100; */ public LightColourData colorHSV; /** * 彩灯情景。 * * SCENE_GOODNIGHT为晚安情景; * SCENE_WORK为工做情景; * SCENE_READ为阅读情景; * SCENE_CASUAL为休闲情景; */ public LightScene scene; }
灯共分为一路灯(仅有白光)、二路灯(白光+冷暖控制)、三路灯(仅有彩光模式)、四路灯(白光+彩光)、五路灯(白光+彩光+冷暖)。
这5种灯具在功能定义上有所区别,在开发相应的UI和控制时有所区别。
该方法可获取当前灯的类型。
/** * 获取当前是几路灯 * * @return {@link LightType} */ LightType lightType();
其中LightType中定义的类型有:
/** * 白光灯,dpCode:bright_value */ TYPE_C, /** * 白光+冷暖,dpCode:bright_value + temp_value */ TYPE_CW, /** * RGB,dpCode:colour_data */ TYPE_RGB, /** * 白光+RGB,dpCode:bright_value + colour_data */ TYPE_RGBC, /** * 白光+冷暖+RGB,dpCode:bright_value + temp_value + colour_data */ TYPE_RGBCW
打开一个设备面板时,须要获取全部功能点值来展现。可经过此接口获取上面提到的LightDataPoint对象。
/** * 获取灯全部功能点的值 */ LightDataPoint getLightDataPoint();
控制灯的开关
方法说明
/** * 开灯 or 关灯 * * @param status true or false * @param resultCallback callback */ void powerSwitch(boolean status, IResultCallback resultCallback);
参数说明
控制工做模式的切换。
方法说明
/** * 切换工做模式 * * @param mode 工做模式 * @param resultCallback callback */ void workMode(LightMode mode, IResultCallback resultCallback);
参数说明
调用示例
如切换到彩光模式:
lightDevice.workMode(LightMode.MODE_COLOUR, new IResultCallback() { @Override public void onError(String code, String error) { Log.i("test_light", "workMode onError:" + code + error); } @Override public void onSuccess() { Log.i("test_light", "workMode onSuccess"); } });
注意:部分灯具必须切换到对应的工做模式才能够控制,好比控制彩光,必须先切换到彩光模式才能够发颜色的值。
控制亮度
方法说明
/** * 亮度控制。 * * @param status 亮度的百分比,取值范围0-100 * @param resultCallback callback */ void brightness(int status, IResultCallback resultCallback);
参数说明
控制灯的冷暖值
方法说明
/** * 色温控制 * * @param status 色温的百分比,取值范围0-100 * @param resultCallback callback */ void colorTemperature(int status, IResultCallback resultCallback);
参数说明
控制彩色灯的颜色
方法说明
/** * 设置彩灯的颜色 * * @param hue 色调 (范围:0-360) * @param saturation 饱和度(范围:0-100) * @param value 明度(范围:0-100) * @param resultCallback callback */ void colorHSV(int hue, int saturation, int value, IResultCallback resultCallback);
切换彩灯的情景模式,目前共有四种模式:
LightScene.SCENE_GOODNIGHT为晚安情景; LightScene.SCENE_WORK为工做情景; LightScene.SCENE_READ为阅读情景; LightScene.SCENE_CASUAL为休闲情景;
方法说明
/** * @param lightScene {@link LightScene} * @param resultCallback callback */ void scene(LightScene lightScene, IResultCallback resultCallback);
现有的定时器不支持标准Code 定时,须要进行标准Code转义成Id才能进行设置定时器,参考原有定时器
/** * @param dpCodes 标准DpCode指令 * @param devId 设备ID */ Map<String, Object> convertCodeToIdMap(Map<String, Object> dpCodes, String devId);
Map<String, Object> dps=TuyaHomeSdk.getDataInstance().getStandardConverter().convertCodeToIdMap(Map<String, Object> dpCodes, String devId); TuyaTimerBuilder builder = new TuyaTimerBuilder.Builder() .taskName(mTaskName) .devId("efw9990wedsew") .deviceType(TimerDeviceTypeEnum.DEVICE) .actions(dps) .loops("1100011") .aliasName("Test") .status(1) .appPush(true) .build(); TuyaHomeSdk.getTimerInstance().addTimer(builder, new IResultCallback() { @Override public void onSuccess() { } @Override public void onError(String errorCode, String errorMsg) { } });