JLChen
2020-07-20 2ca94e0f7e1b5a1c197fb2063ae2973539cefe1d
2020-07-20 1.备份
18个文件已添加
2391 ■■■■■ 已修改文件
.gitignore 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/README.md 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/SUMMARY.md 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/Integrated.md 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_build_device.md 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_build_device_about.md 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control.md 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control_air.md 371 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control_curtain.md 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control_light.md 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control_music.md 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control_scenes.md 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control_security.md 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_control_switch.md 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_mcu.md 408 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_mcu_about.md 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/api_search.md 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Android_HDL_SDK_TTL_DOC/src/update_log.md 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
New file
@@ -0,0 +1,23 @@
# Created by https://www.gitignore.io/api/gitbook
# Edit at https://www.gitignore.io/?templates=gitbook
### GitBook ###
# Node rules:
## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
## Dependency directory
## Commenting this out is preferred by some people, see
## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git
node_modules
# Book build output
_book
# eBook build output
*.epub
*.mobi
*.pdf
# End of https://www.gitignore.io/api/gitbook
Android_HDL_SDK_TTL_DOC/README.md
New file
@@ -0,0 +1,18 @@
#HDL TTL Android SDK 接入指南
##功能概述
HDL TTL SDK提供了以搜索bus设备和控制设备的接口封装,加速应用开发过程,主要包括了以下功能:
- 搜索设备
- 控制设备
- 目前支持设备
    - 灯光类模块
    - 窗帘类模块
    - 空调类模块
    - 逻辑功能类模块
    - 背景音乐功能类模块(不支持简易编程搜索,需要手动添加)
    - 安防功能类模块(不支持简易编程搜索,需要手动添加)
    - 通用开关类模块(不支持简易编程搜索,需要手动添加)
- 手动添加,模拟生成设备列表(在不支持简易编程搜索情况下使用,例如:RCU酒店模块)
Android_HDL_SDK_TTL_DOC/SUMMARY.md
New file
@@ -0,0 +1,19 @@
# Summary
* [前言](README.md)
* [集成SDK](./src/Integrated.md)
* [搜索设备](./src/api_search.md)
* [控制设备](./src/api_control.md)
    * [灯光类模块](./src/api_control_light.md)
    * [窗帘类模块](./src/api_control_curtain.md)
    * [空调类模块](./src/api_control_air.md)
    * [背景音乐功能类模块](./src/api_control_music.md)
    * [安防类模块](./src/api_control_security.md)
    * [场景控制(逻辑模块)](./src/api_control_scenes.md)
    * [通用开关模块](./src/api_control_switch.md)
* [MCU功能接口](./src/api_mcu_about.md)
    * [MCU通信](./src/api_mcu.md)
* [非搜索设备解决方案](./src/api_build_device.md)
    * [生成目标设备数据](./src/api_build_device_about.md)
* [更新日志](./src/update_log.md)
Android_HDL_SDK_TTL_DOC/src/Integrated.md
New file
@@ -0,0 +1,92 @@
# 集成SDK
### 一、创建工程
在Android Studio中建立你的工程。
### 二、build.gradle 配置
将SDK包中的aar文件( 如HDL_TTLSDK_V1.0.1_r.arr )导入到现有的工程中,放入到libs目录下。
build.gradle 文件里添加集成准备中下载的dependencies 依赖库。
```groovy
    dependencies {
        implementation fileTree(include: ['*.jar','*.aar'], dir: 'libs')
        implementation 'org.greenrobot:eventbus:3.0.0'
    }
```
### 三、Application中初始化SDK。
**代码范例**
```java
public class HDLApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //HDL_PATH_NAME (串口路径)
        //HDL_BAUDRATE  (波特率),波特率默认115200
        HDLTtlSdk.init(this, HDL_PATH_NAME, HDL_BAUDRATE);
    }
}
```
### 四、日志打印开关
SKD打印日志默认是打开,用户可以配置为false,即可关闭SDK打印日志。
**代码范例**
```java
public class HDLApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        HDLTtlSdk.init(this, HDL_PATH_NAME, HDL_BAUDRATE);
        HDLTtlSdk.setHDLLogOpen(false);//关闭SDK日志打印
    }
}
```
### 五、EventBus 使用
SKD的大部分回调事件,通过EventBus发布回调事件,所以开发者项目中需要集成EventBus,并在需要的Activity中执行注册订阅事件(register)和取消事件订阅(unregister)。
**代码范例**
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initEventBusRegister();//注册订阅事件
}
/**
 * 注册事件分发初始化
 */
private void initEventBusRegister() {
    if (isRegisterEventBus()) {
        if (!EventBus.getDefault().isRegistered(this)) {
             EventBus.getDefault().register(this);
        }
    }
}
@Override
protected void onDestroy() {
    super.onDestroy();
    unEventBusRegister();//取消事件订阅
}
/**
* 注册事件分发反始化
 */
private void unEventBusRegister() {
    if (isRegisterEventBus()) {
        EventBus.getDefault().unregister(this);
    }
}
```
Android_HDL_SDK_TTL_DOC/src/api_build_device.md
New file
@@ -0,0 +1,38 @@
# 非搜索设备解决方案
## 生成设备列表 手动添加设备
手动添加,模拟生成设备列表(在不支持简易编程搜索情况下使用,例如:RCU酒店模块)
### 说明
```java
   /** SDK目前支持的大类:小类
 * Configuration.LIGTH_BIG_TYPE
 * Configuration.CURTAIN_BIG_TYPE
 * Configuration.AIR_BIG_TYPE
 * Configuration.AUDIO_BIG_TYPE
 * Configuration.LOGIC_BIG_TYPE
 * Configuration.GLOBAL_LOGIC_BIG_TYPE
 * Configuration.SECURITY_BIG_TYPE
 * Configuration.COMMON_SWITCH_BIG_TYPE
 *
 * 灯光类1:0 ,1,9,10 (后面为小类ID号)
 * 窗帘类2:0,1,2
 * 传感器5:0~24
 * 空调类7:0,3
 * 背景音乐功能9:0
 * 逻辑功能12:0
 * 全局场景17:0
 * 安防10:0
 * 通用开关100:0
 *
 * 该方法应用于提供项目交付前的提取批量数据生成好数据。
 * 模拟生成设备回路数据,在项目不支持简易编程搜索情况下,可以通过该方法,先快捷生成目标数据 得到 List<DevicesData> 格式的设备列表数据
 *
 * 上层做本地保存或者云端备份,App启动时读取恢复
 * 每次启动时先加载生成好的设备列表数据,然后在 SDK 初始化后,赋值给 HDLDeviceManager.devicesDataList
 */
```
Android_HDL_SDK_TTL_DOC/src/api_build_device_about.md
New file
@@ -0,0 +1,174 @@
# 生成设备列表
### 添加虚拟回路数据
 ###  SDK目前支持的大类:小类
 * Configuration.LIGTH_BIG_TYPE
 * Configuration.CURTAIN_BIG_TYPE
 * Configuration.AIR_BIG_TYPE
 * Configuration.AUDIO_BIG_TYPE
 * Configuration.LOGIC_BIG_TYPE
 * Configuration.GLOBAL_LOGIC_BIG_TYPE
 * Configuration.SECURITY_BIG_TYPE
 * Configuration.COMMON_SWITCH_BIG_TYPE
 *
 * 灯光类1:0 ,1,9,10
 * 窗帘类2:0,1,2
 * 传感器5:0~24
 * 空调类7:0,3
 * 背景音乐功能9:0
 * 逻辑功能12:0
 * 全局场景17:0
 * 安防10:0
 * 通用开关100:0
 *
 * 该方法应用于提供项目交付前的提取批量数据生成好数据。
 * 模拟生成设备回路数据,在项目不支持简易编程搜索情况下,可以通过该方法,先快捷生成目标数据 得到 List<DevicesData> 格式的设备列表数据
 *
 * 上层做本地保存或者云端备份,App启动时读取恢复
 * 每次启动时先加载生成好的设备列表数据,然后在 SDK 初始化后,赋值给 HDLDeviceManager.devicesDataList
### 一、添加不同类型设备回路
**代码范例**
```java
        /**
         * 添加设备回路
         * 如果存在相同子网号 设备号,则当成混合模块添加到该回路下,不存在则新添加模块
         * @param bigType 回路大类
         * @param littleType 回路小类
         * @param mSubnetID  回路子网ID
         * @param mDeviceID  回路设备ID
         * @param mChannelNum  回路号
         * @param mChannelRemark 回路备注 例如:窗帘、吊灯、厕所灯、电视
         * @param parentRemarks  当前回路模块的备注 例如: 酒店RCU模块
         * @param bSaveAndCallBack 是否马上保存本地并且推送DevicesInfoEvent 事件
         * @return
         */
        //如果存在相同子网号 设备号,则当成混合模块添加到该回路下,不存在则新添加模块
        DevicesData mDevicesData = DeviceParser.addDevicesListWithoutSearching(bigType, littleType, mSubnetID, mDeviceID, mChannelNum, remarksString, parentRemarks,true);
        if (mDevicesData != null) {
            showToast("添加成功");
        } else {
            showToast("添加失败");
        }
```
添加成功后同样会收到DevicesInfoEvent订阅事件,可以通过event.getDesDataList() 来获取生成好的数据。或者直接通过HDLDeviceManager.devicesDataList获取
**代码范例**
```java
    /**
     * ====================EventBus 订阅事件 ====================
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDevicesInfoEventMain(DevicesInfoEvent event) {
        mAllDevicesList.clear();
        mProgressDialog.dismiss();
        if (!event.isSuccess()) {
            Toast.makeText(MainActivity.this, "搜索超时,请重新再试", Toast.LENGTH_SHORT).show();
            tvResult.setText("搜索超时,请重新再试");
            return;
        }
        mDevicesDataList = event.getDesDataList();
        updateDeviceListView();
    }
```
批量添加,仅做演示用
**代码范例**
```java
        //添加一个灯
        DeviceParser.addDevicesListWithoutSearching(Configuration.LIGTH_BIG_TYPE, 0, mSubnetID, mDeviceID, 6, "夜灯", parentRemarks,false);
        //添加一个灯
        DeviceParser.addDevicesListWithoutSearching(Configuration.LIGTH_BIG_TYPE, 0, mSubnetID, mDeviceID, 7, "床头灯", parentRemarks,false);
        //添加一个灯
        DeviceParser.addDevicesListWithoutSearching(Configuration.LIGTH_BIG_TYPE, 0, mSubnetID, mDeviceID, 8, "客房插座", parentRemarks,false);
        //添加一个灯
        DeviceParser.addDevicesListWithoutSearching(Configuration.LIGTH_BIG_TYPE, 0, mSubnetID, mDeviceID, 12, "衣柜灯", parentRemarks,false);
        //添加一个窗帘
        DeviceParser.addDevicesListWithoutSearching(Configuration.CURTAIN_BIG_TYPE, 2, mSubnetID, mDeviceID, 1, "窗帘", parentRemarks,false);
        //添加一个空调
        DeviceParser.addDevicesListWithoutSearching(Configuration.AIR_BIG_TYPE, 0, mSubnetID, mDeviceID, 1, "房间空调", parentRemarks,false);
        //添加一个场景 这里场景号和区号 默认一样
        DeviceParser.addScenesDevicesListWithoutSearching(mSubnetID, mDeviceID, 1, 1, "空置无卡", parentRemarks,false);
        //添加一个场景
        DeviceParser.addScenesDevicesListWithoutSearching(mSubnetID, mDeviceID, 3, 3, "明亮场景", parentRemarks,false);
        //添加一个场景
        DeviceParser.addScenesDevicesListWithoutSearching(mSubnetID, mDeviceID, 4, 4, "房灯", parentRemarks,false);
        //添加一个场景 最后一个bSaveAndCallBack 设置为true
        DeviceParser.addScenesDevicesListWithoutSearching(mSubnetID, mDeviceID, 5, 5, "总开关", parentRemarks,true);
```
### 二、添加场景
**代码范例**
```java
    /**
     * 添加场景设备回路 需指定 场景区号 和 场景号
     * 如果存在相同子网号 设备号,则当成混合模块添加到该回路下,不存在则新添加模块
     *
     * @param mSubnetID
     * @param mDeviceID
     * @param mAreaNum       //场景 区域号
     * @param mAreaSceneNum  //场景 当前区域场景号
     * @param mChannelRemark 读取场景的备注名称 例如: 入住、起床模式、阅读模式
     * @param parentRemarks  当前回路模块的备注 例如: 酒店RCU模块
     * @param bSaveAndCallBack 是否马上保存本地并且推送DevicesInfoEvent 事件
     * @return
     */
    private void AddScenesDevices(int mSubnetID, int mDeviceID, int mAreaNum, int mAreaSceneNum, String mChannelRemark, String parentRemarks, boolean bSaveAndCallBack) {
        //添加场景
        DevicesData mScenesData = DeviceParser.addScenesDevicesListWithoutSearching(mSubnetID, mDeviceID, mAreaNum, mAreaSceneNum, mChannelRemark, parentRemarks,true);
    }
```
添加成功后同样会收到DevicesInfoEvent订阅事件
### 三、初始化设备列表
 * 该方法应用于提供项目交付前的提取批量数据生成好数据。
 * 模拟生成设备回路数据,在项目不支持简易编程搜索情况下,先快捷生成目标数据 得到 List<DevicesData> 格式的设备列表数据
**代码范例**
```java
   /**
     * 初始化 HDLSDK
     */
    private void initHDLSDK() {
        /**SDK初始化 配置串口 路径和波特率参数*/
        //HDL_PATH_NAME (串口路径)
        //HDL_BAUDRATE  (波特率),波特率默认115200
        HDLTtlSdk.init(this, HDL_PATH_NAME, HDL_BAUDRATE);
        //HDLTtlSdk.setHDLLogOpen(false);//配置是否开启SDK打印日志,默认为打开
        /*****不支持简易编程搜索的项目,上层保存读取加载 赋值给SDK*************************/
        List<DevicesData> mDevicesDataList = new ArrayList<>();
        .......
        //mDevicesDataList 上层做本地保存或者云端备份,App启动时读取恢复 加载该设备列表
        .......
        HDLDeviceManager.devicesDataList = mDevicesDataList;
        /*******************不支持简易编程搜索的项目***********************************/
    }
```
Android_HDL_SDK_TTL_DOC/src/api_control.md
New file
@@ -0,0 +1,82 @@
# 控制设备
### 一、控制设备
SDK所有的设备和Mcu控制方法在HDLCommand类中,
开发者可以通过调用里面的方法,并传入对应控制设备的AppliancesInfo参数,则可以成功发送控制指令。
**代码范例**
```java
    //发送控制灯光模块指令
    //appliancesInfo:为需要控制的的模块info参数,里面保存了当前回路模块的所有参数信息
    //lightState:控制改变的亮度值 0~100
    HDLCommand.lightCtrl(appliancesInfo, lightState);
```
### 二、设备类型说明
通过获取设备appliancesInfo里面的bigType参数,可以判断当前设备的类型,跳转加载对应的控制页面,并发送对应的控制命令。
每个bigType大类区分哪个大类模块后,可以再根据DeviceType设备类型来细分具体是哪种设备,例如下面代码范例HVAC空调模块。
**代码范例**
```java
switch (bigType) {
    case Configuration.LIGTH_BIG_TYPE:
        //灯光模块
        break;
    case Configuration.CURTAIN_BIG_TYPE:
        //窗帘模块
        break;
    case Configuration.AIR_BIG_TYPE:
        //空调模块
        if(appliancesInfos.get(position).getDeviceType() == HDLApConfig.TYPE_AC_HVAC){
            //HDLApConfig.TYPE_AC_HVAC为HVAC空调模块
        }else {
            //其他空调模块
        }
        break;
    case Configuration.LOGIC_BIG_TYPE:
        //逻辑模块
        break;
    case Configuration.AUDIO_BIG_TYPE:
        //音乐模块
        break;
    case Configuration.SECURITY_BIG_TYPE:
        //安防模块
        break;
    default:
        break;
}
```
### 三、AppliancesInfo类说明
**类描述**
AppliancesInfo类是SDK搜索或者手机添加设备后,用来保存当前回路模块的所有信息。
**类参数说明代码范例**
```java
    .......
    private String deviceName;//设备名称
    private int bigType;//大类
    private int littleType;//小类
    private int channelNum;//回路号
    private int deviceSubnetID;//设备子网号
    private int deviceDeviceID;//设备号
    private String remarks;//备注
    private String parentRemarks;//模块备注
    private int deviceType;//设备类型
    .......
```
每个模块都会有自己的 大类、小类、子网号、设备号、回路号、设备类型、备注等参数,根据这些参数可以识别出该设备是哪类设备,在哪个子网号、设备号、以及回路号下面,用于区分不同回路设备。后面对设备控制获取状态,监听回复都需要用到里面的这些参数。
Android_HDL_SDK_TTL_DOC/src/api_control_air.md
New file
@@ -0,0 +1,371 @@
# 空调类模块
**空调类模块支持搜索和控制的类型**
HVAC 模块(0)
通用空调面板(3)
### 一、HVAC模块查询状态
**接口描述**
HDLCommand.getHVACDeviceStateFromNetwork(AppliancesInfo info)
调用该接口,获取HVAC空调设备状态。
注:HVAC空调DeviceType设备类型为HDLApConfig.TYPE_AC_HVAC。
**代码范例**
```java
    //查询HVAC空调模块状态信息
    HDLCommand.getHVACDeviceStateFromNetwork(appliancesInfo);
```
**查询状态回调事件监听**
查询状态超时或成功,都会收到DeviceStateEvent订阅事件,SDK所有状态回调都统一用这个事件,如果event.isSuccess()值为false,则代表查询超时,没收到设备回复;
开发者可以在所需要获取状态回调的地方,订阅该事件;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)、AppliancesInfo里面的设备类型(getDeviceType)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备查询状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
    /**
     * 获取单一设备状态回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDeviceStateEventMain(DeviceStateEvent event) {
        if (event.getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
        ) {
            //这个返回的信息是当前状态的
            switch (event.getAppliancesInfo().getDeviceType()) {
                case HDLApConfig.TYPE_AC_HVAC:
                    if (appliancesInfo.getChannelNum() == event.getAppliancesInfo().getChannelNum()) {
                        if (!event.isSuccess()) {
                            showToast("获取空调状态失败,请重新再试");
                            return;
                        }
                        AirHVACBackInfo mAirHVACBackInfo = new AirHVACBackInfo(event.getAppliancesInfo());
                        if (mAirHVACBackInfo == null) {
                            showToast("获取空调状态失败,请重新再试");
                            return;
                        }
                        showAirHVACBackInfo(mAirHVACBackInfo);
                    }
                    break;
                default:
                    //不处理
                    break;
            }
        }
    }
```
### 二、HVAC模块控制改变状态
**接口描述**
HDLCommand.airCtrl(AppliancesInfo info, int type, int state)
type:需要控制功能命令参数
state:需要控制功能对应的状态值
调用该接口,可以控制改变HVAC空调模块的,开、光、模式、风速、温度等状态。
模式:制冷、制热、通风、自动、抽湿5种模式。
风速:自动、高风、中风、低风
温度:温度范围16~30
**代码范例**
```java
    .......
    //发送控制空调模块打开指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.airSwich, AirCtrlParser.airOn);//空调开
    .......
    .......
    //发送控制空调模块改变模式指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.airMode, AirCtrlParser.airModeAuto);//空调模式自动
    .......
    .......
    //发送控制空调模块改变风速指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.airSpeed, AirCtrlParser.airSpeedHigh);//风速高风
    .......
    .......
    //发送控制空调模块改变温度指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.refTem, tempInt);//制冷温度
    .......
```
**控制状态回调事件监听**
控制状态超时或成功,都会收到AirHVACFeedBackEvent订阅事件,如果event.isSuccess()值为false,则代表控制超时,没收到设备回复;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备控制状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
    /**
     * 空调模块控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onAirHVACFeedBackEventMain(AirHVACFeedBackEvent event) {
        if (event.getAirHVACBackInfo().getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getAirHVACBackInfo().getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAirHVACBackInfo().getAppliancesInfo().getChannelNum() == appliancesInfo.getChannelNum()
        ) {
            //        先判断是否超时
            if (!event.isSuccess()) {
                showToast("空调控制超时,请重新再试");
                return;
            }
            AirHVACBackInfo mAirHVACBackInfo = event.getAirHVACBackInfo();
            showAirHVACBackInfo(mAirHVACBackInfo);
        }
    }
    .......
    private void showAirHVACBackInfo(AirHVACBackInfo mAirHVACBackInfo){
        String message = "";
        if(mAirHVACBackInfo.getIsOn() == AirCtrlParser.airOn) {
            message = getSwichStateString(mAirHVACBackInfo.getIsOn());
            message += "\n" + getModeStateString(mAirHVACBackInfo.getAirMode());//模式
            message += "\n" + getSpeedStateString(mAirHVACBackInfo.getAirSpeed());//风速
            message += "\n制冷模式温度:" + mAirHVACBackInfo.getRefTemp();
            message += "\n制热模式温度:" + mAirHVACBackInfo.getHeatTemp();
            message += "\n自动模式温度:" + mAirHVACBackInfo.getAutoTemp();
            message += "\n抽湿模式温度:" + mAirHVACBackInfo.getWettedTemp();
        }else {
            message = getSwichStateString(mAirHVACBackInfo.getIsOn());
        }
        airText.setText(message);
        showToast(message);
        HDLLog.Log(message);
    }
```
### 三、通用空调面板查询状态
**接口描述**
通用空调面板不支持查询状态,
注:通用空调面板空调DeviceType设备类型为HDLApConfig.TYPE_AC_PANEL。
**状态改变回调事件监听**
空调面板状态改变会收到DeviceStateEvent订阅事件,SDK所有状态回调都统一用这个事件,如果event.isSuccess()值为false,则代表查询超时,没收到设备回复;
开发者可以在所需要获取状态改变的地方,订阅该事件;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)、AppliancesInfo里面的设备类型(getDeviceType)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备查询状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
    /**
     * 获取单一设备状态回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDeviceStateEventMain(DeviceStateEvent event) {
        if (event.getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
        ) {
            //这个返回的信息是当前状态的
            switch (event.getAppliancesInfo().getDeviceType()) {
//                case HDLApConfig.TYPE_AC_HVAC:
                case HDLApConfig.TYPE_AC_PANEL:
                    if (appliancesInfo.getChannelNum() == event.getAppliancesInfo().getChannelNum()) {
                        if (!event.isSuccess()) {
                            showToast("获取空调状态失败,请重新再试");
                            return;
                        }
                        byte[] curState = event.getAppliancesInfo().getArrCurState();
                        switch (curState[0] & 0xFF) {
                            case AirCtrlParser.airSwich:
                                //是空调开关状态返回
                                break;
                            case AirCtrlParser.airSpeed:
                                //是风速状态返回
                                break;
                            case AirCtrlParser.airMode:
                                //是空调模式状态返回
                                break;
                            case AirCtrlParser.refTem:
                                //是空调制冷温度状态返回
                                break;
                            case AirCtrlParser.heatTem:
                                //是空调制热温度状态返回
                                break;
                            case AirCtrlParser.autoTem:
                                //是空调自动温度状态返回
                                break;
                            case AirCtrlParser.dehumTem:
                                //是空调抽湿温度状态返回
                                break;
                            case AirCtrlParser.upTem:
                                airTempState = curState[1] & 0xFF;
                                airText.setText("空调调温,上升温度:" + (curState[1] & 0xFF));
                                showToast("空调调温,上升温度:" + (curState[1] & 0xFF));
                                HDLLog.Log("空调调温,上升温度:" + (curState[1] & 0xFF));
                                break;
                            case AirCtrlParser.downTem:
                                airTempState = curState[1] & 0xFF;
                                airText.setText("空调调温,下降温度:" + (curState[1] & 0xFF));
                                showToast("空调调温,下降温度:" + (curState[1] & 0xFF));
                                HDLLog.Log("空调调温,下降温度:" + (curState[1] & 0xFF));
                                break;
                        }
                    }
                    break;
                default:
                    //不处理
                    break;
            }
        }
    }
```
### 四、通用空调面板控制改变状态
**接口描述**
HDLCommand.airCtrl(AppliancesInfo info, int type, int state)
type:需要控制功能命令参数
state:需要控制功能对应的状态值
调用该接口,可以控制改变通用空调面板模块的,开、光、模式、风速、温度等状态。
模式:制冷、制热、通风、自动、抽湿5种模式。
风速:自动、高风、中风、低风
温度:温度范围16~30
注:通用空调面板和HVAC空调模块不一样,通用空调面板控制什么状态就返回什么状态。
例如:控制开关状态,空调面板只会回复当前开关状态,模式、风速、温度等其他状态不会返回,所以监听回调方法时需先判断,当前回复的是什么状态参数,再进行下一步处理。
**代码范例**
```java
    .......
    //发送控制空调模块打开指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.airSwich, AirCtrlParser.airOn);//空调开
    .......
    .......
    //发送控制空调模块改变模式指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.airMode, AirCtrlParser.airModeAuto);//空调模式自动
    .......
    .......
    //发送控制空调模块改变风速指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.airSpeed, AirCtrlParser.airSpeedHigh);//风速高风
    .......
    .......
    //发送控制空调模块改变温度指令
    HDLCommand.airCtrl(appliancesInfo, AirCtrlParser.refTem, tempInt);//制冷温度
    .......
```
**控制状态回调事件监听**
控制状态超时或成功,都会收到AirFeedBackEvent订阅事件,如果event.isSuccess()值为false,则代表控制超时,没收到设备回复;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备控制状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
   /**
     * 空调模块控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onAirFeedBackInfoEventMain(AirFeedBackEvent event) {
        if (event.getAirCtrlBackInfo().getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getAirCtrlBackInfo().getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAirCtrlBackInfo().getAppliancesInfo().getChannelNum() == appliancesInfo.getChannelNum()
        ) {
            //        先判断是否超时
            if (!event.isSuccess()) {
                showToast("空调控制超时,请重新再试");
                return;
            }
            byte[] curState = event.getAirCtrlBackInfo().getCurState();
            switch (curState[0] & 0xFF) {
                case AirCtrlParser.airSwich:
                    //是空调开关状态返回
                    break;
                case AirCtrlParser.airSpeed:
                    //是风速状态返回
                    break;
                case AirCtrlParser.airMode:
                    //是空调模式状态返回
                    break;
                case AirCtrlParser.refTem:
                    //是空调制冷温度状态返回
                    break;
                case AirCtrlParser.heatTem:
                    //是空调制热温度返回
                    break;
                case AirCtrlParser.autoTem:
                    //是空调自动温度返回
                    break;
                case AirCtrlParser.dehumTem:
                    //是空调抽湿热温度返回
                    break;
                case AirCtrlParser.upTem:
                    airTempState = curState[1] & 0xFF;
                    airText.setText("空调调温,上升温度:" + (curState[1] & 0xFF));
                    showToast("空调调温,上升温度:" + (curState[1] & 0xFF));
                    HDLLog.Log("空调调温,上升温度:" + (curState[1] & 0xFF));
                    break;
                case AirCtrlParser.downTem:
                    airTempState = curState[1] & 0xFF;
                    airText.setText("空调调温,下降温度:" + (curState[1] & 0xFF));
                    showToast("空调调温,下降温度:" + (curState[1] & 0xFF));
                    HDLLog.Log("空调调温,下降温度:" + (curState[1] & 0xFF));
                    break;
            }
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_control_curtain.md
New file
@@ -0,0 +1,205 @@
# 窗帘类模块
**窗帘类模块支持搜索和控制的类型**
开合帘电机(00)
卷帘电机(01)
窗帘模块(02)
### 一、查询状态
**接口描述**
HDLCommand.getCurtainDeviceStateFromNetwork(AppliancesInfo info)
调用该接口,可以查询当前窗帘类设备的开关状态信息。
**代码范例**
```java
    //请求获取当前窗帘模块状态信息
    HDLCommand.getCurtainDeviceStateFromNetwork(appliancesInfo);
```
**查询状态回调事件监听**
查询状态超时或成功,都会收到DeviceStateEvent订阅事件,SDK所有状态回调都统一用这个事件,如果event.isSuccess()值为false,则代表查询超时,没收到设备回复;
开发者可以在所需要获取状态回调的地方,订阅该事件;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)、AppliancesInfo里面的设备类型(getDeviceType)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备查询状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
     /**
     * 获取单一设备状态回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDeviceStateEventMain(DeviceStateEvent event) {
        if (event.getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
        ) {
            //这个返回的信息是当前状态的
            switch (event.getAppliancesInfo().getDeviceType()) {
                case HDLApConfig.TYPE_CURTAIN_GLYSTRO:
                case HDLApConfig.TYPE_CURTAIN_ROLLER:
                case HDLApConfig.TYPE_CURTAIN_MODULE:
                    if (appliancesInfo.getChannelNum() == event.getAppliancesInfo().getChannelNum()) {
                        if (!event.isSuccess()) {
                            showToast("获取窗帘状态失败,请重新再试");
                            return;
                        }
                        showMessage = "";
                        //窗帘模块:curState:0=停止,1=打开,2=关闭。
                        //开合帘电机,卷帘电机:curState:1-100开合度。
                        int curState = HDLUtlis.getIntegerByObject(event.getAppliancesInfo().getCurState());
                        if (event.getAppliancesInfo().getDeviceType() == HDLApConfig.TYPE_CURTAIN_MODULE) {//判断是否为窗帘模块,否则为开合帘或卷帘电机
                            switch (curState) {
                                case CurtainCtrlParser.curtainOff:
                                    showMessage = "窗帘关";
                                    curtainBtn.setText(showMessage);
                                    curText1.setText(showMessage);
                                    curtainState = curState;
                                    break;
                                case CurtainCtrlParser.curtainOn:
                                    showMessage = "窗帘开";
                                    curtainBtn.setText(showMessage);
                                    curText1.setText(showMessage);
                                    curtainState = curState;
                                    break;
                                case CurtainCtrlParser.curtainPause:
                                    showMessage = "窗帘暂停";
                                    curtainBtn.setText(showMessage);
                                    curText1.setText(showMessage);
                                    curtainState = curState;
                                    break;
                            }
                        } else {
                            showMessage = "窗帘开到" + curState + "%";
                            curtainBtn5.setText(showMessage);
                            curtainState = curState;
                        }
                        showToast("获取成功:" + showMessage);
                    }
                    break;
                default:
                    //不处理
                    break;
            }
        }
    }
```
**备注**
HDLApConfig.TYPE_CURTAIN_MODULE 为窗帘模块,该类型模块,只有开、关、停止 3种状态;
HDLApConfig.TYPE_CURTAIN_GLYSTRO 为开合帘电机,该类型模块,返回状态0-100%,表示打开百分比;
HDLApConfig.TYPE_CURTAIN_ROLLER 为卷帘电机,该类型模块,返回状态0-100%,表示打开百分比;
### 二、控制改变状态
**接口描述**
HDLCommand.curtainCtrl(AppliancesInfo info, int state)
调用该接口,可以控制改变窗帘类模块的,打开、关闭、停止和打开百分比(窗帘模块不能控制百分百,开合帘电机、卷帘电机才能)。
**代码范例**
```java
    ........
    //发送控制窗帘打开命令
    HDLCommand.curtainCtrl(appliancesInfo, CurtainCtrlParser.curtainOn);
    ........
    ........
    //发送控制开合帘电机打开到50%
    HDLCommand.curtainCtrl(appliancesInfo, 50);
    ........
```
**控制状态回调事件监听**
控制状态超时或成功,都会收到CurtainFeedBackEvent订阅事件,窗帘类控制回调都统一用这个事件,如果event.isSuccess()值为false,则代表控制超时,没收到设备回复;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备控制状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
      /**
     * 窗帘模块控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onCurtainFeedBackInfoEventMain(CurtainFeedBackEvent event) {
//        先判断是否超时
        HDLLog.Log("onCurtainFeedBackInfoEventMain in");
        if (event.getCurtainCtrlBackInfo().getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getCurtainCtrlBackInfo().getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getCurtainCtrlBackInfo().getNum() == appliancesInfo.getChannelNum()
        ) {
            if (!event.isSuccess()) {
                showToast("窗帘控制超时,请重新再试");
                return;
            }
            int curState = event.getCurtainCtrlBackInfo().getState();
            //窗帘模块:curState:0=停止,1=打开,2=关闭。
            //开合帘电机,卷帘电机:curState:1-100开合度。也会返回0,1,2的状态
            //建议开合帘电机,卷帘电机按停止后再读取当前状态来获取当前状态值
            String remarks = event.getCurtainCtrlBackInfo().getRemarks();
            String parentRemarks = event.getCurtainCtrlBackInfo().getParentRemarks();
            int num = event.getCurtainCtrlBackInfo().getNum();
//            showToast(parentRemarks+" 的 "+remarks+" 回路号:"+num+" 返回"+" 状态为:"+curState);
            HDLLog.Log(parentRemarks + " 的 " + remarks + " 回路号:" + num + " 返回" + " 状态为:" + curState);
            if (event.getCurtainCtrlBackInfo().getAppliancesInfo().getDeviceType() == HDLApConfig.TYPE_CURTAIN_MODULE) {
                showMessage = "";
                //判断是否为窗帘模块
                switch (curState) {
                    case CurtainCtrlParser.curtainOff:
                        showMessage = "窗帘关";
                        curtainBtn.setText(showMessage);
                        curText1.setText(showMessage);
                        curtainState = curState;
                        HDLLog.Log("窗帘控制 :窗帘关" + "  回路号:" + num);
                        break;
                    case CurtainCtrlParser.curtainOn:
                        showMessage = "窗帘开";
                        curtainBtn.setText(showMessage);
                        curText1.setText(showMessage);
                        curtainState = curState;
                        HDLLog.Log("窗帘控制 :窗帘开" + "  回路号:" + num);
                        break;
                    case CurtainCtrlParser.curtainPause:
                        showMessage = "窗帘暂停";
                        curtainBtn.setText(showMessage);
                        curText1.setText(showMessage);
                        curtainState = curState;
                        HDLLog.Log("窗帘控制 :窗帘暂停" + "  回路号:" + num);
                        break;
                }
                showToast(showMessage);
            } else {
                //开合帘或卷帘 显示百分比
                curtainBtn5.setText("窗帘开到" + curState + "%");
                curText2.setText("窗帘开到" + curState + "%");
                curtainState = curState;
            }
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_control_light.md
New file
@@ -0,0 +1,132 @@
# 灯光类模块
**灯光类模块支持搜索和控制的类型**
调光回路(00)
开关回路(01)
混合调光类(09)
混合开关类(10)
### 一、查询状态
**接口描述**
HDLCommand.getLightDeviceStateFromNetwork(AppliancesInfo info)
调用该接口,可以查询当前灯光设备的亮度状态信息。
**代码范例**
```java
    //请求获取当前灯光模块状态信息
    HDLCommand.getLightDeviceStateFromNetwork(appliancesInfo);
```
**查询状态回调事件监听**
查询状态超时或成功,都会收到DeviceStateEvent订阅事件,SDK所有状态回调都统一用这个事件,如果event.isSuccess()值为false,则代表查询超时,没收到设备回复;
开发者可以在所需要获取状态回调的地方,订阅该事件;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)、AppliancesInfo里面的设备类型(getDeviceType)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备查询状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
      /**
     * 获取单一设备状态回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDeviceStateEventMain(DeviceStateEvent event) {
        if (event.getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
        ) {
            //这个返回的信息是当前状态的
            switch (event.getAppliancesInfo().getDeviceType()) {
                case HDLApConfig.TYPE_LIGHT_DIMMER:
                case HDLApConfig.TYPE_LIGHT_RELAY:
                case HDLApConfig.TYPE_LIGHT_MIX_DIMMER:
                case HDLApConfig.TYPE_LIGHT_MIX_RELAY:
                    if (appliancesInfo.getChannelNum() == event.getAppliancesInfo().getChannelNum()) {
                        if (!event.isSuccess()) {
                            showToast("获取灯光状态失败,请重新再试");
                            return;
                        }
                        int brightness =  HDLUtlis.getIntegerByObject(event.getAppliancesInfo().getCurState());
                        lightBtn.setText("亮度 = " + brightness);
                        lightText.setText("当前亮度 = " + brightness);
                        showToast("获取状态返回:亮度 = " +  brightness);
                    }
                    break;
                default:
                    //不处理
                    break;
            }
        }
    }
```
### 二、控制改变状态
**接口描述**
HDLCommand.lightCtrl(AppliancesInfo info, int state)
state:范围0~100
调用该接口,可以控制改变灯光模块的,开关状态和亮度值。
**代码范例**
```java
    //发送控制灯光模块指令
    //appliancesInfo:为需要控制的的模块info参数,里面保存了当前回路模块的所有参数信息
    //lightState:控制改变的亮度值 0~100
    HDLCommand.lightCtrl(appliancesInfo, lightState);
```
**控制状态回调事件监听**
控制状态超时或成功,都会收到LightFeedBackEvent订阅事件,灯光控制回调都统一用这个事件,如果event.isSuccess()值为false,则代表控制超时,没收到设备回复;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备控制状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
    /**
     * 灯光控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onLightFeedBackInfoEventMain(LightFeedBackEvent event) {
        if (event.getLightCtrlBackInfo().getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getLightCtrlBackInfo().getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getLightCtrlBackInfo().getChannelNum() == appliancesInfo.getChannelNum()
        ) {
            //        先判断是否超时
            if (!event.isSuccess()) {
                showToast("灯光控制超时,请重新再试");
                lightBtn.setText("灯光控制超时,请重新再试");
                return;
            }
            int brightness = event.getLightCtrlBackInfo().getBrightness();
            lightState = brightness == 100 ? 0 : 100;//如果返回100重置状态为0,反之重置状态100
            lightBtn.setText("当前亮度 = " + brightness);
            lightText.setText("当前亮度 = " + brightness);
            /*以下为灯光推送示例代码,可以识别哪个继电器,哪个调光灯,哪个回路,也可用作控制回馈。
            按需求调用*/
            String remarks = event.getLightCtrlBackInfo().getRemarks();//获取返回的灯光备注。如果每个灯光回路备注都唯一,可以直接通过备注判断
            String parentRemarks = event.getLightCtrlBackInfo().getParentRemarks();//获取继电器或调光灯备注。这里可以知道是哪个设备返回的
            int num = event.getLightCtrlBackInfo().getChannelNum();//获取回路号。这里可以获取到这个继电器或调光灯的回路号
            showToast("模块:" + parentRemarks + " 的 " + remarks + " 回路,回路号为:" + num + " 返回" + " 亮度为:" + brightness);
            HDLLog.Log("当前亮度 = " + brightness);
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_control_music.md
New file
@@ -0,0 +1,213 @@
# 音乐类模块
**音乐类模块支持搜索和控制的类型**
背景音乐模块(0)
### 一、背景音乐控制
**接口描述**
HDLCommand.audioCtrl(AppliancesInfo info, int type)
info:需要控制设备的参数
type:需要控制功能命令参数
调用该接口,可以控制背景音乐模块,获取当前歌曲信息、播放/暂停、播放/停止、上一首、下一首、切换播放模式、获取下一列表、获取上一列表。
**代码范例**
```java
    .......
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.GET_AUDIO_CURRRENT_INFO);//获取当前音乐信息。返回当前歌曲、所有信息。
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.GET_AUDIO_MODE);//获取当前音乐播放模式。仅返回单曲播放等播放模式。
    .......
    .......
    //播放或暂停
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_AUDIO_PLAYPAUSE);
    .......
    .......
    //播放或停止
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_AUDIO_PLAYSTOP);
    .......
    .......
    //上一首
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_PRE_SONG);
    .......
    .......
    //下一首
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_NEXT_SONG);
    .......
    .......
    //切换播放模式
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_AUDIO_MODE_UP);//播放模式+
    //HDLCommand.HDLaudioCtrl(CtrlAudioActivity.this,appliancesInfo,HDLAudio.SET_AUDIO_MODE_DOWN);//播放模式-
    .......
    .......
    //获取下一列表,当前音乐会停止播放
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_NEXT_LIST);
    .......
    .......
    //获取上一列表,当前音乐会停止播放
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_PRE_LIST);
    .......
```
**接口描述**
HDLCommand.audioCtrl(AppliancesInfo info, int type, int value)
调用该接口,可以控制背景音乐模块,获取当前播放列表、控制设备音量。
**代码范例**
```java
    .......
    //获取当前播放列表,此方法如果在歌曲播放状态时调用则会导致歌曲停止播放,硬件设计如此
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.GET_AUDIO_LIST, curListNum);
    .......
    .......
    //设置播放音量
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_AUDIO_VOL, 0);//音量最小:0。小于0,SDK不处理
    .......
```
**接口描述**
HDLCommand.audioCtrl(AppliancesInfo info, int type, int listId, int songId)
listId:当前列表号
songId:要播放的列表中歌曲对应的歌曲ID
调用该接口,可以控制背景音乐模块,选择指定播放的歌曲。
**代码范例**
```java
    .......
    //设置播放音量
    HDLCommand.audioCtrl(appliancesInfo, HDLAudio.SET_CHOOSE_PLAY_SONG, curListNum, position);
    .......
```
**查询状态回调事件监听**
背景音乐模块查询、控制超时或成功,都会收到AudioInfoEvent订阅事件;
开发者可以在所需要获取状态回调的地方,订阅该事件;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)是否一致,从而判断该消息事件为当前设备查询状态返回的消息,进行下一步处理,不一致则过滤不处理。
根据返回的event.getType()类型,判断是什么类型状态返回。
例:getType()等于HDLAudio.CALLBACK_CURRENT_VOLUME 的话,为返回音量类型参数参数
输出打印:HDLLog.Log("当前音量值:" + event.getAudioInfoInt());
**代码范例**
```java
    /**
     * 音乐模块状态回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onAudioEventMain(AudioInfoEvent event) {
        //判断是否为本音乐模块的子网号,设备号
        if (event.getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
        ) {
            HDLLog.Log("onAudioEventMain: " + event.getType());
            switch (event.getType()) {
                case HDLAudio.CALLBACK_SONG_NAME_LIST:
                    listString.clear();
                    for (int i = 0; i < event.getSongNameList().size(); i++) {
                        listString.add(event.getSongNameList().get(i));
                    }
                    adapter.notifyDataSetChanged();
                    break;
                case HDLAudio.CALLBACK_CURRENT_VOLUME:
                    HDLLog.Log("当前音量值:" + event.getAudioInfoInt());
                    break;
                case HDLAudio.CALLBACK_AUDIO_LIST_NUM:
                    int[] listNum = event.getAudioListInfo();
                    curListNum = listNum[0];
                    HDLLog.Log("当前列表号:" + listNum[0] + " 当前共有列表数:" + listNum[1]);
                    if (isInit) {
                        isInit = false;//此操作为仅初始化才请求获取当前音乐列表,厂商可以自行决定何时获取音乐列表
                        HDLCommand.audioCtrl(appliancesInfo, HDLAudio.GET_AUDIO_LIST, curListNum);//获取当前播放列表,此方法如果在歌曲播放状态时调用则会导致歌曲停止播放,硬件设计如此
                    }
                    break;
                case HDLAudio.CALLBACK_CURRENT_LIST_NAME:
                    HDLLog.Log("当前列表名:" + event.getAudioInfoStr());
                    break;
                case HDLAudio.CALLBACK_CURRENT_SONG_NUM:
                    int[] songNum = event.getAudioListInfo();
                    HDLLog.Log("当前歌曲号:" + songNum[0] + " 当前共有歌曲数:" + songNum[1]);
                    break;
                case HDLAudio.CALLBACK_CURRENT_SONG_NAME:
                    HDLLog.Log("当前歌曲名:" + event.getAudioInfoStr());
                    curSongNameTv.setText("当前歌曲名:" + event.getAudioInfoStr());
                    break;
                case HDLAudio.CALLBACK_CURRENT_SONG_INFO:
                    int[] songInfo = event.getAudioListInfo();
                    //songInfo[0],songInfo[1]获得的值为秒,如songInfo[0]=250,即歌曲总时长为250秒。songInfo[2]获得的值为:1、2、3。1:停止,2:播放,3:暂停。
                    String curStatus;
                    switch (songInfo[2]) {
                        case 1:
                            curStatus = "停止";
                            break;
                        case 2:
                            curStatus = "播放";
                            break;
                        case 3:
                            curStatus = "暂停";
                            break;
                        default:
                            curStatus = "未知";
                            break;
                    }
                    HDLLog.Log("当前歌曲总时长:" + songInfo[0] + "秒 ,当前歌曲已播放时长:" + songInfo[1] + "秒, 当前歌曲状态:" + curStatus);
                    curSongInfoTv.setText("当前歌曲总时长:" + songInfo[0] + "秒 ,当前歌曲已播放时长:" + songInfo[1] + "秒, 当前歌曲状态:" + curStatus);
                    break;
                case HDLAudio.CALLBACK_CURRENT_MODE:
                    String curMode;
                    switch (event.getAudioInfoInt()) {
                        case 1:
                            curMode = "单曲播放";
                            break;
                        case 2:
                            curMode = "单曲循环";
                            break;
                        case 3:
                            curMode = "连续播放";
                            break;
                        case 4:
                            curMode = "连播循环";
                            break;
                        default:
                            curMode = "未知";
                            break;
                    }
                    modeBtn.setText(curMode);
                    break;
                default:
                    break;
            }
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_control_scenes.md
New file
@@ -0,0 +1,125 @@
# 场景控制(逻辑模块)
**场景控制的类型**
逻辑模块(大类 12 小类 0 )
全局逻辑模块(大类 17 小类 0)
### 一、查询状态
**接口描述**
HDLCommand.getSceneNumStateFromNetwork(AppliancesInfo info)
调用该接口,可以查询当前场景号信息。
**代码范例**
```java
    //请求获取通用开关状态信息
    HDLCommand.getSceneNumStateFromNetwork(appliancesInfo);
