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

com.huaweicloud.sdk.iot.device.service.AbstractDevice 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.service;

import com.huaweicloud.sdk.iot.device.client.ClientConf;
import com.huaweicloud.sdk.iot.device.client.CustomOptions;
import com.huaweicloud.sdk.iot.device.client.DeviceClient;
import com.huaweicloud.sdk.iot.device.client.IotResult;
import com.huaweicloud.sdk.iot.device.client.requests.Command;
import com.huaweicloud.sdk.iot.device.client.requests.CommandRsp;
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.client.requests.Shadow;
import com.huaweicloud.sdk.iot.device.constants.Constants;
import com.huaweicloud.sdk.iot.device.devicelog.DeviceLogService;
import com.huaweicloud.sdk.iot.device.devicelog.listener.DefaultConnActionLogListener;
import com.huaweicloud.sdk.iot.device.devicelog.listener.DefaultConnLogListener;
import com.huaweicloud.sdk.iot.device.devicerule.DeviceRuleService;
import com.huaweicloud.sdk.iot.device.filemanager.FileManagerService;
import com.huaweicloud.sdk.iot.device.ota.OTAService;
import com.huaweicloud.sdk.iot.device.timesync.TimeSyncService;
import com.huaweicloud.sdk.iot.device.transport.ActionListener;
import com.huaweicloud.sdk.iot.device.utils.IotUtil;

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

import java.io.File;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 抽象设备类
 */
public class AbstractDevice {
    private static final Logger log = LogManager.getLogger(AbstractService.class);

    private DeviceClient client;

    private final String deviceId;

    private final Map services = new ConcurrentHashMap<>();

    private OTAService otaService;

    private FileManagerService fileManagerService;

    private TimeSyncService timeSyncService;

    private DeviceLogService deviceLogService;

    private DeviceRuleService deviceRuleService;

    protected CustomOptions customOptions = new CustomOptions();

    /**
     * 构造函数,使用密码创建设备
     *
     * @param serverUri    平台访问地址,比如ssl://iot-acc.cn-north-4.myhuaweicloud.com:8883
     * @param deviceId     设备id
     * @param deviceSecret 设备密码
     * @param iotCertFile  iot平台的ca证书,用于双向校验时设备侧校验平台
     */
    public AbstractDevice(String serverUri, String deviceId, String deviceSecret, File iotCertFile) {

        ClientConf clientConf = new ClientConf();
        clientConf.setServerUri(serverUri);
        clientConf.setDeviceId(deviceId);
        clientConf.setSecret(deviceSecret);
        clientConf.setFile(iotCertFile);
        this.deviceId = deviceId;
        this.client = new DeviceClient(clientConf, this);
        this.client.setCustomOptions(customOptions);
        initSysServices();
        log.info("create device, the deviceId is {}", clientConf.getDeviceId());

    }

    /**
     * 构造函数,使用证书创建设备
     *
     * @param serverUri   平台访问地址,比如ssl://iot-acc.cn-north-4.myhuaweicloud.com:8883
     * @param deviceId    设备id
     * @param keyStore    证书容器
     * @param keyPassword 证书密码
     * @param iotCertFile iot平台的ca证书,用于双向校验时设备侧校验平台
     */
    public AbstractDevice(String serverUri, String deviceId, KeyStore keyStore, String keyPassword, File iotCertFile) {

        ClientConf clientConf = new ClientConf();
        clientConf.setServerUri(serverUri);
        clientConf.setDeviceId(deviceId);
        clientConf.setKeyPassword(keyPassword);
        clientConf.setKeyStore(keyStore);
        clientConf.setFile(iotCertFile);
        this.deviceId = deviceId;
        this.client = new DeviceClient(clientConf, this);
        this.client.setCustomOptions(customOptions);
        initSysServices();
        log.info("create device {} ", clientConf.getDeviceId());
    }

    /**
     * 构造函数,直接使用客户端配置创建设备
     *
     * @param clientConf 客户端配置
     */
    public AbstractDevice(ClientConf clientConf) {
        if (clientConf.getMode() == Constants.CONNECT_OF_NORMAL_DEVICE_MODE) {
            this.client = new DeviceClient(clientConf, this);
            this.client.setCustomOptions(customOptions);
        }

        this.deviceId = clientConf.getDeviceId();
        initSysServices();
        log.info("create device: {}", clientConf.getDeviceId());
    }

