All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.huaweicloud.sdk.iot.device.gateway.AbstractGateway Maven / Gradle / Ivy

/*
 * Copyright (c) 2020-2023 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.huaweicloud.sdk.iot.device.gateway;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.huaweicloud.sdk.iot.device.IoTDevice;
import com.huaweicloud.sdk.iot.device.client.requests.Command;
import com.huaweicloud.sdk.iot.device.client.requests.DeviceEvent;
import com.huaweicloud.sdk.iot.device.client.requests.DeviceEvents;
import com.huaweicloud.sdk.iot.device.client.requests.DeviceMessage;
import com.huaweicloud.sdk.iot.device.client.requests.PropsGet;
import com.huaweicloud.sdk.iot.device.client.requests.PropsSet;
import com.huaweicloud.sdk.iot.device.client.requests.ServiceProperty;
import com.huaweicloud.sdk.iot.device.gateway.requests.AddedSubDeviceInfo;
import com.huaweicloud.sdk.iot.device.gateway.requests.DeviceInfo;
import com.huaweicloud.sdk.iot.device.gateway.requests.DeviceProperty;
import com.huaweicloud.sdk.iot.device.gateway.requests.DeviceStatus;
import com.huaweicloud.sdk.iot.device.gateway.requests.GtwAddSubDeviceRsp;
import com.huaweicloud.sdk.iot.device.gateway.requests.GtwDelSubDeviceRsp;
import com.huaweicloud.sdk.iot.device.gateway.requests.ScanSubdeviceNotify;
import com.huaweicloud.sdk.iot.device.gateway.requests.SubDevicesInfo;
import com.huaweicloud.sdk.iot.device.transport.ActionListener;
import com.huaweicloud.sdk.iot.device.transport.ConnectListener;
import com.huaweicloud.sdk.iot.device.transport.RawMessage;
import com.huaweicloud.sdk.iot.device.utils.IotUtil;
import com.huaweicloud.sdk.iot.device.utils.JsonUtil;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.security.KeyStore;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 抽象网关,实现了子设备管理,子设备消息转发功能
 */
public abstract class AbstractGateway extends IoTDevice {
    private static final Logger log = LogManager.getLogger(AbstractGateway.class);

    private SubDevDiscoveryListener subDevDiscoveryListener;

    private final SubDevicesPersistence subDevicesPersistence;

    private GtwOperateSubDeviceListener gtwOperateSubDeviceListener;

    /**
     * 构造函数,通过设备密码认证
     *
     * @param subDevicesPersistence 子设备持久化,提供子设备信息保存能力
     * @param serverUri             平台访问地址,比如ssl://c20c0d18c2.st1.iotda-device.cn-north-4.myhuaweicloud.com:8883
     * @param deviceId              设备id
     * @param deviceSecret          设备密码
     * @param file                  iot平台的ca证书,用于双向校验时设备侧校验平台
     */
    public AbstractGateway(SubDevicesPersistence subDevicesPersistence, String serverUri, String deviceId,
        String deviceSecret, File file) {
        super(serverUri, deviceId, deviceSecret, file);
        this.subDevicesPersistence = subDevicesPersistence;

        getClient().setConnectListener(new ConnectListener() {
            @Override
            public void connectionLost(Throwable cause) {

            }

            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                // 建连或重连时,向平台同步子设备信息
                syncSubDevices();
            }
        });

    }

    /**
     * 构造函数,通过设备证书认证
     *
     * @param subDevicesPersistence 子设备持久化,提供子设备信息保存能力
     * @param serverUri             平台访问地址,比如ssl://c20c0d18c2.st1.iotda-device.cn-north-4.myhuaweicloud.com:8883
     * @param deviceId              设备id
     * @param keyStore              证书容器
     * @param keyPassword           证书密码
     * @param file                  iot平台的ca证书,用于双向校验时设备侧校验平台
     */
    public AbstractGateway(SubDevicesPersistence subDevicesPersistence, String serverUri, String deviceId,
        KeyStore keyStore, String keyPassword, File file) {
        super(serverUri, deviceId, keyStore, keyPassword, file);
        this.subDevicesPersistence = subDevicesPersistence;
        getClient().setConnectListener(new ConnectListener() {
            @Override
            public void connectionLost(Throwable cause) {

            }

            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                // 建连或重连时,向平台同步子设备信息
                syncSubDevices();
            }
        });
    }

    /**
     * 设置子设备发现监听器
     *
     * @param subDevDiscoveryListener 子设备发现监听器
     */
    public void setSubDevDiscoveryListener(SubDevDiscoveryListener subDevDiscoveryListener) {
        this.subDevDiscoveryListener = subDevDiscoveryListener;
    }

    /**
     * 设置网关添加子设备监听器
     *
     * @param gtwOperateSubDeviceListener 网关操作子设备监听器
     */
    public void setGtwOperateSubDeviceListener(
        GtwOperateSubDeviceListener gtwOperateSubDeviceListener) {
        this.gtwOperateSubDeviceListener = gtwOperateSubDeviceListener;
    }

    /**
     * 根据设备标识码查询子设备
     *
     * @param nodeId 设备标识码
     * @return 子设备信息
     */
    protected DeviceInfo getSubDeviceByNodeId(String nodeId) {
        return subDevicesPersistence.getSubDevice(nodeId);
    }

    /**
     * 根据设备id查询子设备
     *
     * @param deviceId 设备id
     * @return 子设备信息
     */
    public DeviceInfo getSubDeviceByDeviceId(String deviceId) {
        String nodeId = IotUtil.getNodeIdFromDeviceId(deviceId);
        return subDevicesPersistence.getSubDevice(nodeId);
    }

    /**
     * 上报子设备发现结果
     *
     * @param deviceInfos 子设备信息列表
     * @param listener    发布监听器
     */
    public void reportSubDevList(List deviceInfos, ActionListener listener) {

        DeviceEvent deviceEvent = new DeviceEvent();
        deviceEvent.setServiceId("sub_device_discovery");
        deviceEvent.setEventTime(IotUtil.getTimeStamp());
        deviceEvent.setEventType("scan_result");

        Map para = new HashMap<>();
        para.put("devices", deviceInfos);
        deviceEvent.setParas(para);

        getClient().reportEvent(deviceEvent, listener);

    }

    /**
     * 上报子设备消息
     *
     * @param deviceMessage 设备消息
     * @param listener      监听器
     */
    public void reportSubDeviceMessage(DeviceMessage deviceMessage, ActionListener listener) {
        getClient().reportDeviceMessage(deviceMessage, listener);
    }

    /**
     * 上报子设备属性
     *
     * @param deviceId 子设备id
     * @param services 服务属性列表
     * @param listener 监听器
     */
    public void reportSubDeviceProperties(String deviceId,
        List services,
        ActionListener listener) {

        DeviceProperty deviceProperty = new DeviceProperty();
        deviceProperty.setDeviceId(deviceId);
        deviceProperty.setServices(services);
        reportSubDeviceProperties(Collections.singletonList(deviceProperty), listener);

    }

    /**
     * 批量上报子设备属性
     *
     * @param deviceProperties 子设备属性列表
     * @param listener         发布监听器
     */
    private void reportSubDeviceProperties(List deviceProperties,
        ActionListener listener) {

        ObjectNode node = JsonUtil.createObjectNode();
        node.putPOJO("devices", deviceProperties);

        String topic = "$oc/devices/" + getDeviceId() + "/sys/gateway/sub_devices/properties/report";

        RawMessage rawMessage = new RawMessage(topic, node.toString());

        getClient().publishRawMessage(rawMessage, listener);

    }

    /**
     * 上报子设备状态
     *
     * @param deviceId 子设备id
     * @param status   设备状态
     * @param listener 监听器
     */
    public void reportSubDeviceStatus(String deviceId, String status, ActionListener listener) {

        DeviceStatus deviceStatus = new DeviceStatus();
        deviceStatus.setDeviceId(deviceId);
        deviceStatus.setStatus(status);

        reportSubDeviceStatus(Collections.singletonList(deviceStatus), listener);

    }

    /**
     * 批量上报子设备状态
     *
     * @param statuses 子设备状态列表
     * @param listener 发布监听器
     */
    private void reportSubDeviceStatus(List statuses, ActionListener listener) {

        DeviceEvent deviceEvent = new DeviceEvent();
        deviceEvent.setServiceId("$sub_device_manager");
        deviceEvent.setEventTime(IotUtil.getTimeStamp());
        deviceEvent.setEventType("sub_device_update_status");

        Map para = new HashMap<>();
        para.put("device_statuses", statuses);
        deviceEvent.setParas(para);
        getClient().reportEvent(deviceEvent, listener);

    }

    /**
     * 网关新增子设备请求
     *
     * @param addedSubDeviceInfos 子设备信息列表
     * @param actionListener      发布监听器
     * @param eventId             此次请求的事件Id,不携带则由平台自定生成
     */
    public void gtwAddSubDevice(List addedSubDeviceInfos, String eventId,
        ActionListener actionListener) {

        DeviceEvent deviceEvent = new DeviceEvent();
        deviceEvent.setServiceId("$sub_device_manager");
        deviceEvent.setEventType("add_sub_device_request");
        deviceEvent.setEventTime(IotUtil.getTimeStamp());
        deviceEvent.setEventId(eventId);

        Map para = new HashMap<>();
        para.put("devices", addedSubDeviceInfos);
        deviceEvent.setParas(para);
        getClient().reportEvent(deviceEvent, actionListener);
    }

    /**
     * 网关删除子设备请求
     *
     * @param delSubDevices  要删除的子设备列表
     * @param eventId        此次请求的事件Id,不携带则由平台自定生成
     * @param actionListener 发布监听器
     */
    public void gtwDelSubDevice(List delSubDevices, String eventId, ActionListener actionListener) {
        DeviceEvent deviceEvent = new DeviceEvent();
        deviceEvent.setEventId(eventId);
        deviceEvent.setEventType("delete_sub_device_request");
        deviceEvent.setServiceId("$sub_device_manager");
        deviceEvent.setEventTime(IotUtil.getTimeStamp());

        Map para = new HashMap<>();
        para.put("devices", delSubDevices);
        deviceEvent.setParas(para);
        getClient().reportEvent(deviceEvent, actionListener);
    }

    /**
     * 事件处理回调,由SDK自动调用
     *
     * @param deviceEvents 设备事件
     */
    @Override
    public void onEvent(DeviceEvents deviceEvents) {

        super.onEvent(deviceEvents);

        for (DeviceEvent deviceEvent : deviceEvents.getServices()) {

            if ("start_scan".equals(deviceEvent.getEventType())) {

                ScanSubdeviceNotify scanSubdeviceNotify = JsonUtil.convertMap2Object(
                    deviceEvent.getParas(), ScanSubdeviceNotify.class);

                if (subDevDiscoveryListener != null) {
                    subDevDiscoveryListener.onScan(scanSubdeviceNotify);
                }

            } else if ("add_sub_device_notify".equals(deviceEvent.getEventType())) {

                SubDevicesInfo subDevicesInfo = JsonUtil.convertMap2Object(
                    deviceEvent.getParas(), SubDevicesInfo.class);

                onAddSubDevices(subDevicesInfo);

            } else if ("delete_sub_device_notify".equals(deviceEvent.getEventType())) {

                SubDevicesInfo subDevicesInfo = JsonUtil.convertMap2Object(
                    deviceEvent.getParas(), SubDevicesInfo.class);

                onDeleteSubDevices(subDevicesInfo);

            } else if ("add_sub_device_response".equals(deviceEvent.getEventType())) {

                // 跟接收子设备新增通知处理逻辑不一致
                GtwAddSubDeviceRsp gtwAddSubDeviceRsp = JsonUtil.convertMap2Object(deviceEvent.getParas(),
                    GtwAddSubDeviceRsp.class);

                if (gtwOperateSubDeviceListener != null) {
                    gtwOperateSubDeviceListener.onAddSubDeviceRsp(gtwAddSubDeviceRsp, deviceEvent.getEventId());
                }
            } else if ("delete_sub_device_response".equals(deviceEvent.getEventType())) {

                // 跟接收子设备删除通知处理逻辑不一致
                GtwDelSubDeviceRsp gtwDelSubDeviceRsp = JsonUtil.convertMap2Object(deviceEvent.getParas(),
                    GtwDelSubDeviceRsp.class);

                if (gtwOperateSubDeviceListener != null) {
                    gtwOperateSubDeviceListener.onDelSubDeviceRsp(gtwDelSubDeviceRsp, deviceEvent.getEventId());
                }
            } else {
                this.onSubdevEvent(deviceEvents.getDeviceId(), deviceEvent);
            }
        }
    }

    /**
     * 设备消息处理回调
     *
     * @param message 消息
     */
    @Override
    public void onDeviceMessage(DeviceMessage message) {

        // 子设备的
        if (message.getDeviceId() != null && !message.getDeviceId().equals(this.getDeviceId())) {
            this.onSubdevMessage(message);
        }
    }

    /**
     * 命令处理回调
     *
     * @param requestId 请求id
     * @param command   命令
     */
    @Override
    public void onCommand(String requestId, Command command) {

        // 子设备的
        if (command.getDeviceId() != null && !command.getDeviceId().equals(this.getDeviceId())) {

            this.onSubdevCommand(requestId, command);
            return;
        }

        // 网关的
        super.onCommand(requestId, command);

    }

    /**
     * 属性设置处理回调
     *
     * @param requestId 请求id
     * @param propsSet  属性设置请求
     */
    @Override
    public void onPropertiesSet(String requestId, PropsSet propsSet) {
        // 子设备的
        if (propsSet.getDeviceId() != null && !propsSet.getDeviceId().equals(this.getDeviceId())) {

            this.onSubdevPropertiesSet(requestId, propsSet);
            return;
        }

        // 网关的
        super.onPropertiesSet(requestId, propsSet);
    }

    /**
     * 属性查询处理回调
     *
     * @param requestId 请求id
     * @param propsGet  属性查询请求
     */
    @Override
    public void onPropertiesGet(String requestId, PropsGet propsGet) {

        // 子设备的
        if (propsGet.getDeviceId() != null && !propsGet.getDeviceId().equals(this.getDeviceId())) {

            this.onSubdevPropertiesGet(requestId, propsGet);
            return;
        }

        // 网关的
        super.onPropertiesGet(requestId, propsGet);
    }

    /**
     * 添加子设备处理回调,子类可以重写此接口进行扩展
     *
     * @param subDevicesInfo 子设备信息
     */
    private void onAddSubDevices(SubDevicesInfo subDevicesInfo) {
        if (subDevicesPersistence != null) {
            subDevicesPersistence.addSubDevices(subDevicesInfo);
        }
    }

    /**
     * 删除子设备处理回调,子类可以重写此接口进行扩展
     *
     * @param subDevicesInfo 子设备信息
     * @return 处理结果,0表示成功
     */
    public int onDeleteSubDevices(SubDevicesInfo subDevicesInfo) {
        if (subDevicesPersistence != null) {
            return subDevicesPersistence.deleteSubDevices(subDevicesInfo);
        }

        return -1;
    }

    /**
     * 向平台请求同步子设备信息
     */
    private void syncSubDevices() {
        log.info("start to syncSubDevices, local version is {}", subDevicesPersistence.getVersion());

        DeviceEvent deviceEvent = new DeviceEvent();
        deviceEvent.setEventType("sub_device_sync_request");
        deviceEvent.setServiceId("sub_device_manager");
        deviceEvent.setEventTime(IotUtil.getTimeStamp());

        Map para = new HashMap<>();
        para.put("version", subDevicesPersistence.getVersion());
        deviceEvent.setParas(para);
        getClient().reportEvent(deviceEvent, null);

    }

    /**
     * 子设备命令下发处理,网关需要转发给子设备,需要子类实现
     *
     * @param requestId 请求id
     * @param command   命令
     */
    public abstract void onSubdevCommand(String requestId, Command command);

    /**
     * 子设备属性设置,网关需要转发给子设备,需要子类实现
     *
     * @param requestId 请求id
     * @param propsSet  属性设置
     */
    public abstract void onSubdevPropertiesSet(String requestId, PropsSet propsSet);

    /**
     * 子设备读属性,,网关需要转发给子设备,需要子类实现
     *
     * @param requestId 请求id
     * @param propsGet  属性查询
     */
    public abstract void onSubdevPropertiesGet(String requestId, PropsGet propsGet);

    /**
     * 子设备消息下发,网关需要转发给子设备,需要子类实现
     *
     * @param message 设备消息
     */
    public abstract void onSubdevMessage(DeviceMessage message);

    /**
     * 子设备事件下发,网关需要转发给子设备,需要子类实现
     *
     * @param deviceId 子设备ID
     * @param deviceEvent 事件服务
     */
    public abstract void onSubdevEvent(String deviceId, DeviceEvent deviceEvent);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy