package com.hdl.sdk.connect.socket; import android.text.TextUtils; import com.google.gson.JsonObject; 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.LogUtils; import com.hdl.sdk.common.utils.ThreadToolUtils; import com.hdl.sdk.common.utils.gson.GsonConvert; import com.hdl.sdk.connect.bean.request.BroadcastRequest; import com.hdl.sdk.connect.bean.response.BaseLocalResponse; import com.hdl.sdk.connect.bean.request.DeviceControlRequest; import com.hdl.sdk.connect.bean.request.FunctionAttributeRequest; import com.hdl.sdk.connect.bean.LinkRequest; import com.hdl.sdk.connect.bean.LinkResponse; import com.hdl.sdk.connect.bean.request.PropertyReadRequest; import com.hdl.sdk.connect.callback.HDLLinkCallBack; import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack; 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.codec.MessagePipeLine; import com.hdl.sdk.socket.listener.ConnectStatusListener; import com.hdl.sdk.socket.listener.SendListener; 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 { /** * tcp默认端口 */ private static final int TCP_PORT = 8586; private SocketBoot tcpBoot; private ConnectStatusListener statusListener; private HDLSocket() { statusListener = new ConnectStatusListener() { @Override public void onConnecting() { broadcastRequest(); } @Override public void onConnected() { } @Override public void onConnectFailed() { } }; } /** * 广播自身信息给主网关 */ private void broadcastRequest() { String time = String.valueOf(System.currentTimeMillis()); if (null == HDLLinkConfig.getInstance().getDeviceInfoBean()) { LogUtils.i("DeviceInfoBean为空,请设置当前对象"); return; } BroadcastRequest request = new BroadcastRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), "200"); HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request),true); HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true, new HDLLinkResponseCallBack() { @Override public void onSuccess(LinkResponse msg) { LogUtils.i("广播信息给主网关成功!"); } @Override public void onError(HDLLinkException e) { } }); HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request),true); } private static class SingletonInstance { private static final HDLSocket INSTANCE = new HDLSocket(); } public static HDLSocket getInstance() { return SingletonInstance.INSTANCE; } SocketOptions options; private SocketOptions getTcpOptions() { if(null!=options){ return options; } options = new SocketOptions(); final MessagePipeLine pipeLine = new MessagePipeLine(); pipeLine.add(new LinkMessageDecoder()); pipeLine.add(new LinkMessageEncoder()); options.setHandleMessage(pipeLine); options.addConnectStatusListener(statusListener); return options; } public int getTcpPort() { return TCP_PORT; } public String getTcpIp() { return HDLLinkConfig.getInstance().getIpAddress(); } public String getGatewayId() { return HDLLinkConfig.getInstance().getGatewayId(); } /** * 获取设备列表 */ 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("请搜索网关"); } //如果没有初始化,或者网关IP更改了,就重新初始化 if (tcpBoot == null||!getTcpOptions().getIp().equals(getTcpIp())) { 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)); } } } /** * 通用TCP发送指令 只发一次,不监听回复,不重发 * * @param topic 发送数据 * @param bodyStr 回复的主题 */ public void tcpSendMsg(String topic, String bodyStr) { try { if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) { LogUtils.e("udpSendMsg", "参数不能为空"); return; } LinkRequest message = new LinkRequest(topic, bodyStr); getTcp().sendMsg(message.getSendBytes()); } catch (Exception e) { LogUtils.e("tcpSendMsg", "发送失败 :"+e.getMessage()); } } /** * 发送指令 * 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) { LogUtils.i("sendMsg onSuccess"); threadPool.shutdownNow(); LogUtils.i("sendMsg eventListener remove"); EventDispatcher.getInstance().remove(eventTag, this); if (callBack != null) { callBack.onSuccess(msg.toString()); } } } }; threadPool.scheduleWithFixedDelay(new Runnable() { @Override public void run() { if (sendCount.get() < 3) { sendCount.set(sendCount.get() + 1); getTcp().sendMsg(data); } else { threadPool.shutdownNow(); LogUtils.e("sendMsg eventListener remove"); 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)); } } }); } } }