怎么样利用涂鸦App SDK完成智能灯光控制器Android开发

更新时间2021-05-14 03:36:12

概况

假想一下,当你结束了一天繁重的工作带着惺忪的双眼,背着沉重的电脑包回到家里。一开灯,刺眼的冷白光芒迎面而来,本来就沉重的心情,彷佛被一层层寒气所萦绕。

时光机往后拨一下,当你晚上回家,打开门的时候,一束温暖的灯光,伴随着门的打开流露出来,有点像小学课本里,游子在家门不远处看到母亲打着灯笼的光若隐若现。

我们是新世纪的开发者,肩负着改变世界的重任。打造一款智能灯 App,改变用户对灯的认识,改善人们的生活环境是非常重要的。例如,用户早上起床时,伴随着闹钟,冷光灯亮起,走到厨房,自动启动照明;晚上回家后,暖光在开门前就已经亮起。

物料清单

硬件 (1)
  • 一款智能硬件产品

    数量:1

    本教程假设您已经拥有了一款智能硬件产品,该产品可以是您从涂鸦硬件开发平台创建的,也可以是您在涂鸦智选(TuyaGo)平台购买的。查看详情

步骤

  • 第 1 步:了解智能灯 App

    那么如何实现一款智能灯App呢?首先,您需要了解下智能灯的基础功能。

    智能灯 App 基础功能

    • 智能定时功能:可以按照日、周进行设计定时器,可以实现单次,循环定时,可以对分组进行设置定时。

    • 远程控制功能:通过家用无线路由器组成的局域网与其他终端设备(手机、平板等)进行通讯,还可以远程遥控灯光操作,实现对灯光的开,关,调光,场景,彩光模式等控制。

    • 色彩调节功能:通过色彩调节功能,可以实现多达 16777216 种颜色的调节。

    • 地理围栏功能:智能灯控App可以为用户实现离家和到家模式。

    • 智能音乐灯功能:可以通过手机音乐和灯结合在一起,实现灯随着音乐有节律的闪烁。

    • 智能场景功能:通过专家精心调优出四大场景功能,可以实现柔光模式、缤纷模式、炫彩模式、斑斓模式。

    智能灯应用场景

    • 办公场景:针对办公场景,智能灯具有白光调节模式,还拥有阅读模式的场景可以选择。

    • 会客场景:可以采用休闲模式,调节气氛。

    • 卧室场景:卧室场景推荐使用暖光模式。

    • 唤醒场景:可以通过设置智能定时实现起床播放音乐,并唤醒音乐灯。

  • 第 2 步:获取涂鸦 App SDK

    1. 涂鸦 IoT 平台的 App 工作台App 工作台 中点击 App SDK,点击 创建 App

      image.png

    2. 填写 App 相关信息,点击确认

      • 应用名称:填写您的 App 名称。
      • iOS 应用包名:填写您的 iOS App 包名(建议格式:com.xxxxx.xxxxx)。
      • 安卓应用包名:填写您的安卓 App 包名(两者可以保持一致,也可以不一致)。
      • 渠道标识符:不是必填项,如果不填写,系统会根据包名自动生成。
    3. 您可以根据实际需求选择需要的选择方案,支持多选,然后根据 Podfile 和 Gradle 进行 SDK 的集成。

      image.png

    4. 点击获取密码,获取 SDK 的 AppKey,AppSecret,安全图片等信息。

      image.png

  • 第 3 步:在 Android Studio 中新建工程

    1. 在 Android Studio 中新建工程。

    2. 配置 build.gradle。

      1. 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'
        }
        
      2. 在根目录的 build.gradle 文件中增加 jcenter() 仓库

        repositories {
        	jcenter()
        }
        

        说明

        • 涂鸦智能 3.10.0 之前的版本的 SDK 默认只支持 armeabi-v7a。
        • 3.11.0 版本后已经将 armeabi-v7a、arm64-v8a 集成进 SDK,请将本地手动放入的 SDK 的相关 so 库移除,使用 SDK 中提供的。
        • 如果集成新版本 so 库。请移除之前老版本手动集成的库,防止冲突或者代码版本不一致导致的问题。
        • 如有其他平台需要可前往 GitHub 获取。
    3. 集成安全图片

      1. 点击 “下载安全图片” ——“安全图片下载” 下载安全图片。

        image 4.png

      2. 在集成准备中点击“下载安全图片”。将下载的安全图片命名为 “t_s.bmp”,放置到工程目录的 assets 文件夹下。

        image 6.png

    4. 在 AndroidManifest.xml 文件里配置 appkey 和 appSecret,在配置相应的权限等。

      <meta-data
      android:name="TUYA_SMART_APPKEY"
      android:value="应用 Appkey" />
      <meta-data
      android:name="TUYA_SMART_SECRET"
      android:value="应用密钥 AppSecret" />
      
    5. 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.**
      
  • 第 4 步:集成并初始化 Home SDK

    1. 在 Application 中初始化 SDK,确保所有进程都能初始化。以下为示例代码:

      public class TuyaSmartApp extends Application {
      	@Override
      	public void onCreate() {
      		super.onCreate();
      		TuyaHomeSdk.init(this);
      	}
      }
      
    2. appIdappSecret 等信息配置在 AndroidManifest.xml 文件里,或者您也可以在初始化代码里初始化。

      TuyaHomeSdk.init(Application application, String appkey, String appSerect)
      
    3. 在退出应用的时候调用以下接口注销掉涂鸦智能云连接。

      TuyaHomeSdk.onDestroy();
      
    4. 在 debug 模式下可以开启 SDK 的日志开关,查看更多的日志信息,帮助快速定位问题。在 release 模式下建议关闭日志开关。

      TuyaHomeSdk.setDebugMode(true);
      
  • 第 5 步:集成照明控制SDK

    在接入 照明控制 SDK 之前,您可以先了解一下 照明灯的DEMO,需要把DEMO跑起来,登录成功之后,再进行下列操作。照明控制 SDK 需要依赖 Home SDK 其中的一部分,本步骤也会介绍到依赖的这一部分。

    依赖说明

    // home sdk 依赖,注意,必须使用大于等于此版本的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 接入

    1. 在根目录的build.gradle中引入kotlin插件的依赖。

      buildscript {
      	ext.kotlin_version = '1.3.72'
      	dependencies {
      		...
      		classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
      	}
      }
      
    2. 在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,如 101、102 之类的给设备来控制。其中 101 就是这个设备定义的开关 DPID。

    这么做的缺点是,如果另一个设备也有开关功能,但是不是101控制开关,你就需要传入不同的参数来控制。而当n个设备都有开关功能,但是却dpId都不同,就要写非常多的适配逻辑。

    为了解决同一个功能定义的 ID 不同的问题,引入了标准指令的概念。标准指令就是特定功能的标准编号。如照明类设备的开灯功能,其标准指令一定是"switch_led"。发送控制指令switch_led,一定可以控制照明设备的开关。详情请参考 标准指令

    判断当前产品是否支持标准指令

    1. 根据产品 ID 判断当前产品是否支持标准指令。

      使用标准指令需要判断当前设备是否支持标准指令控制,不支持的设备不可以使用该控制方式,只能使用之前的接口控制。

      示例代码:

      boolean isStandard = TuyaHomeSdk.getDataInstance().isStandardProduct("your_product_id");
      

      其中的 productId 是产品 id,可从 DeviceBean 中获取。

    2. 在集成了此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 是指灯具的 category 值。使用 category 字段可以判断当前设备是什么产品,来展示不同的面板。

    此表格包含大多数支持的品类,具体可参见 IoT 平台。

    品类 category 值
    开关 kg
    插座 cz
    排插 pc
    场景开关 cjkg
    窗帘开关 clkg
    灯具 dj
    扫地机 sd
    电茶壶 bh
    香薰机 xxj
    加湿器 jsq
    空调 kt
    空气净化器 kj
    晾衣架 lyj
    取暖器 qn
    空调控制器 ktkzq
    窗帘 cl
    温控器 wk
    风扇 fs
    门磁传感器 mcs
    水浸传感器 sj
    温湿度传感器 wsdcg
    PIR传感器 pir
    震动传感器 zd
    压力传感器 ylcg
    亮度传感器 ldcg
    烟雾报警传感器 ywbj
    声光报警传感器 sgbj
    CO2传感器 co2bj
    CO传感器 cobj
    pm2.5传感器 pm2.5
    燃气报警传感器 rqbj
    sos传感器 sos
    门锁 ms

    获取产品的品类值(category)

    通过产品 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:");
        }
    });
    
  • 第 6 步:了解更多 API

    您可以在这一步中了解更多的 App SDK API,实现更丰富的 App 控制功能。

    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;
    }
    

    API:获取当前灯的类型

    灯共分为一路灯(仅有白光)、二路灯(白光+冷暖控制)、三路灯(仅有彩光模式)、四路灯(白光+彩光)、五路灯(白光+彩光+冷暖)。

    这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
    

    API:获取当前设备所有功能的值

    打开一个设备面板时,需要获取所有功能点值来展示。可通过此接口获取上面提到的LightDataPoint对象。

    /**
     * 获取灯所有功能点的值
     */
    LightDataPoint getLightDataPoint();
    

    API:开关

    控制灯的开关

    方法说明

    /**
     * 开灯 or 关灯
     *
     * @param status         true or false
     * @param resultCallback callback
     */
    void powerSwitch(boolean status, IResultCallback resultCallback);
    

    参数说明

    字段 含义
    status true为开
    resultCallback 仅表示此次发送指令成功or失败,真正控制成功需要识别ILightListener中的dp变化

    API:工作模式

    控制工作模式的切换。

    方法说明

    /**
     * 切换工作模式
     *
     * @param mode           工作模式
     * @param resultCallback callback
     */
    void workMode(LightMode mode, IResultCallback resultCallback);
    

    参数说明

    字段 含义
    mode 工作模式,其值有MODE_WHITE(白光), MODE_COLOUR(彩光), MODE_SCENE(情景模式)
    resultCallback 仅表示此次发送指令成功or失败,真正控制成功需要识别ILightListener中的dp变化

    调用示例

    如切换到彩光模式:

    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");
        }
    });
    

    注意:部分灯具必须切换到对应的工作模式才可以控制,比如控制彩光,必须先切换到彩光模式才可以发颜色的值。

    API:亮度

    控制亮度

    方法说明

    /**
     * 亮度控制。
     *
     * @param status         亮度的百分比,取值范围0-100
     * @param resultCallback callback
     */
    void brightness(int status, IResultCallback resultCallback);
    

    参数说明

    字段 含义
    status 亮度的百分比
    resultCallback 仅表示此次发送指令成功or失败,真正控制成功需要识别ILightListener中的dp变化

    API:冷暖

    控制灯的冷暖值

    方法说明

    /**
     * 色温控制
     *
     * @param status         色温的百分比,取值范围0-100
     * @param resultCallback callback
     */
    void colorTemperature(int status, IResultCallback resultCallback);
    

    参数说明

    字段 含义
    status 色温的百分比
    resultCallback 仅表示此次发送指令成功or失败,真正控制成功需要识别ILightListener中的dp变化

    API:彩光

    控制彩色灯的颜色

    方法说明

    /**
     * 设置彩灯的颜色
     *
     * @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);
    

    API:情景

    切换彩灯的情景模式,目前共有四种模式:

    • 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 名称 数据类型 取值描述 说明
    switch_led 开关 Boolean {}
    work_mode 模式 Enum {“range”:[“white”, “colour”, “scene”, “music”, “scene_1”, “scene_2”, “scene_3”, “scene_4”]}
    bright_value 亮度 Integer {“min”:25,“scale”:0,“unit”:"", “max”:255,“step”:1}
    bright_value_v2 亮度 Integer {“min”:10,“scale”:0,“unit”:"", “max”:1000,“step”:1}
    temp_value 冷暖 Integer {“min”:0,“scale”:0,“unit”:"", “max”:255,“step”:1}
    temp_value_v2 冷暖 Integer {“min”:0,“scale”:0,“unit”:"", “max”:1000,“step”:1}
    colour_data 彩光模式数 Json {}
    colour_data_v2 彩光模式数 Json {}
    scene_data 情景模式数 Json {}
    scene_data_v2 情景模式数 Json {}
    flash_scene_1 柔光模式 Json {}
    flash_scene_2 缤纷模式 Json {}
    flash_scene_3 炫彩模式 Json {}
    flash_scene_4 斑斓模式 Json {}
    music_data 音乐灯模式控制 Json {}
    control_data 调节dp控制 Json {}
    countdown_1 倒计时 Integer {“unit”:"", “min”:0,“max”:86400,“scale”:0,“step”:1}
    scene_select 场景选择 Enum {“range”:[“1”, “2”, “3”, “4”, “5”]} 旧版本
    switch_health_read 健康阅读开关 Boolean {} 旧版本
    read_time 健康阅读-阅读时间设置 Integer {“unit”:“minute”, “min”:1,“max”:60,“scale”:0,“step”:1} 旧版本
    rest_time 健康阅读-休息时间设置 Integer {“unit”:“minute”, “min”:1,“max”:60,“scale”:0,“step”:1} 旧版本