    /**
     * 初始化系统默认service,系统service以$作为开头
     */
    private void initSysServices() {
        this.otaService = new OTAService();
        this.addService("$ota", otaService);
        this.fileManagerService = new FileManagerService();
        this.addService("$file_manager", fileManagerService);
        this.addService("$sdk", new SdkInfo());

        this.timeSyncService = new TimeSyncService();
        this.addService("$time_sync", timeSyncService);

        this.deviceLogService = new DeviceLogService();
        this.addService("$log", deviceLogService);

        this.deviceRuleService = new DeviceRuleService();
        this.addService("$device_rule", deviceRuleService);
    }

    /**
     * 初始化,创建到平台的连接
     *
     * @return 如果连接成功,返回0;其它表示失败
     */
    public int init() {

        // 如果日志上报开关是关闭状态或者已过日志收集结束时间,则取消上报设备连接状态相关日志
        if (deviceLogService.canReportLog()) {
            DefaultConnLogListener defaultConnLogListener = new DefaultConnLogListener(deviceLogService);
            client.setConnectListener(defaultConnLogListener);

            DefaultConnActionLogListener defaultConnActionLogListener = new DefaultConnActionLogListener(
                deviceLogService);
            client.setConnectActionListener(defaultConnActionLogListener);
        }

        return client.connect();
    }

    /**
     * 添加服务。用户基于AbstractService定义自己的设备服务,并添加到设备
     *
     * @param serviceId     服务id,要和设备模型定义一致
     * @param deviceService 服务实例
     */
    public void addService(String serviceId, AbstractService deviceService) {

        deviceService.setIotDevice(this);
        deviceService.setServiceId(serviceId);

        services.putIfAbsent(serviceId, deviceService);
    }

    /**
     * 删除服务
     *
     * @param serviceId 服务id
     */
    public void delService(String serviceId) {
        services.remove(serviceId);
    }

    /**
     * 查询服务
     *
     * @param serviceId 服务id
     * @return AbstractService 服务实例
     */
    public AbstractService getService(String serviceId) {

        return services.get(serviceId);
    }

    /**
     * 触发属性变化,SDK会上报变化的属性
     *
     * @param serviceId  服务id
     * @param properties 属性列表
     */
    protected void firePropertiesChanged(String serviceId, String... properties) {
        AbstractService deviceService = getService(serviceId);
        if (deviceService == null) {
            return;
        }
        Map props = deviceService.onRead(properties);

        ServiceProperty serviceProperty = new ServiceProperty();
        serviceProperty.setServiceId(deviceService.getServiceId());
        serviceProperty.setProperties(props);
        serviceProperty.setEventTime(IotUtil.getTimeStamp());

        getClient().scheduleTask(new Runnable() {
            @Override
            public void run() {
                client.reportProperties(Arrays.asList(serviceProperty), new ActionListener() {
                    @Override
                    public void onSuccess(Object context) {

                    }

                    @Override
                    public void onFailure(Object context, Throwable var2) {
                        log.error("reportProperties failed: " + var2.toString());
                    }
                });
            }
        });

    }

    /**
     * 触发多个服务的属性变化,SDK自动上报变化的属性到平台
     *
     * @param serviceIds 发生变化的服务id列表
     */
    protected void fireServicesChanged(List serviceIds) {
        List serviceProperties = new ArrayList<>();
        for (String serviceId : serviceIds) {
            AbstractService deviceService = getService(serviceId);
            if (deviceService == null) {
                log.error("service not found: " + serviceId);
                continue;
            }

            Map props = deviceService.onRead();

            ServiceProperty serviceProperty = new ServiceProperty();
            serviceProperty.setServiceId(deviceService.getServiceId());
            serviceProperty.setProperties(props);
            serviceProperty.setEventTime(IotUtil.getTimeStamp());
            serviceProperties.add(serviceProperty);
        }

        if (serviceProperties.isEmpty()) {
            return;
        }

        getClient().scheduleTask(new Runnable() {
            @Override
            public void run() {
                client.reportProperties(serviceProperties, new ActionListener() {
                    @Override
                    public void onSuccess(Object context) {

                    }

                    @Override
                    public void onFailure(Object context, Throwable var2) {
                        log.error("reportProperties failed: " + var2.toString());
                    }
                });
            }
        });
    }

