| | |
| | | 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; |
| | |
| | | beans.add(new DemoBean("设备功能列表")); |
| | | beans.add(new DemoBean("UDP发送")); |
| | | beans.add(new DemoBean("TCP发送")); |
| | | beans.add(new DemoBean("UDP发送,监听主题回复,带重发带回调")); |
| | | beans.add(new DemoBean("TCP发送,监听主题回复,带重发带回调")); |
| | | demoAdapter = new DemoAdapter(beans); |
| | | rv.setAdapter(demoAdapter); |
| | | |
| | |
| | | searchGatewayBroadcast(); |
| | | break; |
| | | case 2: |
| | | //获取功能列表 |
| | | //获取功能列表 |
| | | getFunctionList(); |
| | | break; |
| | | case 3: |
| | | //功能属性读取 |
| | | getFunctionAttribute(); |
| | | getFunctionAttribute(); |
| | | break; |
| | | case 4: |
| | | //设备控制 |
| | |
| | | //TCP发送 |
| | | tcpSend(); |
| | | break; |
| | | case 11: |
| | | //UDP发送,监听主题回复,带重发带回调 |
| | | udpSendWithCallback(); |
| | | break; |
| | | case 12: |
| | | //TCP发送,监听主题回复,带重发带回调 |
| | | tcpSendWithCallback(); |
| | | break; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | |
| | | public void showToast(String text) { |
| | |
| | | /** |
| | | * 检测是否认证过 |
| | | */ |
| | | void checkIfCertified(){ |
| | | void checkIfCertified() { |
| | | boolean isCertified = HDLLink.getInstance().checkIfCertified(); |
| | | String mes = isCertified?"已经认证过":"未认证"; |
| | | String mes = isCertified ? "已经认证过" : "未认证"; |
| | | showToast(mes); |
| | | tv.setText(mes); |
| | | } |
| | |
| | | /** |
| | | * 注册所有主题数据的监听 |
| | | */ |
| | | void registerAllTopicsListener(){ |
| | | void registerAllTopicsListener() { |
| | | allTopicsListener = new EventListener() { |
| | | @Override |
| | | public void onMessage(Object msg) { |
| | | LinkResponse response = (LinkResponse)msg; |
| | | LinkResponse response = (LinkResponse) msg; |
| | | } |
| | | }; |
| | | HDLLink.getInstance().registerAllTopicsListener(allTopicsListener); |
| | |
| | | |
| | | /** |
| | | * 处理收到的主题 |
| | | * |
| | | * @param response |
| | | */ |
| | | private void handleLinkResponse(LinkResponse response){ |
| | | private void handleLinkResponse(LinkResponse response) { |
| | | //网关搜索回复 |
| | | if(response.getTopic().contains("/user/all/custom/gateway/search_reply")){ |
| | | if (response.getTopic().contains("/user/all/custom/gateway/search_reply")) { |
| | | String data = response.getData(); |
| | | if (!TextUtils.isEmpty(data)) { |
| | | Log.i("handleLinkResponse", "data:"+data); |
| | | Log.i("handleLinkResponse", "data:" + data); |
| | | final BaseLocalResponse<GatewaySearchBean> bean = GsonConvert.getGson().fromJson(data, new TypeToken<BaseLocalResponse<GatewaySearchBean>>() { |
| | | }.getType()); |
| | | GatewaySearchBean searchBean = bean.getObjects(); |
| | | Log.i("handleLinkResponse", "GatewaySearchBean: "+searchBean.getGatewayId()); |
| | | Log.i("handleLinkResponse", "GatewaySearchBean: " + searchBean.getGatewayId()); |
| | | } |
| | | }else{ |
| | | } else { |
| | | //其它主题 |
| | | |
| | | } |
| | |
| | | }.getType()); |
| | | searchBean = response.getObjects(); |
| | | } |
| | | |
| | | } |
| | | return searchBean; |
| | | } |
| | |
| | | /** |
| | | * 移除所有主题数据的监听 |
| | | */ |
| | | void removeAllTopicsListener(){ |
| | | void removeAllTopicsListener() { |
| | | HDLLink.getInstance().removeAllTopicsListener(allTopicsListener); |
| | | } |
| | | |
| | | /** |
| | | * 入网认证 |
| | | */ |
| | | void sendAuthenticateRequest(){ |
| | | void sendAuthenticateRequest() { |
| | | 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()); |
| | |
| | | * 如果已经认证后,搜索指定网关是否在线 |
| | | * 广播搜索认证过的网关是否在线 |
| | | */ |
| | | void searchGatewayBroadcast(){ |
| | | void searchGatewayBroadcast() { |
| | | tv.setText("搜索网关中..."); |
| | | HDLLink.getInstance().searchGatewayBroadcast(new HDLAuthSocket.SearchGatewayCallBack() { |
| | | @Override |
| | |
| | | tv.setText("网关不在线"); |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | |
| | | @Override |
| | | public void onSuccess(GatewaySearchBean gatewaySearchBean) { |
| | | tv.setText("网关在线"); |
| | | responseTv.setText("搜索成功 网关id:"+gatewaySearchBean.getGatewayId()); |
| | | responseTv.setText("搜索成功 网关id:" + gatewaySearchBean.getGatewayId()); |
| | | // LogUtils.i("TAG", "onSuccess: 搜索成功:"+gatewaySearchBean.getGatewayId()); |
| | | } |
| | | }); |
| | |
| | | /** |
| | | * 获取功能列表 |
| | | */ |
| | | void getFunctionList(){ |
| | | void getFunctionList() { |
| | | tv.setText("获取功能列表中..."); |
| | | responseTv.setText(""); |
| | | HDLLink.getInstance().getFunctionList(new HDLLinkCallBack() { |
| | |
| | | * 功能属性读取 |
| | | * 支持批量读取 |
| | | */ |
| | | void getFunctionAttribute(){ |
| | | void getFunctionAttribute() { |
| | | tv.setText("功能属性读取"); |
| | | List<String> sids = new ArrayList<>(); |
| | | sids.add(testLightSid); |
| | |
| | | * 读取设备状态 |
| | | * 支持批量读取 |
| | | */ |
| | | void propertyRead(){ |
| | | void propertyRead() { |
| | | tv.setText("读取状态中..."); |
| | | List<String> list = new ArrayList<>(); |
| | | list.add(testLightSid);//要读取设备的sid |
| | |
| | | tv.setText("读取成功"); |
| | | responseTv.setText(data); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLLinkException e) { |
| | | tv.setText("读取失败"); |
| | |
| | | * 控制失败 |
| | | * 回复响应code为200 代表执行成功 |
| | | */ |
| | | void controlDecide(){ |
| | | void controlDecide() { |
| | | tv.setText("控制设备"); |
| | | 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(); |
| | | List<DeviceControlRequest.StatusBean> statusBeanList = new ArrayList<>(); |
| | | DeviceControlRequest.StatusBean bean = new DeviceControlRequest.StatusBean(); |
| | | bean.setKey("on_off"); |
| | | bean.setValue(isOn ? "on" : "off"); |
| | | statusBeanList.add(bean); |
| | |
| | | /** |
| | | * 获取场景列表 |
| | | */ |
| | | void getSceneList(){ |
| | | void getSceneList() { |
| | | tv.setText("读取场景列表"); |
| | | HDLLink.getInstance().getSceneList(new HDLLinkCallBack() { |
| | | @Override |
| | |
| | | |
| | | //场景列表 |
| | | // {"id":"8a5eaa143ce943b987b577df5a66759b","time_stamp":"1637040217235","objects":[{"sid":"04010560D2C7170A0A0100000000","name":"回家模式","status":"off","group":"255","delay":"0","modify_time":"1634871490"},{"sid":"04010560D2C76E0A0A0100010000","name":"离家模式","status":"off","group":"255","delay":"0","modify_time":"1634785823"}]} |
| | | |
| | | /** |
| | | * 控制场景 |
| | | * 执行成功的话 响应code为200 |
| | | */ |
| | | void controlScene(){ |
| | | void controlScene() { |
| | | tv.setText("场景控制"); |
| | | //控制场景sid列表,支持批量控制 |
| | | List<String> sids = new ArrayList<>(); |
| | | isOn = !isOn; |
| | | if(isOn){ |
| | | if (isOn) { |
| | | sids.add("04010560D2C7170A0A0100000000"); |
| | | }else{ |
| | | } else { |
| | | sids.add("04010560D2C76E0A0A0100010000"); |
| | | } |
| | | HDLLink.getInstance().controlScene(sids,new HDLLinkCallBack() { |
| | | HDLLink.getInstance().controlScene(sids, new HDLLinkCallBack() { |
| | | @Override |
| | | public void onSuccess(String msg) { |
| | | responseTv.setText(msg); |
| | |
| | | } |
| | | |
| | | |
| | | void startDevicesListActivity(){ |
| | | void startDevicesListActivity() { |
| | | Intent intent = new Intent(this, DevicesListActivity.class); |
| | | startActivity(intent); |
| | | } |
| | |
| | | * 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()); |
| | | tv.setText("TCP发送 只发一次,不监听回复,不重发"); |
| | | String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId()); |
| | | String bodyStr = getPropertyDownBodyStr(); |
| | | HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr); |
| | | } |
| | | |
| | | /** |
| | | * 只发一次,不监听回复,不重发 |
| | | * UDP只发一次,不监听回复,不重发 |
| | | */ |
| | | private void udpSend() { |
| | | tv.setText("UDP发送 只发一次,不监听回复,不重发"); |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | | * UDP发送,监听主题回复,带重发带回调 |
| | | */ |
| | | private void udpSendWithCallback() { |
| | | tv.setText("UDP发送,监听主题回复,带重发带回调"); |
| | | String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId()); |
| | | String bodyStr = getPropertyDownBodyStr(); |
| | | HDLLink.getInstance().udpSendMsg(propertyDownTopic, bodyStr, new HDLLinkResponseCallBack() { |
| | | @Override |
| | | public void onSuccess(LinkResponse msg) { |
| | | Log.i("udpSendWithCallback", "udpSendWithCallback"); |
| | | responseTv.setText(GsonConvert.getGson().toJson(msg)); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLLinkException e) { |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * TCP发送,监听主题回复,带重发带回调 |
| | | */ |
| | | private void tcpSendWithCallback() { |
| | | tv.setText("TCP发送,监听主题回复,带重发带回调"); |
| | | String propertyDownTopic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId()); |
| | | String bodyStr = getPropertyDownBodyStr(); |
| | | HDLLink.getInstance().tcpSendMsg(propertyDownTopic, bodyStr, new HDLLinkCallBack() { |
| | | @Override |
| | | public void onSuccess(String msg) { |
| | | Log.i("tcpSendWithCallback", "tcpSendWithCallback"); |
| | | responseTv.setText(msg); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLLinkException e) { |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | |
| | | package com.hdl.hdlsdk.device;
|
| | |
|
| | | import android.content.Context;
|
| | | import android.util.Log;
|
| | | import android.view.LayoutInflater;
|
| | | import android.view.View;
|
| | | import android.view.ViewGroup;
|
| | |
| | | requestList.add(request);
|
| | | String time = String.valueOf(System.currentTimeMillis());
|
| | |
|
| | | final BaseLocalResponse<List<DeviceControlRequest>> data = new BaseLocalResponse<>();
|
| | | data.setId(IdUtils.getUUId());
|
| | | data.setTime_stamp(time);
|
| | | data.setObjects(requestList);
|
| | | HDLLink.getInstance().propertyDown(requestList, new HDLLinkCallBack() {
|
| | | @Override
|
| | | public void onSuccess(String data) {
|
| | | Log.i("propertyDown",data);
|
| | | }
|
| | |
|
| | | String topic = String.format(TopicConstant.PROPERTY_DOWN, HDLLinkConfig.getInstance().getGatewayId());
|
| | | @Override
|
| | | public void onError(HDLLinkException e) {
|
| | | Log.e("propertyDown", "ERROR :"+ e.getMsg());
|
| | | }
|
| | | });
|
| | |
|
| | | HDLLink.getInstance().tcpSendMsg(topic, GsonConvert.getGson().toJson(data));
|
| | | // HDLLink.getInstance().udpSendMsg(topic, GsonConvert.getGson().toJson(data));
|
| | | }
|
| | | } |
| | |
| | | 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,"获取功能属性失败"), |
| | |
| | | } |
| | | |
| | | /** |
| | | * 重新保存 |
| | | */ |
| | | public void reSaveConfig() { |
| | | this.saveConfig(this.localSecret, this.gatewayId, this.ipAddress); |
| | | } |
| | | |
| | | /** |
| | | * 检测是否已经认证过 |
| | | * |
| | | * @return |
| | |
| | | public String getIpAddress() { |
| | | return ipAddress; |
| | | } |
| | | public void setIpAddress(String ipAddress){ |
| | | this.ipAddress = ipAddress; |
| | | } |
| | | |
| | | public boolean isLocalEncrypt() { |
| | | return isLocalEncrypt; |
| | |
| | | package com.hdl.sdk.connect.socket; |
| | | |
| | | import android.net.ipsec.ike.TunnelModeChildSessionParams; |
| | | import android.text.TextUtils; |
| | | |
| | | import com.google.gson.Gson; |
| | |
| | | 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; |
| | |
| | | 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; |
| | | |
| | |
| | | /** |
| | | * Created by jlchen on 11/11/21. |
| | | * |
| | | * @Description : HDLAuthSocket |
| | | * @Description : HDLAuthSocket 由于前期已经命名好,不做更改,可用作Udp服务端使用 |
| | | */ |
| | | public class HDLAuthSocket { |
| | | private static final String TAG = "HDLAuth"; |
| | |
| | | * udp默认端口 |
| | | */ |
| | | private static final int UDP_PORT = 8585; |
| | | private static SocketBoot updBoot; |
| | | /** |
| | | * 因为考虑到使用一个端口,要支持接收多网关的数据,所以只允许使用一个 |
| | | */ |
| | | private static UdpSocketBoot udpSocketBoot; |
| | | // private EventListener authEvent; |
| | | //搜索网关 |
| | | private EventListener searchGatewayEvent; |
| | |
| | | private volatile static HDLAuthSocket instance; |
| | | |
| | | private HDLAuthSocket() { |
| | | initListenerGatewayEvent(); |
| | | initSearchGatewayEvent(); |
| | | } |
| | | |
| | |
| | | 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(); |
| | | |
| | | /** |
| | | * 获取当前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; |
| | | } |
| | | |
| | | /** |
| | |
| | | public void startAuthenticateRequest(AuthenticateRequest request, HDLLinkCallBack callBack) { |
| | | HDLLinkConfig.getInstance().clearConfig(); |
| | | //1.启动Socket 开启监听 |
| | | getUdpBoot(IpUtils.getBroadcastAddress()); |
| | | getUdpBoot(); |
| | | //2.构建监听Listener |
| | | // authEvent = |
| | | //3.监听网关广播的入网指令 |
| | |
| | | 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)); |
| | |
| | | * @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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @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); |
| | | } |
| | | |
| | | |
| | |
| | | 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; |
| | |
| | | } |
| | | 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; |
| | |
| | | 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) { |
| | |
| | | private SearchGatewayCallBack mSearchGatewayCallBack; |
| | | |
| | | private void initSearchGatewayEvent() { |
| | | LogUtils.i("搜索网关--", "initSearchGatewayEvent"); |
| | | LogUtils.i("搜索网关", "initSearchGatewayEvent"); |
| | | searchGatewayEvent = new EventListener() { |
| | | @Override |
| | | public void onMessage(Object msg) { |
| | |
| | | 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()); |
| | |
| | | }; |
| | | } |
| | | |
| | | 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; |
| | | //重置参数 |
| | |
| | | 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(); |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | * 移除搜索网关监听 |
| | | */ |
| | | private void removeSearchGatewayEvent() { |
| | | LogUtils.i("搜索网关--", "移除搜索网关监听"); |
| | | LogUtils.i("搜索网关", "移除搜索网关监听"); |
| | | EventDispatcher.getInstance().remove(TopicConstant.GATEWAY_SEARCH_REPLY, searchGatewayEvent); |
| | | } |
| | | |
| | |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 搜索在线所有的网关,包括当前住宅的及没有绑定过其它住宅的网关 |
| | | * |
| | | * @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(); |
| | | } |
| | | } |
| | |
| | | */
|
| | | 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() {
|
| | |
| | |
|
| | | }
|
| | | };
|
| | | // 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 {
|
| | |
| | | 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();
|
| | |
| | | return options;
|
| | | }
|
| | |
|
| | | private int getUdpPort() {
|
| | | return UDP_PORT;
|
| | | }
|
| | |
|
| | | public int getTcpPort() {
|
| | | return TCP_PORT;
|
| | |
| | | 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();
|
| | | // }
|
| | | //
|
| | | // }
|
| | |
|
| | |
|
| | | /**
|
| | | * 获取设备列表
|
| | |
| | | @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);
|
| | | }
|
| | | };
|
| | |
|
| | |
| | | }
|
| | | }, 1000, 500, TimeUnit.MILLISECONDS);
|
| | | EventDispatcher.getInstance().register(eventTag, eventListener);
|
| | | //先发送一次
|
| | | getTcp().sendMsg(data, new SendListener() {
|
| | | @Override
|
| | | public void onSucceed() {
|
| | |
| | |
|
| | | import com.hdl.sdk.common.event.EventDispatcher;
|
| | | import com.hdl.sdk.common.event.EventListener;
|
| | | import com.hdl.sdk.common.utils.LogUtils;
|
| | | 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;
|
| | |
| | | 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;
|
| | |
|
| | | private String observeTopic;
|
| | |
|
| | | public interface HdlSocketListener {
|
| | | void onSucceed(Object msg);
|
| | |
| | | void onFailure();
|
| | | }
|
| | |
|
| | | private HdlSocketHelper(Long sendAwaitTime, int maxRetry, SocketBoot boot, LinkRequest linkRequest, String observeTopic, HdlSocketListener listener) {
|
| | | 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.boot = boot;
|
| | | this.udpSocketBoot = udpSocketBoot;
|
| | | this.ipAddress = ipAddress;
|
| | | this.port = port;
|
| | | this.linkRequest = linkRequest;
|
| | | this.listener = listener;
|
| | | this.observeTopic = observeTopic;
|
| | | this.sendNumber = new AtomicInteger(0);
|
| | | eventListener = new EventListener() {
|
| | | @Override
|
| | |
| | | if (sendThread != null) {
|
| | | sendThread.shutdownNow();
|
| | | }
|
| | | EventDispatcher.getInstance().remove(eventListener);
|
| | | //移除监听
|
| | | removeListener();
|
| | | }
|
| | | };
|
| | | EventDispatcher.getInstance().register(observeTopic, eventListener);
|
| | | //注册监听
|
| | | registerListener();
|
| | | }
|
| | |
|
| | | public static void send(SocketBoot boot, LinkRequest linkRequest, String observeTopic, HdlSocketListener listener, Long sendAwaitTime, int maxRetry) {
|
| | |
|
| | | /**
|
| | | * 注册监听
|
| | | */
|
| | | void registerListener() {
|
| | | if (!TextUtils.isEmpty(observeTopic)) {
|
| | | EventDispatcher.getInstance().register(observeTopic, eventListener);
|
| | | // LogUtils.i("HdlSocketHelper", "register event");
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * 移除监听
|
| | | */
|
| | | void removeListener() {
|
| | | if (!TextUtils.isEmpty(observeTopic)) {
|
| | | EventDispatcher.getInstance().remove(observeTopic, eventListener);
|
| | | // LogUtils.i("HdlSocketHelper", "remove event");
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * 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(sendAwaitTime, maxRetry, boot, linkRequest, observeTopic, listener);
|
| | | socketHelper.resend();
|
| | | HdlSocketHelper socketHelper = new HdlSocketHelper(DEF_SEND_TIMEOUT, retry, udpSocketBoot, ipAddress, port, linkRequest, observeTopic, listener);
|
| | | socketHelper.send();
|
| | | }
|
| | |
|
| | | public static void send(SocketBoot boot, LinkRequest linkRequest, String observeTopic, HdlSocketListener listener) {
|
| | | send(boot, linkRequest, observeTopic, listener, DEF_SEND_TIMEOUT, DEF_MAX_RETRY);
|
| | | /**
|
| | | * 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, "", DEF_MAX_RETRY, listener);
|
| | | }
|
| | |
|
| | |
|
| | | public static void send(SocketBoot boot, LinkRequest linkRequest, HdlSocketListener listener) {
|
| | | send(boot, linkRequest, "", listener, DEF_SEND_TIMEOUT, DEF_MAX_RETRY);
|
| | | /**
|
| | | * Udp的发送方法
|
| | | *
|
| | | * @param udpSocketBoot Udp当前对接
|
| | | * @param ipAddress 发送的目标IP地址
|
| | | * @param port 目的端口
|
| | | * @param linkRequest 发送的数据
|
| | | */
|
| | | public static void sendUdpOne(UdpSocketBoot udpSocketBoot, String ipAddress, int port, LinkRequest linkRequest) {
|
| | | HdlSocketHelper socketHelper = new HdlSocketHelper(DEF_SEND_TIMEOUT, DEF_SEND_ONE, udpSocketBoot, ipAddress, port, linkRequest, null, null);
|
| | | socketHelper.send();
|
| | | }
|
| | |
|
| | | public static void sendOne(SocketBoot boot, LinkRequest linkRequest, HdlSocketListener listener) {
|
| | | send(boot, linkRequest, "", listener, DEF_SEND_TIMEOUT, DEF_SEND_ONE);
|
| | | }
|
| | |
|
| | | private void resend() {
|
| | | 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);
|
| | | }
|
| | |
| | | }
|
| | |
|
| | |
|
| | | /**
|
| | | * 发送失败
|
| | | */
|
| | | private void notifyFailure() {
|
| | | //移除监听
|
| | | removeListener();
|
| | | if (sendThread != null) {
|
| | | sendThread.shutdownNow();
|
| | | sendThread = null;
|
| | | }
|
| | | if (listener != null) {
|
| | | listener.onFailure();
|
| | | listener = null;
|
| | | }
|
| | |
|
| | | EventDispatcher.getInstance().remove(eventListener);
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | private final IClient client;
|
| | |
|
| | | public IClient getClient() {
|
| | | return client;
|
| | | }
|
| | |
|
| | | /**
|
| | | * socket是否在运行
|
| | | */
|
| | |
| | | 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());
|
| | |
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | | * 初始化接收线程,只需要初始化一次
|
| | | */
|
| | | 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 线程退出接收数据");
|
| | | }
|
| | | }
|
| | | });
|
| | |
|
| | | });
|
| | | }
|
| | | }
|
| | |
|
| | |
|
| | |
| | | @Override
|
| | | public void run() {
|
| | | if (isRun.get()) {
|
| | | LogUtils.d("====", "===发送心跳包===");
|
| | | // LogUtils.d("====", "===发送心跳包===");
|
| | | if (client.getOptions() != null) {
|
| | | final byte[] heartBeat = client.getOptions().getHeartbeatData();
|
| | | if (heartBeat != null) {
|
| | |
| | | if (!client.isConnect()) {
|
| | | resetConnect(false);
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | if (!client.isConnect() && isOpenRetry.get()) {
|
| | | resetConnect(false);
|
| | | }
|
| | |
|
| | | }
|
| | | }, 3000, TimeUnit.MILLISECONDS);
|
| | | }
|
| | |
| | | */
|
| | | public class SocketOptions {
|
| | |
|
| | | //发送目标地址IP
|
| | | private String ip;
|
| | |
|
| | | //设置读取缓存
|
| | | private int readMaxBufferSize = 512;
|
| | |
|
| | |
| | | private int soTimeout;
|
| | | private boolean soLinger;
|
| | |
|
| | | public String getIp() {
|
| | | return ip;
|
| | | }
|
| | |
|
| | | public void setIp(String ip) {
|
| | | this.ip = ip;
|
| | | }
|
| | |
|
| | | public IHandleMessage getHandleMessage() {
|
| | | return handleMessage;
|
| | |
| | | mUdpClientPool.put(address.toString(), socket);
|
| | | return socket;
|
| | | }
|
| | |
|
| | | }
|
New file |
| | |
| | | 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; |
| | | |
| | | } |
| | |
| | | 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;
|
| | |
| | | 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) {
|
| | | private DatagramSocket mSocket;
|
| | |
|
| | | /**
|
| | | * 接收数据包
|
| | | */
|
| | | private DatagramPacket receivePacket;
|
| | |
|
| | | /**
|
| | | * 缓冲区大小
|
| | | */
|
| | | private final int BUFFER = 2 * 1024;
|
| | |
|
| | | /**
|
| | | * 本地监听IP地址
|
| | | */
|
| | | private String ipAddress;
|
| | | /**
|
| | | * 本地监听端口
|
| | | */
|
| | | private int port;
|
| | |
|
| | | /**
|
| | | * socket配置信息
|
| | | */
|
| | | private UdpSocketOptions socketOptions;
|
| | |
|
| | | /**
|
| | | * 初始化参数
|
| | | * @param ipAddress 本地监听端口
|
| | | * @param port 本地监听端口
|
| | | * @param socketOptions
|
| | | */
|
| | | private UdpClient(String ipAddress,int port, UdpSocketOptions socketOptions) {
|
| | | this.ipAddress = ipAddress;
|
| | | this.port = port;
|
| | | this.socketOptions = socketOptions;
|
| | | this.ip = ip;
|
| | | this.port = port;
|
| | | this.sendPort = sendPort;
|
| | | this.monitorPort = monitorPort;
|
| | | this.receiveByte = new byte[BUFFER];
|
| | | byte[] receiveByte = new byte[BUFFER];
|
| | | receivePacket = new DatagramPacket(receiveByte, receiveByte.length);
|
| | | }
|
| | |
|
| | | public UdpClient(String ip, int port) {
|
| | | this.ip = ip;
|
| | | this.port = port;
|
| | | this.receiveByte = new byte[BUFFER];
|
| | | /**
|
| | | * 初始化参数
|
| | | * @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, int sendPort, SocketOptions options) {
|
| | | return new SocketBoot(new UdpClient(ip, port, monitorPort, sendPort, 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, int monitorPort, SocketOptions options) {
|
| | | return init(ip, port, monitorPort, -1, 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(ip);
|
| | | 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);
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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();
|
| | | }
|
| | | }
|
New file |
| | |
| | | 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;
|
| | | }
|
| | | }
|
| | |
| | | |
| | | import com.chad.library.adapter.base.BaseQuickAdapter; |
| | | import com.chad.library.adapter.base.listener.OnItemClickListener; |
| | | import com.google.gson.JsonObject; |
| | | import com.google.gson.reflect.TypeToken; |
| | | import com.hdl.hdlsdk.device.DevicesListActivity; |
| | | import com.hdl.sdk.common.config.TopicConstant; |
| | | import com.hdl.sdk.common.event.EventListener; |
| | | 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.gson.GsonConvert; |
| | | import com.hdl.sdk.connect.HDLLink; |
| | | import com.hdl.sdk.connect.bean.LinkRequest; |
| | | import com.hdl.sdk.connect.bean.LinkResponse; |
| | | import com.hdl.sdk.connect.bean.request.AuthenticateRequest; |
| | | import com.hdl.sdk.connect.bean.request.PropertyReadRequest; |
| | |
| | | beans.add(new DemoBean("获取场景列表")); |
| | | beans.add(new DemoBean("场景控制")); |
| | | beans.add(new DemoBean("设备功能列表")); |
| | | beans.add(new DemoBean("UDP发送,监听主题回复,带重发带回调")); |
| | | beans.add(new DemoBean("TCP发送,监听主题回复,带重发带回调")); |
| | | beans.add(new DemoBean("UDP发送,不回调不重发")); |
| | | beans.add(new DemoBean("TCP发送,不回调不重发")); |
| | | demoAdapter = new DemoAdapter(beans); |
| | | rv.setAdapter(demoAdapter); |
| | | |
| | | |
| | | // final SocketOptions options = new SocketOptions(); |
| | | // |
| | | MessagePipeLine pipeLine = new MessagePipeLine(); |
| | | // MessagePipeLine pipeLine = new MessagePipeLine(); |
| | | // options.setHandleMessage(pipeLine); |
| | | // options.setEnabledHeartbeat(false); |
| | | |
| | |
| | | //功能列表 |
| | | startDevicesListActivity(); |
| | | break; |
| | | case 9: |
| | | //UDP发送 |
| | | udpSendWithCallback(); |
| | | break; |
| | | case 10: |
| | | //TCP发送 |
| | | tcpSendWithCallback(); |
| | | case 11: |
| | | //UDP发送 |
| | | udpSend(); |
| | | break; |
| | | case 12: |
| | | //TCP发送 |
| | | tcpSend(); |
| | | break; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | public void showToast(String text) { |
| | | Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); |
| | | } |
| | |
| | | @Override |
| | | public void onMessage(Object msg) { |
| | | LinkResponse response = (LinkResponse)msg; |
| | | if(response != null){ |
| | | Log.i(TAG, "AllTopicsListener" |
| | | + "\nTopic: " + response.getTopic() |
| | | +"\n Data: " + response.getData()); |
| | | handleLinkResponse(response); |
| | | } |
| | | |
| | | } |
| | | }; |
| | | HDLLink.getInstance().registerAllTopicsListener(allTopicsListener); |
| | |
| | | tv.setText("开始入网认证..."); |
| | | //认证提交参数准备 |
| | | |
| | | 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()); |
| | |
| | | //1.设置认证信息 |
| | | AuthenticateRequest.RequestBean requestBean = new AuthenticateRequest.RequestBean(); |
| | | requestBean.setMAC(macStr); |
| | | requestBean.setSupplier("HDL"); |
| | | requestBean.setSupplier("raysgem"); |
| | | requestBean.setFirmwareVersion(versionString); |
| | | requestBean.setHardwareModel("1956F"); |
| | | AuthenticateRequest.AuthBean authbean = new AuthenticateRequest.AuthBean(); |
| | |
| | | infoBean.setDeviceName("红外宝");//设备名字 |
| | | infoBean.setDeviceModel("HDL");// |
| | | infoBean.setAccessMode("WIFI"); |
| | | infoBean.setIPGateway("192.168.12.1"); |
| | | infoBean.setIPGateway("192.168.88.1"); |
| | | infoBean.setIPAddress(IpUtils.getIP(this)); |
| | | |
| | | infoBean.setOID("010105000000FE08"); |
| | |
| | | Intent intent = new Intent(this, DevicesListActivity.class); |
| | | startActivity(intent); |
| | | } |
| | | |
| | | /** |
| | | * TCP发送,监听主题回复,带重发带回调 |
| | | */ |
| | | private void tcpSendWithCallback() { |
| | | 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(), new HDLLinkCallBack() { |
| | | @Override |
| | | public void onSuccess(String data) { |
| | | responseTv.setText(data); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLLinkException e) { |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * UDP发送,监听主题回复,带重发带回调 |
| | | */ |
| | | private void udpSendWithCallback() { |
| | | 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(), new HDLLinkResponseCallBack() { |
| | | @Override |
| | | public void onSuccess(LinkResponse linkResponse) { |
| | | if(linkResponse != null){ |
| | | responseTv.setText(linkResponse.getData()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onError(HDLLinkException e) { |
| | | responseTv.setText(e.getMsg()); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 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()); |
| | | } |
| | | |
| | | /** |
| | | * 只发一次,不监听回复,不重发 |
| | | */ |
| | | private void udpSend() { |
| | | 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()); |
| | | } |
| | | } |
| | |
| | | package com.hdl.hdlsdk.device;
|
| | |
|
| | | import android.content.Context;
|
| | | import android.util.Log;
|
| | | import android.view.LayoutInflater;
|
| | | import android.view.View;
|
| | | import android.view.ViewGroup;
|
| | | import android.widget.CompoundButton;
|
| | | import android.widget.Switch;
|
| | | import android.widget.TextView;
|
| | |
|
| | |
|
| | | import androidx.annotation.NonNull;
|
| | | import androidx.annotation.Nullable;
|
| | | import androidx.recyclerview.widget.RecyclerView;
|
| | |
|
| | | import com.chad.library.adapter.base.BaseMultiItemQuickAdapter;
|
| | | import com.chad.library.adapter.base.viewholder.BaseViewHolder;
|
| | | import com.hdl.hdlsdk.DemoBean;
|
| | | import com.hdl.hdlsdk.R;
|
| | | import com.hdl.sdk.common.config.TopicConstant;
|
| | | import com.hdl.sdk.common.exception.HDLLinkException;
|
| | | import com.hdl.sdk.common.utils.IdUtils;
|
| | | import com.hdl.sdk.common.utils.LogUtils;
|
| | | import com.hdl.sdk.common.utils.gson.GsonConvert;
|
| | | import com.hdl.sdk.connect.HDLLink;
|
| | | import com.hdl.sdk.connect.bean.request.DeviceControlRequest;
|
| | | import com.hdl.sdk.connect.bean.response.BaseLocalResponse;
|
| | | import com.hdl.sdk.connect.callback.HDLLinkCallBack;
|
| | | import com.hdl.sdk.connect.config.HDLLinkConfig;
|
| | |
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | public class DevicesListAdapter extends RecyclerView.Adapter<DevicesListAdapter.ViewHolder> {
|
| | |
| | | @Override
|
| | | public void onBindViewHolder(ViewHolder holder, int position) {
|
| | | holder.item_tv.setText(mList.get(position).getName());
|
| | | holder.device_on_off_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
| | | @Override
|
| | | public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
|
| | | propertyDown(mList.get(position), isChecked);
|
| | | }
|
| | | });
|
| | | }
|
| | |
|
| | | @Override
|
| | |
| | | //自定义的ViewHolder,持有每个Item的的所有界面元素
|
| | | public static class ViewHolder extends RecyclerView.ViewHolder {
|
| | | public TextView item_tv;
|
| | | public Switch device_on_off_switch;
|
| | |
|
| | | public ViewHolder(View view) {
|
| | | super(view);
|
| | | item_tv = (TextView) view.findViewById(R.id.device_title_tv);
|
| | | device_on_off_switch = view.findViewById(R.id.device_on_off_switch);
|
| | | }
|
| | | }
|
| | |
|
| | | private void propertyDown(FunctionBean functionBean, Boolean isOn){
|
| | | List<DeviceControlRequest> requestList = new ArrayList<>();
|
| | | DeviceControlRequest request = new DeviceControlRequest();
|
| | | request.setSid(functionBean.getSid());
|
| | | 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());
|
| | |
|
| | | HDLLink.getInstance().propertyDown(requestList, new HDLLinkCallBack() {
|
| | | @Override
|
| | | public void onSuccess(String data) {
|
| | | Log.i("propertyDown",data);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void onError(HDLLinkException e) {
|
| | | Log.e("propertyDown", "ERROR :"+ e.getMsg());
|
| | | }
|
| | | });
|
| | |
|
| | | }
|
| | | } |