對於如今上班打工族來講,當你帶着惺忪的雙眼,揹着沉重的電腦包,爬着長長的樓梯,回到租的房屋,一開門,烏七八黑,頓時片刻的孤獨席捲而來,奈何還須要用手沿着冰冷的牆壁,去摸索着開關。一開燈,刺眼的光芒射進眼球裏,原本就沉重的心,又澆了一壺冰水。時光機日後撥一下,當你晚上回家,打開門的時候,一束溫暖的燈光,伴隨着門的打開流露出來,有點像小學課本里,遊子在家門不遠處看到母親打着燈籠的光若隱若散。時光機回到如今,對於新世紀的程序員,咱們艱鉅着改變世界的重任,實現一款智能燈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) { } });