package com.hdl.sdk.connect.socket; import android.text.TextUtils; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import com.hdl.sdk.common.config.TopicConstant; import com.hdl.sdk.common.event.EventDispatcher; import com.hdl.sdk.common.event.EventListener; import com.hdl.sdk.common.exception.HDLLinkCode; import com.hdl.sdk.common.exception.HDLLinkException; import com.hdl.sdk.common.utils.IdUtils; import com.hdl.sdk.common.utils.IpUtils; import com.hdl.sdk.common.utils.SPUtils; import com.hdl.sdk.common.utils.ThreadToolUtils; import com.hdl.sdk.common.utils.gson.GsonConvert; import com.hdl.sdk.connect.bean.response.BaseLocalResponse; import com.hdl.sdk.connect.bean.request.DeviceControlRequest; import com.hdl.sdk.connect.bean.request.FunctionAttributeRequest; import com.hdl.sdk.connect.bean.response.GatewaySearchBean; import com.hdl.sdk.connect.bean.LinkRequest; import com.hdl.sdk.connect.bean.LinkResponse; import com.hdl.sdk.connect.bean.request.PropertyReadRequest; import com.hdl.sdk.connect.bean.request.PropertyUpRequest; import com.hdl.sdk.connect.callback.BaseCallBack; import com.hdl.sdk.connect.callback.HDLLinkCallBack; import com.hdl.sdk.connect.config.HDLLinkConfig; 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.TcpClient; import com.hdl.sdk.socket.client.UdpClient; import com.hdl.sdk.socket.codec.MessagePipeLine; import com.hdl.sdk.socket.listener.ConnectStatusListener; import com.hdl.sdk.socket.listener.SendListener; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * Created by Tong on 2021/9/26. * 1、通过Udp 组播或者广播搜索网关 * 2、通过Udp 获取Tcp ip 端口统一8586 */ 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() { @Override public void onConnecting() { } @Override public void onConnected() { } @Override public void onConnectFailed() { } }; // 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 response = GsonConvert.getGson().fromJson(data, new TypeToken>() { // }.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 { private static final HDLSocket INSTANCE = new HDLSocket(); } public static HDLSocket getInstance() { 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(); final MessagePipeLine pipeLine = new MessagePipeLine(); pipeLine.add(new LinkMessageDecoder()); pipeLine.add(new LinkMessageEncoder()); options.setHandleMessage(pipeLine); options.setEnabledHeartbeat(false); return options; } private int getUdpPort() { return UDP_PORT; } public int getTcpPort() { return TCP_PORT; } public String getTcpIp() { return HDLLinkConfig.getInstance().getIpAddress(); } 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(); // } // // } /** * 获取设备列表 */ public void getDeviceList(HDLLinkCallBack callBack) { if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { String time = String.valueOf(System.currentTimeMillis()); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", IdUtils.getUUId()); jsonObject.addProperty("time_stamp", time); String topic = String.format(TopicConstant.GET_DEVICE_LIST, getGatewayId()); LinkRequest message = new LinkRequest(topic, jsonObject.toString()); String replyTopic = String.format(TopicConstant.GET_DEVICE_LIST_REPLY, getGatewayId()); try { sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_DEVICE_LIST_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_DEVICE_LIST_ERROR)); } } } else { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UNAUTHORIZED_ERROR)); } } } /** * 获取功能列表 */ public void getFunctionList(HDLLinkCallBack callBack) { if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { String time = String.valueOf(System.currentTimeMillis()); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", IdUtils.getUUId()); jsonObject.addProperty("time_stamp", time); String topic = String.format(TopicConstant.GET_FUNCTION_LIST, getGatewayId()); LinkRequest message = new LinkRequest(topic, jsonObject.toString()); String replyTopic = String.format(TopicConstant.GET_FUNCTION_LIST_REPLY, getGatewayId()); try { sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_FUNCTION_LIST_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_FUNCTION_LIST_ERROR)); } } } else { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UNAUTHORIZED_ERROR)); } } } /** * 获取功能属性 * * @param sids * @param callBack */ public void getFunctionAttribute(List sids, HDLLinkCallBack callBack) { if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { String time = String.valueOf(System.currentTimeMillis()); final BaseLocalResponse> data = new BaseLocalResponse<>(); data.setId(IdUtils.getUUId()); data.setTime_stamp(time); List list = new ArrayList<>(); for (String s : sids) { list.add(new FunctionAttributeRequest(s)); } data.setObjects(list); String topic = String.format(TopicConstant.GET_FUNCTION_ATTRIBUTE, getGatewayId()); LinkRequest message = new LinkRequest(topic, GsonConvert.getGson().toJson(data)); String replyTopic = String.format(TopicConstant.GET_FUNCTION_ATTRIBUTE_REPLY, getGatewayId()); try { sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_FUNCTION_PROPERTIES_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_FUNCTION_PROPERTIES_ERROR)); } } } else { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UNAUTHORIZED_ERROR)); } } } /** * 设备控制 */ public void propertyDown(List request, HDLLinkCallBack callBack) { if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { String time = String.valueOf(System.currentTimeMillis()); final BaseLocalResponse> data = new BaseLocalResponse<>(); data.setId(IdUtils.getUUId()); data.setTime_stamp(time); data.setObjects(request); String topic = String.format(TopicConstant.PROPERTY_DOWN, getGatewayId()); LinkRequest message = new LinkRequest(topic, GsonConvert.getGson().toJson(data)); String replyTopic = String.format(TopicConstant.PROPERTY_DOWN_REPLY, getGatewayId()); try { sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } } else { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } } // /** // * 状态上报 // */ // public void propertyUp(List request, CallBack callBack) { // if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { // String time = String.valueOf(System.currentTimeMillis()); // // final BaseLocalResponse> data = new BaseLocalResponse<>(); // data.setId(IdUtils.getUUId()); // data.setTime_stamp(time); // data.setObjects(request); // // // String topic = String.format(TopicConstant.PROPERTY_UP, getGatewayId()); // LinkRequest message = new LinkRequest(topic, // GsonConvert.getGson().toJson(request)); // // String replyTopic = String.format(TopicConstant.PROPERTY_UP_REPLY, getGatewayId()); // try { // sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { // @Override // public void onSucceed() { // // } // // @Override // public void onError() { // if (callBack != null) { // callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); // } // } // }); // } catch (Exception e) { // if (callBack != null) { // callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); // } // } // } else { // if (callBack != null) { // callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); // } // } // } /** * 读取状态 */ public void propertyRead(List sids, HDLLinkCallBack callBack) { if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { String time = String.valueOf(System.currentTimeMillis()); final BaseLocalResponse> data = new BaseLocalResponse<>(); data.setId(IdUtils.getUUId()); data.setTime_stamp(time); List list = new ArrayList<>(); for (String s : sids) { list.add(new PropertyReadRequest(s)); } data.setObjects(list); String topic = String.format(TopicConstant.PROPERTY_READ, getGatewayId()); LinkRequest message = new LinkRequest(topic, GsonConvert.getGson().toJson(data)); String replyTopic = String.format(TopicConstant.PROPERTY_READ_REPLY, getGatewayId()); try { sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } } else { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } } public SocketBoot getTcp() throws RuntimeException { if (TextUtils.isEmpty(getTcpIp())) { throw new RuntimeException("请搜索网关"); } if (tcpBoot == null) { tcpBoot = TcpClient.init(getTcpIp(), getTcpPort(), getTcpOptions()); } return tcpBoot; } /** * 获取场景列表 */ public void getSceneList(HDLLinkCallBack callBack) { if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { String time = String.valueOf(System.currentTimeMillis()); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", IdUtils.getUUId()); jsonObject.addProperty("time_stamp", time); String topic = String.format(TopicConstant.SCENE_LIST_GET, getGatewayId()); LinkRequest message = new LinkRequest(topic, jsonObject.toString()); String replyTopic = topic + "_reply"; try { sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_FUNCTION_LIST_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_FUNCTION_LIST_ERROR)); } } } else { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UNAUTHORIZED_ERROR)); } } } /** * 场景控制 * @param sids 场景sid列表 * @param callBack 回调 */ public void controlScene(List sids, HDLLinkCallBack callBack) { if (!TextUtils.isEmpty(getGatewayId()) && !TextUtils.isEmpty(getTcpIp())) { String time = String.valueOf(System.currentTimeMillis()); final BaseLocalResponse> data = new BaseLocalResponse<>(); data.setId(IdUtils.getUUId()); data.setTime_stamp(time); List list = new ArrayList<>(); for (String s : sids) { list.add(new PropertyReadRequest(s)); } data.setObjects(list); String topic = String.format(TopicConstant.SCENE_CONTROL, getGatewayId()); LinkRequest message = new LinkRequest(topic, GsonConvert.getGson().toJson(data)); String replyTopic = topic + "_reply"; try { sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } } else { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } } // /** // * 清空缓存 // */ // public void clearCache() { // SPUtils.remove(TCP_IP_KEY); // SPUtils.remove(GATEWAY_KEY); // } /** * 通用TCP发送指令 * 1秒没响应就让他重新发送,重试3次 * * @param topic 发送数据 * @param bodyStr 回复的主题 * @param callBack 回调 */ public void tcpSendMsg(String topic, String bodyStr, HDLLinkCallBack callBack) { try { LinkRequest message = new LinkRequest(topic, bodyStr); String replyTopic = topic + "_reply"; sendMsg(message.getSendBytes(), replyTopic, callBack, new SendListener() { @Override public void onSucceed() { } @Override public void onError() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } }); } catch (Exception e) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } } /** * 发送指令 * 1秒没响应就让他重新发送,重试3次 */ public void sendMsg(byte[] data, String eventTag, HDLLinkCallBack callBack, SendListener sendListener) { try { final AtomicInteger sendCount = new AtomicInteger(0); final ScheduledExecutorService threadPool = ThreadToolUtils.getInstance().newScheduledThreadPool(1); final EventListener eventListener = new EventListener() { @Override public void onMessage(Object msg) { if (msg instanceof LinkResponse) { if (callBack != null) { callBack.onSuccess(msg.toString()); } threadPool.shutdownNow(); } } }; threadPool.scheduleWithFixedDelay(new Runnable() { @Override public void run() { if (sendCount.get() < 3) { sendCount.set(sendCount.get() + 1); getTcp().sendMsg(data); } else { threadPool.shutdownNow(); EventDispatcher.getInstance().remove(eventTag, eventListener); ThreadToolUtils.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } }); } } }, 1000, 500, TimeUnit.MILLISECONDS); EventDispatcher.getInstance().register(eventTag, eventListener); getTcp().sendMsg(data, new SendListener() { @Override public void onSucceed() { if (sendListener != null) { sendListener.onSucceed(); } } @Override public void onError() { if (sendListener != null) { sendListener.onError(); } } }); } catch (Exception e) { e.printStackTrace(); ThreadToolUtils.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEND_ERROR)); } } }); } } }