panlili2024
2024-09-19 071a8328823a2861f93ce556a4da3e4119cab1a3
HDL_TTLSDK485/src/main/java/com/hdl/sdk/ttl/HDLDeviceManger/Core/HDLCommand.java
@@ -1,6 +1,7 @@
package com.hdl.sdk.ttl.HDLDeviceManger.Core;
import android.content.Context;
import android.util.Log;
import com.hdl.sdk.ttl.Config.Configuration;
import com.hdl.sdk.ttl.Config.MCUConstants;
@@ -11,20 +12,39 @@
import com.hdl.sdk.ttl.HDLAppliances.HDLCommonSwitch.CommonSwitchBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLCurtain.CurtainCtrlBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLCurtain.Parser.CurtainCtrlParser;
import com.hdl.sdk.ttl.HDLAppliances.HDLDoorMachine.DoorMachineBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLDoorMachine.Parser.DoorMachineParser;
import com.hdl.sdk.ttl.HDLAppliances.HDLFreshAir.FreshAirBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLFreshAir.FreshAirJinMaoBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLFreshAir.Parser.FreshAirJinMaoParser;
import com.hdl.sdk.ttl.HDLAppliances.HDLFreshAir.Parser.FreshAirParser;
import com.hdl.sdk.ttl.HDLAppliances.HDLGeothermal.GeothermalBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLGeothermal.Parser.GeothermalParser;
import com.hdl.sdk.ttl.HDLAppliances.HDLLight.ColourLightCtrlBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLLight.LightCtrlBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLLight.Parser.LightCtrlParser;
import com.hdl.sdk.ttl.HDLAppliances.HDLLogic.LogicCtrlBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLLogic.SceneCtrlBackInfo;
import com.hdl.sdk.ttl.HDLAppliances.HDLSecurity.Parser.SecurityParser;
import com.hdl.sdk.ttl.HDLDeviceManger.Bean.AppliancesInfo;
import com.hdl.sdk.ttl.HDLDeviceManger.Bean.DeviceStateBean;
import com.hdl.sdk.ttl.HDLDeviceManger.Bean.MCUDataBean;
import com.hdl.sdk.ttl.HDLDeviceManger.Bean.ScenesData;
import com.hdl.sdk.ttl.HDLDeviceManger.Bean.SendDatas;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.AirFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.ColourLightFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.CommonSwitchCtrlBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.CurtainFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.DeviceStateEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.DoorMachineFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.EventCode;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.FreshAirFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.FreshAirJinMaoFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.GeothermalFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.LightFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.LogicFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.MCUFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.SceneFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.SecurityArmingFeedBackEvent;
import com.hdl.sdk.ttl.HDLDeviceManger.EventBusEvent.UpdateRemarkFeedBackEvent;
import com.hdl.sdk.ttl.Utils.HDLUtlis.HDLUtlis;
@@ -45,6 +65,7 @@
public class HDLCommand {
    public static int mRequestTimeout = 5000;//默认请求超时时间
    public static int mRequestCurtainTimeout = 8000;//默认请求超时时间
    private static Timer getStateFailTimer = null;//获取设备状态失败Timer
    private static Timer lightCtrlFailTimer = null;//控制灯光失败Timer
    private static Timer curtainCtrlFailTimer = null;//控制窗帘失败Timer
@@ -55,6 +76,9 @@
    private static Timer securityCtrlFailTimer = null;//安防模块操作失败Timer
    private static Timer commonSwitchCtrlFailTimer = null;//通用开关失败Timer
    private static Timer freshAirCtrlFailTimer = null;//控制新风失败Timer
    private static Timer geothermalCtrlFailTimer = null;//控制地热失败Timer 2020-07-20
    private static Timer doorMachineCtrlFailTimer = null;//控制门锁失败Timer
//    /**
//     * 初始化 SDK
@@ -82,18 +106,40 @@
//        HDLDeviceManager.release();
//    }
    /**
     * 搜索网关
     */
    public static void seachGateway() {
        HandleSearch.seachGateway();
    }
    /**
     * 获取家居设备
     */
    public static void getHomeDevices() {
        HandleSearch.getHomeDevices();
    public static void getHomeDevices(int subnetID, int deviceID) {
        HandleSearch.getHomeDevices(subnetID, deviceID);
    }
    /**
     * 获取家居场景
     */
    public static void getHomeScenes(int subnetID, int deviceID) {
        HandleSearch.seachHomeScenes(subnetID, deviceID);
    }
    /**
     * 获取家居设备备注
     */
    public static void getDevRemarks() {
        HandleSearch.getDevRemarks();
    }
    /**
     * 发现新设备搜索,不会清空原设备列表数据
     */
    public static void getNewHomeDevices() {
        HandleSearch.getNewHomeDevices();
    public static void getNewHomeDevices(int subnetID, int deviceID) {
        HandleSearch.getNewHomeDevices(subnetID, deviceID);
    }
    /**
@@ -233,6 +279,40 @@
        }, mRequestTimeout);
    }
    /**
     * 控制CCT OR RGB
     *
     * @param info
     * @param brightness 亮度
     * @param color
     */
    public static void colourLightCtrl(final AppliancesInfo info, int brightness, int color) {
        HDLDeviceManager.setDeviceCtrlSuccessStateWithInfo(info, false);
        if (lightCtrlFailTimer != null) {
            lightCtrlFailTimer.cancel();
            lightCtrlFailTimer = null;
        }
        if (info.getBigType() == Configuration.LIGTH_BIG_TYPE) {
            addSendData(info, LightCtrlParser.getColourLightAddByte(info, brightness, color), Configuration.CONTROL);
            lightCtrlFailTimer = new Timer();
            lightCtrlFailTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (!HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info)) {
                        ColourLightCtrlBackInfo colourLightCtrlBackInfo = new ColourLightCtrlBackInfo(info);
                        EventBus.getDefault().post(new ColourLightFeedBackEvent(colourLightCtrlBackInfo, false));
                    }
                }
            }, mRequestTimeout);
        } else {
            HDLLog.I("灯光设备控制不在范围内"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    /**
     * 控制窗帘
@@ -240,8 +320,7 @@
     * @param info
     * @param state
     */
    public static void curtainCtrl(final AppliancesInfo info, int state) {
//        HDLDeviceManager.isCurtainCtrlSuccess = false;
    public static void curtainCtrl(final AppliancesInfo info, int state, int type) {
        HDLDeviceManager.setDeviceCtrlSuccessStateWithInfo(info, false);
        if (curtainCtrlFailTimer != null) {
            curtainCtrlFailTimer.cancel();
@@ -249,19 +328,23 @@
        }
        byte[] bytes;
        if (info.getBigType() == Configuration.CURTAIN_BIG_TYPE) {
            if (info.getLittleType() == 1 || info.getLittleType() == 0) {
                //这里是判断卷帘电机和开合帘电机
            if (info.getLittleType() == 1 || info.getLittleType() == 0 || info.getLittleType() == 3) {//判断卷帘电机/开合帘电机/香格里拉帘电机
                int newChannelNum;
                if (state == CurtainCtrlParser.curtainOff
                        || state == CurtainCtrlParser.curtainOn
                        || state == CurtainCtrlParser.curtainPause) {
                    newChannelNum = info.getChannelNum();
                if (type == 0) {
                    if (state == CurtainCtrlParser.curtainOff
                            || state == CurtainCtrlParser.curtainOn
                            || state == CurtainCtrlParser.curtainPause) {
                        newChannelNum = info.getChannelNum();
                    } else {
                        newChannelNum = info.getChannelNum() + 16;
                    }
                } else {
                    newChannelNum = info.getChannelNum() + 16;
                    newChannelNum = info.getChannelNum();
                }
                bytes = CurtainCtrlParser.getCurtainAddByte(newChannelNum, state);
                bytes = CurtainCtrlParser.getCurtainAddByte(newChannelNum, state, type);
            } else {
                bytes = CurtainCtrlParser.getCurtainAddByte(info.getChannelNum(), state);
                bytes = CurtainCtrlParser.getCurtainAddByte(info.getChannelNum(), state, type);
            }
            addSendData(info, bytes, Configuration.CONTROL);
@@ -275,11 +358,11 @@
                        CurtainCtrlBackInfo curtainCtrlBackInfo = new CurtainCtrlBackInfo();
                        curtainCtrlBackInfo.setAppliancesInfo(info);
                        curtainCtrlBackInfo.setNum(info.getChannelNum());
                        EventBus.getDefault().post(new CurtainFeedBackEvent(curtainCtrlBackInfo, false));
                    }
                }
            }, mRequestTimeout);
            }, mRequestCurtainTimeout);
        } else {
            HDLLog.I("djlCtrl;  不是窗帘设备"
@@ -308,6 +391,11 @@
        if (info.getBigType() == Configuration.AIR_BIG_TYPE) {
            if (info.getDeviceType() == HDLApConfig.TYPE_AC_PANEL) {
                addSendData(info, AirCtrlParser.getAirPanelAddByte(type, state), Configuration.CONTROL);
            } else if (info.getDeviceType() == HDLApConfig.TYPE_AC_TECHSYS || info.getDeviceType() == HDLApConfig.TYPE_AC_KNXTECHSYS) {
                byte[] airbytes = AirCtrlParser.getAirTechAddByte(info, type, state);
                if (airbytes != null) {
                    addSendData(info, airbytes, Configuration.CONTROL);
                }
            } else {
                byte[] airbytes = AirCtrlParser.getAcAddByte(info, type, state);
                if (airbytes != null) {
@@ -379,6 +467,7 @@
    /**
     * 获取通用开关状态
     *
     * @param info
     */
    public static void getCommonSwitchStateFromNetwork(final AppliancesInfo info) {
@@ -400,6 +489,7 @@
    /**
     * 安防模块 布防设置
     * 2019-7-29
     *
     * @param info
     */
    public static void securityArmingCtrl(final AppliancesInfo info, int state) {
@@ -417,7 +507,7 @@
                @Override
                public void run() {
                    if (!HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info)) {
                        EventBus.getDefault().post(new SecurityArmingFeedBackEvent(info,0, false));
                        EventBus.getDefault().post(new SecurityArmingFeedBackEvent(info, 0, false));
                    }
                }
            }, 5000);
@@ -433,6 +523,7 @@
    /**
     * 安防模块 报警设置
     * 2019-7-29
     *
     * @param info
     * @param state 发送的报警内容,只报警一种
     */
@@ -484,56 +575,42 @@
                }
            }, mRequestTimeout);
        } else {
            HDLLog.I("djlCtrl: 逻辑模块设备控制不在范围内"
            HDLLog.I("逻辑模块设备控制不在范围内"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    //  获取单一回路设备状态
    //  读取设备状态
//    public static void getDeviceState(final AppliancesInfo I) {
//        HDLDeviceManager.isGetDeviceStateSuccess = false;
//        switch (I.getBigType()) {
//            case Configuration.LIGTH_BIG_TYPE:
//                addSendData(I, new byte[]{}, Configuration.STATE);
//                break;
//            case Configuration.CURTAIN_BIG_TYPE:
//                if (I.getDeviceType() == HDLApConfig.TYPE_CURTAIN_MODULE) {
//                    addSendData(I, new byte[]{(byte) I.getChannelNum()}, Configuration.STATE);
//                } else {
//                    addSendData(I, new byte[]{(byte) (I.getChannelNum() + 16)}, Configuration.STATE);
//                }
//                break;
//            case Configuration.AIR_BIG_TYPE:
//                addSendData(I, new byte[]{AirCtrlParser.airSwich}, Configuration.STATE);
////                addSendData(I,new byte[]{AirCtrlParser.refTem},Configuration.STATE);
//                addSendData(I, new byte[]{AirCtrlParser.airSpeed}, Configuration.STATE);
//                addSendData(I, new byte[]{AirCtrlParser.airMode}, Configuration.STATE);
////                addSendData(I,new byte[]{AirCtrlParser.heatTem},Configuration.STATE);
////                addSendData(I,new byte[]{AirCtrlParser.autoTem},Configuration.STATE);
//                break;
//        }
//
//        if (I.getBigType() == Configuration.AIR_BIG_TYPE) {
//            return;
//        }
//        if (getStateFailTimer != null) {
//            getStateFailTimer.cancel();
//            getStateFailTimer = null;
//        }
//        getStateFailTimer = new Timer();
//        getStateFailTimer.schedule(new TimerTask() {
//            @Override
//            public void run() {
//                if (!HDLDeviceManager.isGetDeviceStateSuccess) {
//                    EventBus.getDefault().post(new DeviceStateEvent(I, false));
//                }
//            }
//        }, mRequestTimeout);
//
//    }
    /**
     * 场景控制
     *
     * @param scenesData
     */
    public static void sceneCtrl(final ScenesData scenesData) {
        cusSendCommand(Configuration.LOGIC_CTRL_COMMAND, scenesData.getSourceSubnetID(), scenesData.getSourceDeviceID(), new byte[]{
                (byte) (scenesData.getAreaCodeID()),
                (byte) (scenesData.getSceneID())
        });
        if (sceneCtrlFailTimer != null) {
            sceneCtrlFailTimer.cancel();
            sceneCtrlFailTimer = null;
        }
        sceneCtrlFailTimer = new Timer();
        sceneCtrlFailTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (!HDLDeviceManager.isSceneCtrlSuccess()) {
                    HDLLog.I("场景控制失败");
                    SceneCtrlBackInfo sceneCtrlBackInfo = new SceneCtrlBackInfo();
                    sceneCtrlBackInfo.setAreaCodeID(scenesData.getAreaCodeID());
                    sceneCtrlBackInfo.setSceneID(scenesData.getSceneID());
                    EventBus.getDefault().post(new SceneFeedBackEvent(sceneCtrlBackInfo, false));
                }
            }
        }, mRequestTimeout);
    }
    /**
     * 控制窗帘
@@ -612,6 +689,7 @@
    /**
     * 获取窗帘设备状态
     *
     * @param info
     */
    public static void getCurtainDeviceStateFromNetwork(final AppliancesInfo info) {
@@ -620,10 +698,14 @@
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_CURTAIN_MODULE:
                addSendData(info, new byte[]{(byte) info.getChannelNum(), 0, 1}, Configuration.STATE);
                break;
            case HDLApConfig.TYPE_CURTAIN_GLYSTRO:
            case HDLApConfig.TYPE_CURTAIN_ROLLER:
            case HDLApConfig.TYPE_CURTAIN_MODULE:
                addSendData(info, new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
            case HDLApConfig.TYPE_CURTAIN_SHANGRILA:
                //只读取百分比,不读取开关停
                addSendData(info, new byte[]{(byte) info.getChannelNum(), 0, 2}, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是窗帘设备");
@@ -633,6 +715,7 @@
    /**
     * 获取灯光设备状态
     *
     * @param info
     */
    public static void getLightDeviceStateFromNetwork(final AppliancesInfo info) {
@@ -645,8 +728,9 @@
            case HDLApConfig.TYPE_LIGHT_RELAY:
            case HDLApConfig.TYPE_LIGHT_MIX_DIMMER:
            case HDLApConfig.TYPE_LIGHT_MIX_RELAY:
                //发送获灯光状态数据
                addSendData(info, new byte[0], Configuration.STATE);
                //发送获取灯光状态数据
                byte[] sendbytes = new byte[]{(byte) info.getChannelNum()};
                addSendData(info, sendbytes, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是灯光设备");
@@ -654,10 +738,35 @@
        }
    }
    /**
     * 获取CTT or RGB灯设备状态
     *
     * @param info
     */
    public static void getColourLightDeviceStateFromNetwork(final AppliancesInfo info) {
        if (info == null) {
            return;
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_LIGHT_CCT:
            case HDLApConfig.TYPE_LIGHT_RGB:
            case HDLApConfig.TYPE_LIGHT_DALI:
            case HDLApConfig.TYPE_LIGHT_DMX:
                //发送获取灯光状态数据
                byte[] sendbytes = new byte[]{(byte) info.getChannelNum()};
                addSendData(info, sendbytes, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是CTT or RGB灯光设备");
                break;
        }
    }
    /**
     * 获取逻辑 场景号
     *
     * @param info
     */
    public static void getLogicDeviceStateFromNetwork(final AppliancesInfo info) {
@@ -679,6 +788,7 @@
    /**
     * 获取安防模块状态
     *
     * @param info
     */
    public static void getSecurityStateFromNetwork(final AppliancesInfo info) {
@@ -699,6 +809,7 @@
    /**
     * 获取传感器模块状态
     *
     * @param info
     */
    public static void getSensorStateFromNetwork(final AppliancesInfo info) {
@@ -707,34 +818,11 @@
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_SENSOR_DRY_CONTACT:
            case HDLApConfig.TYPE_SENSOR_MOVEMENT_DETECTOR:
            case HDLApConfig.TYPE_SENSOR_TEMP:
            case HDLApConfig.TYPE_SENSOR_HUMIDITY:
            case HDLApConfig.TYPE_SENSOR_ILLUMINACE:
            case HDLApConfig.TYPE_SENSOR_VOC:
            case HDLApConfig.TYPE_SENSOR_PM_2_POINT_5:
            case HDLApConfig.TYPE_SENSOR_C02:
            case HDLApConfig.TYPE_SENSOR_LPG:
            case HDLApConfig.TYPE_SENSOR_CO_H2:
            case HDLApConfig.TYPE_SENSOR_CH4:
            case HDLApConfig.TYPE_SENSOR_SMOG:
            case HDLApConfig.TYPE_SENSOR_WIND_SPEED:
            case HDLApConfig.TYPE_SENSOR_WIND_PRESSURE:
            case HDLApConfig.TYPE_SENSOR_LIQUID_FLOW:
            case HDLApConfig.TYPE_SENSOR_LIQUID_PRESSURE:
            case HDLApConfig.TYPE_SENSOR_LIQUID_DEPTH:
            case HDLApConfig.TYPE_SENSOR_RAIN_FALL:
            case HDLApConfig.TYPE_SENSOR_WEIGHT:
            case HDLApConfig.TYPE_SENSOR_HEIGHT_LENGTH:
            case HDLApConfig.TYPE_SENSOR_OBJECT_SPEED:
            case HDLApConfig.TYPE_SENSOR_SHAKE:
            case HDLApConfig.TYPE_SENSOR_VOLTAGE:
            case HDLApConfig.TYPE_SENSOR_ELECTRICITY:
            case HDLApConfig.TYPE_SENSOR_POWER:
            case HDLApConfig.TYPE_SENSOR_FLOODING:
            case HDLApConfig.TYPE_SENSOR_DOOR_MAGNET:
            case HDLApConfig.TYPE_SENSOR_EMERGENCY_BUTTON:
            case HDLApConfig.TYPE_SENSOR_PM_10:
                //发送获传感器模块状态数据
                byte[] sendDatabyte = new byte[]{
                        (byte) info.getBigType(),
@@ -752,6 +840,7 @@
    /**
     * 获取干接点传感器模块状态
     *
     * @param info
     */
    public static void getDryContactSensorStateFromNetwork(final AppliancesInfo info) {
@@ -788,6 +877,7 @@
            case HDLApConfig.TYPE_SENSOR_FLOODING:
            case HDLApConfig.TYPE_SENSOR_DOOR_MAGNET:
            case HDLApConfig.TYPE_SENSOR_EMERGENCY_BUTTON:
            case HDLApConfig.TYPE_SENSOR_PM_10:
                //发送获传感器模块状态数据
                byte[] sendDatabyte = new byte[]{
                        (byte) 1,
@@ -804,6 +894,7 @@
    /**
     * 获取HVAC空调设备状态
     *
     * @param info
     */
    public static void getHVACDeviceStateFromNetwork(final AppliancesInfo info) {
@@ -815,10 +906,59 @@
            case HDLApConfig.TYPE_AC_HVAC:
//            case HDLApConfig.TYPE_AC_PANEL:
                //发送HVAC状态数据
                addSendData(info,  new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
                addSendData(info, new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是HVAC空调设备");
                break;
        }
    }
    /**
     * 获取科技系统状态
     *
     * @param info
     */
    public static void getTechSysDeviceStateFromNetwork(final AppliancesInfo info) {
        if (info == null) {
            return;
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_AC_TECHSYS:
            case HDLApConfig.TYPE_AC_KNXTECHSYS:
                //发送科技系统状态数据
                addSendData(info, new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是科技系统设备");
                break;
        }
    }
    /**
     * 获取科技系统室内湿度状态
     *
     * @param info
     */
    public static void getTechSysDeviceHumidityFromNetwork(final AppliancesInfo info) {
        if (info == null) {
            return;
        }
        info.setGetDeviceStateSuccess(false);
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_AC_KNXTECHSYS:
                //发送科技系统状态数据
                byte[] sendDatabyte = new byte[]{
                        (byte) info.getBigType(),
                        (byte) info.getLittleType(),
                        (byte) info.getChannelNum()
                };
                addCommandSendData(info, sendDatabyte, Configuration.SENSOR_STATE_COMMAND);
                break;
            default:
                HDLLog.I("不是科技系统设备");
                break;
        }
    }
@@ -848,6 +988,7 @@
            case HDLApConfig.TYPE_CURTAIN_GLYSTRO:
            case HDLApConfig.TYPE_CURTAIN_ROLLER:
            case HDLApConfig.TYPE_CURTAIN_MODULE:
            case HDLApConfig.TYPE_CURTAIN_SHANGRILA:
                int curtainState = getCurtainState(info);
                info.setCurState(curtainState);
                EventBus.getDefault().post(new DeviceStateEvent(info, true));
@@ -857,6 +998,8 @@
            case HDLApConfig.TYPE_AC_COOLMASTER:
            case HDLApConfig.TYPE_AC_INFRARED:
            case HDLApConfig.TYPE_AC_PANEL:
            case HDLApConfig.TYPE_AC_TECHSYS:
            case HDLApConfig.TYPE_AC_KNXTECHSYS:
                //2019-8-21 增加判空
                byte[] acState = getACState(info);
                if (acState != null && acState.length >= 4) {
@@ -1081,6 +1224,8 @@
                        switch (info.getDeviceType()) {
                            case HDLApConfig.TYPE_AC_HVAC:
                            case HDLApConfig.TYPE_AC_PANEL:
                            case HDLApConfig.TYPE_AC_TECHSYS:
                            case HDLApConfig.TYPE_AC_KNXTECHSYS:
                                curState = infos.get(j).getArrCurState();
                                break;
                            default:
@@ -1127,6 +1272,321 @@
    }
    /**
     * 获取新风
     *
     * @param info
     */
    public static void getFreshAirDeviceStateFromNetwork(final AppliancesInfo info) {
        if (info == null) {
            return;
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_FRESH_AIR:
            case HDLApConfig.TYPE_FRESH_AIR_JINMAO:
                //发送获取新风系统所有数据
                addSendData(info, new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是新风系统设备");
                break;
        }
    }
    /**
     * 控制新风系统
     *
     * @param info
     * @param type
     * @param state 2020-07-20
     */
    public static void freshAirCtrl(final AppliancesInfo info, int type, int state) {
//        HDLDeviceManager.isFreshAirCtrlSuccess = false;
        HDLDeviceManager.setDeviceCtrlSuccessStateWithInfo(info, false);
        if (freshAirCtrlFailTimer != null) {
            freshAirCtrlFailTimer.cancel();
            freshAirCtrlFailTimer = null;
        }
        if (info.getBigType() == Configuration.FRESH_AIR_BIG_TYPE) {
            byte[] freshAirbytes = FreshAirParser.getFreshAirAddByte(info, type, state);
            addSendData(info, freshAirbytes, Configuration.CONTROL);
            freshAirCtrlFailTimer = new Timer();
            freshAirCtrlFailTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (!HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info)) {
                        FreshAirBackInfo mFreshAirBackInfo = new FreshAirBackInfo();
                        mFreshAirBackInfo.setAppliancesInfo(info);
                        EventBus.getDefault().post(new FreshAirFeedBackEvent(mFreshAirBackInfo, false));
                    }
                }
            }, mRequestTimeout);
        } else {
            HDLLog.I("新风设备控制不在范围内"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    /**
     * 获取金茂新风状态
     *
     * @param info
     */
    public static void getFreshAirJinMaoDeviceStateFromNetwork(final AppliancesInfo info) {
        if (info == null) {
            return;
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_FRESH_AIR_JINMAO:
                //发送获取新风系统所有数据
                addSendData(info, new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是金茂新风系统设备");
                break;
        }
    }
    /**
     * 控制金茂新风
     *
     * @param info
     * @param type
     * @param state 2020-07-20
     */
    public static void freshAirJinMaoCtrl(final AppliancesInfo info, int type, int state) {
//        HDLDeviceManager.isFreshAirCtrlSuccess = false;
        HDLDeviceManager.setDeviceCtrlSuccessStateWithInfo(info, false);
        if (freshAirCtrlFailTimer != null) {
            freshAirCtrlFailTimer.cancel();
            freshAirCtrlFailTimer = null;
        }
        if (info.getDeviceType() == HDLApConfig.TYPE_FRESH_AIR_JINMAO) {
            byte[] sendBytes = FreshAirJinMaoParser.getFreshAirAddByte(info, type, state);
            addSendData(info, sendBytes, Configuration.CONTROL);
            freshAirCtrlFailTimer = new Timer();
            freshAirCtrlFailTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (!HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info)) {
                        FreshAirJinMaoBackInfo mFreshAirJinMaoBackInfo = new FreshAirJinMaoBackInfo();
                        mFreshAirJinMaoBackInfo.setAppliancesInfo(info);
                        EventBus.getDefault().post(new FreshAirJinMaoFeedBackEvent(mFreshAirJinMaoBackInfo, false));
                    }
                }
            }, mRequestTimeout);
        } else {
            HDLLog.I("不是金茂新风系统设备");
        }
    }
    /**
     * 获取地热状态
     *
     * @param info
     */
    public static void getGeothermalStateFromNetwork(final AppliancesInfo info) {
        if (info == null) {
            return;
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_GEOTHERMAL_JINMAO:
            case HDLApConfig.TYPE_GEOTHERMAL_MODULE:
                //发送获取地热系统所有数据
                addSendData(info, new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是地热设备");
                break;
        }
    }
    /**
     * 控制地热模块温度
     *
     * @param info
     * @param tempInt 2020-03-15
     */
    public static void geothermalCtrlTemp(final AppliancesInfo info, int tempInt) {
//        HDLDeviceManager.isGeothermalCtrlSuccess = false;
        HDLDeviceManager.setDeviceCtrlSuccessStateWithInfo(info, false);
        if (geothermalCtrlFailTimer != null) {
            geothermalCtrlFailTimer.cancel();
            geothermalCtrlFailTimer = null;
        }
        if (info.getBigType() == Configuration.GEOTHERMAL_BIG_TYPE) {
            byte[] sendbytes = GeothermalParser.getGeothermalAddByteTemp(info, tempInt);
            addSendData(info, sendbytes, Configuration.CONTROL);
            geothermalCtrlFailTimer = new Timer();
            geothermalCtrlFailTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (!HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info)) {
                        GeothermalBackInfo mGeothermalBackInfo = new GeothermalBackInfo();
                        mGeothermalBackInfo.setAppliancesInfo(info);
                        EventBus.getDefault().post(new GeothermalFeedBackEvent(mGeothermalBackInfo, EventCode.FAILURE_TIMEOUT));
                    }
                }
            }, mRequestTimeout);
        } else {
            HDLLog.I("地热模块控制不在范围内"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    /**
     * 控制地热模块
     *
     * @param info
     * @param type
     * @param state 2019-07-10
     */
    public static void geothermalCtrl(final AppliancesInfo info, int type, int state) {
//        HDLDeviceManager.isGeothermalCtrlSuccess = false;
        HDLDeviceManager.setDeviceCtrlSuccessStateWithInfo(info, false);
        if (geothermalCtrlFailTimer != null) {
            geothermalCtrlFailTimer.cancel();
            geothermalCtrlFailTimer = null;
        }
        if (info.getBigType() == Configuration.GEOTHERMAL_BIG_TYPE) {
            byte[] sendbytes = GeothermalParser.getGeothermalAddByte(info, type, state);
            addSendData(info, sendbytes, Configuration.CONTROL);
            geothermalCtrlFailTimer = new Timer();
            geothermalCtrlFailTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (!HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info)) {
                        GeothermalBackInfo mGeothermalBackInfo = new GeothermalBackInfo();
                        mGeothermalBackInfo.setAppliancesInfo(info);
                        EventBus.getDefault().post(new GeothermalFeedBackEvent(mGeothermalBackInfo, EventCode.FAILURE_TIMEOUT));
                    }
                }
            }, 5000);
        } else {
            HDLLog.I("地热模块控制不在范围内"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    /**
     * 获取门锁状态
     *
     * @param info
     */
    public static void getDoorMachineDeviceStateFromNetwork(final AppliancesInfo info) {
        if (info == null) {
            return;
        }
        HDLDeviceManager.isGetDeviceStateSuccess = false;
        switch (info.getDeviceType()) {
            case HDLApConfig.TYPE_DOOR_MACHINE:
                //发送获取门锁所有数据
                addSendData(info, new byte[]{(byte) info.getChannelNum()}, Configuration.STATE);
                break;
            default:
                HDLLog.I("不是门锁设备");
                break;
        }
    }
    /**
     * 门锁模块 远程开锁获取密钥
     * 2023-8-25
     *
     * @param info
     */
    public static void doorMachineGetSecret(final AppliancesInfo info) {
        if (info.getBigType() == Configuration.DOOR_MACHINE_BIG_TYPE) {
            byte[] sendbytes = new byte[]{(byte) info.getChannelNum()};
            cusSendCommand(Configuration.DOOR_MACHINE_MODULE_CTRL_FRIST_COMMAND, info.getDeviceSubnetID(), info.getDeviceDeviceID(), sendbytes);
        } else {
            HDLLog.I("不是门锁模块"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    /**
     * 控制门锁远程开锁
     *
     * @param info
     * @param secretBytes 密钥
     * @param password    开锁密码 2023-08-22
     */
    public static void doorMachineCtrl(final AppliancesInfo info, byte[] secretBytes, String password, int doorStatus) {
        HDLDeviceManager.setDeviceCtrlSuccessStateWithInfo(info, false);
        if (doorMachineCtrlFailTimer != null) {
            doorMachineCtrlFailTimer.cancel();
            doorMachineCtrlFailTimer = null;
        }
        if (info.getBigType() == Configuration.DOOR_MACHINE_BIG_TYPE) {
            byte[] doorMachinebytes = DoorMachineParser.getDoorMachineAddByte(info, secretBytes, password, doorStatus);
            addSendData(info, doorMachinebytes, Configuration.CONTROL);
            doorMachineCtrlFailTimer = new Timer();
            doorMachineCtrlFailTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (!HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info)) {
                        DoorMachineBackInfo mDoorMachineBackInfo = new DoorMachineBackInfo();
                        mDoorMachineBackInfo.setAppliancesInfo(info);
                        EventBus.getDefault().post(new DoorMachineFeedBackEvent(mDoorMachineBackInfo, false));
                    }
                }
            }, mRequestTimeout);
        } else {
            HDLLog.I("门锁控制不在范围内"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    /**
     * 门锁模块 设置临时密码
     * 2023-8-25
     *
     * @param info
     * @param tempPassword 临时密码
     * @param startTime    开始时间戳
     * @param endTime      结束时间戳
     */
    public static void doorMachineSettingPwd(final AppliancesInfo info, String tempPassword, String startTime, String endTime) {
        if (info.getBigType() == Configuration.DOOR_MACHINE_BIG_TYPE) {
            byte[] sendbytes = DoorMachineParser.getDoorMachineSettingPwdByte(info, tempPassword, startTime, endTime);
            cusSendCommand(Configuration.DOOR_MACHINE_MODULE_SETTING_PASSWORD_COMMAND, info.getDeviceSubnetID(), info.getDeviceDeviceID(), sendbytes);
        } else {
            HDLLog.I("不是门锁模块"
                    + " LittleType = " + info.getLittleType()
                    + " BigType = " + info.getBigType()
            );
        }
    }
    /**
     * 背景音乐控制
@@ -1341,40 +1801,25 @@
            @Override
            public void run() {
                //2019-07 控制发送次数
                if (sendDatas.count >= 4) {
                if (sendDatas.count >= 3) {
                    sendCycleTimer.cancel();
                } else {
                    sendDatas.count++;
                    if (type == Configuration.STATE) {
                        sendDatas.command = info.getStateCommand();
                        HDLLog.I("---getDevice: " + info.getDeviceKey() + " ---getStateCommand: " + Integer.toHexString(info.getStateCommand()));//2019-8-2
                        sendDatas.isCtrlSuccess = HDLDeviceManager.isGetDeviceStateSuccess;
                    } else if (type == Configuration.CONTROL) {
                        sendDatas.command = info.getCtrlCommand();
                        HDLLog.I("getDeviceKey: " + info.getDeviceKey());//2019-8-2
                        HDLLog.I("---getDevice: " + info.getDeviceKey() + " ---getCtrlCommand: " + Integer.toHexString(info.getCtrlCommand()));//2019-8-2
                        sendDatas.isCtrlSuccess = HDLDeviceManager.getDeviceCtrlSuccessStateWithInfo(info);
//                        switch (info.getBigType()) {
//                            case Configuration.LIGTH_BIG_TYPE:
//                                sendDatas.isCtrlSuccess = HDLDeviceManager.isLightCtrlSuccess;
//                                break;
//                            case Configuration.CURTAIN_BIG_TYPE:
//                                sendDatas.isCtrlSuccess = HDLDeviceManager.isCurtainCtrlSuccess;
//                                break;
//                            case Configuration.AIR_BIG_TYPE:
//                                sendDatas.isCtrlSuccess = HDLDeviceManager.isACCtrlSuccess;
//                                break;
//                            case Configuration.LOGIC_BIG_TYPE:
//                                sendDatas.isCtrlSuccess = HDLDeviceManager.isSceneCtrlSuccess;
//                                break;
//                            case Configuration.SECURITY_BIG_TYPE:
//                                sendDatas.isCtrlSuccess = HDLDeviceManager.isSecurityCtrlSuccess;
//                                break;
//                            default:
//                                sendDatas.isCtrlSuccess = false;
//                        }
                    }
                    if (!sendDatas.isCtrlSuccess) {
                        HDLLog.I("控制发送第" + sendDatas.count + "次");
                        if (type == Configuration.STATE) {
                            HDLLog.I("读取发送第" + sendDatas.count + "次");
                        } else if (type == Configuration.CONTROL) {
                            HDLLog.I("控制发送第" + sendDatas.count + "次");
                        }
                        cusSendCommand(sendDatas.command, info.getDeviceSubnetID(), info.getDeviceDeviceID(), sendDatas.addBytes);
                    } else {
                        sendCycleTimer.cancel();
@@ -1383,10 +1828,44 @@
            }
        }, 1, 500);
    }
    /**
     * 单设备发送命令
     * 目前控制发送次数为3次
     * 发一条,补发3条,间隔500ms
     *
     * @param info
     * @param addBytes
     */
    private static void addCommandSendData(final AppliancesInfo info, byte[] addBytes, final int command) {
        final Crc sendDatas = new Crc(info.getStateCommand(), info.getDeviceSubnetID(), info.getDeviceDeviceID(), addBytes);
        sendDatas.count = 0;
        final Timer sendCycleTimer = new Timer();
        sendCycleTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                //2019-07 控制发送次数
                if (sendDatas.count >= 3) {
                    sendCycleTimer.cancel();
                } else {
                    sendDatas.count++;
                    sendDatas.command = command;
                    HDLLog.I("---getDevice: " + info.getDeviceKey() + " ---command: " + Integer.toHexString(command));//2019-8-2
                    sendDatas.isCtrlSuccess = info.isGetDeviceStateSuccess();
                    if (!sendDatas.isCtrlSuccess) {
                        HDLLog.I("读取发送第" + sendDatas.count + "次");
                        cusSendCommand(sendDatas.command, info.getDeviceSubnetID(), info.getDeviceDeviceID(), sendDatas.addBytes);
                    } else {
                        sendCycleTimer.cancel();
                    }
                }
            }
        }, 1, 500);
    }
    /**
     * 发送广播或点对点命令
@@ -1397,9 +1876,12 @@
     * @param addBytes 附加数据
     */
    public static void cusSendCommand(int command, int subnetID, int deviceID, byte[] addBytes) {
        Crc sendDatas = new Crc(command, subnetID, deviceID, addBytes);
        HDLSerialPortCore.sendData(sendDatas);
        if (HDLSerialPortCore.getIsModule()) {
            Crc sendDatas = new Crc(command, subnetID, deviceID, addBytes);
            HDLSerialPortCore.sendData(sendDatas);
        } else {
            SendDatas.AddSendData(command, subnetID, deviceID, addBytes);
        }
    }
    /**