```
**查询状态回调事件监听**
    查询状态成功,会收到ScenesStateBackEvent订阅事件,同时场景变化也会收到该事件回调
**代码范例**
```java
      /**
     * 当前场景状态变化都会推送这个通知Event
     * 更加项目需要, 这里的区号有的情况下不需处理,有的设备固定是1 只需处理场景号,判断目前执行了那个场景就行
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onScenesStateBackEventMain(ScenesStateBackEvent event) {
        if (event.getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()) {
//            //
//            int mAreaNum = event.getAreaNum();
//            int mSceneNum = event.getSceneNum();
//
//            //可以自己通过区号 和 场景号 来匹配判断当前执行了什么场景
//            sceneText.setText("当前模块执行的场景区号: " + mAreaNum + "  场景号: "+mSceneNum);
            int mSceneNum = event.getSceneNum();
            //可以自己通过场景号 来匹配判断当前执行了什么场景
            sceneText.setText("当前模块执行的场景号: "+mSceneNum);
        }
    }
```
### 二、控制改变状态
**接口描述**
HDLCommand.logicCtrl(AppliancesInfo info)
调用该接口,可以执行相应的场景。
**代码范例**
```java
    //发送场景控制指令
    //appliancesInfo:为需要控制的的模块info参数,里面保存了当前回路模块的所有参数信息
    HDLCommand.logicCtrl(appliancesInfo);
```
**控制状态回调事件监听**
控制场景超时或成功,都会收到LogicFeedBackEvent 订阅事件,通用开关控制回调都统一用这个事件,如果event.isSuccess()值为false,则代表控制超时,没收到设备回复;
如果控制成功的话,场景状态变化,也会收到ScenesStateBackEvent订阅事件,可以自己通过场景号 来匹配判断当前执行了什么场景
**代码范例**
```java
      /**
     * 逻辑模块控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onLogicFeedBackInfoEventMain(LogicFeedBackEvent event) {
//        先判断是否超时
        if (event.getLogicCtrlBackInfo().getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getLogicCtrlBackInfo().getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getLogicCtrlBackInfo().getAppliancesInfo().getChannelNum() == appliancesInfo.getChannelNum()
        ) {
            if (!event.isSuccess()) {
                showToast("场景控制超时,请重新再试");
                return;
            }
            showToast("场景控制成功");
        }
    }
   /**
     * 当前场景状态变化都会推送这个通知Event
     * 更加项目需要, 这里的区号有的情况下不需处理,有的设备固定是1 只需处理场景号,判断目前执行了那个场景就行
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onScenesStateBackEventMain(ScenesStateBackEvent event) {
        if (event.getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()) {
//            //
//            int mAreaNum = event.getAreaNum();
//            int mSceneNum = event.getSceneNum();
//
//            //可以自己通过区号 和 场景号 来匹配判断当前执行了什么场景
//            sceneText.setText("当前模块执行的场景区号: " + mAreaNum + "  场景号: "+mSceneNum);
            int mSceneNum = event.getSceneNum();
            //可以自己通过场景号 来匹配判断当前执行了什么场景
            sceneText.setText("当前模块执行的场景号: "+mSceneNum);
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_control_security.md
New file
@@ -0,0 +1,141 @@
# 安防类模块
**安防类模块支持搜索和控制的类型**
安防模块(0)
### 一、查询布防状态
**接口描述**
HDLCommand.getSecurityStateFromNetwork(AppliancesInfo info)
调用该接口,可以查询当前安防的布防状态信息。
**代码范例**
```java
    //请求获取当前安防模块布防状态信息
    HDLCommand.getSecurityStateFromNetwork(appliancesInfo);
```
**查询状态回调事件监听**
查询状态超时或成功,都会收到DeviceStateEvent订阅事件,SDK所有状态回调都统一用这个事件,如果event.isSuccess()值为false,则代表查询超时,没收到设备回复;
开发者可以在所需要获取状态回调的地方,订阅该事件;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)、AppliancesInfo里面的设备类型(getDeviceType)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备查询状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
     /**
     * 查询布防状态 回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDeviceStateEventMain(DeviceStateEvent event) {
        if (event.getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
        ) {
            //这个返回的信息是当前状态的
            switch (event.getAppliancesInfo().getDeviceType()) {
                case HDLApConfig.TYPE_SECURITY_MODULE:
                    if (appliancesInfo.getChannelNum() == event.getAppliancesInfo().getChannelNum()) {
                        if (!event.isSuccess()) {
                            tv_mesSetText("获取布防状态失败,请重新再试");
                            return;
                        }
                        SecurityArmingStateBackInfo mSecurityArmingStateBackInfo = new SecurityArmingStateBackInfo(event.getAppliancesInfo().getArrCurState());
                        if (mSecurityArmingStateBackInfo == null) {
                            tv_mesSetText("获取布防状态失败,请重新再试");
                            return;
                        }
                        int armingStateBack = mSecurityArmingStateBackInfo.getArmingState();
                        if (armingStateBack == 0) {   //读取返回0为撤防
                            armingState = SecurityParser.ARMING_DISARMING;
                            spinner_arming.setSelection(armingState - 1, true);
                            tv_mesSetText("获取成功,当前状态:" + armingTypeItems[armingState - 1]);
                        } else if (armingStateBack >= 1 && armingStateBack <= 6) {
                            armingState = armingStateBack;//更新状态值
                            spinner_arming.setSelection(armingState - 1, true);
                            tv_mesSetText("获取成功,当前状态:" + armingTypeItems[armingState - 1]);
                        } else {
                            tv_mesSetText("获取成功,未知布防状态");
                        }
                    }
                    break;
            }
        }
    }
```
**注:返回的 armingState布防状态对应关系: 5 = 白天布防 4 = 晚上有客布防 3 = 夜间布防 2 = 离开布防 1 = 假期布防  0 = 撤防**
### 二、控制改变状态
**接口描述**
HDLCommand.securityArmingCtrl(AppliancesInfo info, int state)
调用该接口,修改安防模块的布防状态。
**注:控制的state布防状态对应关系:6 = 撤防 5 = 白天布防 4 = 晚上有客布防 3 = 夜间布防 2 = 离开布防 1 = 假期布防**
    **撤防状态下才能布防,所以想修改其他布防模式需先撤防**
**代码范例**
```java
    //发送修改布防状态命令
    HDLCommand.securityArmingCtrl(appliancesInfo, armingState);
```
**控制状态回调事件监听**
布防超时或成功,都会收到SecurityArmingFeedBackEvent订阅事件,如果event.isSuccess()值为false,则代表控制超时,没收到设备回复;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备控制状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
    /**
     * 布防设置回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSecurityArmingFeedBackEventMain(SecurityArmingFeedBackEvent event) {
        if (event.getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getAppliancesInfo().getChannelNum() == appliancesInfo.getChannelNum()
        ) {
            //先判断是否超时
            if (!event.isSuccess()) {
                tv_mesSetText("布防设置超时,请重新再试");
                return;
            }
            int armingStateGet = event.getArmingState();
            if (armingStateGet >= 1 && armingStateGet <= 6) {
                armingState = armingStateGet;
                spinner_arming.setSelection(armingState - 1, true);
                tv_mesSetText("布防成功,当前状态:" + armingTypeItems[armingState - 1]);
            } else if (armingState == SecurityParser.ARMING_FAIL) {
                tv_mesSetText("布防失败");
            } else {
                tv_mesSetText("未知布防状态");
            }
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_control_switch.md
New file
@@ -0,0 +1,116 @@
# 通用开关模块
**通用开关模块的类型**
通用开关(大类 100 小类 0)
### 一、查询状态
**接口描述**
HDLCommand.getCommonSwitchStateFromNetwork(AppliancesInfo info)
调用该接口,可以查询当前通用开关设备的开关状态。
**代码范例**
```java
    //请求获取通用开关状态信息
    HDLCommand.getCommonSwitchStateFromNetwork(appliancesInfo);
```
**查询状态回调事件监听**
查询状态超时或成功,都会收到onCommonSwitchStateEventMain订阅事件,如果event.isSuccess()值为false,则代表查询超时,没收到设备回复;
开发者可以在所需要获取状态回调的地方,订阅该事件;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)、AppliancesInfo里面的设备类型(getDeviceType)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备查询状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
    /**
     * 通用开关状态 回复回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onCommonSwitchStateEventMain(CommonSwitchStateBackEvent event) {
        if (event.getCommonSwitchBackInfo().getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getCommonSwitchBackInfo().getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getCommonSwitchBackInfo().getAppliancesInfo().getChannelNum() == appliancesInfo.getChannelNum()
        ) {
            if (!event.isSuccess()) {
                showToast("通用开关读取状态超时,请重新再试");
                return;
            }
//            showToast("通用开关控制成功");
            switchState =  event.getCommonSwitchBackInfo().getSwitchState();
            if(switchState>0){
                switchText.setText("当前状态:开");
            }else{
                switchText.setText("当前状态:关");
            }
        }
    }
```
### 二、控制改变状态
**接口描述**
HDLCommand.commonSwitchCtrl(AppliancesInfo info, int )
调用该接口,可以控制通用开关模块的开关状态。
**代码范例**
```java
    //发送控制通用开关指令
    //appliancesInfo:为需要控制的的模块info参数,里面保存了当前回路模块的所有参数信息
    //0=关 255=开
    HDLCommand.commonSwitchCtrl(appliancesInfo, state);
```
**控制状态回调事件监听**
控制超时或成功,都会收到CommonSwitchCtrlBackEvent订阅事件,通用开关控制回调都统一用这个事件,如果event.isSuccess()值为false,则代表控制超时,没收到设备回复;
并通过比较前设备和回调状态设备的子网号(getDeviceSubnetID)、设备号(getDeviceDeviceID)和回路号(getChannelNum)是否一致,从而判断该消息事件为当前设备控制状态返回的消息,进行下一步处理,不一致则过滤不处理。
**代码范例**
```java
    /**
     * 通用开关控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onCommonSwitchCtrlEventMain(CommonSwitchCtrlBackEvent event) {
        if (event.getCommonSwitchBackInfo().getAppliancesInfo().getDeviceDeviceID() == appliancesInfo.getDeviceDeviceID()
                && event.getCommonSwitchBackInfo().getAppliancesInfo().getDeviceSubnetID() == appliancesInfo.getDeviceSubnetID()
                && event.getCommonSwitchBackInfo().getAppliancesInfo().getChannelNum() == appliancesInfo.getChannelNum()
        ) {
            if (!event.isSuccess()) {
                showToast("通用开关控制超时,请重新再试");
                return;
            }
            showToast("通用开关控制成功");
            switchState =  event.getCommonSwitchBackInfo().getSwitchState();
            if(switchState>0){
                 switchText.setText("当前状态:开");
            }else{
                switchText.setText("当前状态:关");
            }
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_mcu.md
New file
@@ -0,0 +1,408 @@
# MCU通信
  <!-- * [读配置信息](./src/Integrated.md)
  * [写配置信息](./src/Integrated.md)
  * [申请升级](./src/Integrated.md)
  * [重启MCU](./src/Integrated.md)
  * [检测丢包状态](./src/Integrated.md) -->
### MCU控制统一回调
MCU的所有请求回调,超时、出错或成功都会统一收到MCUFeedBackEvent订阅事件,用户通过获取返回操作码(event.getMCUDataBean().command)来判断是哪种回调信息,从而实现处理不同回调的数据。
**代码范例**
```java
    /**
     * MCU控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMCUFeedBackEventMain(MCUFeedBackEvent event) {
        if (event.getEventCode() == EventCode.FAILURE_TIMEOUT) {
            if (TextUtils.isEmpty(event.getError())) {
                showToast("MCU请求超时,请稍后再试");
            } else {
                showToast(event.getError());
            }
            return;
        }
        switch (event.getMCUDataBean().command) {
            case MCUConstants.MCU_COMMAND_SEND_BACK:    //
                //透传返回的数据
                handleMCUPassThroughDataBack(event);
                break;
            case MCUConstants.MCU_READ_CONFIGURATION_BACK:// 读配置返回
            case MCUConstants.MCU_WRITE_CONFIGURATION_BACK:// 写配置信息返回
                handleMCUConfigurationBack(event);
                break;
            // case MCUConstants.MCU_DETECT_PACKET_LOSS_STATUS_BACK:// 检测丢包状态返回
            //     //待处理
            //     handleDetectPacketLossStatusBack(event);
                break;
            case MCUConstants.MCU_REQUEST_UPGRADE_BACK:   // 请求升级返回
                handleRequestUpgradeBack(event);
                break;
            case MCUConstants.MCU_RESTART_BACK:     //0x86 重启返回
                handleRestartBack(event);
                break;
            default:
                break;
        }
    }
```
### 一、读配置参数
**接口描述**
HDLCommand.mcuReadConfiguration()
调用该接口,可以读取MCU的配置参数,协议类型、波特率、数据位、校验位和停止位 。
**代码范例**
发送读取MCU配置请求
```java
    //读取MCU配置请求
     HDLCommand.mcuReadConfiguration();
```
读配置信息回调
当监听到command为MCUConstants.MCU_READ_CONFIGURATION_BACK时,为读取配置信息的回调,成功获取MCU配置数据处理并显示;
MCU的配置参数:协议类型、波特率、数据位、校验位和停止位 ,都可以从返回event中获取。
获取方法:event.getMCUDataBean().getMCUConfigurationBean()
**代码范例**
```java
    .......
    case MCUConstants.MCU_READ_CONFIGURATION_BACK:// 写配置信息返回
        handleMCUConfigurationBack(event);//处理MCU读写配置返回数据
    .......
    /**
     * 处理MCU读写配置返回数据
     *
     * @param event
     */
    private void handleMCUConfigurationBack(MCUFeedBackEvent event) {
        if (event.getEventCode() != EventCode.SUCCESS) {
            tv_config_mesSetText("MCU读写配置出错,返回数据异常");
            return;
        }
        tv_config_mesSetText("成功获取配置");
        bGetMCUConfiguration = true;
        updateMCUConfiguration(event.getMCUDataBean().getMCUConfigurationBean());//获取配置参数并显示
    }
```
### 二、写配置参数
**接口描述**
HDLCommand.mcuWriteConfiguration(byte[] sendBytes)
调用该接口,可以修改MCU的配置参数,协议类型、波特率、数据位、校验位和停止位 。
**代码范例**
发送写MCU配置请求,开发者通过修改更新mMCUConfigurationBean对应的参数后,直接调用接口并参入参数即可。
```java
    .......
    private MCUConfigurationBean mMCUConfigurationBean;//配置参数
    .......
    .......
    mMCUConfigurationBean.setMcuDataBit(0);//修改数据位参数
    .......
    //MCU写配置请求
    HDLCommand.mcuWriteConfiguration(mMCUConfigurationBean.getMCUConfigurationSendBytes());
```
写配置信息回调
当监听到command为MCUConstants.MCU_READ_CONFIGURATION_BACK时,为读取配置信息的回调,成功获取MCU配置数据处理并显示;
MCU的配置参数:协议类型、波特率、数据位、校验位和停止位 ,都可以从返回event中获取。
获取方法:event.getMCUDataBean().getMCUConfigurationBean()
**代码范例**
```java
    .......
    case MCUConstants.MCU_WRITE_CONFIGURATION_BACK:// 写配置信息返回
        handleMCUConfigurationBack(event);//处理MCU读写配置返回数据
    .......
    /**
     * 处理MCU读写配置返回数据
     *
     * @param event
     */
    private void handleMCUConfigurationBack(MCUFeedBackEvent event) {
        if (event.getEventCode() != EventCode.SUCCESS) {
            tv_config_mesSetText("MCU读写配置出错,返回数据异常");
            return;
        }
        tv_config_mesSetText("成功获取配置");
        bGetMCUConfiguration = true;
        updateMCUConfiguration(event.getMCUDataBean().getMCUConfigurationBean());//获取配置参数并显示
    }
