3个文件已添加
9个文件已修改
1068 ■■■■■ 已修改文件
HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/exception/HDLLinkCode.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/config/HDLLinkConfig.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLAuthSocket.java 226 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HdlSocketHelper.java 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketBoot.java 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketPool.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/IUdpClient.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/UdpClient.java 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/udp/UdpSocketBoot.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/udp/UdpSocketOptions.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
@@ -37,6 +37,7 @@
import com.hdl.sdk.connect.bean.response.GatewaySearchBean;
import com.hdl.sdk.connect.callback.HDLLinkCallBack;
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;
import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
@@ -228,7 +229,6 @@
                }.getType());
                searchBean = response.getObjects();
            }
        }
        return searchBean;
    }
@@ -247,9 +247,16 @@
        tv.setText("开始入网认证...");
        //认证提交参数准备
        String spkStr = "screen.mirror";//产品spk
        String macStr = "AA000000000000AC";//设备唯一MAC地址
        String secret = "ee62124c151b737c";//通过spk和mac提交云端认证后分配的secret
        //测试服务
        String spkStr = "ir.module";//产品spk
        String macStr = "AA000000000000BB";//设备唯一MAC地址
        String secret = "87ae414b7a853f65";//通过spk和mac提交云端认证后分配的secret
        //正式服务器
//        String spkStr = "screen.mirror";//产品spk
//        String macStr = "AA000000000000AC";//设备唯一MAC地址
//        String secret = "ee62124c151b737c";//通过spk和mac提交云端认证后分配的secret
        String mac_key = stringToMD5(stringToMD5(macStr + secret));
        String versionString = "HDL_V1.0.1";//
        String time = String.valueOf(System.currentTimeMillis());
@@ -490,21 +497,39 @@
     * TCP发送 只发一次,不监听回复,不重发
     */
    private void tcpSend() {
        String time = String.valueOf(System.currentTimeMillis());
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("id", IdUtils.getUUId());
        jsonObject.addProperty("time_stamp", time);
        HDLLink.getInstance().tcpSendMsg(TopicConstant.GATEWAY_SEARCH, jsonObject.toString());
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr);
    }
    /**
     * 只发一次,不监听回复,不重发
     */
    private void udpSend() {
        String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
        String bodyStr = getPropertyDownBodyStr();
        HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr);
    }
    private String getPropertyDownBodyStr(){
        isOn = !isOn;
        List<DeviceControlRequest> requestList = new ArrayList<>();
        DeviceControlRequest request = new DeviceControlRequest();
        request.setSid(testLightSid);
        List<DeviceControlRequest.StatusBean>  statusBeanList= new ArrayList<>();
        DeviceControlRequest.StatusBean bean =  new DeviceControlRequest.StatusBean();
        bean.setKey("on_off");
        bean.setValue(isOn ? "on" : "off");
        statusBeanList.add(bean);
        request.setStatus(statusBeanList);
        requestList.add(request);
        String time = String.valueOf(System.currentTimeMillis());
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("id", IdUtils.getUUId());
        jsonObject.addProperty("time_stamp", time);
        HDLLink.getInstance().udpSendMsg(TopicConstant.GATEWAY_SEARCH, jsonObject.toString());
        final BaseLocalResponse<List<DeviceControlRequest>> data = new BaseLocalResponse<>();
        data.setId(IdUtils.getUUId());
        data.setTime_stamp(time);
        data.setObjects(requestList);
        return GsonConvert.getGson().toJson(data);
    }
}
HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/exception/HDLLinkCode.java
@@ -15,6 +15,7 @@
    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,"获取功能属性失败"),
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/config/HDLLinkConfig.java
@@ -87,6 +87,13 @@
    }
    /**
     * 重新保存
     */
    public void reSaveConfig() {
        this.saveConfig(this.localSecret, this.gatewayId, this.ipAddress);
    }
    /**
     * 检测是否已经认证过
     *
     * @return
@@ -114,6 +121,9 @@
    public String getIpAddress() {
        return ipAddress;
    }
    public void setIpAddress(String ipAddress){
        this.ipAddress = ipAddress;
    }
    public boolean isLocalEncrypt() {
        return isLocalEncrypt;
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLAuthSocket.java
@@ -1,6 +1,5 @@
package com.hdl.sdk.connect.socket;
import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.text.TextUtils;
import com.google.gson.Gson;
@@ -12,6 +11,7 @@
import com.hdl.sdk.common.exception.HDLLinkException;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.connect.HDLLink;
import com.hdl.sdk.connect.bean.response.AuthenticateResponse;
import com.hdl.sdk.connect.bean.response.NetworkAccessBroadcastResponse;
import com.hdl.sdk.connect.callback.BaseCallBack;
@@ -30,15 +30,13 @@
import com.hdl.sdk.connect.bean.LinkResponse;
import com.hdl.sdk.connect.protocol.LinkMessageDecoder;
import com.hdl.sdk.connect.protocol.LinkMessageEncoder;
import com.hdl.sdk.socket.SocketBoot;
import com.hdl.sdk.socket.SocketOptions;
import com.hdl.sdk.socket.client.UdpClient;
import com.hdl.sdk.socket.codec.MessagePipeLine;
import com.hdl.sdk.socket.listener.SendListener;
import com.hdl.sdk.socket.udp.UdpSocketBoot;
import com.hdl.sdk.socket.udp.UdpSocketOptions;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -47,7 +45,7 @@
/**
 * Created by jlchen on 11/11/21.
 *
 * @Description : HDLAuthSocket
 * @Description : HDLAuthSocket 由于前期已经命名好,不做更改,可用作Udp服务端使用
 */
