wjc
2023-06-28 99bc815e07e39354f51421b77f4012ffd35594d8
HDLLinkLocalSdk/src/main/java/com/hdl/sdk/link/core/connect/HDLZigbeeConnect.java
New file
@@ -0,0 +1,358 @@
package com.hdl.sdk.link.core.connect;
import android.text.TextUtils;
import com.hdl.sdk.link.common.config.TopicConstant;
import com.hdl.sdk.link.common.event.EventDispatcher;
import com.hdl.sdk.link.common.event.EventListener;
import com.hdl.sdk.link.common.exception.HDLLinkCode;
import com.hdl.sdk.link.common.exception.HDLLinkException;
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.ZigbeeResponse;
import com.hdl.sdk.link.core.bean.gateway.GatewayBean;
import com.hdl.sdk.link.core.callback.ZigbeeCallBack;
import com.hdl.sdk.link.core.config.HDLLinkConfig;
import com.hdl.sdk.link.gateway.HDLLinkLocalGateway;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 * Created by hxb on 2021/12/8.
 * 原生通讯相关接口
 */
public class HDLZigbeeConnect {
    private static final String TAG="HDLZigbeeConnect";
    private static HDLZigbeeConnect instance;
    /**
     * 内部用,主要是处理处理掉透传主题及link主题后,还原Zigbee原生数据及主题用
     */
    private final String zigbeeAllTopic = "/Zigbee";
    /**
     * 返回当前实例,不存在就创建并同时注册监听事件
     *
     * @return
     */
    public static HDLZigbeeConnect getInstance() {
        if (null == instance) {
            instance = new HDLZigbeeConnect();
            instance.initEventListener();
        }
        return instance;
    }
    /**
     * 注册监听Zigbee所有原生主题及数据
     *
     * @param eventListener
     */
    public void registerListener(EventListener eventListener) {
        if(null==eventListener){
            return;
        }
        EventDispatcher.getInstance().register(zigbeeAllTopic, eventListener);
    }
    /**
     * 移除监听Zigbee原生主题及数据
     *
     * @param eventListener
     */
    public void removeListener(EventListener eventListener) {
        if(null==eventListener){
            return;
        }
        EventDispatcher.getInstance().remove(zigbeeAllTopic, eventListener);
    }
    /**
     * 初始化监听事件
     */
    private void initEventListener() {
        final EventListener eventListener = new EventListener() {
            @Override
            public void onMessage(Object msg) {
                try {
                    if (msg instanceof LinkResponse) {
                        LinkResponse linkResponse = (LinkResponse) msg;
                        String body = linkResponse.getData();
                        int index = body.indexOf("{");
                        //zigbee回复的数据前有主题,后面才是数据
                        if (index <= 0)
                            return;
                        String zigbeeTopic = body.substring(0, index).trim();
                        //zigbee的负载数据
                        String bodyData = body.substring(index);
                        ZigbeeResponse zigbeeResponse = new ZigbeeResponse();
                        zigbeeResponse.setTopic(zigbeeTopic);
                        zigbeeResponse.setData(bodyData);
                        String oid = null;
                        //是否是通过主网关透传主题
                        if (linkResponse.getTopic().contains("/slaveoid/")) {
                            oid = linkResponse.getTopic().split("/")[8];
                        } else {
                            oid = linkResponse.getTopic().split("/")[2];
                        }
                        zigbeeResponse.setOid(oid);
                        for (GatewayBean gatewayBean : HDLLinkLocalGateway.getInstance().getGatewayList()) {
                            if (oid.equals(gatewayBean.getGatewayId()) || oid.equals(gatewayBean.getDevice_mac()) || oid.equals(gatewayBean.getOid())) {
                                //上面的oid可能是网关id或者mac或者是oid,不管是哪个统一使用oid表示方式
                                zigbeeResponse.setOid(gatewayBean.getOid());
                                break;
                            }
                        }
                        EventDispatcher.getInstance().post(zigbeeTopic, zigbeeResponse);
                        //发布Zigbee原生主题及数据
                        EventDispatcher.getInstance().post(zigbeeAllTopic, zigbeeResponse);
                    }
                } catch (Exception e) {
                    LogUtils.e(TAG,"LinkResponse转ZigbeeResponse异常:"+ e.getMessage());
                }
            }
        };
        //
        //注册直接通讯的主题,包括直接和主网关通讯或者直接和从网关通讯
//        registerListener(String.format(TopicConstant.NATIVE_ZIGBEE_DOWN_REPLY, "+"), eventListener);
        //注册直接通讯的主题,包括直接和主网关通讯或者直接和从网关通讯
        registerListener(String.format(TopicConstant.NATIVE_ZIGBEE_UP, "+"), eventListener);
        //注册通过主网关透传从网关的主题
//        registerListener(String.format(TopicConstant.NATIVE_ZIGBEE_DOWN_SLAVE_REPLY, "+", "+"), eventListener);
        registerListener(String.format(TopicConstant.NATIVE_ZIGBEE_UP_SLAVE, "+", "+"), eventListener);
    }
    /**
     * 发送原生数据
     *
     * @param gatewayOidOrGatewayId 目标网关的oid或者网关Id
     * @param responeTopic          回复主题
     * @param payload               发送数据
     * @param zigbeeCallBack        结果回调
     */
    public void Send(String gatewayOidOrGatewayId,String responeTopic, String payload, final ZigbeeCallBack zigbeeCallBack) {
        //如果本地有链接这个网关,则用本地连接
        GatewayBean gatewayBean = HDLLinkLocalGateway.getInstance().getGatewayByOidOrGatewayId(gatewayOidOrGatewayId);
        if (null == gatewayBean) {
            LogUtils.i("找不到网关,Oid是" + gatewayOidOrGatewayId);
            if (null != zigbeeCallBack) {
                zigbeeCallBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GATEWAY_NOT_EXIST));
            }
            return;
        }
        String tempTopic = String.format(TopicConstant.NATIVE_ZIGBEE_DOWN, gatewayOidOrGatewayId);
        LinkRequest request = new LinkRequest(tempTopic, payload, gatewayBean.getIsLocalEncrypt());
        if ("true".equals(gatewayBean.getMaster())) {
            request.setCloudTopic(String.format(TopicConstant.NATIVE_ZIGBEE_DOWN, HDLLinkConfig.getInstance().getGatewayId()));
        } else {
            request.setCloudTopic(String.format(TopicConstant.NATIVE_ZIGBEE_DOWN_SLAVE, HDLLinkConfig.getInstance().getGatewayId(), gatewayOidOrGatewayId));
        }
        request.setReplyTopic(responeTopic);
//        final boolean[] isCallBack = {false};
//        //透传命令主题处理
//        final EventListener eventListener = new EventListener() {
//            @Override
//            public void onMessage(Object msg) {
//                if (msg instanceof ZigbeeResponse) {
//                    ZigbeeResponse linkResponse = (ZigbeeResponse) msg;
//                    //TODO 如果配置从网关的信息,通过主网关转达,这里oid要判断下
//                    if (responeTopic.equals(linkResponse.getTopic())) {
//                        isCallBack[0] = true;
//                        removeListener(zigbeeAllTopic, this);
//                        if (null != zigbeeCallBack) {
//                            zigbeeCallBack.onSuccess(linkResponse.getData());
//                        }
//                    }
//                }
//            }
//        };
//        //注册监听
//        registerListener(zigbeeAllTopic, eventListener);
        long timeout = 8 * 1000;
        /**
         * 需要特殊处理一些主题  需要延长超时时间
         */
        if (responeTopic.equals("Bind/SetBind_Respon") || responeTopic.equals("Bind/ClearBindInfo_Respon")) {
            timeout = 20 * 1000;
        }
//        //一定时间后还没有接收到数据,就回调失败
//        ScheduledExecutorService scheduledExecutorService = ThreadToolUtils.getInstance().newScheduledThreadPool(1);
//        scheduledExecutorService.schedule(new Runnable() {
//            @Override
//            public void run() {
//                removeListener(zigbeeAllTopic, eventListener);
//                scheduledExecutorService.shutdownNow();
//                if (!isCallBack[0]) {
//                    if (null != zigbeeCallBack) {
//                        zigbeeCallBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_Zigbee_FAILURE_ERROR));
//                    }
//                }
//            }
//        }, timeout, TimeUnit.SECONDS);
        new HDLConnectHelper(timeout, 1, gatewayBean.getIp_address(), 8586, request, new HDLConnectHelper.HdlSocketListener() {
            @Override
            public void onSucceed(Object msg) {
                if (msg instanceof String) {
                    if (null != zigbeeCallBack) {
                        zigbeeCallBack.onSuccess(msg+"");
                    }
                }
            }
            @Override
            public void onFailure(HDLLinkCode hdlLinkCode) {
                if (null != zigbeeCallBack) {
                    zigbeeCallBack.onError(HDLLinkException.getErrorWithCode(hdlLinkCode));
                }
            }
        }, true).send();
    }
    /**
     * 发送原生透传命令数据
     *
     * @param gatewayOidOrGatewayId 目标网关的oid或者网关Id
     * @param responeTopic          回复主题
     * @param payload               发送数据
     * @param zigbeeCallBack        结果回调
     */
    public void SendThrough(String gatewayOidOrGatewayId, String responeTopic, String payload, final ZigbeeCallBack zigbeeCallBack) {
//        //如果本地有链接这个网关,则用本地连接
//        GatewayBean gatewayBean = HDLLinkLocalGateway.getInstance().getGatewayByOidOrGatewayId(gatewayOidOrGatewayId);
//        if (null == gatewayBean) {
//            LogUtils.i("找不到网关,Oid是" + gatewayOidOrGatewayId);
//            if (null != zigbeeCallBack) {
//                zigbeeCallBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GATEWAY_NOT_EXIST));
//            }
//            return;
//        }
//        boolean isLocal = gatewayBean.getIsLocalGateway();
//        //如果是本地通讯
//        if (isLocal == true) {
//
//            String tempTopic = String.format("/user/%s/custom/native/zigbee/down", gatewayOidOrGatewayId);
//            String tempTopicReply = String.format("/user/%s/custom/native/zigbee/up", gatewayOidOrGatewayId);
//
//            final boolean[] isCallBack = {false};
//            //透传命令主题处理
//            final EventListener eventListener = new EventListener() {
//                @Override
//                public void onMessage(Object msg) {
//                    if (msg instanceof LinkResponse) {
//                        LinkResponse linkResponse = (LinkResponse) msg;
//                        //TODO 如果配置从网关的信息,通过主网关转达,这里oid要判断下
//                        String body = getZigbeeData(responeTopic, linkResponse);
//                        if (null != body) {
//                            isCallBack[0] = true;
//                            removeListener(tempTopicReply, this);
//                            if (null != zigbeeCallBack) {
//                                zigbeeCallBack.onSuccess(body);
//                            }
//                        }
//                    }
//                }
//            };
//            //注册监听
//            registerListener(tempTopicReply, eventListener);
//
//            //一定时间后还没有接收到数据,就回调失败
//            ScheduledExecutorService scheduledExecutorService = ThreadToolUtils.getInstance().newScheduledThreadPool(1);
//            scheduledExecutorService.schedule(new Runnable() {
//                @Override
//                public void run() {
//                    removeListener(tempTopicReply, eventListener);
//                    scheduledExecutorService.shutdownNow();
//                    if (!isCallBack[0]) {
//                        if (null != zigbeeCallBack) {
//                            zigbeeCallBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_GET_Zigbee_FAILURE_ERROR));
//                        }
//                    }
//                }
//            }, 5, TimeUnit.SECONDS);
//
//            //本地发送
//            LinkRequest request = new LinkRequest(tempTopic, payload, gatewayBean.getIsLocalEncrypt());
//            new HDLConnectHelper(gatewayBean.getIp_address(), request,true).send();
//        } else {
//            //请求主题
//            String tempTopic = null;
//            //回复主题
//            String tempTopicReply = null;
//
//            //远程发送
//            if ("true".equals(gatewayBean.getMaster())) {
//                tempTopic = String.format("/user/%s/custom/native/zigbee/down", com.hdl.sdk.link.core.config.HDLLinkConfig.getInstance().getGatewayId());
//                tempTopicReply = String.format("/user/%s/custom/native/zigbee/up", com.hdl.sdk.link.core.config.HDLLinkConfig.getInstance().getGatewayId());
//            } else {
//                tempTopic = String.format("/user/%s/custom/native/zigbee/slaveoid/%s/down", com.hdl.sdk.link.core.config.HDLLinkConfig.getInstance().getGatewayId(), gatewayOidOrGatewayId);
//                tempTopicReply = String.format("/user/%s/custom/native/zigbee/slaveoid/%s/up", com.hdl.sdk.link.core.config.HDLLinkConfig.getInstance().getGatewayId(), "+");
//            }
//            //TODO 后续完善云端的发送接收方法
//        }
    }
    /**
     * 处理zigbee回复的数据
     *
     * @param responeTopic   回复主题
     * @param linkResponse   回复的透传数据
     */
    private static String getZigbeeData(String responeTopic, LinkResponse linkResponse) {
        //主题为空不处理
        if(TextUtils.isEmpty(responeTopic)){
            return null;
        }
        String body = linkResponse.getData();
        int index = body.indexOf("{");
        //zigbee回复的数据前有主题,后面才是数据
        if (index <= 0)
            return null;
        String zigbeeTopic = body.substring(0, index).trim();
        //zigbee的负载数据
        String bodyData = body.substring(index);
        //不是当前请求的数据,不处理
        if (!zigbeeTopic.startsWith(responeTopic)) {
            return null;
        }
        return bodyData;
        //Zigbee以前的接收逻辑
//        HdlZbGatewayReceiveLogic.Current.ZigbeeOldReceiveLogic(reportTopic, bodyData, gatewayMac);
    }
    /**
     * 注册监听
     */
    static void registerListener(String responseTopic, EventListener eventListener) {
        if (!TextUtils.isEmpty(responseTopic)) {
            EventDispatcher.getInstance().register(responseTopic, eventListener);
        }
    }
    /**
     * 移除监听
     */
    static void removeListener(String responseTopic, EventListener eventListener) {
        if (!TextUtils.isEmpty(responseTopic)) {
            EventDispatcher.getInstance().remove(responseTopic, eventListener);
        }
    }
}