```
### 三、MCU重启
**接口描述**
HDLCommand.mcuSendRestart()
调用该接口,可以让MCU重启。
**代码范例**
发送MCU重启请求
```java
    //MCU重启请求
    HDLCommand.mcuSendRestart();
```
MCU重启回调
当监听到command为MCUConstants.MCU_RESTART_BACK时,为MCU重启回调;
**代码范例**
```java
    .......
    case MCUConstants.MCU_RESTART_BACK:     //重启返回
                handleRestartBack(event);
    .......
    /**
     * 处理MCU请求重启返回数据
     *
     * @param event
     */
    private void handleRestartBack(MCUFeedBackEvent event) {
        if (event.getEventCode() != EventCode.SUCCESS) {
            showToast("MCU请求重启返回错误,重启失败");
            return;
        }
        if (bUpdating) {
            bUpdating = false;
            tv_update_mes.setText("MCU重启成功,升级完成!");
            tv_other_mesSetText("MCU重启成功,升级完成!");
        } else {
            tv_other_mesSetText("MCU重启成功!");
        }
    }
```
### 四、升级MCU固件
**接口描述**
HDLCommand.mcuRequestUpgradeWithFile(byte[] upgradeFileDatas)
调用该接口,可以升级MCU固件。
**代码范例**
开发者首先需选择本地bin升级文件,并转换成byte[]类型升级文件数据,然后调用升级接口,并传入升级文件参数即可;
```java
    .......
    private byte[] upgradeFileDatas;//升级文件数据
    .......
    .......
    //读取升级文件
    fis = new FileInputStream(file);
    int length = fis.available();
    upgradeFileDatas = new byte[length];
    fis.read(upgradeFileDatas);
    fis.close();
    .......
    .......
    //开始升级
    if (upgradeFileDatas == null) {
        showToast("请先选择升级文件");
        return;
    }
    HDLCommand.mcuRequestUpgradeWithFile(upgradeFileDatas);//传入升级文件并开始升级
    .......
```
**升级进度监听**
首先activity继承IMcuOtaListener,并实现对应的接口方法;
**代码范例**
```java
    .......
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        .......
        HDLSerialPortCore.setIMcuOtaListener(this);//设置监听
    }
    .......
    .......
    @Override
    public void onSuccess() {
        sendRestartTimer();//升级10S超时提示
        HDLLog.Log("IMcuOtaListener onSuccess");
        runOnUiThread(new Runnable() {  //要在主线程更新UI
            public void run() {
                tv_update_mesSetText("升级成功,等待重启...");
            }
        });
    }
    @Override
    public void onFailure(int code, final String error) {
        HDLLog.Log("IMcuOtaListener onFailure");
        runOnUiThread(new Runnable() {
            public void run() {
                tv_update_mesSetText("升级失败: " + error);
            }
        });
    }
    @Override
    public void onProgress(final int progress) {
        HDLLog.Log("IMcuOtaListener onProgress:" + progress);
        runOnUiThread(new Runnable() {
            public void run() {
                tv_update_mes.setText("升级进度:" + progress + "%");
            }
        });
    }
    .......
```
升级成功后,MCU会自动重启,监听到重启完毕,才代表完成升级;
**MCU升级状态回调**
当监听到command为MCUConstants.MCU_REQUEST_UPGRADE_BACK时,为MCU升级状态回调;
**代码范例**
```java
    .......
    case MCUConstants.MCU_REQUEST_UPGRADE_BACK:   // 请求升级返回
                handleRequestUpgradeBack(event);
    .......
     /**
     * 处理MCU请求升级返回数据
     *
     * @param event
     */
    private void handleRequestUpgradeBack(MCUFeedBackEvent event) {
        if (event.getEventCode() != EventCode.SUCCESS) {
            tv_update_mesSetText("MCU请求升级出错");
            return;
        }
        bUpdating = true;
        tv_update_mesSetText("MCU请求升级成功,开始升级...");
    }
```
### 五、发送透传数据
**接口描述**
HDLCommand.mcuSendTransparentData(byte[] sendBytes)
调用该接口,可以发送透传数据,不走bus协议,直接转发,不做数据格式处理。
调用该接口之后收到的数据,默认走数据透传不做格式处理,不需要时可调接口关闭。
**代码范例**
```java
    .......
    // 发送透传数据
    byte[] sendBytes = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
    HDLCommand.mcuSendTransparentData(sendBytes);
    .......
```
透传数据接收
当监听到command为MCUConstants.MCU_COMMAND_SEND_BACK时,为返回接收到的透传数据;
接收的透传数据可以直接从event获取,event.getMCUDataBean().receiveBytes。
**代码范例**
```java
    .......
    case MCUConstants.MCU_COMMAND_SEND_BACK:    //
        //透传返回的数据
        handleMCUPassThroughDataBack(event);
    .......
    /**
     * 处理MCU透传回调数据
     * 透传数据,不走bus协议,直接转发,不做数据格式处理
     *
     * @param event
     */
    private void handleMCUPassThroughDataBack(MCUFeedBackEvent event) {
        if (event.getEventCode() != EventCode.SUCCESS) {
            tv_other_mesSetText("MCU透传数据出错,返回数据异常");
            return;
        }
        String receiveString = HDLStringUtils.ByteArrToHex(event.getMCUDataBean().receiveBytes, 0, event.getMCUDataBean().receiveBytes.length);
        tv_other_mes.setText("收到的透传数据:" + receiveString);
        HDLLog.Log("收到的透传数据:" + receiveString);
    }
```
### 六、开启和关闭透传数据
**接口描述**
HDLCommand.setHDLPassThroughOpen(boolean bOpen)
调用该接口,可以开启和关闭透传数据,关闭数据透传默认走bus协议;其他协议下,开发者可以打开数据透传,自己自定义收发数据。
注:SDK每次重新初始化启动后,默认都是关闭,如果要数据透传,需要初始化完毕后调用改接口打开。
**代码范例**
```java
    .......
    //关闭透传数据
     HDLCommand.setHDLPassThroughOpen(false);
    .......
```
Android_HDL_SDK_TTL_DOC/src/api_mcu_about.md
New file
@@ -0,0 +1,57 @@
# MCU通信
  <!-- * [读配置信息](./src/Integrated.md)
  * [写配置信息](./src/Integrated.md)
  * [申请升级](./src/Integrated.md)
  * [重启MCU](./src/Integrated.md)
  * [检测丢包状态](./src/Integrated.md) -->
### MCU控制统一回调
MCU的所有请求回调,超时、出错或成功都会统一收到MCUFeedBackEvent订阅事件,用户通过获取返回操作码(event.getMCUDataBean().command)来判断是哪种回调信息,从而实现处理不同回调的数据。
**代码范例**
```java
    /**
     * MCU控制回调Event
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMCUFeedBackEventMain(MCUFeedBackEvent event) {
        if (event.getEventCode() == EventCode.FAILURE_TIMEOUT) {
            if (TextUtils.isEmpty(event.getError())) {
                showToast("MCU请求超时,请稍后再试");
            } else {
                showToast(event.getError());
            }
            return;
        }
        switch (event.getMCUDataBean().command) {
            case MCUConstants.MCU_COMMAND_SEND_BACK:    //
                //透传返回的数据
                handleMCUPassThroughDataBack(event);
                break;
            case MCUConstants.MCU_READ_CONFIGURATION_BACK:// 读配置返回
            case MCUConstants.MCU_WRITE_CONFIGURATION_BACK:// 写配置信息返回
                handleMCUConfigurationBack(event);
                break;
            // case MCUConstants.MCU_DETECT_PACKET_LOSS_STATUS_BACK:// 检测丢包状态返回
            //     //待处理
            //     handleDetectPacketLossStatusBack(event);
                break;
            case MCUConstants.MCU_REQUEST_UPGRADE_BACK:   // 请求升级返回
                handleRequestUpgradeBack(event);
                break;
            case MCUConstants.MCU_RESTART_BACK:     //0x86 重启返回
                handleRestartBack(event);
                break;
            default:
                break;
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/api_search.md
New file
@@ -0,0 +1,157 @@
# 搜索设备
### 一、搜索设备
**接口描述**
HDLCommand.getHomeDevices()
调用该接口,会清空原本地设备列表数据,重新搜索设备(可以搜索出支持简易编程搜索的设备)。
**代码范例**
发送搜索设备请求
```java
    /**全部重新搜索,清空原设备列表数据*/
    HDLCommand.getHomeDevices();
```
搜索设备回调事件
搜索超时或搜索成功,都会收到DevicesInfoEvent订阅事件。
搜索成功后,会返回搜到到的所有模块设备数据,通过event.getDesDataList()取出,后面的所有的控制设备操作都需要用到这个List里面的AppliancesInfo设备参数,SDK做了本地保存操作,同样开发者可以根据需要自己另外保存。
```java
    /**
     * ====================EventBus 订阅事件 ====================
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDevicesInfoEventMain(DevicesInfoEvent event) {
        mAllDevicesList.clear();
        mProgressDialog.dismiss();
        if (!event.isSuccess()) {
            Toast.makeText(MainActivity.this, "搜索超时,请重新再试", Toast.LENGTH_SHORT).show();
            tvResult.setText("搜索超时,请重新再试");
            return;
        }
        mDevicesDataList = event.getDesDataList();
        updateDeviceListView();
    }
```
### 二、手动添加安防模块设备
**接口描述**
HDLDeviceManager.addSecurityDevicesManually(int mSubnetID, int mDeviceID, int mChannelNum, String mRemarks)
调用该接口,可以手动添加安防模块(不支持简易编程搜索的设备,只能手动添加)。
需要传入该安防模块当前的子网号,设备号,回路号,以及它的备注名。
**代码范例**
```java
    .......
    //isSuccess 返回true则代表添加成功
    isSuccess = HDLDeviceManager.addSecurityDevicesManually(subnetID, deviceID, channelNum, "安防模块1");
    .......
```
添加成功后同样会收到DevicesInfoEvent订阅事件,更新返回当前所有的设备列表数据
**代码范例**
```java
    /**
     * ====================EventBus 订阅事件 ====================
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDevicesInfoEventMain(DevicesInfoEvent event) {
        mAllDevicesList.clear();
        mProgressDialog.dismiss();
        if (!event.isSuccess()) {
            Toast.makeText(MainActivity.this, "搜索超时,请重新再试", Toast.LENGTH_SHORT).show();
            tvResult.setText("搜索超时,请重新再试");
            return;
        }
        mDevicesDataList = event.getDesDataList();
        updateDeviceListView();
    }
```
### 三、手动添加音乐模块设备
**接口描述**
HDLDeviceManager.addAudioDevicesManually(int mSubnetID, int mDeviceID, int mChannelNum, String mRemarks)
调用该接口,可以手动添加安防模块(不支持简易编程搜索的设备,只能手动添加)。
需要传入该安防模块当前的子网号,设备号,回路号,以及它的备注名。
**代码范例**
```java
    .......
    //isSuccess 返回true则代表添加成功
    isSuccess = HDLDeviceManager.addAudioDevicesManually(subnetID, deviceID, channelNum, "音乐模块1");
    .......
```
添加成功后同样会收到DevicesInfoEvent订阅事件,更新返回当前所有的设备列表数据
**代码范例**
```java
    /**
     * ====================EventBus 订阅事件 ====================
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDevicesInfoEventMain(DevicesInfoEvent event) {
        mAllDevicesList.clear();
        mProgressDialog.dismiss();
        if (!event.isSuccess()) {
            Toast.makeText(MainActivity.this, "搜索超时,请重新再试", Toast.LENGTH_SHORT).show();
            tvResult.setText("搜索超时,请重新再试");
            return;
        }
        mDevicesDataList = event.getDesDataList();
        updateDeviceListView();
    }
```
### 四、加载本地设备
**接口描述**
HDLDeviceManager.getLocalDevicesDataList()
调用该接口,会读取加载SDK本地保存的设备列表数据。
**代码范例**
```java
    /**
     * 读取和加载本地数据
     */
    private void getLocalDevicesDataList() {
        mDevicesDataList = HDLDeviceManager.getLocalDevicesDataList();//加载本地数据
        if (mDevicesDataList.size() > 0) {
            updateDeviceListView();
        } else {
            showToast("本地数据为空");
        }
    }
```
Android_HDL_SDK_TTL_DOC/src/update_log.md
New file
@@ -0,0 +1,20 @@
### 1.0.7+  2020-4-1
* 1.增加小类是3的音乐播放器支持。
* 2.增加RCU混合调光混合开关 类模块,使用物理回路问题。
* 3.增加通用开关类型设备支持。
* 4.增加场景状态回复,通知事件接口。
* 5.增加虚拟添加生成设备功能接口(应用于不支持简易编程搜索的项目)
### 1.0.1+ 2019
* 搜索设备
* 控制设备
* 目前支持设备
    * 灯光类模块
    *  窗帘类模块
    * 空调类模块
    *  逻辑功能类模块
    *  背景音乐功能类模块(不支持简易编程搜索,需要手动添加)
    * 安防功能类模块(不支持简易编程搜索,需要手动添加)
* MCU通信