package com.hdl.sdk.link.core.connect; import android.content.Context; import android.net.wifi.WifiManager; import android.text.TextUtils; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import com.hdl.link.error.HDLLinkCode; import com.hdl.sdk.link.HDLLinkLocalSdk; import com.hdl.sdk.link.bean.LoginRequest; import com.hdl.sdk.link.common.event.EventDispatcher; import com.hdl.sdk.link.common.event.EventListener; import com.hdl.sdk.link.common.exception.HDLLinkException; import com.hdl.sdk.link.common.utils.IpUtils; import com.hdl.sdk.link.common.utils.LogUtils; import com.hdl.sdk.link.common.utils.ThreadToolUtils; import com.hdl.sdk.link.core.bean.LinkRequest; import com.hdl.sdk.link.core.bean.LinkResponse; import com.hdl.sdk.link.core.bean.gateway.GatewayBean; import com.hdl.sdk.link.core.bean.request.AuthenticateRequest; import com.hdl.sdk.link.core.bean.response.AuthenticateResponse; import com.hdl.sdk.link.core.bean.response.BaseLocalResponse; import com.hdl.sdk.link.core.bean.response.GatewaySearchBean; import com.hdl.sdk.link.core.bean.response.NetworkAccessBroadcastResponse; import com.hdl.sdk.link.core.callback.BaseCallBack; import com.hdl.sdk.link.core.callback.HDLLinkCallBack; import com.hdl.sdk.link.core.callback.HDLLinkResponseCallBack; import com.hdl.sdk.link.common.config.TopicConstant; import com.hdl.sdk.link.common.utils.IdUtils; import com.hdl.sdk.link.common.utils.gson.GsonConvert; import com.hdl.sdk.link.core.config.HDLLinkConfig; import com.hdl.sdk.link.core.protocol.LinkMessageDecoderUdp; import com.hdl.sdk.link.gateway.HDLLinkLocalGateway; import com.hdl.sdk.link.socket.client.UdpClient; import com.hdl.sdk.link.socket.codec.MessagePipeLine; import com.hdl.sdk.link.socket.udp.UdpSocketBoot; import com.hdl.sdk.link.socket.udp.UdpSocketOptions; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import static com.hdl.sdk.link.common.config.TopicConstant.DEIVCE_AUTH_REQUEST; /** * Created by jlchen on 11/11/21. * * @Description : HDLAuthSocket 由于前期已经命名好,不做更改,可用作Udp服务端使用 */ public class HDLUdpConnect { private static final String TAG = "HDLAuth"; /** * udp默认端口 */ public static final int UDP_PORT = 8585; /** * 因为考虑到使用一个端口,要支持接收多网关的数据,所以只允许使用一个 */ private static UdpSocketBoot udpSocketBoot; // private EventListener authEvent; //搜索网关 private EventListener searchGatewayEvent; /** * udp默认组播ip */ private static final String UDP_GROUP_IP = "239.0.168.188"; private static boolean bindSuccess; public static boolean isBindSuccess() { return bindSuccess; } /** * instance */ private volatile static HDLUdpConnect instance; private HDLUdpConnect() { initListenerGatewayEvent(); initSearchGatewayEvent(); } /** * getInstance * * @return HDLAuthSocket */ public static synchronized HDLUdpConnect getInstance() { if (instance == null) { synchronized (HDLLinkConfig.class) { if (instance == null) { instance = new HDLUdpConnect(); } } } return instance; } private UdpSocketOptions getUdpOptions() { final UdpSocketOptions options = new UdpSocketOptions(); WifiManager manager = (WifiManager) HDLLinkLocalSdk.getInstance().getContext().getApplicationContext() .getSystemService(Context.WIFI_SERVICE); options.setWifiManager(manager); final MessagePipeLine pipeLine = new MessagePipeLine(); pipeLine.add(new LinkMessageDecoderUdp()); // pipeLine.add(new LinkMessageEncoder()); options.setHandleMessage(pipeLine); return options; } /** * 获取当前udp对象,如果不存在就创建 * * @return 返回当前对象 */ public synchronized UdpSocketBoot getUdpBoot() { if (null == initUdp()) { return null; } return udpSocketBoot; } /** * 初始化udp 监听功能 * * @return 返回当前对象 */ public synchronized UdpSocketBoot initUdp() { try { if (udpSocketBoot == null) { udpSocketBoot = UdpClient.init("0.0.0.0",UDP_PORT, getUdpOptions()); udpSocketBoot.bind(); bindSuccess=true; } } catch (Exception e) { LogUtils.e("初始化网关失败:"+e.getMessage()); return null; } return udpSocketBoot; } /** * 开始监听和发起入网及认证请求 * * @param request 认证请求信息 * @param callBack 结果回调 */ public void startAuthenticateRequest(AuthenticateRequest request, HDLLinkCallBack callBack) { HDLLinkConfig.getInstance().clearConfig(); //1.启动Socket 开启监听 getUdpBoot(); //2.构建监听Listener // authEvent = //3.监听网关广播的入网指令 EventDispatcher.getInstance().register(TopicConstant.GATEWAY_AUTH_BROADCAST, new EventListener() { @Override public void onMessage(Object msg) { NetworkAccessBroadcastResponse bean = getNetworkAccessBroadcastResponse(msg); if (bean != null) { LogUtils.i(TAG, "网关入网广播IP: " + bean.getIPAddress()); String ipStr = bean.getIPAddress(); if (!TextUtils.isEmpty(ipStr)) { sendAuthenticateRequest(ipStr, request, callBack); } } //移除监听 EventDispatcher.getInstance().remove(TopicConstant.GATEWAY_AUTH_BROADCAST); LogUtils.i(TAG, "移除监听 authEvent"); } }); } /** * 结束监听入网及认证广播 */ public void endAuthenticateRequest() { //移除监听 EventDispatcher.getInstance().remove(TopicConstant.GATEWAY_AUTH_BROADCAST); } /** * 发送入网及认证请求 * * @param ip 网关IP * @param request 认证请求信息 * @param callBack 结果回调 */ public void sendAuthenticateRequest(String ip, AuthenticateRequest request, HDLLinkCallBack callBack) { if (request == null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_NULL_ERROR)); } String topic = DEIVCE_AUTH_REQUEST; Gson gs = new Gson(); String requestStr = gs.toJson(request); LinkRequest linkRequest = new LinkRequest(topic, requestStr, false); // linkRequest.setReplyTopic(requestStr + "_reply"); new HDLConnectHelper(ip, linkRequest, new HDLConnectHelper.HdlSocketListener() { @Override public void onSucceed(Object msg) { if (callBack == null) return; try { AuthenticateResponse bean = getAuthenticateResponseBean(msg); if (bean != null) { 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)); } } catch (Exception e) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_ERROR)); } } @Override public void onFailure(HDLLinkCode hdlLinkCode) { LogUtils.i(TAG, "onFailure: "); if (callBack == null) return; callBack.onError(HDLLinkException.getErrorWithCode(hdlLinkCode)); } }, false).send(); } // /** // * 发送入网及认证请求 // * // * @param callBack 结果回调 // */ // public void sendAuthenticateRequest(CallBack callBack) { // String macStr = "AA000000000000BB"; // String secret = "87ae414b7a853f65"; // 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.setFirmwareVersion(versionString); // requestBean.setHardwareModel("1956F"); // AuthenticateRequest.AuthBean authbean = new AuthenticateRequest.AuthBean(); // authbean.setSpk("ir.module"); // authbean.setMACKey(mac_key); // authbean.setRequest(requestBean); // // // //2.设置设备信息 // AuthenticateDeviceInfoBean infoBean = new AuthenticateDeviceInfoBean(); // infoBean.setDeviceMAC(macStr); // infoBean.setIPMAC(macStr); // infoBean.setDeviceName("HDL面板"); // infoBean.setAccessMode("HDL"); // infoBean.setOID(getOid()); // infoBean.setSid(getSid()); //// infoBean.set // AuthenticateRequest.VersionBean[] versionBeans = new AuthenticateRequest.VersionBean[]{new AuthenticateRequest.VersionBean("FW", versionString), new AuthenticateRequest.VersionBean("HW", "1956F")}; // infoBean.setVersions(versionBeans); // AuthenticateRequest request = new AuthenticateRequest(IdUtils.getUUId(), time, infoBean, authbean); // // String ip = IpUtils.getBroadcastAddress(); // ip = "192.168.10.102"; // sendAuthenticateRequest(ip, request, callBack); // } public interface SearchGatewayCallBack extends BaseCallBack { /** * 搜索网关成功 * * @param gatewaySearchBean */ void onSuccess(GatewaySearchBean gatewaySearchBean); } /** * 暂停搜索网关 */ public void endSearchAllGateway() { } /** * 组播搜索指定网关是否在线,搜索到则返回指定的网关对象 * * @param callBack 回调 */ public void searchGatewayMulticast(SearchGatewayCallBack 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, UDP_PORT, callBack); } /** * 通用发送指令 * 1秒没响应就让他重新发送,重试3次 * * @param topic 发送数据 * @param bodyStr 回复的主题 * @param broadcast 是否要广播 * @param callBack 回调 */ public void udpSendMsg(String topic, String bodyStr, boolean broadcast, HDLLinkResponseCallBack callBack) { if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_NULL_ERROR)); } return; } if (!HDLLinkConfig.getInstance().checkIfCertified()) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_UNAUTHORIZED_ERROR)); } return; } LinkRequest message = new LinkRequest(topic, bodyStr, false); String ip = HDLLinkConfig.getInstance().getIpAddress(); if (broadcast) { ip = IpUtils.getBroadcastAddress(); } new HDLConnectHelper(ip, message, new HDLConnectHelper.HdlSocketListener() { @Override public void onSucceed(Object msg) { if (callBack == null) return; callBack.onSuccess((LinkResponse) msg); } @Override public void onFailure(HDLLinkCode hdlLinkCode) { if (callBack == null) return; callBack.onError(HDLLinkException.getErrorWithCode(hdlLinkCode)); } } , false).send(); } /** * 通用发送指令 只发一次,不监听回复,不重发 * * @param topic 发送数据 * @param bodyStr 回复的主题 * @param broadcast 是否广播 */ public void udpSendMsg(String topic, String bodyStr, boolean broadcast) { if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) { LogUtils.e("udpSendMsg", "参数不能为空"); return; } if (!HDLLinkConfig.getInstance().checkIfCertified()) { LogUtils.e("udpSendMsg", "未认证,请先认证"); return; } LinkRequest message = new LinkRequest(topic, bodyStr, HDLLinkConfig.getInstance().isLocalEncrypt()); String ip = HDLLinkConfig.getInstance().getIpAddress(); if (broadcast) { ip = IpUtils.getBroadcastAddress(); } new HDLConnectHelper(ip, message, false).send(); } private GatewaySearchBean getGatewaySearchBean(Object msg) { GatewaySearchBean searchBean = null; 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()); searchBean = response.getObjects(); } } return searchBean; } private AuthenticateResponse getAuthenticateResponseBean(Object msg) { AuthenticateResponse mBean = null; if (msg instanceof LinkResponse) { LinkResponse linkResponse = (LinkResponse) msg; String data = linkResponse.getData(); if (!TextUtils.isEmpty(data)) { AuthenticateResponse response = GsonConvert.getGson().fromJson(data, new TypeToken() { }.getType()); mBean = response; } } return mBean; } private NetworkAccessBroadcastResponse getNetworkAccessBroadcastResponse(Object msg) { NetworkAccessBroadcastResponse mBean = null; if (msg instanceof LinkResponse) { LinkResponse linkResponse = (LinkResponse) msg; String data = linkResponse.getData(); if (!TextUtils.isEmpty(data)) { NetworkAccessBroadcastResponse response = GsonConvert.getGson().fromJson(data, new TypeToken() { }.getType()); mBean = response; } } return mBean; } /** * 网关搜索相关 */ private static final int MAX_SEARCH_COUNT = 10;//总共搜索测试 private final AtomicInteger searchGatewayCount = new AtomicInteger(0); ; private final AtomicBoolean isSearchGatewaySuccess = new AtomicBoolean(true); private String searchGatewayId = ""; private SearchGatewayCallBack mSearchGatewayCallBack; private void initSearchGatewayEvent() { LogUtils.i("搜索网关", "initSearchGatewayEvent"); searchGatewayEvent = 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 && !TextUtils.isEmpty(searchBean.getGatewayId())) { if (searchBean.getGatewayId().contains(searchGatewayId)) { removeSearchGatewayEvent();//移除搜索网关监听 isSearchGatewaySuccess.set(true);//搜索成功标记 searchGatewayCount.set(11);//次数标记 HDLLinkConfig.getInstance().setLocalEncrypt(searchBean.isLocalEncrypt());//设置是否加密 if (mSearchGatewayCallBack != null) { mSearchGatewayCallBack.onSuccess(searchBean); } } } } } } catch (Exception e) { } } }; } 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 response = GsonConvert.getGson().fromJson(data, new TypeToken>() { }.getType()); GatewayBean gateway = response.getObjects(); if (gateway != null) { // if (!TextUtils.isEmpty(HDLLinkConfig.getInstance().getGatewayId()) // && !TextUtils.isEmpty(HDLLinkConfig.getInstance().getHomeId())) { // //主网关并且是当前绑定的网关 // if ("true".equals(gateway.getMaster().toLowerCase())) { // if (gateway.getGatewayId().equals(HDLLinkConfig.getInstance().getGatewayId()) // || gateway.getDevice_mac().equals(HDLLinkConfig.getInstance().getGatewayId()) // || gateway.getOid().equals(HDLLinkConfig.getInstance().getGatewayId()) // || gateway.getHomeId().equals(HDLLinkConfig.getInstance().getHomeId())) { // HDLLinkConfig.getInstance().setLocalEncrypt(gateway.getIsLocalEncrypt());//设置是否加密 // HDLLinkConfig.getInstance().setIpAddress(gateway.getIp_address()); // //更新当前网关的信息 // HDLLinkConfig.getInstance().reSaveConfig(); // } // } if (!TextUtils.isEmpty(gateway.getHomeId())) { //主网关并且是当前绑定的网关 if ("true".equals(gateway.getMaster().toLowerCase())) { if (gateway.getHomeId().equals(HDLLinkConfig.getInstance().getHomeId())) { HDLLinkConfig.getInstance().setLocalEncrypt(gateway.getIsLocalEncrypt());//设置是否加密 HDLLinkConfig.getInstance().setIpAddress(gateway.getIp_address()); //更新当前网关的信息 HDLLinkConfig.getInstance().reSaveConfig(); } } } //没有绑定的网关或与当前绑定到当前住宅的网关,建立连接。后面如果考虑也显示其它住宅的网关,这个限制要去掉 // if(TextUtils.isEmpty(gateway.getHomeId())||gateway.getHomeId().equals(HDLLinkConfig.getInstance().getHomeId())) { HDLTcpConnect.initTcp(gateway.getIp_address());//初始化TCP连接 // } } } } } catch (Exception e) { } } }; EventDispatcher.getInstance().register(TopicConstant.GATEWAY_SEARCH_REPLY, gatewayEvent); } /** * 搜索指定网关是否在线,搜索到则返回指定的网关对象 * * @param gatewayId 网关id * @param ipAddress 目标的IP地址 * @param port 目标的端口 * @param callBack 回调 */ public void searchGateway(String gatewayId, 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(), false); //注册搜索网关监听 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() + "次"); new HDLConnectHelper(ipAddress, message, false).send(); Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } } if (!isSearchGatewaySuccess.get()) { //搜索10次,指定网关都没回复,回调超时 callBackSearchGatewayTimeout(); LogUtils.e("搜索10次,指定网关都没回复,回调超时"); } } }).start(); } /** * 注册搜索网关监听 */ private void registerSearchGatewayEvent() { LogUtils.i("注册搜索网关监听"); EventDispatcher.getInstance().register(TopicConstant.GATEWAY_SEARCH_REPLY, searchGatewayEvent); } /** * 移除搜索网关监听 */ private void removeSearchGatewayEvent() { LogUtils.i("搜索网关", "移除搜索网关监听"); EventDispatcher.getInstance().remove(TopicConstant.GATEWAY_SEARCH_REPLY, searchGatewayEvent); } /** * 回调搜索网关超时 */ private void callBackSearchGatewayTimeout() { removeSearchGatewayEvent(); ThreadToolUtils.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (mSearchGatewayCallBack != null) { mSearchGatewayCallBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_SEARCH_GATEWAY_TIMEOUT_ERROR)); } } }); } }