    /**
     * 获取设备客户端。获取到设备客户端后,可以直接调用客户端提供的消息、属性、命令等接口
     *
     * @return 设备客户端实例
     */
    public DeviceClient getClient() {
        return client;
    }

    /**
     * 查询设备id
     *
     * @return 设备id
     */
    public String getDeviceId() {
        return deviceId;
    }

    /**
     * 命令回调函数,由SDK自动调用
     *
     * @param requestId 请求id
     * @param command   命令
     */
    public void onCommand(String requestId, Command command) {

        IService service = getService(command.getServiceId());

        if (service != null) {
            CommandRsp rsp = service.onCommand(command);
            client.respondCommand(requestId, rsp);
        }

    }

    /**
     * 属性设置回调,,由SDK自动调用
     *
     * @param requestId 请求id
     * @param propsSet  属性设置请求
     */
    public void onPropertiesSet(String requestId, PropsSet propsSet) {

        for (ServiceProperty serviceProp : propsSet.getServices()) {
            IService deviceService = getService(serviceProp.getServiceId());

            if (deviceService != null) {

                // 如果部分失败直接返回
                IotResult result = deviceService.onWrite(serviceProp.getProperties());
                if (result.getResultCode() != IotResult.SUCCESS.getResultCode()) {
                    client.respondPropsSet(requestId, result);
                    return;
                }
            }
        }
        client.respondPropsSet(requestId, IotResult.SUCCESS);

    }

    /**
     * 属性查询回调,由SDK自动调用
     *
     * @param requestId 请求id
     * @param propsGet  属性查询请求
     */
    public void onPropertiesGet(String requestId, PropsGet propsGet) {

        List serviceProperties = new ArrayList<>();

        // 查询所有
        if (propsGet.getServiceId() == null) {

            for (String ss : services.keySet()) {
                IService deviceService = getService(ss);
                if (deviceService != null) {
                    Map properties = deviceService.onRead();
                    ServiceProperty serviceProperty = new ServiceProperty();
                    serviceProperty.setProperties(properties);
                    serviceProperty.setServiceId(ss);
                    serviceProperties.add(serviceProperty);
                }
            }
        } else {
            IService deviceService = getService(propsGet.getServiceId());

            if (deviceService != null) {
                Map properties = deviceService.onRead();
                ServiceProperty serviceProperty = new ServiceProperty();
                serviceProperty.setProperties(properties);
                serviceProperty.setServiceId(propsGet.getServiceId());
                serviceProperties.add(serviceProperty);

            }
        }

        client.respondPropsGet(requestId, serviceProperties);

    }

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

        // 子设备的
        if (deviceEvents.getDeviceId() != null && !deviceEvents.getDeviceId().equals(getDeviceId())) {
            return;
        }

        for (DeviceEvent event : deviceEvents.getServices()) {
            IService deviceService = getService(event.getServiceId());
            if (deviceService != null) {
                deviceService.onEvent(event);
            }
        }
    }

    /**
     * 事件回调,网桥场景下使用
     *
     * @param deviceId     设备Id
     * @param deviceEvents 设备事件内容
     */
    public void onBridgeEvent(String deviceId, DeviceEvents deviceEvents) {
        for (DeviceEvent event : deviceEvents.getServices()) {
            IService deviceService = getService(event.getServiceId());
            if (deviceService != null) {
                deviceService.onBridgeEvent(deviceId, event);
            }
        }
    }

    /**
     * 消息回调,由SDK自动调用
     *
     * @param message 消息
     */
    public void onDeviceMessage(DeviceMessage message) {

    }

    /**
     * 影子回调函数,由SDK自动调用
     *
     * @param requestId 请求id
     * @param shadow   影子
     */
    public void onShadow(String requestId, Shadow shadow) {

    }

    /**
     * 获取OTA服务
     *
     * @return OTAService
     */
    public OTAService getOtaService() {
        return otaService;
    }

    /**
     * 获取时间同步服务
     *
     * @return TimeSyncService
     */
    public TimeSyncService getTimeSyncService() {
        return timeSyncService;
    }

    public DeviceLogService getDeviceLogService() {
        return deviceLogService;
    }

    public FileManagerService getFileManagerService() {
        return fileManagerService;
    }

    public DeviceRuleService getDeviceRuleService() {
        return deviceRuleService;
    }

    public void setFileManagerService(FileManagerService fileManagerService) {
        this.fileManagerService = fileManagerService;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy