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; } }