public class HDLAuthSocket {
    private static final String TAG = "HDLAuth";
@@ -55,7 +53,10 @@
     * udp默认端口
     */
    private static final int UDP_PORT = 8585;
    private static SocketBoot updBoot;
    /**
     * 因为考虑到使用一个端口,要支持接收多网关的数据,所以只允许使用一个
     */
    private static UdpSocketBoot udpSocketBoot;
    //    private EventListener authEvent;
    //搜索网关
    private EventListener searchGatewayEvent;
@@ -70,6 +71,7 @@
    private volatile static HDLAuthSocket instance;
    private HDLAuthSocket() {
        initListenerGatewayEvent();
        initSearchGatewayEvent();
    }
@@ -93,26 +95,32 @@
        return instance;
    }
    private SocketOptions getUdpOptions() {
        final SocketOptions options = new SocketOptions();
    private UdpSocketOptions getUdpOptions() {
        final UdpSocketOptions options = new UdpSocketOptions();
        final MessagePipeLine pipeLine = new MessagePipeLine();
        pipeLine.add(new LinkMessageDecoder());
        pipeLine.add(new LinkMessageEncoder());
        options.setHandleMessage(pipeLine);
        options.setHeartbeatTimeInterval(10*1000L);
        options.setHeartbeatData("UDP");
        options.setEnabledHeartbeat(true);//是否开启心跳包发送检测
        return options;
    }
    private SocketBoot getUdpBoot(String ip) {
        if (updBoot == null) {
            updBoot = UdpClient.init(ip, UDP_PORT, getUdpOptions());
            updBoot.connect();
        }else{
            updBoot.getClient().getOptions().setIp(ip);
    /**
     * 获取当前udp对象,如果不存在就创建
     *
     * @return 返回当前对象
     */
    private UdpSocketBoot getUdpBoot() {
        try {
            if (udpSocketBoot == null) {
                udpSocketBoot = UdpClient.init(UDP_PORT, getUdpOptions());
                udpSocketBoot.bind();
            }
        } catch (Exception e) {
            return null;
        }
        return updBoot;
        return udpSocketBoot;
    }
    /**
@@ -124,7 +132,7 @@
    public void startAuthenticateRequest(AuthenticateRequest request, HDLLinkCallBack callBack) {
        HDLLinkConfig.getInstance().clearConfig();
        //1.启动Socket 开启监听
        getUdpBoot(IpUtils.getBroadcastAddress());
        getUdpBoot();
        //2.构建监听Listener
//        authEvent =
        //3.监听网关广播的入网指令
@@ -170,30 +178,39 @@
        String requestStr = gs.toJson(request);
        LinkRequest message = new LinkRequest(topic, requestStr);
        HdlSocketHelper.send(getUdpBoot(ip), message, new HdlSocketHelper.HdlSocketListener() {
        HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, new HdlSocketHelper.HdlSocketListener() {
            @Override
            public void onSucceed(Object msg) {
                if (callBack == null) return;
                try {
                    AuthenticateResponse bean = getAuthenticateResponseBean(msg);
                    if (bean != null) {
                        String localSecret = "";
                        String gatewayId = "";
                        String ipAddress = "";
                        if(bean.getAuth() != null) {
                            localSecret = bean.getAuth().getLocalSecret();
                        }
                        if(bean.getObjects() != null){
                             gatewayId = bean.getObjects().getGatewayID();
                             ipAddress = bean.getObjects().getIPAddress();
                        }
                        //判断网关是否已经注册到云端
                        if (TextUtils.isEmpty(localSecret) || TextUtils.isEmpty(gatewayId)) {
                            //认证失败,网关未注册到云端
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_ERROR_GATEWAY_NOT_REGISTERED));
                        } else {
                            HDLLinkConfig.getInstance().saveConfig(localSecret, gatewayId, ipAddress);
                            callBack.onSuccess("认证成功");
                        if (bean.getCode().equals("200")) {
                            String localSecret = "";
                            String gatewayId = "";
                            String ipAddress = "";
                            if (bean.getAuth() != null) {
                                localSecret = bean.getAuth().getLocalSecret();
                            }
                            if (bean.getObjects() != null) {
                                gatewayId = bean.getObjects().getGatewayID();
                                ipAddress = bean.getObjects().getIPAddress();
                            }
                            //判断网关是否已经注册到云端
                            if (TextUtils.isEmpty(localSecret) || TextUtils.isEmpty(gatewayId)) {
                                //认证失败,网关未注册到云端
                                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_ERROR_GATEWAY_NOT_REGISTERED));
                            } else {
                                HDLLinkConfig.getInstance().saveConfig(localSecret, gatewayId, ipAddress);
                                callBack.onSuccess("认证成功");
                            }
                        } else if (bean.getCode().equals("14013")){
                            //认证失败,该MAC对应的设备密钥不存在
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_MAC_KEY_ERROR_));
                        } else{
                            //认证失败,错误码:
                            LogUtils.e("认证失败,错误码:" + bean.getCode());
                            callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_AUTH_ERROR));
                        }
                    } else {
                        callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_ERROR));
@@ -286,7 +303,7 @@
     * @param callBack 回调
     */
    public void searchGatewayMulticast(SearchGatewayCallBack callBack) {
        searchGateway(HDLLinkConfig.getInstance().getGatewayId(), UDP_GROUP_IP, callBack);
        searchGateway(HDLLinkConfig.getInstance().getGatewayId(), UDP_GROUP_IP, UDP_PORT, callBack);
    }
    /**
@@ -295,8 +312,14 @@
     * @param callBack 回调
     */
    public void searchGatewayBroadcast(SearchGatewayCallBack callBack) {
        if (!HDLLinkConfig.getInstance().checkIfCertified()) {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UNAUTHORIZED_ERROR));
            }
            return;
        }
        String ip = IpUtils.getBroadcastAddress();
        searchGateway(HDLLinkConfig.getInstance().getGatewayId(), ip, callBack);
        searchGateway(HDLLinkConfig.getInstance().getGatewayId(), ip, UDP_PORT, callBack);
    }
@@ -314,7 +337,7 @@
                GsonConvert.getGson().toJson(data));
        String ip = IpUtils.getBroadcastAddress();
        HdlSocketHelper.send(getUdpBoot(ip), message, new HdlSocketHelper.HdlSocketListener() {
        HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, new HdlSocketHelper.HdlSocketListener() {
            @Override
            public void onSucceed(Object msg) {
                if (callBack == null) return;
@@ -345,9 +368,17 @@
            }
            return;
        }
        if (!HDLLinkConfig.getInstance().checkIfCertified()) {
            if (callBack != null) {
                callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UNAUTHORIZED_ERROR));
            }
            return;
        }
        LinkRequest message = new LinkRequest(topic, bodyStr);
        String ip = IpUtils.getBroadcastAddress();
        HdlSocketHelper.send(getUdpBoot(ip), message, new HdlSocketHelper.HdlSocketListener() {
        String ip = HDLLinkConfig.getInstance().getIpAddress();
        HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, new HdlSocketHelper.HdlSocketListener() {
                    @Override
                    public void onSucceed(Object msg) {
                        if (callBack == null) return;
@@ -374,9 +405,13 @@
            LogUtils.e("udpSendMsg", "参数不能为空");
            return;
        }
        if (!HDLLinkConfig.getInstance().checkIfCertified()) {
            LogUtils.e("udpSendMsg", "未认证,请先认证");
            return;
        }
        LinkRequest message = new LinkRequest(topic, bodyStr);
        String ip = IpUtils.getBroadcastAddress();
        getUdpBoot(ip).sendMsg(message.getSendBytes());
        String ip = HDLLinkConfig.getInstance().getIpAddress();// IpUtils.getBroadcastAddress();
        HdlSocketHelper.sendUdpOne(getUdpBoot(), ip, UDP_PORT, message);
    }
    private GatewaySearchBean getGatewaySearchBean(Object msg) {
@@ -435,7 +470,7 @@
    private SearchGatewayCallBack mSearchGatewayCallBack;
    private void initSearchGatewayEvent() {
        LogUtils.i("搜索网关--", "initSearchGatewayEvent");
        LogUtils.i("搜索网关", "initSearchGatewayEvent");
        searchGatewayEvent = new EventListener() {
            @Override
            public void onMessage(Object msg) {
@@ -443,7 +478,6 @@
                    if (msg instanceof LinkResponse) {
                        LinkResponse linkResponse = (LinkResponse) msg;
                        String data = linkResponse.getData();
                        LogUtils.i("搜索到网关->" + data);
                        if (!TextUtils.isEmpty(data)) {
                            final BaseLocalResponse<GatewaySearchBean> response = GsonConvert.getGson().fromJson(data, new TypeToken<BaseLocalResponse<GatewaySearchBean>>() {
                            }.getType());
@@ -469,14 +503,49 @@
        };
    }
    private void initListenerGatewayEvent() {
        LogUtils.i("初始化永久监听网关广播事件,不用移除此事件");
        EventListener gatewayEvent = new EventListener() {
            @Override
            public void onMessage(Object msg) {
                try {
                    if (msg instanceof LinkResponse) {
                        LinkResponse linkResponse = (LinkResponse) msg;
                        String data = linkResponse.getData();
                        LogUtils.i("接收到网关信息:" + data);
                        if (!TextUtils.isEmpty(data)) {
                            final BaseLocalResponse<GatewaySearchBean> response = GsonConvert.getGson().fromJson(data, new TypeToken<BaseLocalResponse<GatewaySearchBean>>() {
                            }.getType());
                            GatewaySearchBean gateway = response.getObjects();
                            if (gateway != null && !TextUtils.isEmpty(gateway.getGatewayId())) {
                                //主网关并且是当前绑定的网关
                                if ("true".equals(gateway.getMaster().toLowerCase()) && gateway.getGatewayId().equals(HDLLinkConfig.getInstance().getGatewayId())) {
                                    HDLLinkConfig.getInstance().setCurrentGateway(gateway);//设置当前网关
                                    HDLLinkConfig.getInstance().setLocalEncrypt(gateway.isLocalEncrypt());//设置是否加密
                                    HDLLinkConfig.getInstance().setIpAddress(gateway.getIp_address());
                                    //更新当前网关的信息
                                    HDLLinkConfig.getInstance().reSaveConfig();
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                }
            }
        };
        EventDispatcher.getInstance().registerIo(TopicConstant.GATEWAY_SEARCH_REPLY, gatewayEvent);
    }
    /**
     * 搜索指定网关是否在线,搜索到则返回指定的网关对象
     *
     * @param gatewayId 网关id
     * @param ip        接收目标的ip地址
     * @param ipAddress 目标的IP地址
     * @param port      目标的端口
     * @param callBack  回调
     */
    public void searchGateway(String gatewayId, String ip, SearchGatewayCallBack callBack) {
    public void searchGateway(String gatewayId, String ipAddress, int port, SearchGatewayCallBack callBack) {
        this.searchGatewayId = gatewayId;
        this.mSearchGatewayCallBack = callBack;
        //重置参数
@@ -497,8 +566,8 @@
                    try {
                        //搜索网关
                        searchGatewayCount.set(searchGatewayCount.get() + 1);
                        LogUtils.i("搜索网关--", "搜索网关第" + searchGatewayCount.get() + "次");
                        getUdpBoot(ip).sendMsg(message.getSendBytes());
                        LogUtils.i("搜索网关", "搜索网关第" + searchGatewayCount.get() + "次");
                        getUdpBoot().sendMsg(ipAddress, port, message.getSendBytes());
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
@@ -508,18 +577,18 @@
                if (!isSearchGatewaySuccess.get()) {
                    //搜索10次,指定网关都没回复,回调超时
                    callBackSearchGatewayTimeout();
                    LogUtils.e("搜索网关--", "搜索10次,指定网关都没回复,回调超时");
                    LogUtils.e("搜索网关", "搜索10次,指定网关都没回复,回调超时");
                }
            }
        }).start();
    }
    /**
     * 注册搜索网关监听
     */
    private void registerSearchGatewayEvent() {
        LogUtils.i("搜索网关--", "注册搜索网关监听");
        LogUtils.i("搜索网关", "注册搜索网关监听");
        EventDispatcher.getInstance().registerIo(TopicConstant.GATEWAY_SEARCH_REPLY, searchGatewayEvent);
    }
@@ -527,7 +596,7 @@
     * 移除搜索网关监听
     */
    private void removeSearchGatewayEvent() {
        LogUtils.i("搜索网关--", "移除搜索网关监听");
        LogUtils.i("搜索网关", "移除搜索网关监听");
        EventDispatcher.getInstance().remove(TopicConstant.GATEWAY_SEARCH_REPLY, searchGatewayEvent);
    }
@@ -546,4 +615,49 @@
        });
    }
    /**
     * 搜索在线所有的网关,包括当前住宅的及没有绑定过其它住宅的网关
     *
     * @param ipAddress 目标的IP地址
     * @param port      目标的端口
     * @param callBack  回调
     */
    public void searchGateway(String ipAddress, int port, SearchGatewayCallBack callBack) {
//        this.searchGatewayId = gatewayId;
//        this.mSearchGatewayCallBack = callBack;
//        //重置参数
//        searchGatewayCount.set(0);
//        isSearchGatewaySuccess.set(false);
        String time = String.valueOf(System.currentTimeMillis());
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("id", IdUtils.getUUId());
        jsonObject.addProperty("time_stamp", time);
        LinkRequest message = new LinkRequest(TopicConstant.GATEWAY_SEARCH,
                jsonObject.toString());
        //注册搜索网关监听
        registerSearchGatewayEvent();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (searchGatewayCount.get() < 10 && (!isSearchGatewaySuccess.get())) {
                    try {
                        //搜索网关
                        searchGatewayCount.set(searchGatewayCount.get() + 1);
                        LogUtils.i("搜索网关", "搜索网关第" + searchGatewayCount.get() + "次");
                        getUdpBoot().sendMsg(ipAddress, port, message.getSendBytes());
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (!isSearchGatewaySuccess.get()) {
                    //搜索10次,指定网关都没回复,回调超时
                    callBackSearchGatewayTimeout();
                    LogUtils.e("搜索网关", "搜索10次,指定网关都没回复,回调超时");
                }
            }
        }).start();
    }
}
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java
@@ -50,40 +50,14 @@
 */
public class HDLSocket {
//    public interface CallBack extends BaseCallBack {
//        void onResponse(String data);
//    }
//
//    /**
//     * udp默认组播ip
//     */
//    private static final String UDP_GROUP_IP = "239.0.168.188";
    /**
     * udp默认端口
     */
    private static final int UDP_PORT = 8585;
    /**
     * tcp默认端口
     */
    private static final int TCP_PORT = 8586;
    //    private String tcpIp;
//    private int tcpPort;
//    private int udpPort;
//    private String udpIp;
//    private static SocketBoot updBoot;
    private SocketBoot tcpBoot;
    private ConnectStatusListener statusListener;
//    private EventListener searchEvent;
//    private CallBack searchCallBack;
//    private ScheduledExecutorService searchGatewayThread;
//    private final AtomicInteger searchCount = new AtomicInteger(0);
    private HDLSocket() {
        statusListener = new ConnectStatusListener() {
@@ -102,43 +76,6 @@
            }
        };
//        searchEvent = new EventListener() {
//            @Override
//            public void onMessage(Object msg) {
//                try {
//                    if (msg instanceof LinkResponse) {
//                        LinkResponse linkResponse = (LinkResponse) msg;
//                        String data = linkResponse.getData();
//                        if (!TextUtils.isEmpty(data)) {
//                            final BaseLocalResponse<GatewaySearchBean> response = GsonConvert.getGson().fromJson(data, new TypeToken<BaseLocalResponse<GatewaySearchBean>>() {
//                            }.getType());
//                            GatewaySearchBean searchBean = response.getObjects();
//                            if (searchBean != null) {
////                                gatewayId = searchBean.getGatewayId();
////                                if (!TextUtils.isEmpty(gatewayId)) {
////                                    SPUtils.put(GATEWAY_KEY, gatewayId);
////                                }
////                                tcpIp = searchBean.getIp_address();
////                                if (!TextUtils.isEmpty(tcpIp)) {
////                                    SPUtils.put(TCP_IP_KEY, tcpIp);
////                                }
//                            }
//
//                            if (searchCallBack != null) {
//                                searchCallBack.onResponse(linkResponse.toString());
//                            }
//                        }
//
//                    }
//                } catch (Exception e) {
//                    if (searchCallBack != null) {
//                        searchCallBack.onError("解析失败");
//                    }
//                }
//
//
//            }
//        };
    }
    private static class SingletonInstance {
@@ -149,16 +86,6 @@
        return SingletonInstance.INSTANCE;
    }
//    private SocketOptions getUdpOptions() {
//        final SocketOptions options = new SocketOptions();
//        final MessagePipeLine pipeLine = new MessagePipeLine();
//        pipeLine.add(new LinkMessageDecoder());
//        pipeLine.add(new LinkMessageEncoder());
//        options.setHandleMessage(pipeLine);
//        options.setEnabledHeartbeat(false);
//        return options;
//    }
    private SocketOptions getTcpOptions() {
        final SocketOptions options = new SocketOptions();
@@ -173,9 +100,6 @@
        return options;
    }
    private int getUdpPort() {
        return UDP_PORT;
    }
    public int getTcpPort() {
        return TCP_PORT;
@@ -188,90 +112,6 @@
    public String getGatewayId() {
        return HDLLinkConfig.getInstance().getGatewayId();
    }
//    private String getUdpIp() {
//        if (TextUtils.isEmpty(udpIp)) {
//            udpIp = UDP_GROUP_IP;
//        }
//        return udpIp;
//    }
//    public void searchGateway() {
//        searchGateway(null);
//    }
//
//    /**
//     * 组播搜索
//     */
//    public void searchGateway(CallBack callBack) {
////        gatewayId = "";//重置网关ID
////        this.searchCallBack = callBack;
////
////        if (searchGatewayThread != null) {
////            searchGatewayThread.shutdownNow();
////        }
////
////
////        new Thread(new Runnable() {
////            @Override
////            public void run() {
////                while (TextUtils.isEmpty(gatewayId)) {
////                    //搜索网关
////                    searchGateway(IdUtils.getUUId(), searchEvent);
////                    try {
////                        Thread.sleep(1000L);
////                    } catch (InterruptedException e) {
////                        e.printStackTrace();
////                    }
////                }
////            }
////        }).start();
//    }
//
//
//    /**
//     * 通过组播搜索网关
//     */
//    public void searchGateway(String msgId, EventListener eventListener) {
//        searchGateway(getUdpIp(), getUdpPort(), msgId, eventListener);
//    }
//
//    /**
//     * 通过广播搜索网关
//     */
//    public void searchGatewayByBroadcast(String msgId, EventListener eventListener) {
//        searchGateway(IpUtils.getBroadcastAddress(), getUdpPort(), msgId, eventListener);
//    }
//
//    /**
//     * 默认是组播搜索网关
//     */
//    public void searchGateway(String ip, int port, String msgId, EventListener eventListener) {
//
//        if (updBoot == null) {
//            updBoot = UdpClient.init(ip, port, getUdpOptions());
//            updBoot.connect();
//        }
//
//
//        String time = String.valueOf(System.currentTimeMillis());
//        JsonObject jsonObject = new JsonObject();
//        jsonObject.addProperty("id", msgId);
//        jsonObject.addProperty("time_stamp", time);
//
//        EventDispatcher.getInstance().registerIo(TopicConstant.GATEWAY_SEARCH_REPLY, eventListener);
//        LinkRequest message = new LinkRequest(TopicConstant.GATEWAY_SEARCH,
//                jsonObject.toString());
//
//        try {
//            updBoot.sendMsg(message.getSendBytes());
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
//
//    }
    /**
     * 获取设备列表
@@ -718,14 +558,14 @@
                @Override
                public void onMessage(Object msg) {
                    if (msg instanceof LinkResponse) {
                        LogUtils.e("sendMsg onSuccess");
                        LogUtils.i("sendMsg onSuccess");
                        threadPool.shutdownNow();
                        LogUtils.i("sendMsg eventListener remove");
                        EventDispatcher.getInstance().remove(eventTag, this);
                        if (callBack != null) {
                            callBack.onSuccess(msg.toString());
                        }
                        threadPool.shutdownNow();
                    }
                    LogUtils.e("sendMsg eventListener remove");
                    EventDispatcher.getInstance().remove(eventTag, this);
                }
            };
@@ -751,6 +591,7 @@
                }
            }, 1000, 500, TimeUnit.MILLISECONDS);
            EventDispatcher.getInstance().register(eventTag, eventListener);
            //先发送一次
            getTcp().sendMsg(data, new SendListener() {
                @Override
                public void onSucceed() {
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HdlSocketHelper.java
@@ -7,7 +7,9 @@
import com.hdl.sdk.common.utils.ThreadToolUtils;
import com.hdl.sdk.connect.bean.LinkRequest;
import com.hdl.sdk.socket.SocketBoot;
import com.hdl.sdk.socket.udp.UdpSocketBoot;
import java.net.InetSocketAddress;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -25,15 +27,24 @@
    private final Long sendAwaitTime;
    private final int maxRetry;
    private final SocketBoot boot;
    private SocketBoot boot;
    private UdpSocketBoot udpSocketBoot;
    /**
     * 发送的目标IP
     */
    private String ipAddress;
    /**
     * 发送的目标地址
     */
    private int port;
    private final LinkRequest linkRequest;
    private final EventListener eventListener;
    private final AtomicInteger sendNumber;
    private final AtomicBoolean isSend = new AtomicBoolean();
    private final AtomicBoolean isSend = new AtomicBoolean(false);
    private final HdlSocketListener listener;
    private HdlSocketListener listener;
    private ScheduledExecutorService sendThread;
@@ -66,12 +77,38 @@
        EventDispatcher.getInstance().register(observeTopic, eventListener);
    }
    private HdlSocketHelper(Long sendAwaitTime, int maxRetry, UdpSocketBoot udpSocketBoot,
                            String ipAddress,int port , LinkRequest linkRequest, String observeTopic, HdlSocketListener listener) {
        this.sendAwaitTime = sendAwaitTime;
        this.maxRetry = maxRetry;
        this.udpSocketBoot = udpSocketBoot;
        this.ipAddress = ipAddress;
        this.port = port;
        this.linkRequest = linkRequest;
        this.listener = listener;
        this.sendNumber = new AtomicInteger(0);
        eventListener = new EventListener() {
            @Override
            public void onMessage(Object msg) {
                isSend.set(true);
                if (listener != null) {
                    listener.onSucceed(msg);
                }
                if (sendThread != null) {
                    sendThread.shutdownNow();
                }
                EventDispatcher.getInstance().remove(eventListener);
            }
        };
        EventDispatcher.getInstance().register(observeTopic, eventListener);
    }
    public static void send(SocketBoot boot, LinkRequest linkRequest, String observeTopic, HdlSocketListener listener, Long sendAwaitTime, int maxRetry) {
        if (TextUtils.isEmpty(observeTopic)) {
            observeTopic = linkRequest.getTopic() + "_reply";
        }
        HdlSocketHelper socketHelper = new HdlSocketHelper(sendAwaitTime, maxRetry, boot, linkRequest, observeTopic, listener);
        socketHelper.resend();
        socketHelper.send();
    }
    public static void send(SocketBoot boot, LinkRequest linkRequest, String observeTopic, HdlSocketListener listener) {
@@ -87,34 +124,90 @@
        send(boot, linkRequest, "", listener, DEF_SEND_TIMEOUT, DEF_SEND_ONE);
    }
    private void resend() {
    /**
     * Udp的发送方法
     *
     * @param udpSocketBoot     Udp当前对接
     * @param ipAddress 发送的目标IP地址
     * @param port 目的端口
     * @param linkRequest       发送的数据
     * @param observeTopic      发送的主题
     * @param retry 重发数次
     * @param listener          回调
     */
    public static void sendUdp(UdpSocketBoot udpSocketBoot, String  ipAddress ,int port, LinkRequest linkRequest, String observeTopic, int retry,HdlSocketListener listener) {
        if (TextUtils.isEmpty(observeTopic)) {
            observeTopic = linkRequest.getTopic() + "_reply";
        }
        HdlSocketHelper socketHelper = new HdlSocketHelper(DEF_SEND_TIMEOUT, retry, udpSocketBoot, ipAddress,port, linkRequest, observeTopic, listener);
        socketHelper.send();
    }
    /**
     * Udp的发送方法
     *
     * @param udpSocketBoot     Udp当前对接
     * @param ipAddress 发送的目标IP地址
     * @param port 目的端口
     * @param linkRequest       发送的数据
     * @param listener          回调
     */
    public static void sendUdp(UdpSocketBoot udpSocketBoot, String  ipAddress ,int port, LinkRequest linkRequest, HdlSocketListener listener) {
        sendUdp(udpSocketBoot,ipAddress,port,linkRequest,null,DEF_MAX_RETRY,listener);
    }
    /**
     * Udp的发送方法
     *
     * @param udpSocketBoot     Udp当前对接
     * @param ipAddress 发送的目标IP地址
     * @param port 目的端口
     * @param linkRequest       发送的数据
     */
    public static void sendUdpOne(UdpSocketBoot udpSocketBoot, String  ipAddress ,int port, LinkRequest linkRequest) {
        sendUdp(udpSocketBoot, ipAddress, port, linkRequest, null, DEF_SEND_ONE, null);
    }
    private void send() {
        getSendThread().scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                if ((sendNumber.get() < maxRetry + 2) || !isSend.get()) {
                //发送次数小于重发次数
                if ((sendNumber.get() < maxRetry)) {
                    try {
                        if (sendNumber.get() < maxRetry + 1) {
                        //还没有收到回复,再发送
                        if (!isSend.get()) {
                            sendNumber.set(sendNumber.get() + 1);
                            //如是tcp
                            if (boot != null) {
                                boot.sendMsg(linkRequest.getSendBytes());
                            }
                            sendNumber.set(sendNumber.get() + 1);
                        } else {
                            notifyFailure();
                            //如果是udp
                            if (null != udpSocketBoot) {
                                udpSocketBoot.sendMsg(ipAddress,port, linkRequest.getSendBytes());
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        sendNumber.set(sendNumber.get() + 1);
                    } finally {
                        if (sendNumber.get() > maxRetry + 1 && !isSend.get()) {
                            notifyFailure();
                        }
                    }
                } else {
                    //超出重发次数并没有收到回复
                    if (!isSend.get()) {
                        notifyFailure();
                    }
                }
            }
        }, sendAwaitTime, sendAwaitTime, TimeUnit.MILLISECONDS);
        }, 0, sendAwaitTime, TimeUnit.MILLISECONDS);
        //initialdelay - 首次执行的延迟时间 0
        //delay - 一次执行终止和下一次执行开始之间的延迟
    }
    public ScheduledExecutorService getSendThread() {
    /**
     * 获取发送线程
     *
     * @return 返回获取到的线程
     */
    private ScheduledExecutorService getSendThread() {
        if (sendThread == null) {
            sendThread = ThreadToolUtils.getInstance().newScheduledThreadPool(1);
        }
@@ -122,14 +215,18 @@
    }
    /**
     * 发送失败
     */
    private void notifyFailure() {
        EventDispatcher.getInstance().remove(eventListener);
        if (sendThread != null) {
            sendThread.shutdownNow();
            sendThread = null;
        }
        if (listener != null) {
            listener.onFailure();
            listener = null;
        }
        EventDispatcher.getInstance().remove(eventListener);
    }
}
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketBoot.java
@@ -131,12 +131,10 @@
            public void run() {
                while (isRun.get()) {
                    if (client.isConnect()) {
                        LogUtils.d("=====", "==发送数据==");
                        try {
                            SocketRequest socketRequest = mMessageQueue.take();
                            final String sendStr = new String(socketRequest.getData(), 0, socketRequest.getData().length);
                            LogUtils.d("=====", "==发送数据==:"+sendStr);
                            LogUtils.i("发送数据:"+sendStr);
                            final String action = socketRequest.getAction();
                            try {
                                client.sendMsg(socketRequest.getData());
@@ -176,28 +174,30 @@
    }
    /**
     * 初始化接收线程,只需要初始化一次
     */
    public void initReceiveThread() {
        if (receiveThread == null) {
            receiveThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
        }
        receiveThread.execute(new Runnable() {
            @Override
            public void run() {
                while (isRun.get()) {
                    if (client.isConnect()) {
                        try {
                            //读取数据
                            client.onHandleResponse();
                        } catch (Exception e) {
                            e.printStackTrace();
                            LogUtils.d("====", "断开连接" + e.getMessage());
                            disconnectError();
            receiveThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (isRun.get()) {
                        if (client.isConnect()) {
                            try {
                                //读取数据
                                client.onHandleResponse();
                            } catch (Exception e) {
                                e.printStackTrace();
                                disconnectError();
                            }
                        }
                    }
                    LogUtils.i("Socket 线程退出接收数据");
                }
            }
        });
            });
        }
    }
@@ -262,7 +262,6 @@
        if (!client.isConnect()) {
            resetConnect(false);
        }
    }
    /**
@@ -282,7 +281,6 @@
                    if (!client.isConnect() && isOpenRetry.get()) {
                        resetConnect(false);
                    }
                }
            }, 3000, TimeUnit.MILLISECONDS);
        }
HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketPool.java
@@ -51,5 +51,4 @@
        mUdpClientPool.put(address.toString(), socket);
        return socket;
    }
}
HDLSDK/hdl-socket/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-socket/src/main/java/com/hdl/sdk/socket/client/UdpClient.java
@@ -1,18 +1,16 @@
package com.hdl.sdk.socket.client;
import android.util.Log;
import android.text.TextUtils;
import com.hdl.sdk.common.HDLSdk;
import com.hdl.sdk.common.utils.IpUtils;
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.SocketPool;
import com.hdl.sdk.socket.annotation.ConnectStatus;
import com.hdl.sdk.socket.udp.UdpSocketBoot;
import com.hdl.sdk.socket.udp.UdpSocketOptions;
import com.hdl.sdk.socket.codec.IHandleMessage;
import com.hdl.sdk.socket.listener.ConnectStatusListener;
import java.io.IOException;
import java.net.DatagramPacket;
@@ -20,185 +18,157 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
 * Created by Tong on 2021/9/15.
 * 组播需要android.permission.CHANGE_WIFI_MULTICAST_STATE权限
 * MulticastSocket
 * Created by hxb on 2021/12/12.
 */
public class UdpClient implements IClient {
    private static DatagramSocket mSocket;
    private DatagramPacket receivePacket;
    private final int BUFFER = 4 * 1024;
    private final byte[] receiveByte;
//    private final String ip;
    private final int port;
    private int monitorPort;
    private int sendPort;
    private SocketOptions socketOptions;
    private final AtomicBoolean isConnect = new AtomicBoolean(false);
public class UdpClient implements IUdpClient {
    /**
     * @param sendPort -1 表示随机端口
     * 当前socket
     */
    private UdpClient(String ip, int port, int monitorPort, int sendPort, SocketOptions socketOptions) {
        this.socketOptions = socketOptions;
        this.socketOptions.setIp(ip);
    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.sendPort = sendPort;
        this.monitorPort = monitorPort;
        this.receiveByte = new byte[BUFFER];
        this.socketOptions = socketOptions;
        byte[] receiveByte = new byte[BUFFER];
        receivePacket = new DatagramPacket(receiveByte, receiveByte.length);
    }
    public static SocketBoot init(String ip, int port, int monitorPort, int sendPort, SocketOptions options) {
        return new SocketBoot(new UdpClient(ip, port, monitorPort, sendPort, options));
    /**
     * 初始化参数
     * @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));
    }
    public static SocketBoot init(String ip, int port, int monitorPort, SocketOptions options) {
        return init(ip, port, monitorPort, -1, options);
    /**
     * 初始化参数
     * @param port 本地监听端口
     * @param options
     * @return
     */
    public static UdpSocketBoot init(int port, UdpSocketOptions options) {
        return init(null, port, options);
    }
    public static SocketBoot init(String ip, int port, SocketOptions options) {
        return init(ip, port, port, -1, options);
    }
    @Override
    public void connect() throws Exception {
    public void bind() throws Exception {
        try {
            mSocket = SocketPool.getInstance().getUdpSocket(new InetSocketAddress(monitorPort));
            //已经绑定过就不用再绑定
            if (null != mSocket) {
                return;
            }
            if (TextUtils.isEmpty(ipAddress)) {
                mSocket = SocketPool.getInstance().getUdpSocket(new InetSocketAddress(port));
            }
            mSocket.setBroadcast(true);
            mSocket.setReuseAddress(true);
            isConnect.set(true);
            if (receivePacket == null) {
                receivePacket = new DatagramPacket(receiveByte, BUFFER);
            }
        } catch (Exception e) {
            isConnect.set(false);
            LogUtils.e("初始化Socket 失败:" + e.getMessage());
            throw e;
        }
    }
    @Override
    public void disconnect() {
        if (mSocket != null) {
    public boolean close() {
        try {
            mSocket.close();
        } catch (Exception e) {
        }
        isConnect.set(false);
        mSocket = null;
        return true;
    }
    @Override
    public boolean isConnect() {
        return isConnect.get();
    }
    @Override
    public synchronized SocketOptions getOptions() {
        if (socketOptions == null) {
            socketOptions = new SocketOptions();
        }
        return socketOptions;
    public UdpSocketOptions getOptions() {
        return this.socketOptions;
    }
    @Override
    public void onHandleResponse() throws Exception {
        if (receivePacket == null || mSocket == null) {
        if (mSocket == null) {
            return;
        }
        try {
           mSocket.receive(receivePacket);
            mSocket.receive(receivePacket);
        } catch (IOException e) {
            e.printStackTrace();
            isConnect.set(false);
        }
        if (receivePacket.getLength() == 0) {
            return;
        }
        //排除自己发出去的
        try {
            if (IpUtils.isLocalIpAddress( receivePacket.getAddress().getHostAddress()))
            if (IpUtils.isLocalIpAddress(receivePacket.getAddress().getHostAddress()))
                return;
        } catch (Exception ignored) {
        }
        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);
        }
        final String receive = new String(receivePacket.getData(), 0, receivePacket.getLength());
        try {
            LogUtils.i("接收到Udp数据包,网络地址:" + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
        LogUtils.d("---->", receive + " from " + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
        //重置长度
        if (receivePacket != null) {
            receivePacket.setLength(BUFFER);
        }
    }
    @Override
    public void sendMsg(byte[] msg) throws Exception {
        if (msg == null) {
            msg = new byte[1];
        }
        InetAddress serverAddress = InetAddress.getByName(getOptions().getIp());
        LogUtils.e("发送目标IP地址:"+getOptions().getIp());
        final DatagramPacket sendPacket = new DatagramPacket(msg, msg.length, serverAddress, port);
        if (sendPort < 0) {
            final DatagramSocket sendSocket = new DatagramSocket();
            sendSocket.send(sendPacket);
            sendSocket.close();
        } else if (sendPort == monitorPort) {
            mSocket.send(sendPacket);
        } else {
            final DatagramSocket sendSocket = new DatagramSocket(sendPort);
            sendSocket.send(sendPacket);
            sendSocket.close();
        }
    }
    @Override
    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;
                        }
                    }
                }
            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);
            }
        });
        } 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-socket/src/main/java/com/hdl/sdk/socket/udp/UdpSocketBoot.java
New file
@@ -0,0 +1,133 @@
package com.hdl.sdk.socket.udp;
import android.text.TextUtils;
import androidx.collection.ArrayMap;
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.annotation.ConnectStatus;
import com.hdl.sdk.socket.client.IClient;
import com.hdl.sdk.socket.client.IUdpClient;
import com.hdl.sdk.socket.listener.SendListener;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
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 ArrayMap<String, SendListener> sendMap = new ArrayMap<>();
    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);
            }
            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-socket/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;
    }
}