562935844@qq.com
2022-12-28 30e96788f05f5ce28b58d991051c79e9c952c824
修改入网认证流程
41个文件已添加
1个文件已删除
7个文件已修改
2718 ■■■■■ 已修改文件
HDLSDK/.idea/gradle.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/com.hdl.sdk/build.gradle 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/build.gradle 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/.DS_Store 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/HDLSdk.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/IHDLClient.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/config/TopicConstant.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/event/EventListener.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/exception/HDLLinkCode.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/exception/HDLLinkException.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/ByteUtils.java 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/IdUtils.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/IpUtils.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/LogUtils.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/SPUtils.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/ThreadToolUtils.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/gson/GsonConvert.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/gson/ParameterizedTypeImpl.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LoginRequest.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/DeviceInfoResponse.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java 150 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/.DS_Store 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketBoot.java 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketOptions.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketPool.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketRequest.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/annotation/ConnectStatus.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/IClient.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/IHeartbeat.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/IUdpClient.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/TcpClient.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/UdpClient.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/ByteToMessageDecoder.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/IHandleFlow.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/IHandleMessage.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/IMessagePipeLine.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/MessagePipeLine.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/MessageToByteEncoder.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/listener/ConnectStatusListener.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/listener/SendListener.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/udp/UdpSocketBoot.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/udp/UdpSocketOptions.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/settings.gradle 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO.rar 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/build.gradle 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.0.17.aar 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.0.20.aar 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/.idea/gradle.xml
@@ -11,9 +11,7 @@
          <set>
            <option value="$PROJECT_DIR$" />
            <option value="$PROJECT_DIR$/com.hdl.sdk" />
            <option value="$PROJECT_DIR$/hdl-common" />
            <option value="$PROJECT_DIR$/hdl-connect" />
            <option value="$PROJECT_DIR$/hdl-socket" />
          </set>
        </option>
        <option name="resolveModulePerSourceSet" value="false" />
HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
@@ -329,6 +329,7 @@
            public void onSuccess(String msg) {
                tv.setText("认证成功");
                responseTv.setText(msg.toString());
                Log.i("TAG", "onSuccess: 认证成功");
            }
        });
    }
HDLSDK/com.hdl.sdk/build.gradle
@@ -32,9 +32,9 @@
//    embed(name: 'hdl-connect-release',ext: 'aar')
//    embed(name: 'hdl-socket-release',ext: 'aar')
    embed project(path: ':hdl-common', configuration:'default')
//    embed project(path: ':hdl-common', configuration:'default')
    embed project(path: ':hdl-connect', configuration:'default')
    embed project(path: ':hdl-socket', configuration:'default')
//    embed project(path: ':hdl-socket', configuration:'default')
}
//打包的
HDLSDK/hdl-connect/build.gradle
@@ -9,7 +9,7 @@
        minSdkVersion rootProject.minSdkVersion
        targetSdkVersion rootProject.targetSdkVersion
        versionCode 2
        versionName "1.0.15"
        versionName "1.0.21"
        consumerProguardFiles "consumer-rules.pro"
    }
@@ -27,5 +27,6 @@
}
dependencies {
    api project(path: ':hdl-socket')
//    api project(path: ':hdl-socket')
    api 'com.google.code.gson:gson:2.8.8'
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/.DS_Store
Binary files differ
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/HDLSdk.java
New file
@@ -0,0 +1,67 @@
package com.hdl.sdk.common;
import android.content.Context;
import android.util.Log;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.IdUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.bean.request.BroadcastRequest;
import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.connect.socket.HDLAuthSocket;
import com.hdl.sdk.connect.socket.HDLSocket;
/**
 * Created by Tong on 2021/9/28.
 */
public class HDLSdk {
    private Context context;
    /**
     * 获取当前版本
     *
     * @return
     */
    public String getVersion() {
        return version;
    }
    private String version = "1.0.22";
    private HDLSdk() {
    }
    private static class SingletonInstance {
        private static final HDLSdk INSTANCE = new HDLSdk();
    }
    public static HDLSdk getInstance() {
        return SingletonInstance.INSTANCE;
    }
    public void init(Context context) {
        this.context = context.getApplicationContext();
        HDLSocket.getInstance().broadcastRequest();
        LogUtils.i("HDLSdk Version:" + version);
    }
    public Context getContext() {
        return context;
    }
    /**
     * 设置打印是否开启
     *
     * @param enable
     */
    public void setLogEnabled(boolean enable) {
        LogUtils.setEnabled(enable);
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/IHDLClient.java
New file
@@ -0,0 +1,52 @@
package com.hdl.sdk.common;
/**
 * Created by Tong on 2021/9/28.
 * 包含所有操作
 */
public interface IHDLClient {
    /**
     * 搜索网关
     */
    void searchGateway();
    /**
     * 获取网关详细信息
     */
    void getGatewayInfo();
    /**
     * 获取设备列表
     */
    void getDeviceList();
    /**
     * 获取功能列表
     */
    void getFunctionList();
    /**
     * 获取功能属性
     */
    void getFunctionAttribute();
    /**
     * 设备控制
     */
    void deviceControl();
    /**
     * 获取设备状态
     */
    void getDeviceStatus();
    /**
     * 改变设备状态
     */
    void changeDeviceStatus();
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/config/TopicConstant.java
New file
@@ -0,0 +1,101 @@
package com.hdl.sdk.common.config;
/**
 * Created by Tong on 2021/9/22.
 */
public class TopicConstant {
    //网关广播入网指令
    public static final String GATEWAY_AUTH_BROADCAST = "/user/all/custom/device/network_access/broadcast";
    //设备入网和认证
    public static final String DEIVCE_AUTH_REQUEST = "/user/all/custom/device/network_access/request";
    //设备入网和认证响应
    public static final String DEIVCE_AUTH_REQUEST_REPLY = "/user/all/custom/device/network_access/request_reply";
    //搜索网关
    public static final String GATEWAY_SEARCH = "/user/all/custom/gateway/search";
    //搜索网关响应
    public static final String GATEWAY_SEARCH_REPLY = "/user/all/custom/gateway/search_reply";
    //网关详细信息获取s=gw_id
    public static final String GATEWAY_INFO = "/user/%s/custom/gateway/get";
    //获取物理设备列表
    public static final String GET_DEVICE_LIST = " /user/%s/custom/device/list/get";
    //获取物理设备列表响应
    public static final String GET_DEVICE_LIST_REPLY = " /user/%s/custom/device/list/get_reply";
    //获取功能列表
    public static final String GET_FUNCTION_LIST = "/user/%s/custom/function/list/get";
    //获取功能响应
    public static final String GET_FUNCTION_LIST_REPLY = "/user/%s/custom/function/list/get_reply";
    //功能属性读取
    public static final String GET_FUNCTION_ATTRIBUTE = "/user/%s/custom/function/attribute/get";
    //功能属性响应
    public static final String GET_FUNCTION_ATTRIBUTE_REPLY = "/user/%s/custom/function/attribute/get_reply";
    //控制
    public static final String PROPERTY_DOWN = "/base/%s/thing/property/down";
    //控制响应
    public static final String PROPERTY_DOWN_REPLY = "/base/%s/thing/property/down_reply";
    //状态上报
    public static final String PROPERTY_UP = "/base/%s/thing/property/up";
    //状态上报响应
    public static final String PROPERTY_UP_REPLY = "/base/%s/thing/property/up_reply";
    //读取状态
    public static final String PROPERTY_READ = "/base/%s/thing/property/read";
    //读取状态响应
    public static final String PROPERTY_READ_REPLY = "/base/%s/thing/property/read_reply";
    //8.1获取场景列表
    public static final String SCENE_LIST_GET = "/user/%s/custom/scene/list/get";
    //8.2获取场景
    public static final String SCENE_GET = "/user/%s/custom/scene/get";
    //8.3执行场景
    public static final String SCENE_CONTROL = "/user/%s/custom/scene/execute";
    //8.4场景增加
    public static final String SCENE_ADD = "/user/%s/custom/scene/add";
    //8.5场景编辑
    public static final String SCENE_EDIT = "/user/%s/custom/scene/edit";
    //8.6场景删除
    public static final String SCENE_DELETE = "/user/%s/custom/scene/delete";
    //link tcp 登录
    public static final String GATEWAY_LOGIN = "/user/%s/custom/gateway/login";
    /**
     * 设备连接TCP之前广播
     */
    public static final String BROADCAST="/user/all/custom/gateway/broadcast";
    /**
     * 主网关回复
     */
    public static final String BROADCAST_REPLY="/user/all/custom/gateway/broadcast_reply";
    /**
     * 心跳检测
     */
    public static final String HEARTBEAT="/user/%s/custom/gateway/heartbeat";
    /**
     * 心跳检测回复
     */
    public static final String HEARTBEAT_REPLY="/user/%s/custom/gateway/heartbeat_reply";
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/event/EventDispatcher.java
New file
@@ -0,0 +1,239 @@
package com.hdl.sdk.common.event;
import android.util.ArrayMap;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
/**
 * Created by Tong on 2021/9/22.
 * 事件分发
 */
public class EventDispatcher {
    private static final List<EventListener> ALL_TOPICS_EVENT = new ArrayList<>();//所有主题消息
    private static final ConcurrentHashMap<Object, List<EventListener>> EVENT = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<EventListener, Integer> TYPE = new ConcurrentHashMap<>();
    private static final int MAIN_TYPE = 0;
    private static final int IO_TYPE = 1;
    private static final ExecutorService ioThread = ThreadToolUtils.getInstance().newFixedThreadPool(3);
    private EventDispatcher() {
    }
    //    private static class SingletonInstance {
    private static final EventDispatcher instance = new EventDispatcher();
//    }
    public static EventDispatcher getInstance() {
        return instance;
    }
    public void register(Object tag, EventListener listener) {
        synchronized (this) {
            try {
                LogUtils.i("注册主题:" + tag);
                if (tag == null) return;
                if (!EVENT.containsKey(tag)) {
                    EVENT.put(tag, new ArrayList<>());
                }
                if (listener == null) {
                    LogUtils.i("监听事件为空");
                    return;
                }
                Objects.requireNonNull(EVENT.get(tag)).add(listener);
                TYPE.put(listener, MAIN_TYPE);
            } catch (Exception e) {
                LogUtils.e("register:" + e.getMessage());
            }
        }
    }
    public void registerIo(Object tag, EventListener listener) {
        synchronized (this) {
            LogUtils.i("注册主题:" + tag);
            if (tag == null) return;
            if (!EVENT.containsKey(tag)) {
                EVENT.put(tag, new ArrayList<>());
            }
            try {
                if (listener == null) {
                    LogUtils.i("监听事件为空");
                    return;
                }
                Objects.requireNonNull(EVENT.get(tag)).add(listener);
                TYPE.put(listener, IO_TYPE);
            } catch (Exception e) {
                LogUtils.e("registerIo:" + e.getMessage());
            }
        }
    }
    public void remove(Object tag) {
        synchronized (this) {
            if (tag == null) {
                return;
            }
            try {
                if (EVENT.containsKey(tag)) {
                    LogUtils.i("移除key:" + tag);
                    List<EventListener> list = EVENT.get(tag);
                    for (EventListener eventListener : list) {
                        if (eventListener == null) {
                            continue;
                        }
                        TYPE.remove(eventListener);
                    }
                    EVENT.remove(tag);
                }
            } catch (Exception ignored) {
                LogUtils.e("移除event异常1:" + ignored.getMessage());
            }
        }
    }
    public void remove(Object tag, EventListener listener) {
        synchronized (this) {
            try {
                if (tag == null || listener == null) {
                    return;
                }
                if (EVENT.containsKey(tag)) {
                    LogUtils.i("移除key:" + tag);
                    List<EventListener> ev = EVENT.get(tag);
                    if (ev != null && !ev.isEmpty()) {
                        TYPE.remove(listener);
                        ev.remove(listener);
                    }
                }
            } catch (Exception ignored) {
                LogUtils.e("移除event异常1:" + ignored.getMessage());
            }
        }
    }
    public synchronized void post(Object tag, Object o) {
        if (tag == null) {
            LogUtils.i("post tag为空");
            return;
        }
        try {
            if (EVENT.containsKey(tag)) {
                LogUtils.i("post:" + tag);
                List<EventListener> list = EVENT.get(tag);
                if (list != null && !list.isEmpty()) {
                    for (EventListener listener : list) {
                        if (listener == null) {
                            continue;
                        }
                        ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    if (listener != null) {
                                        listener.onMessage(o);
                                    }
                                } catch (Exception e) {
                                    LogUtils.e("post异常1:" + e.getMessage());
                                }
                            }
                        });
                    }
                }
            }
            //所有主题的Listener通知
            if (ALL_TOPICS_EVENT != null && !ALL_TOPICS_EVENT.isEmpty()) {
                for (EventListener listener : ALL_TOPICS_EVENT) {
                    if (listener == null) {
                        continue;
                    }
                    ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                if (listener != null) {
                                    listener.onMessage(o);
                                }
                            } catch (Exception e) {
                            }
                        }
                    });
                }
            }
        } catch (Exception e) {
            LogUtils.e("post异常2:" + e.getMessage());
        }
    }
    /**
     * 注册所有主题消息的监听
     *
     * @param listener
     */
    public synchronized void registerAllTopicsListener(EventListener listener) {
        if (listener == null) {
            return;
        }
        try {
            if (ALL_TOPICS_EVENT != null && !ALL_TOPICS_EVENT.contains(listener)) {
                ALL_TOPICS_EVENT.add(listener);
            }
            TYPE.put(listener, MAIN_TYPE);
        } catch (Exception e) {
            LogUtils.e("registerAllTopicsListener:" + e.getMessage());
        }
    }
    /**
     * 取消所有主题消息的监听
     *
     * @param listener
     */
    public synchronized void removeAllTopicsListener(EventListener listener) {
        try {
            ioThread.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (listener == null) {
                            return;
                        }
                        if (ALL_TOPICS_EVENT != null && !ALL_TOPICS_EVENT.isEmpty()) {
                            TYPE.remove(listener);
                            ALL_TOPICS_EVENT.remove(listener);
                        }
                    } catch (Exception ignored) {
                        LogUtils.e("移除event异常1:" + ignored.getMessage());
                    }
                }
            });
        } catch (Exception e) {
            LogUtils.e("移除event异常2:" + e.getMessage());
        }
    }
    public synchronized void clear() {
        ALL_TOPICS_EVENT.clear();
        EVENT.clear();
        TYPE.clear();
    }
    public synchronized void release() {
        clear();
        ioThread.shutdownNow();
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/event/EventListener.java
New file
@@ -0,0 +1,10 @@
package com.hdl.sdk.common.event;
/**
 * Created by Tong on 2021/9/22.
 */
public interface EventListener {
    void onMessage(Object msg);
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/exception/HDLLinkCode.java
New file
@@ -0,0 +1,47 @@
package com.hdl.sdk.common.exception;
/**
 * Created by jlchen on 11/15/21.
 *
 * @Description : HDLError
 */
public enum HDLLinkCode {
    HDL_DATA_ERROR(-2000,"参数异常"),
    HDL_DATA_NULL_ERROR(-2001,"参数不能为空"),
    HDL_AUTH_ERROR(-2002,"认证失败"),
    HDL_SEND_ERROR(-2003,"发送失败"),
    HDL_TIMEOUT_ERROR(-2004,"超时"),
    HDL_UNAUTHORIZED_ERROR(-2005,"未认证,请先认证"),
    HDL_AUTH_ERROR_GATEWAY_NOT_REGISTERED(-2006,"认证失败,网关未注册到云端"),
    HDL_SEARCH_GATEWAY_TIMEOUT_ERROR(-2007,"搜索网关失败,超时"),
    HDL_AUTH_MAC_KEY_ERROR_(-2008,"认证失败,该MAC对应的设备密钥不存在"),
    HDL_GET_DEVICE_LIST_ERROR(-2100,"获取设备列表失败"),
    HDL_GET_FUNCTION_LIST_ERROR(-2101,"获取功能列表失败"),
    HDL_GET_FUNCTION_PROPERTIES_ERROR(-2102,"获取功能属性失败"),
    HDL_CONTROL_FAILURE_ERROR(-2103,"控制失败");
    private String msg;
    private int code;
    private HDLLinkCode(int code, String msg) {
        this.msg = msg;
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/exception/HDLLinkException.java
New file
@@ -0,0 +1,64 @@
package com.hdl.sdk.common.exception;
/**
 * Created by Tong on 2021/11/11.
 */
public class HDLLinkException extends RuntimeException {
    private int code = 0;
    private String msg = "";
    private Throwable rawThrowable;
    public HDLLinkException() {
    }
    public HDLLinkException(String msg) {
        this.msg = msg;
    }
    public HDLLinkException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public HDLLinkException(int code) {
        this.code = code;
    }
    public HDLLinkException(Throwable rawThrowable) {
        this.rawThrowable = rawThrowable;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public
    String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public Throwable getRawThrowable() {
        return rawThrowable;
    }
    public void setRawThrowable(Throwable rawThrowable) {
        this.rawThrowable = rawThrowable;
    }
    public static HDLLinkException getErrorWithCode(HDLLinkCode code){
        return new HDLLinkException(code.getCode(), code.getMsg());
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/ByteUtils.java
New file
@@ -0,0 +1,151 @@
package com.hdl.sdk.common.utils;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
 * Created by Tong on 2021/9/23.
 */
public class ByteUtils {
    public static byte[] toByteArray(List<Byte> list) {
        Byte[] temps = list.toArray(new Byte[0]);
        byte[] result = new byte[temps.length];
        for (int i = 0; i < result.length; i++) {
            result[i] = temps[i];
        }
        return result;
    }
    public static List<Byte> toByteList(byte[] bytes) {
        final List<Byte> list = new ArrayList<>();
        for (byte aByte : bytes) {
            list.add(aByte);
        }
        return list;
    }
    public static byte[] getRangeBytes(List<Byte> list, int start, int end) {
        Byte[] temps = Arrays.copyOfRange(list.toArray(new Byte[0]), start, end);
        byte[] result = new byte[temps.length];
        for (int i = 0; i < temps.length; i++) {
            result[i] = temps[i];
        }
        return result;
    }
    /**
     * 拼接byte
     */
    public static byte[] concatBytes(byte[] bt1, byte[] bt2) {
        if (bt1 == null) {
            return bt2;
        }
        if (bt2 == null) {
            return bt1;
        }
        byte[] bt3 = new byte[bt1.length + bt2.length];
        System.arraycopy(bt1, 0, bt3, 0, bt1.length);
        System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
        return bt3;
    }
    public boolean endWith(Byte[] src, byte[] target) {
        if (src.length < target.length) {
            return false;
        }
        for (int i = 0; i < target.length; i++) {
            if (target[target.length - i - 1] != src[src.length - i - 1]) {
                return false;
            }
        }
        return true;
    }
    public static int byteIndexOf(byte[] searched, byte[] find, int start) {
        boolean matched;
        int end = find.length - 1;
        int skip = 0;
        for (int index = start; index <= searched.length - find.length; ++index) {
            matched = true;
            if (find[0] != searched[index] || find[end] != searched[index + end]) continue;
            else skip++;
            if (end > 10)
                if (find[skip] != searched[index + skip] || find[end - skip] != searched[index + end - skip])
                    continue;
                else skip++;
            for (int subIndex = skip; subIndex < find.length - skip; ++subIndex) {
                if (find[subIndex] != searched[index + subIndex]) {
                    matched = false;
                    break;
                }
            }
            if (matched) {
                return index;
            }
        }
        return -1;
    }
    public static int getByteIndexOf(byte[] sources, byte[] src) {
        return getByteIndexOf(sources, src, 0, sources.length);
    }
    //判断一个byte数值在另外一个byte数组中对应的游标值
    public static int getByteIndexOf(byte[] sources, byte[] src, int startIndex) {
        return getByteIndexOf(sources, src, startIndex, sources.length);
    }
    //判断一个byte数值在另外一个byte数组中对应的游标值,指定开始的游标和结束的游标位置
    public static int getByteIndexOf(byte[] sources, byte[] src, int startIndex, int endIndex) {
        if (sources == null || src == null || sources.length == 0 || src.length == 0) {
            return -1;
        }
        if (endIndex > sources.length) {
            endIndex = sources.length;
        }
        int i, j;
        for (i = startIndex; i < endIndex; i++) {
            if (sources[i] == src[0] && i + src.length < endIndex) {
                for (j = 1; j < src.length; j++) {
                    if (sources[i + j] != src[j]) {
                        break;
                    }
                }
                if (j == src.length) {
                    return i;
                }
            }
        }
        return -1;
    }
    /**
     * 字符串to Bytes
     * @param str 字符串
     * @return
     */
    public static byte[] stringToBytes(String str) {
        try {
            // 使用指定的字符集将此字符串编码为byte序列并存到一个byte数组中
            return str.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new byte[]{};
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/IdUtils.java
New file
@@ -0,0 +1,12 @@
package com.hdl.sdk.common.utils;
import java.util.UUID;
/**
 * Created by Tong on 2021/10/8.
 */
public class IdUtils {
    public static String getUUId() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/IpUtils.java
New file
@@ -0,0 +1,89 @@
package com.hdl.sdk.common.utils;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
/**
 * Created by Tong on 2021/9/27.
 */
public class IpUtils {
    /**
     * @return 广播地址
     */
    public static String getBroadcastAddress() {
//        try {
//            for (Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
//                 niEnum.hasMoreElements(); ) {
//                NetworkInterface ni = niEnum.nextElement();
//                if (!ni.isLoopback()) {
//                    for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
//                        if (interfaceAddress.getBroadcast() != null) {
//                            return interfaceAddress.getBroadcast().toString().substring(1);
//                        }
//                    }
//                }
//            }
//        } catch (SocketException e) {
//            e.printStackTrace();
//        }
        return "255.255.255.255";
    }
    public static boolean isLocalIpAddress(String ipAddress) {
        try {
            for (Enumeration<NetworkInterface> niEnum = NetworkInterface.getNetworkInterfaces();
                 niEnum.hasMoreElements(); ) {
                NetworkInterface ni = niEnum.nextElement();
                for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
                    if (ipAddress.equals(interfaceAddress.getAddress().getHostAddress())) {
                        return true;
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return false;
    }
    public static String getIP(Context application) {
        WifiManager wifiManager = (WifiManager) application.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (!wifiManager.isWifiEnabled()) {
            try {
                for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                    NetworkInterface intf = en.nextElement();
                    for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                        InetAddress inetAddress = enumIpAddr.nextElement();
                        if (!inetAddress.isLoopbackAddress()) {
                            return inetAddress.getHostAddress();
                        }
                    }
                }
            } catch (SocketException e) {
                e.printStackTrace();
            }
        } else {
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            int ipAddress = wifiInfo.getIpAddress();
            return intToIp(ipAddress);
        }
        return null;
    }
    private static String intToIp(int i) {
        return (i & 0xFF) + "." +
                ((i >> 8) & 0xFF) + "." +
                ((i >> 16) & 0xFF) + "." +
                (i >> 24 & 0xFF);
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/LogUtils.java
New file
@@ -0,0 +1,63 @@
package com.hdl.sdk.common.utils;
import android.util.Log;
/**
 * Created by Tong on 2021/9/23.
 */
public class LogUtils {
    private static final String TAG = "HDLSDK";
    private static boolean isEnabled = true;
    public static boolean isEnabled() {
        return isEnabled;
    }
    public static void setEnabled(boolean enabled) {
        isEnabled = enabled;
    }
    public static void d(String tag, String msg) {
        if (tag != null && msg != null && isEnabled) {
            Log.d(TAG, tag + "-- " + msg);
        }
    }
    public static void e(String tag, String msg) {
        if (tag != null && msg != null && isEnabled) {
            Log.e(TAG, tag + "-- " + msg);
        }
    }
    public static void w(String tag, String msg) {
        if (tag != null && msg != null && isEnabled) {
            Log.w(TAG, tag + "-- " + msg);
        }
    }
    public static void v(String tag, String msg) {
        if (tag != null && msg != null && isEnabled) {
            Log.v(TAG, tag + "-- " + msg);
        }
    }
    public static void i(String tag, String msg) {
        if (tag != null && msg != null && isEnabled) {
            Log.i(TAG, tag + "-- " + msg);
        }
    }
    public static void i(String msg) {
        if (msg != null && isEnabled) {
            Log.i(TAG, msg);
        }
    }
    public static void e(String msg) {
        if (msg != null && isEnabled) {
            Log.e(TAG, msg);
        }
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/SPUtils.java
New file
@@ -0,0 +1,150 @@
package com.hdl.sdk.common.utils;
import android.content.Context;
import android.content.SharedPreferences;
import com.hdl.sdk.common.HDLSdk;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
 * Created by Tong on 2021/9/28.
 */
public class SPUtils {
    private static final String APP_PREFERENCES_KEY = "profile";
    private static final SharedPreferences PREFERENCES =
            HDLSdk.getInstance().getContext().getApplicationContext().getSharedPreferences(APP_PREFERENCES_KEY, Context.MODE_PRIVATE);
    private static SharedPreferences getAppPreference() {
        return PREFERENCES;
    }
    //======通用存储========
    public static void put(final String key, final String value) {
        getAppPreference().edit().putString(key, value).apply();
    }
    public static String getString(final String key) {
        return getString(key, "");
    }
    public static String getString(final String key, final String defaultValue) {
        return getAppPreference().getString(key, defaultValue);
    }
    public static void put(final String key, final int value) {
        put(key, value, false);
    }
    public static void put(final String key, final int value, final boolean isCommit) {
        getAppPreference().edit().putInt(key, value).apply();
    }
    public static int getInt(final String key) {
        return getInt(key, -1);
    }
    public static int getInt(final String key, final int defaultValue) {
        return getAppPreference().getInt(key, defaultValue);
    }
    public static void put(final String key, final long value) {
        getAppPreference().edit().putLong(key, value).apply();
    }
    public static long getLong(final String key) {
        return getLong(key, -1L);
    }
    public static long getLong(final String key, final long defaultValue) {
        return getAppPreference().getLong(key, defaultValue);
    }
    public static void put(final String key, final float value) {
        getAppPreference().edit().putFloat(key, value).apply();
    }
    public static float getFloat(final String key) {
        return getFloat(key, -1f);
    }
    public static float getFloat(final String key, final float defaultValue) {
        return getAppPreference().getFloat(key, defaultValue);
    }
    public static void put(final String key, final boolean value) {
        getAppPreference().edit().putBoolean(key, value).apply();
    }
    public static boolean getBoolean(final String key) {
        return getBoolean(key, false);
    }
    public static boolean getBoolean(final String key, final boolean defaultValue) {
        return getAppPreference().getBoolean(key, defaultValue);
    }
    public static void put(final String key,
                           final Set<String> value
    ) {
        getAppPreference().edit().putStringSet(key, value).apply();
    }
    public static Set<String> getStringSet(final String key) {
        return getStringSet(key, Collections.<String>emptySet());
    }
    public static Set<String> getStringSet(final String key,
                                           final Set<String> defaultValue) {
        return getAppPreference().getStringSet(key, defaultValue);
    }
    public static Map<String, ?> getAll() {
        return getAppPreference().getAll();
    }
    public static boolean contains(final String key) {
        return getAppPreference().contains(key);
    }
    public static void remove(final String key) {
        getAppPreference().edit().remove(key).apply();
    }
    public static void clear() {
        getAppPreference()
                .edit()
                .clear()
                .apply();
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/ThreadToolUtils.java
New file
@@ -0,0 +1,73 @@
package com.hdl.sdk.common.utils;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
 * Created by Tong on 2021/9/15.
 */
public class ThreadToolUtils {
    private final Handler uiHandler = new Handler(Looper.getMainLooper());
    //cpu 最大线程容纳量
    private final int coreSize = Runtime.getRuntime().availableProcessors() + 1;
    private ThreadToolUtils() {
    }
//    private static class SingletonInstance {
//    }
    private static final ThreadToolUtils instance = new ThreadToolUtils();
    public static ThreadToolUtils getInstance() {
        return instance;
    }
    /**
     * 线程数量固定的线程池
     */
    public ExecutorService newFixedThreadPool(int size) {
        if (size == 0 || coreSize < size) {
            return Executors.newFixedThreadPool(coreSize);
        }
        return Executors.newFixedThreadPool(size);
    }
    /**
     * 定时任务线程池
     */
    public ScheduledExecutorService newScheduledThreadPool(int size) {
        if (size == 0 || coreSize < size) {
            return Executors.newScheduledThreadPool(coreSize);
        }
        return Executors.newScheduledThreadPool(size);
    }
    /**
     * 单一线程
     */
    public ExecutorService newSingleThreadPool() {
        return Executors.newSingleThreadExecutor();
    }
    public ExecutorService newCachedThreadPool() {
        return Executors.newCachedThreadPool();
    }
    /**
     * 切换回主线程
     */
    public void runOnUiThread(Runnable run) {
        uiHandler.post(run);
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/gson/GsonConvert.java
New file
@@ -0,0 +1,55 @@
package com.hdl.sdk.common.utils.gson;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
/**
 * Created by Tong on 2021/9/8.
 */
public class GsonConvert {
    private static Gson gson = null;
    public static Gson getGson() {
        if (gson == null) {
            synchronized (GsonConvert.class) {
                if (gson == null) {
                    gson = new GsonBuilder()
                            .setPrettyPrinting()
                            .disableHtmlEscaping()
                            .registerTypeAdapter(String.class, new StringTypeAdapter())
                            .create();
                }
            }
        }
        return gson;
    }
    private static class StringTypeAdapter implements JsonSerializer<String>, JsonDeserializer<String> {
        @Override
        public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            if (json instanceof JsonPrimitive) {
                return json.getAsString();
            } else {
                return json.toString();
            }
        }
        @Override
        public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/common/utils/gson/ParameterizedTypeImpl.java
New file
@@ -0,0 +1,43 @@
package com.hdl.sdk.common.utils.gson;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
 * Created by Tong on 2021/9/17.
 */
public class ParameterizedTypeImpl implements ParameterizedType {
    private final Type[] actualTypeArguments;
    private final Type rawType;
    private final Type ownerType;
    public ParameterizedTypeImpl(Type rawType, Type[] actualTypeArguments, Type ownerType) {
        this.ownerType = ownerType;
        this.rawType = rawType;
        this.actualTypeArguments = actualTypeArguments;
    }
    public static Type getType(Type rawType, Type[] actualTypeArguments) {
        return new ParameterizedTypeImpl(rawType, actualTypeArguments, null);
    }
    @Override
    public Type[] getActualTypeArguments() {
        return actualTypeArguments;
    }
    @Override
    public Type getRawType() {
        return rawType;
    }
    @Override
    public Type getOwnerType() {
        return ownerType;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LoginRequest.java
New file
@@ -0,0 +1,30 @@
package com.hdl.sdk.connect.bean;
import java.io.Serializable;
/**
 * Created by Tong on 2022/09/23.
 */
public class LoginRequest implements Serializable {
    private String clientType;
    private String version;
    public String getClientType() {
        return clientType;
    }
    public void setClientType(String clientType) {
        this.clientType = clientType;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/response/DeviceInfoResponse.java
New file
@@ -0,0 +1,70 @@
package com.hdl.sdk.connect.bean.response;
import java.io.Serializable;
/**
 * Created by jlchen on 11/12/21.
 *
 * @Description : DeviceInfoResponse
 */
public class DeviceInfoResponse extends BaseResponse {
    private GatewayObjects objects;
    public GatewayObjects getObjects() {
        return objects;
    }
    public void setObjects(GatewayObjects value) {
        this.objects = value;
    }
    public class GatewayObjects implements Serializable {
        private String ip_address;
        private String gatewayId;
        private String oid;
        private String homeId;
        private String mac;
        public String getIPAddress() {
            return ip_address;
        }
        public void setIPAddress(String value) {
            this.ip_address = value;
        }
        public String getGatewayID() {
            return gatewayId;
        }
        public void setGatewayID(String value) {
            this.gatewayId = value;
        }
        public String getOID() {
            return oid;
        }
        public void setOID(String value) {
            this.oid = value;
        }
        public String getHomeId() {
            return homeId;
        }
        public void setHomeId(String homeId) {
            this.homeId = homeId;
        }
        public String getMac() {
            return mac;
        }
        public void setMac(String mac) {
            this.mac = mac;
        }
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java
@@ -4,6 +4,7 @@
import android.util.Log;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.hdl.sdk.common.config.TopicConstant;
import com.hdl.sdk.common.event.EventDispatcher;
import com.hdl.sdk.common.event.EventListener;
@@ -11,15 +12,20 @@
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.IdUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.SPUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.common.utils.gson.GsonConvert;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.LoginRequest;
import com.hdl.sdk.connect.bean.request.BroadcastRequest;
import com.hdl.sdk.connect.bean.response.AuthenticateResponse;
import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
import com.hdl.sdk.connect.bean.request.FunctionAttributeRequest;
import com.hdl.sdk.connect.bean.LinkRequest;
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.bean.request.PropertyReadRequest;
import com.hdl.sdk.connect.bean.response.DeviceInfoResponse;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack;
import com.hdl.sdk.connect.config.HDLLinkConfig;
@@ -59,7 +65,7 @@
        statusListener = new ConnectStatusListener() {
            @Override
            public void onConnecting() {
                broadcastRequest();
                //broadcastRequest();
            }
            @Override
@@ -74,43 +80,67 @@
        };
    }
    public boolean isBroadcast = false;
    /**
     * 广播自身信息给主网关
     */
    private void broadcastRequest() {
    public void broadcastRequest() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    LogUtils.i("广播设备本身信息");
                while (true) {
                    try {
                        Thread.sleep(1000);
//                        LogUtils.i("checkIfCertified=" + HDLLink.getInstance().checkIfCertified() + " getTcp().connected=" + getTcp().connected);
                        try {
                            if (!HDLLink.getInstance().checkIfCertified() || getTcp().connected) {
                                continue;
                            }
                        } catch (Exception e) {
                    String time = String.valueOf(System.currentTimeMillis());
                    if (null == HDLLinkConfig.getInstance().getDeviceInfoBean()) {
                        LogUtils.i("DeviceInfoBean为空,请设置当前对象");
                        return;
                        }
                        LogUtils.i("广播设备本身信息");
                        String time = String.valueOf(System.currentTimeMillis());
                        if (null == HDLLinkConfig.getInstance().getDeviceInfoBean()) {
                            LogUtils.i("DeviceInfoBean为空,请设置当前对象");
                            continue;
                        }
                        BroadcastRequest request = new BroadcastRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), "200");
                        HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true, new HDLLinkResponseCallBack() {
                            @Override
                            public void onSuccess(LinkResponse msg) {
                                getTcp();
                                String data = msg.getData();
                                if (!TextUtils.isEmpty(data)) {
                                    DeviceInfoResponse response = GsonConvert.getGson().fromJson(data, new TypeToken<DeviceInfoResponse>() {
                                    }.getType());
                                    HDLLinkConfig.getInstance().setIpAddress(response.getObjects().getIPAddress());
                                    HDLLinkConfig.getInstance().reSaveConfig();
                                }
                                isBroadcast = true;
                                LogUtils.i("广播信息给主网关成功!");
                            }
                            @Override
                            public void onError(HDLLinkException e) {
                                isBroadcast = false;
                                LogUtils.i("广播信息给主网关失败!");
                            }
                        });
//                        HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true);
                        //HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true);
                    } catch (Exception e) {
                        LogUtils.e("广播设备本身信息失败,失败信息:" + e.getMessage());
                    }
                    BroadcastRequest request = new BroadcastRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), "200");
                    HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true, new HDLLinkResponseCallBack() {
                        @Override
                        public void onSuccess(LinkResponse msg) {
                            LogUtils.i("广播信息给主网关成功!");
                        }
                        @Override
                        public void onError(HDLLinkException e) {
                            LogUtils.i("广播信息给主网关失败!");
                        }
                    });
                    HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true);
                    HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true);
                } catch (Exception e) {
                    LogUtils.e("广播设备本身信息失败,失败信息:" + e.getMessage());
                }
            }
        }).start();
    }
//    private static class SingletonInstance {
    //    private static class SingletonInstance {
//    }
    private static final HDLSocket instance = new HDLSocket();
@@ -119,8 +149,9 @@
    }
    SocketOptions options;
    private SocketOptions getTcpOptions() {
        if(null!=options){
        if (null != options) {
            return options;
        }
        options = new SocketOptions();
@@ -423,13 +454,13 @@
            throw new RuntimeException("请搜索网关");
        }
        //如果没有初始化,或者网关IP更改了,就重新初始化
        if (tcpBoot == null||!getTcpOptions().getIp().equals(getTcpIp())) {
        if (tcpBoot == null || !getTcpOptions().getIp().equals(getTcpIp())) {
            tcpBoot = TcpClient.init(getTcpIp(), getTcpPort(), getTcpOptions());
            tcpBoot.SetHeartbeat(new IHeartbeat() {
                @Override
                public void heartbeat() {
                    if(HDLLinkConfig.getInstance().getDeviceInfoBean()==null||HDLLinkConfig.getInstance().getDeviceInfoBean().getOID()==null) {
                    if (HDLLinkConfig.getInstance().getDeviceInfoBean() == null || HDLLinkConfig.getInstance().getDeviceInfoBean().getOID() == null) {
                        LogUtils.i("DeviceInfoBean为空,需要设置才能正常心跳");
                        return;
                    }
@@ -493,8 +524,9 @@
    }
    /**
     *  场景控制
     * @param sids 场景sid列表
     * 场景控制
     *
     * @param sids     场景sid列表
     * @param callBack 回调
     */
    public void controlScene(List<String> sids, HDLLinkCallBack callBack) {
@@ -535,6 +567,56 @@
                }
            }
        } else {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
            }
        }
    }
    /**
     * tcp登录方便获取状态
     *
     * @param clientType 客户端类型
     *                   应用:app;
     *                   调试软件:program;
     *                   第三方:third_party;
     *                   网关:gateway;
     *                   其它:other
     * @param version    协议版本
     */
    public void tcpLogin(String clientType, String version, HDLLinkCallBack callBack) {
        final String msgId = IdUtils.getUUId();
        String time = String.valueOf(System.currentTimeMillis());
        final BaseLocalResponse<LoginRequest> data = new BaseLocalResponse<>();
        data.setId(msgId);
        data.setTime_stamp(time);
        final LoginRequest request = new LoginRequest();
        request.setVersion(version);
        request.setClientType(clientType);
        data.setObjects(request);
        String topic = String.format(TopicConstant.GATEWAY_LOGIN, HDLLinkConfig.getInstance().getGatewayId());
        LinkRequest message = new LinkRequest(topic,
                GsonConvert.getGson().toJson(data));
        String replyTopic = topic + "_reply";
        try {
            sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() {
                @Override
                public void onSucceed() {
                    LogUtils.i("tcpLogin onSucceed");
                }
                @Override
                public void onError() {
                    if (callBack != null) {
                        callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
                    }
                }
            });
        } catch (Exception e) {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR));
            }
@@ -584,8 +666,8 @@
    /**
     * 通用TCP发送指令 只发一次,不监听回复,不重发
     *
     * @param topic    发送数据
     * @param bodyStr  回复的主题
     * @param topic   发送数据
     * @param bodyStr 回复的主题
     */
    public void tcpSendMsg(String topic, String bodyStr) {
        try {
@@ -596,7 +678,7 @@
            LinkRequest message = new LinkRequest(topic, bodyStr);
            getTcp().sendMsg(message.getSendBytes());
        } catch (Exception e) {
            LogUtils.e("tcpSendMsg", "发送失败 :"+e.getMessage());
            LogUtils.e("tcpSendMsg", "发送失败 :" + e.getMessage());
        }
    }
@@ -607,7 +689,7 @@
    public void sendMsg(byte[] data, String eventTag, HDLLinkCallBack callBack, SendListener sendListener) {
        try {
            if(eventTag!=null) {
            if (eventTag != null) {
                final AtomicInteger sendCount = new AtomicInteger(0);
                final ScheduledExecutorService threadPool = ThreadToolUtils.getInstance().newScheduledThreadPool(1);
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/.DS_Store
Binary files differ
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketBoot.java
New file
@@ -0,0 +1,270 @@
package com.hdl.sdk.socket;
import android.text.TextUtils;
import com.hdl.sdk.common.HDLSdk;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.connect.socket.HDLSocket;
import com.hdl.sdk.socket.annotation.ConnectStatus;
import com.hdl.sdk.socket.client.IClient;
import com.hdl.sdk.socket.client.IHeartbeat;
import com.hdl.sdk.socket.client.TcpClient;
import com.hdl.sdk.socket.listener.SendListener;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
/**
 * Created by Tong on 2021/9/26.
 * Tcp/Udp 启动器
 */
public class SocketBoot {
    private ExecutorService connectThread;
    private ExecutorService sendThread;
    private ExecutorService receiveThread;
    private ExecutorService heartbeatThread;
    private final IClient client;
    private IHeartbeat iHeartbeat;
    public void SetHeartbeat(IHeartbeat iHeartbeat) {
        this.iHeartbeat = iHeartbeat;
    }
    /**
     * 当前接收到数据的时间
     */
    private static long time = System.currentTimeMillis();
    /**
     * tcp是否已经连接
     */
    public boolean connected = false;
    public IClient getClient() {
        return client;
    }
    private final BlockingQueue<SocketRequest> mMessageQueue = new LinkedBlockingDeque<>();
    private final ConcurrentMap<String, SendListener> sendMap = new ConcurrentHashMap<>();
    public SocketBoot(IClient client) {
        this.client = client;
        initConnectThread();
        initReceiveThread();
        initSendThread();
        initHeartbeat();
    }
    /**
     * 连接tcp,内部维护掉,可以不用开放外部,根据这个业务我特性处理好
     */
    private synchronized void connect() {
        try {
            LogUtils.i("TCP连接");
            client.onConnectStatus(ConnectStatus.CONNECTING);
            Thread.sleep(1000);
            client.connect();
            connected = true;
            HDLSocket.getInstance().tcpLogin("third_party", HDLSdk.getInstance().getVersion(),null);
            LogUtils.i("TCP连接成功");
            client.onConnectStatus(ConnectStatus.CONNECTED);
        } catch (Exception e) {
            LogUtils.e("连接异常" + e.getMessage());
        }
    }
    /**
     * 初始化发送线程,只需要初始化一次
     */
    private void initSendThread() {
        if (sendThread == null) {
            sendThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            sendThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            if (!connected) {
                                Thread.sleep(200);
                                continue;
                            }
                            SocketRequest socketRequest = mMessageQueue.take();
//                            final String sendStr = new String(socketRequest.getData(), 0, socketRequest.getData().length);
//                            LogUtils.i("发送数据:" + sendStr);
                            if (System.currentTimeMillis() - socketRequest.getTime() > 10000) {
                                continue;
                            }
                            final String action = socketRequest.getAction();
                            try {
                                client.sendMsg(socketRequest.getData());
                                if (!TextUtils.isEmpty(action)) {
                                    SendListener sendListener = sendMap.get(action);
                                    if (sendListener != null) {
                                        sendListener.onSucceed();
                                    }
                                }
                            } catch (Exception e) {
                                HDLSocket.getInstance().isBroadcast=false;
                                connected = false;
                                LogUtils.e("发送失败:" + e.getMessage());
                                if (!TextUtils.isEmpty(action)) {
                                    SendListener sendListener = sendMap.get(action);
                                    if (sendListener != null) {
                                        sendListener.onError();
                                    }
                                }
                            }
                        } catch (Exception e) {
                        }
                    }
                }
            });
        }
    }
    /**
     * 初始化接收线程,只需要初始化一次
     */
    public void initReceiveThread() {
        if (receiveThread == null) {
            receiveThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            receiveThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            if (connected) {
                                //读取数据
                                client.onHandleResponse();
                                time = System.currentTimeMillis();
                            } else {
                                try {
                                    Thread.sleep(1000);
                                } catch (Exception ee) {
                                }
                            }
                        } catch (Exception e) {
                            HDLSocket.getInstance().isBroadcast= false;
                            connected = false;
                            LogUtils.e("接收数据线程异常" + e.getMessage());
                        }
                    }
                }
            });
        }
    }
    /**
     * 初始化重新连接线程
     */
    private void initConnectThread() {
        if (connectThread == null) {
            connectThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            //一定时间检测一次连接情况,没有连接就执行连接,连接统一由这里维护
            connectThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
//                            LogUtils.i("initConnectThread: connected=" + connected + " isBroadcast=" + HDLSocket.getInstance().isBroadcast);
                            if (!connected && HDLSocket.getInstance().isBroadcast) {
                                reconect();
                            }
                            Thread.sleep(3 * 1000);
                        } catch (Exception e) {
                            LogUtils.e("定时连接失败:" + e.getMessage());
                        }
                    }
                }
            });
        }
    }
    /**
     * 初始化重新心跳线程
     */
    private void initHeartbeat() {
        if (heartbeatThread == null) {
            heartbeatThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            heartbeatThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            //10秒
                            if (connected && 10 * 1000 < (System.currentTimeMillis() - time)) {
                                time = System.currentTimeMillis();
                                //心跳检测
                                if (iHeartbeat != null)
                                    iHeartbeat.heartbeat();
                            }
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            LogUtils.e("定时心跳检测网关异常:" + e.getMessage());
                        }
                    }
                }
            });
        }
    }
    /**
     * 重新连接
     */
    private void reconect() {
        disconnect();
        connect();
    }
    /**
     * 发送无需回调
     *
     * @param msg 发送的数据
     */
    public void sendMsg(byte[] msg) {
        sendMsg(msg, null);
    }
    /**
     * @param listener 一般情况无需监听
     */
    public void sendMsg(byte[] msg, SendListener listener) {
        try {
            SocketRequest request = new SocketRequest(msg);
            if (listener != null && !TextUtils.isEmpty(request.getAction())) {
                sendMap.put(request.getAction(), listener);
            }
            mMessageQueue.put(request);
        } catch (Exception e) {
            LogUtils.e("发送数据失败:" + e.getMessage());
        }
    }
    /**
     * 关闭连接
     */
    private synchronized void disconnect() {
        try {
            client.disconnect();
            //断开连接
            client.onConnectStatus(ConnectStatus.DISCONNECT);
        } catch (Exception e) {
        }
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketOptions.java
New file
@@ -0,0 +1,75 @@
package com.hdl.sdk.socket;
import com.hdl.sdk.socket.codec.IHandleMessage;
import com.hdl.sdk.socket.listener.ConnectStatusListener;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by Tong on 2021/9/22.
 * socket配置
 */
public class SocketOptions {
    //发送目标地址IP
    private String ip="";
    private int port;
    //处理数据
    private IHandleMessage handleMessage;
    //监听状态
    private List<ConnectStatusListener> mConnectStatusListener;
    public String getIp() {
        return ip;
    }
    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        this.port = port;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
    public IHandleMessage getHandleMessage() {
        return handleMessage;
    }
    public void setHandleMessage(IHandleMessage handleMessage) {
        this.handleMessage = handleMessage;
    }
    public void clearConnectStatusListener() {
        if (mConnectStatusListener != null && !mConnectStatusListener.isEmpty()) {
            mConnectStatusListener.clear();
        }
    }
    public void addConnectStatusListener(ConnectStatusListener connectStatusListener) {
        if (mConnectStatusListener == null) {
            mConnectStatusListener = new ArrayList<>();
        }
        mConnectStatusListener.add(connectStatusListener);
    }
    public void removeConnectStatusListener(ConnectStatusListener connectStatusListener) {
        if (mConnectStatusListener != null) {
            mConnectStatusListener.remove(connectStatusListener);
        }
    }
    public List<ConnectStatusListener> getConnectStatusListener() {
        return mConnectStatusListener;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketPool.java
New file
@@ -0,0 +1,51 @@
package com.hdl.sdk.socket;
import com.hdl.sdk.socket.client.IClient;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.concurrent.ConcurrentHashMap;
/**
 * Created by Tong on 2021/10/19.
 * 计划参考generic-pool、Commons Pool进行完善
 */
public class SocketPool {
    private final ConcurrentHashMap<String, IClient> mPool;
    private final ConcurrentHashMap<String, DatagramSocket> mUdpClientPool;
    private SocketPool() {
        mPool = new ConcurrentHashMap<>();
        mUdpClientPool = new ConcurrentHashMap<>();
    }
    private static final SocketPool instance = new SocketPool();
    public static SocketPool getInstance() {
        return instance;
    }
    public void clear() {
        mPool.clear();
        mUdpClientPool.clear();
    }
    public synchronized DatagramSocket getUdpSocket(InetSocketAddress address) throws SocketException {
        DatagramSocket socket;
        final String key = address.toString();
        if (mUdpClientPool.containsKey(key)) {
            socket = mUdpClientPool.get(key);
            if (socket != null && !socket.isClosed()) {
                return socket;
            } else {
                socket = new DatagramSocket(address);
            }
        } else {
            socket = new DatagramSocket(address);
        }
        mUdpClientPool.put(address.toString(), socket);
        return socket;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/SocketRequest.java
New file
@@ -0,0 +1,41 @@
package com.hdl.sdk.socket;
import java.util.UUID;
/**
 * Created by Tong on 2021/9/22.
 */
public class SocketRequest {
    private String action;
    private byte[] data;
    private long time = System.currentTimeMillis();
    public SocketRequest(byte[] data) {
        this.data = data;
        action = UUID.randomUUID().toString();
    }
    public String getAction() {
        return action;
    }
    public void setAction(String action) {
        this.action = action;
    }
    public byte[] getData() {
        return data;
    }
    public void setData(byte[] data) {
        this.data = data;
    }
    public long getTime() {
        return time;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/annotation/ConnectStatus.java
New file
@@ -0,0 +1,24 @@
package com.hdl.sdk.socket.annotation;
/**
 * Created by Tong on 2021/9/22.
 */
public class ConnectStatus {
    /**
     * 连接中
     */
    public static final int CONNECTING = 0;
    /**
     * 连接成功
     */
    public static final int CONNECTED = 1;
    /**
     * 连接关闭
     */
    public static final int DISCONNECT = 2;
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/IClient.java
New file
@@ -0,0 +1,32 @@
package com.hdl.sdk.socket.client;
import com.hdl.sdk.socket.SocketOptions;
/**
 * Created by Tong on 2021/9/22.
 */
public interface IClient {
    void connect() throws Exception;
    void disconnect();
    SocketOptions getOptions();
    /**
     * 监听数据
     */
    void onHandleResponse() throws Exception;
    /**
     * 发送消息
     */
    void sendMsg(byte[] msg) throws Exception;
    /**
     * 连接状态
     */
    void onConnectStatus(int status);
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/IHeartbeat.java
New file
@@ -0,0 +1,8 @@
package com.hdl.sdk.socket.client;
/**
 * Created by hxb on 2022/2/16.
 */
public interface IHeartbeat {
    void heartbeat();
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/IUdpClient.java
New file
@@ -0,0 +1,42 @@
package com.hdl.sdk.socket.client;
import com.hdl.sdk.socket.SocketOptions;
import com.hdl.sdk.socket.udp.UdpSocketOptions;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
/**
 * Created by hxb on 2021/12/12.
 */
public interface IUdpClient {
    /**
     * 绑定端口
     */
    void bind() throws Exception;
    /**
     * 关闭当前连接
     * @return
     */
    boolean close();
    UdpSocketOptions getOptions();
    /**
     * 监听数据
     */
    void onHandleResponse() throws Exception;
    /**
     * 发送数据
     * @param ipAddress 目标IP
     * @param port 端口
     * @param msg 发送数据
     * @throws Exception
     */
    void sendMsg(String ipAddress,int port, byte[] msg) throws Exception;
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/TcpClient.java
New file
@@ -0,0 +1,199 @@
package com.hdl.sdk.socket.client;
import com.hdl.sdk.common.utils.ByteUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.socket.SocketBoot;
import com.hdl.sdk.socket.SocketOptions;
import com.hdl.sdk.socket.annotation.ConnectStatus;
import com.hdl.sdk.socket.codec.IHandleMessage;
import com.hdl.sdk.socket.listener.ConnectStatusListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.StandardSocketOptions;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by Tong on 2021/9/15.
 */
public final class TcpClient implements IClient {
    private SocketOptions socketOptions;
    private final String ip;
    private final int port;
    private Socket mSocket;
    private final static List<TcpClient> tcpClientList = new ArrayList();
    /**
     * 从连接池中找出当前IP及端口的连接客户端
     * @param ipAdderss 连接IP地址
     * @param port 连接端口
     * @return
     */
    public static TcpClient getTcpClientByIP(String ipAdderss,int port) {
        for(TcpClient tcpClient:tcpClientList){
            if(tcpClient.ip.equals(ipAdderss)&&tcpClient.port==port)
            {
                return tcpClient;
            }
        }
        return  null;
    }
    private byte[] readBuffer = new byte[4*1024];
    private TcpClient(String ip, int port, SocketOptions socketOptions) {
        this.socketOptions = socketOptions;
        this.ip = ip;
        this.port = port;
        socketOptions.setIp(ip);
        socketOptions.setPort(port);
    }
    public static SocketBoot init(String ip, int port, SocketOptions options) {
        return new SocketBoot(new TcpClient(ip, port, options));
    }
    @Override
    public void connect() throws Exception {
        mSocket = getSocket();
//        SocketOptions options = getOptions();
        mSocket.connect(new InetSocketAddress(ip, port), 3 * 1000);
        mSocket.setTcpNoDelay(true);
        mSocket.setReuseAddress(true);
//        mSocket.setKeepAlive(true);
        mSocket.setSoTimeout(25 * 1000);
        tcpClientList.add(this);
    }
    @Override
    public void disconnect() {
        if (mSocket != null) {
            try {
                mSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public synchronized SocketOptions getOptions() {
        if (socketOptions == null) {
            socketOptions = new SocketOptions();
        }
        return socketOptions;
    }
    @Override
    public void onHandleResponse() throws Exception {
        final InputStream stream = getInputStream();
        if (stream != null && getOptions() != null) {
            while ( true) {
                int len=getInputStream().read(readBuffer);
                if(len<=0){
                    throw  new Exception("接收异常,接收数据长度len="+len);
                }
                IHandleMessage handleMessage = getOptions().getHandleMessage();
                if (handleMessage != null) {
                    byte []bytes = new byte[len];
                    System.arraycopy(readBuffer,0,bytes,0,len);
                    //完整的数据才回调
                    handleMessage.read(bytes,ip);
                }
            }
        }
    }
    @Override
    public void sendMsg(byte[] msg) throws Exception {
        final OutputStream outputStream = getOutStream();
        if (outputStream != null && getOptions() != null) {
                IHandleMessage handleMessage = getOptions().getHandleMessage();
                handleMessage.write(handleMessage.write(msg));
                outputStream.write(msg);
                outputStream.flush();
        }
    }
    /**
     * 处理连接状态
     */
    public void onConnectStatus(int status) {
        ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                final List<ConnectStatusListener> list = getOptions().getConnectStatusListener();
                if (list != null && !list.isEmpty()) {
                    for (ConnectStatusListener listener : list) {
                        switch (status) {
                            case ConnectStatus
                                    .CONNECTING:
                                listener.onConnecting();
                                break;
                            case ConnectStatus
                                    .CONNECTED:
                                listener.onConnected();
                                break;
                            case ConnectStatus
                                    .DISCONNECT:
                                listener.onConnectFailed();
                                break;
                        }
                    }
                }
            }
        });
    }
    private synchronized Socket getSocket() {
        return new Socket();
    }
    private InputStream getInputStream() {
        if (mSocket != null && mSocket.isConnected() && !mSocket.isClosed()) {
            try {
                return mSocket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    private OutputStream getOutStream() {
        if (mSocket != null && mSocket.isConnected() && !mSocket.isClosed()) {
            try {
                return mSocket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/client/UdpClient.java
New file
@@ -0,0 +1,176 @@
package com.hdl.sdk.socket.client;
import android.text.TextUtils;
import com.hdl.sdk.common.utils.IpUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.socket.SocketBoot;
import com.hdl.sdk.socket.SocketOptions;
import com.hdl.sdk.socket.SocketPool;
import com.hdl.sdk.socket.udp.UdpSocketBoot;
import com.hdl.sdk.socket.udp.UdpSocketOptions;
import com.hdl.sdk.socket.codec.IHandleMessage;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.atomic.AtomicBoolean;
/**
 * Created by hxb on 2021/12/12.
 */
public class UdpClient implements IUdpClient {
    /**
     * 当前socket
     */
    private  DatagramSocket mSocket;
    /**
     * 接收数据包
     */
    private DatagramPacket receivePacket;
    /**
     * 缓冲区大小
     */
    private final int BUFFER = 2 * 1024;
    /**
     * 本地监听IP地址
     */
    private String ipAddress;
    /**
     * 本地监听端口
     */
    private int port;
    /**
     * socket配置信息
     */
    private UdpSocketOptions socketOptions;
    /**
     * 初始化参数
     * @param ipAddress 本地监听端口
     * @param port 本地监听端口
     * @param socketOptions
     */
    private UdpClient(String ipAddress,int port, UdpSocketOptions socketOptions) {
        this.ipAddress = ipAddress;
        this.port = port;
        this.socketOptions = socketOptions;
        byte[] receiveByte = new byte[BUFFER];
        receivePacket = new DatagramPacket(receiveByte, receiveByte.length);
    }
    /**
     * 初始化参数
     * @param ipAddress 本地监听IP地址
     * @param port 本地监听端口
     * @param options
     * @return
     */
    public static UdpSocketBoot init(String ipAddress, int port, UdpSocketOptions options) {
        return new UdpSocketBoot(new UdpClient(ipAddress, port, options));
    }
    /**
     * 初始化参数
     * @param port 本地监听端口
     * @param options
     * @return
     */
    public static UdpSocketBoot init(int port, UdpSocketOptions options) {
        return init("0.0.0.0", port, options);
    }
    @Override
    public void bind() throws Exception {
        try {
            //已经绑定过就不用再绑定
            if (null != mSocket) {
                return;
            }
            if (TextUtils.isEmpty(ipAddress)) {
                mSocket = SocketPool.getInstance().getUdpSocket(new InetSocketAddress(port));
            }else {
                mSocket = SocketPool.getInstance().getUdpSocket(new InetSocketAddress(ipAddress,port));
            }
            mSocket.setBroadcast(true);
//            mSocket.setReuseAddress(true);
        } catch (Exception e) {
            LogUtils.e("初始化Socket 失败:" + e.getMessage());
            throw e;
        }
    }
    @Override
    public boolean close() {
        try {
            mSocket.close();
        } catch (Exception e) {
        }
        mSocket = null;
        return true;
    }
    @Override
    public UdpSocketOptions getOptions() {
        return this.socketOptions;
    }
    @Override
    public void onHandleResponse() throws Exception {
        if (mSocket == null) {
            return;
        }
        try {
            mSocket.receive(receivePacket);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (receivePacket.getLength() == 0) {
            return;
        }
        //排除自己发出去的
        try {
            if (IpUtils.isLocalIpAddress(receivePacket.getAddress().getHostAddress()))
                return;
        } catch (Exception ignored) {
        }
        try {
            LogUtils.i("接收到Udp数据包,网络地址:" + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
            IHandleMessage handleMessage = getOptions().getHandleMessage();
            if (handleMessage != null) {
                byte[] data = new byte[receivePacket.getLength()];
                System.arraycopy(receivePacket.getData(), 0, data, 0, data.length);
                handleMessage.read(data,receivePacket.getAddress().getHostAddress());
            }
        } catch (Exception e) {
        }
    }
    @Override
    public void sendMsg(String ipAddress,int port, byte[] msg) throws Exception {
        if (msg == null) {
            return;
        }
        final DatagramPacket sendPacket = new DatagramPacket(msg, msg.length, InetAddress.getByName(ipAddress), port);
        mSocket.send(sendPacket);
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/ByteToMessageDecoder.java
New file
@@ -0,0 +1,20 @@
package com.hdl.sdk.socket.codec;
/**
 * Created by Tong on 2021/9/22.
 */
public abstract class ByteToMessageDecoder<T> implements IHandleFlow<T> {
    protected abstract T decoder(Object msg,String ipaddress)
            throws Exception;
    @Override
    public final T read(Object data,String ipaddress) throws Exception {
        return decoder(data,ipaddress);
    }
    @Override
    public final byte[] write(byte[] data) {
        return data;
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/IHandleFlow.java
New file
@@ -0,0 +1,12 @@
package com.hdl.sdk.socket.codec;
/**
 * Created by Tong on 2021/9/23.
 */
public interface IHandleFlow<T> {
    T read(Object data,String ipaddress) throws Exception;
    byte[] write(byte[] data) throws Exception;
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/IHandleMessage.java
New file
@@ -0,0 +1,10 @@
package com.hdl.sdk.socket.codec;
/**
 * Created by Tong on 2021/9/27.
 */
public interface IHandleMessage {
    void read(byte[] data,String ipaddress) throws Exception;
    byte[] write(byte[] data) throws Exception;
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/IMessagePipeLine.java
New file
@@ -0,0 +1,11 @@
package com.hdl.sdk.socket.codec;
/**
 * Created by Tong on 2021/9/23.
 */
public interface IMessagePipeLine {
    void add(IHandleFlow flow);
    void clear();
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/MessagePipeLine.java
New file
@@ -0,0 +1,51 @@
package com.hdl.sdk.socket.codec;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
 * Created by Tong on 2021/9/23.
 */
public class MessagePipeLine implements IMessagePipeLine, IHandleMessage {
    public final List<IHandleFlow> queue = new ArrayList<>();
    @Override
    public void add(IHandleFlow flow) {
        queue.add(flow);
    }
    @Override
    public synchronized void clear() {
        queue.clear();
    }
    @Override
    public void read(byte[] data,String ipaddress) throws Exception {
        Object out = data;
        for (int i = 0; i < queue.size(); i++) {
            IHandleFlow flow = queue.get(i);
            Object read = flow.read(out,ipaddress);
            try {
                out = Objects.requireNonNull(read);
            } catch (Exception ignored) {
            }
        }
    }
    @Override
    public byte[] write(byte[] data) throws Exception {
        byte[] out = data;
        for (int i = 0; i < queue.size(); i++) {
            IHandleFlow flow = queue.get(i);
            byte[] write = flow.write(out);
            try {
                out = Objects.requireNonNull(write);
            } catch (Exception ignored) {
            }
        }
        return new byte[0];
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/codec/MessageToByteEncoder.java
New file
@@ -0,0 +1,24 @@
package com.hdl.sdk.socket.codec;
/**
 * Created by Tong on 2021/9/22.
 */
public abstract class MessageToByteEncoder implements IHandleFlow {
    protected abstract byte[] encode(byte[] data)
            throws Exception;
    @Override
    public final Object read(Object data,String ipaddress) {
        return data;
    }
    @Override
    public byte[] write(byte[] data) throws Exception {
        return encode(data);
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/listener/ConnectStatusListener.java
New file
@@ -0,0 +1,27 @@
package com.hdl.sdk.socket.listener;
/**
 * Created by Tong on 2021/9/22.
 * 连接状态
 */
public interface ConnectStatusListener {
    /**
     * 连接中
     */
    default void onConnecting() {
    }
    /**
     * 连接成功
     */
    default void onConnected() {
    }
    /**
     * 连接失败
     */
    default void onConnectFailed() {
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/listener/SendListener.java
New file
@@ -0,0 +1,11 @@
package com.hdl.sdk.socket.listener;
/**
 * Created by Tong on 2021/9/22.
 */
public interface SendListener {
    void onSucceed();
    void onError();
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/udp/UdpSocketBoot.java
New file
@@ -0,0 +1,124 @@
package com.hdl.sdk.socket.udp;
import android.text.TextUtils;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.socket.SocketRequest;
import com.hdl.sdk.socket.client.IUdpClient;
import com.hdl.sdk.socket.listener.SendListener;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * Created by hxb on 2021/12/12.
 */
public class UdpSocketBoot {
    private final IUdpClient client;
    private final AtomicBoolean isOpenRetry = new AtomicBoolean(false);
    private final AtomicInteger resendCount = new AtomicInteger(0);
    private ExecutorService receiveThread;
    private final ConcurrentMap<String, SendListener> sendMap = new ConcurrentHashMap<>();
    public UdpSocketBoot(IUdpClient client) {
        this.client = client;
    }
    /**
     * 绑定 socket
     * @throws Exception 可能端口冲突
     */
    public void bind() throws Exception {
        client.bind();
        initReceiveThread();
    }
    /**
     * 初始化接收线程
     */
    private void initReceiveThread() {
        if(null!=receiveThread){
            return;
        }
        receiveThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
        receiveThread.execute(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        client.onHandleResponse();
                    } catch (Exception e) {
                       LogUtils.i("接收线程异常:"+e.getMessage());
                    }
                }
            }
        });
    }
    /**
     * 发送数据
     * @param ipAddress 目的的IP地址
     * @param port 端口
     * @param msg 发送数据
     * @param listener 发送回调
     */
    public void sendMsg(String ipAddress,int port,byte[] msg, SendListener listener) {
        sendMsg(ipAddress,port, msg, true, listener);
    }
    /**
     * 发送数据
     * @param ipAddress 目的的IP地址
     * @param port 端口
     * @param msg 发送数据
     */
    public void sendMsg(String ipAddress,int port,byte[] msg) {
        sendMsg(ipAddress,port, msg, true, null);
    }
    /**
     * 发送数据
     * @param ipAddress 目的IP地址
     * @param port 端口
     * @param msg 发送的数据
     * @param isRefreshRetry 是否要重发
     * @param listener 发送回调
     */
    public void sendMsg(String ipAddress,int port, byte[] msg, boolean isRefreshRetry, SendListener listener) {
        if (isRefreshRetry) {
            //重置连接次数
            resendCount.set(0);
        }
        try {
            SocketRequest request = new SocketRequest(msg);
            if (listener != null && !TextUtils.isEmpty(request.getAction())) {
                sendMap.put(request.getAction(), listener);
            }
            LogUtils.i("发送目标IP和端口", ipAddress + ":" + port);
            client.sendMsg(ipAddress, port, msg);
        } catch (Exception e) {
            LogUtils.i("发送失败:" + e.getMessage());
        }
    }
    /**
     * 关闭当前socket
     */
    public synchronized void close() {
        isOpenRetry.set(false);
        sendMap.clear();
        receiveThread.shutdown();
        receiveThread=null;
        client.close();
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/socket/udp/UdpSocketOptions.java
New file
@@ -0,0 +1,26 @@
package com.hdl.sdk.socket.udp;
import com.hdl.sdk.socket.codec.IHandleMessage;
import com.hdl.sdk.socket.listener.ConnectStatusListener;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by hxb on 2021/12/12.
 */
public class UdpSocketOptions {
    //处理数据
    private IHandleMessage handleMessage;
    public IHandleMessage getHandleMessage() {
        return handleMessage;
    }
    public void setHandleMessage(IHandleMessage handleMessage) {
        this.handleMessage = handleMessage;
    }
}
HDLSDK/settings.gradle
@@ -1,6 +1,6 @@
//include ':app'
include ':hdl-socket'
//include ':hdl-socket'
include ':hdl-connect'
include ':hdl-common'
//include ':hdl-common'
include ':com.hdl.sdk'
HDLSDK_DEMO.rar
Binary files differ
HDLSDK_DEMO/app/build.gradle
@@ -40,5 +40,5 @@
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
    implementation 'com.google.code.gson:gson:2.8.8'
//    implementation project(path: ':hdl-connect')
    implementation files('libs\\com.hdl.sdk-v1.0.17.aar')
    implementation files('libs\\com.hdl.sdk-v1.0.20.aar')
}
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.0.17.aar
Binary files differ
HDLSDK_DEMO/app/libs/com.hdl.sdk-v1.0.20.aar
Binary files differ