Merge branch 'main' of https://git.robotstorm.tech/DevelopmentTeam/MassageRobot_Dobot into main
This commit is contained in:
commit
b96c979023
10
IoT/config.yaml
Normal file
10
IoT/config.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
server_uri: "6396c4c5d6.st1.iotda-device.cn-south-1.myhuaweicloud.com"
|
||||||
|
port: 1883
|
||||||
|
product_id: "673602f0d14760402fbd033b"
|
||||||
|
secret: "RobotStorm"
|
||||||
|
max_files: 20
|
||||||
|
watch_dirs:
|
||||||
|
- "/home/jsfb/jsfb_ws/collected_data"
|
||||||
|
- "/home/jsfb/jsfb_ws/LanguageLog"
|
||||||
|
- "/home/jsfb/jsfb_ws/UILog"
|
||||||
|
- "/home/jsfb/jsfb_ws/MassageLog"
|
20
IoT/iot.service
Executable file
20
IoT/iot.service
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=IoT service
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=/home/jsfb/jsfb_ws/MassageRobot_Dobot/IoT
|
||||||
|
Environment="PATH=/home/jsfb/anaconda3/envs/CPU_robotarm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
ExecStart=/home/jsfb/anaconda3/envs/CPU_robotarm/bin/python iot_lite.pyc
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5s
|
||||||
|
StartLimitIntervalSec=0
|
||||||
|
StartLimitBurst=0
|
||||||
|
User=jsfb
|
||||||
|
Group=jsfb
|
||||||
|
TimeoutStopSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
BIN
IoT/iot_device_sdk_python/__init__.pyc
Normal file
BIN
IoT/iot_device_sdk_python/__init__.pyc
Normal file
Binary file not shown.
0
IoT/iot_device_sdk_python/client/__init__.py
Normal file
0
IoT/iot_device_sdk_python/client/__init__.py
Normal file
BIN
IoT/iot_device_sdk_python/client/__init__.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/__init__.pyc
Normal file
Binary file not shown.
48
IoT/iot_device_sdk_python/client/client_conf.py
Normal file
48
IoT/iot_device_sdk_python/client/client_conf.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.connect_auth_info import ConnectAuthInfo
|
||||||
|
from iot_device_sdk_python.client.mqtt_connect_conf import MqttConnectConf
|
||||||
|
|
||||||
|
|
||||||
|
class ClientConf:
|
||||||
|
"""
|
||||||
|
客户端配置
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, connect_auth_info: ConnectAuthInfo, mqtt_connect_conf: Optional[MqttConnectConf] = None):
|
||||||
|
self.__connect_auth_info = connect_auth_info
|
||||||
|
self.__mqtt_connect_conf = MqttConnectConf()
|
||||||
|
if mqtt_connect_conf is not None:
|
||||||
|
self.__mqtt_connect_conf = mqtt_connect_conf
|
||||||
|
|
||||||
|
@property
|
||||||
|
def connect_auth_info(self):
|
||||||
|
return self.__connect_auth_info
|
||||||
|
|
||||||
|
@connect_auth_info.setter
|
||||||
|
def connect_auth_info(self, value):
|
||||||
|
self.__connect_auth_info = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mqtt_connect_conf(self):
|
||||||
|
return self.__mqtt_connect_conf
|
||||||
|
|
||||||
|
@mqtt_connect_conf.setter
|
||||||
|
def mqtt_connect_conf(self, value):
|
||||||
|
self.__mqtt_connect_conf = value
|
BIN
IoT/iot_device_sdk_python/client/client_conf.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/client_conf.pyc
Normal file
Binary file not shown.
319
IoT/iot_device_sdk_python/client/connect_auth_info.py
Normal file
319
IoT/iot_device_sdk_python/client/connect_auth_info.py
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectAuthInfo:
|
||||||
|
"""
|
||||||
|
连接鉴权配置
|
||||||
|
"""
|
||||||
|
SECRET_AUTH = 0
|
||||||
|
X509_AUTH = 1
|
||||||
|
PROTOCOL_MQTT = "MQTT"
|
||||||
|
BS_MODE_DIRECT_CONNECT = 0
|
||||||
|
BS_MODE_STANDARD_BOOTSTRAP = 1
|
||||||
|
BS_MODE_BOOTSTRAP_WITH_SCOPEID = 2
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
""" id,在平台注册设备获得 """
|
||||||
|
self._id: Optional[str] = None
|
||||||
|
|
||||||
|
""" 认证的类型:0表示密码方式,1表示x509证书方式;默认为0 """
|
||||||
|
self._auth_type: int = self.SECRET_AUTH
|
||||||
|
|
||||||
|
""" 设备密码 """
|
||||||
|
self._secret: Optional[str] = None
|
||||||
|
|
||||||
|
""" x509证书的pem文件路径 """
|
||||||
|
self._cert_path: Optional[str] = None
|
||||||
|
|
||||||
|
""" x509证书的key文件路径 """
|
||||||
|
self._key_path: Optional[str] = None
|
||||||
|
|
||||||
|
""" iot平台的ca证书存放路径,用于设备侧校验平台 """
|
||||||
|
self._iot_cert_file: Optional[str] = None
|
||||||
|
|
||||||
|
""" 设备自注册场景下使用 """
|
||||||
|
self._scope_id: Optional[str] = None
|
||||||
|
|
||||||
|
""" 设备接入平台地址(不包括端口) """
|
||||||
|
self._server_uri: Optional[str] = None
|
||||||
|
|
||||||
|
""" 端口 """
|
||||||
|
self._port: Optional[int] = None
|
||||||
|
|
||||||
|
""" 协议类型,不填则默认为MQTT """
|
||||||
|
self._protocol: str = self.PROTOCOL_MQTT
|
||||||
|
|
||||||
|
""" 0表示直连模式,1表示标准设备发放流程,2表示通过自注册的方式进行批量发放;默认为0 """
|
||||||
|
self._bs_mode: int = self.BS_MODE_DIRECT_CONNECT
|
||||||
|
|
||||||
|
""" 设备发放平台的证书路径 """
|
||||||
|
self._bs_cert_path: Optional[str] = None
|
||||||
|
|
||||||
|
""" 设备发放时上报的消息 ,在静态策略数据上报方式中,需要在上报的属性 “baseStrategyKeyword” 包含设置的关键字"""
|
||||||
|
self._bs_message: Optional[str] = None
|
||||||
|
|
||||||
|
""" 是否校验时间戳,"0"表示HMACSHA256不校验时间戳,"1"表示HMACSHA256校验时间戳;默认为"1"。 """
|
||||||
|
self._check_timestamp: str = "1"
|
||||||
|
|
||||||
|
""" 是否支持重连,True表示支持重连, False表示不支持重连"""
|
||||||
|
self._reconnect_on_failure = True
|
||||||
|
""" 最小退避时间, 默认1s"""
|
||||||
|
self._min_backoff = 1 * 1000 # 1s
|
||||||
|
""" 最大退避时间,默认30s"""
|
||||||
|
self._max_backoff = 30 * 1000
|
||||||
|
""" 是否开启端侧规则"""
|
||||||
|
self._enable_rule_manage = False
|
||||||
|
""" max buffer max"""
|
||||||
|
self._max_buffer_message = 0
|
||||||
|
""" qos1时最多可以同时发布多条消息,默认20条 """
|
||||||
|
self._inflight_messages: Optional[int] = 20
|
||||||
|
""" 是否自动上报版本号"""
|
||||||
|
self._auto_report_device_info: Optional[bool] = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
"""
|
||||||
|
id,在平台注册设备获得
|
||||||
|
"""
|
||||||
|
return self._id
|
||||||
|
|
||||||
|
@id.setter
|
||||||
|
def id(self, value):
|
||||||
|
self._id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def auth_type(self):
|
||||||
|
"""
|
||||||
|
认证的类型:0表示密码方式,1表示x509证书方式;默认为0
|
||||||
|
"""
|
||||||
|
return self._auth_type
|
||||||
|
|
||||||
|
@auth_type.setter
|
||||||
|
def auth_type(self, value):
|
||||||
|
self._auth_type = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def secret(self):
|
||||||
|
"""
|
||||||
|
设备密码
|
||||||
|
"""
|
||||||
|
return self._secret
|
||||||
|
|
||||||
|
@secret.setter
|
||||||
|
def secret(self, value):
|
||||||
|
self._secret = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cert_path(self):
|
||||||
|
"""
|
||||||
|
x509证书的pem文件路径
|
||||||
|
"""
|
||||||
|
return self._cert_path
|
||||||
|
|
||||||
|
@cert_path.setter
|
||||||
|
def cert_path(self, value):
|
||||||
|
self._cert_path = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key_path(self):
|
||||||
|
"""
|
||||||
|
x509证书的key文件路径
|
||||||
|
"""
|
||||||
|
return self._key_path
|
||||||
|
|
||||||
|
@key_path.setter
|
||||||
|
def key_path(self, value):
|
||||||
|
self._key_path = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def iot_cert_path(self):
|
||||||
|
"""
|
||||||
|
iot平台的ca证书存放路径,用于设备侧校验平台
|
||||||
|
"""
|
||||||
|
return self._iot_cert_file
|
||||||
|
|
||||||
|
@iot_cert_path.setter
|
||||||
|
def iot_cert_path(self, value):
|
||||||
|
self._iot_cert_file = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def server_uri(self):
|
||||||
|
"""
|
||||||
|
设备接入平台地址(不包括端口)
|
||||||
|
"""
|
||||||
|
return self._server_uri
|
||||||
|
|
||||||
|
@server_uri.setter
|
||||||
|
def server_uri(self, value):
|
||||||
|
self._server_uri = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port(self):
|
||||||
|
"""
|
||||||
|
端口
|
||||||
|
"""
|
||||||
|
return self._port
|
||||||
|
|
||||||
|
@port.setter
|
||||||
|
def port(self, value):
|
||||||
|
self._port = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def protocol(self):
|
||||||
|
"""
|
||||||
|
协议类型,不填则默认为MQTT
|
||||||
|
"""
|
||||||
|
return self._protocol
|
||||||
|
|
||||||
|
@protocol.setter
|
||||||
|
def protocol(self, value):
|
||||||
|
self._protocol = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def scope_id(self):
|
||||||
|
"""
|
||||||
|
设备自注册场景下使用
|
||||||
|
"""
|
||||||
|
return self._scope_id
|
||||||
|
|
||||||
|
@scope_id.setter
|
||||||
|
def scope_id(self, value):
|
||||||
|
self._scope_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_mode(self):
|
||||||
|
"""
|
||||||
|
是否为设备发放场景,默认为1
|
||||||
|
"""
|
||||||
|
return self._bs_mode
|
||||||
|
|
||||||
|
@bs_mode.setter
|
||||||
|
def bs_mode(self, value):
|
||||||
|
self._bs_mode = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_cert_path(self):
|
||||||
|
"""
|
||||||
|
设备发放平台的证书路径
|
||||||
|
"""
|
||||||
|
return self._bs_cert_path
|
||||||
|
|
||||||
|
@bs_cert_path.setter
|
||||||
|
def bs_cert_path(self, value):
|
||||||
|
self._bs_cert_path = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_message(self):
|
||||||
|
"""
|
||||||
|
静态策略数据上报方式下上报的数据
|
||||||
|
"""
|
||||||
|
return self._bs_message
|
||||||
|
|
||||||
|
@bs_message.setter
|
||||||
|
def bs_message(self, value):
|
||||||
|
self._bs_message = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def check_timestamp(self):
|
||||||
|
"""
|
||||||
|
是否校验时间戳,默认为"1"
|
||||||
|
"""
|
||||||
|
return self._check_timestamp
|
||||||
|
|
||||||
|
@check_timestamp.setter
|
||||||
|
def check_timestamp(self, value):
|
||||||
|
self._check_timestamp = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reconnect_on_failure(self):
|
||||||
|
"""
|
||||||
|
是否支持重连,TRUE支持重连
|
||||||
|
"""
|
||||||
|
return self._reconnect_on_failure
|
||||||
|
|
||||||
|
@reconnect_on_failure.setter
|
||||||
|
def reconnect_on_failure(self, value):
|
||||||
|
self._reconnect_on_failure = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def min_backoff(self):
|
||||||
|
"""
|
||||||
|
最小退避时间
|
||||||
|
"""
|
||||||
|
return self._min_backoff
|
||||||
|
|
||||||
|
@min_backoff.setter
|
||||||
|
def min_backoff(self, value):
|
||||||
|
self._min_backoff = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_backoff(self):
|
||||||
|
"""
|
||||||
|
最大退避时间
|
||||||
|
"""
|
||||||
|
return self._max_backoff
|
||||||
|
|
||||||
|
@max_backoff.setter
|
||||||
|
def max_backoff(self, value):
|
||||||
|
self._max_backoff = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enable_rule_manage(self):
|
||||||
|
"""
|
||||||
|
是否支持端侧规则
|
||||||
|
"""
|
||||||
|
return self._enable_rule_manage
|
||||||
|
|
||||||
|
@enable_rule_manage.setter
|
||||||
|
def enable_rule_manage(self, value):
|
||||||
|
self._enable_rule_manage = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_buffer_message(self):
|
||||||
|
"""
|
||||||
|
最大缓存消息,默认为0,不缓存消息
|
||||||
|
断链时,生产失败的消息存放队列,待重连后重新发送
|
||||||
|
"""
|
||||||
|
return self._max_buffer_message
|
||||||
|
|
||||||
|
@max_buffer_message.setter
|
||||||
|
def max_buffer_message(self, value):
|
||||||
|
self._max_buffer_message = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def inflight_messages(self):
|
||||||
|
"""
|
||||||
|
qos1时最多可以同时发布多条消息,默认20条
|
||||||
|
"""
|
||||||
|
return self._inflight_messages
|
||||||
|
|
||||||
|
@inflight_messages.setter
|
||||||
|
def inflight_messages(self, value):
|
||||||
|
self._inflight_messages = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def auto_report_device_info(self):
|
||||||
|
"""
|
||||||
|
qos1时最多可以同时发布多条消息,默认20条
|
||||||
|
"""
|
||||||
|
return self._auto_report_device_info
|
||||||
|
|
||||||
|
@auto_report_device_info.setter
|
||||||
|
def auto_report_device_info(self, value):
|
||||||
|
self._auto_report_device_info = value
|
BIN
IoT/iot_device_sdk_python/client/connect_auth_info.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/connect_auth_info.pyc
Normal file
Binary file not shown.
798
IoT/iot_device_sdk_python/client/device_client.py
Normal file
798
IoT/iot_device_sdk_python/client/device_client.py
Normal file
@ -0,0 +1,798 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""
|
||||||
|
设备客户端,提供和平台的通讯能力,包括:
|
||||||
|
|
||||||
|
消息:双向,异步,不需要定义模型
|
||||||
|
|
||||||
|
属性:双向,设备可以上报属性,平台可以向设备读写属性,属性需要在模型定义
|
||||||
|
|
||||||
|
命令:单向,同步,平台向设备调用设备的命令
|
||||||
|
|
||||||
|
时间:双向,异步,需要在模型定义
|
||||||
|
|
||||||
|
用户不能直接创建DeviceClient实例,只能先创建IoTDevice实例,然后通过IoTDevice的get_client方法获取DeviceClient实例
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, annotations
|
||||||
|
from typing import TYPE_CHECKING, List, Optional
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import stat
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.connect_auth_info import ConnectAuthInfo
|
||||||
|
from iot_device_sdk_python.client.iot_result import IotResult
|
||||||
|
from iot_device_sdk_python.client.listener.command_listener import CommandListener
|
||||||
|
from iot_device_sdk_python.client.listener.device_message_listener import DeviceMessageListener
|
||||||
|
from iot_device_sdk_python.client.listener.device_shadow_listener import DeviceShadowListener
|
||||||
|
from iot_device_sdk_python.client.listener.property_listener import PropertyListener
|
||||||
|
from iot_device_sdk_python.client.listener.raw_device_message_listener import RawDeviceMessageListener
|
||||||
|
from iot_device_sdk_python.client.mqtt_connect_conf import MqttConnectConf
|
||||||
|
from iot_device_sdk_python.client.request.device_message import DeviceMessage
|
||||||
|
from iot_device_sdk_python.client.request.raw_device_message import RawDeviceMessage
|
||||||
|
from iot_device_sdk_python.client.request.shadow_data import ShadowData
|
||||||
|
from iot_device_sdk_python.transport.mqtt.mqtt_connection import MqttConnection
|
||||||
|
from iot_device_sdk_python.client.request.device_event import DeviceEvent
|
||||||
|
from iot_device_sdk_python.client.request.device_events import DeviceEvents
|
||||||
|
from iot_device_sdk_python.transport.raw_message import RawMessage
|
||||||
|
from iot_device_sdk_python.transport.raw_message_listener import RawMessageListener
|
||||||
|
from iot_device_sdk_python.transport.action_listener import ActionListener
|
||||||
|
from iot_device_sdk_python.transport.connection import Connection
|
||||||
|
from iot_device_sdk_python.utils.iot_util import get_request_id_from_msg, str_is_empty, get_event_time
|
||||||
|
from iot_device_sdk_python.client.request.service_property import ServiceProperty
|
||||||
|
from iot_device_sdk_python.client.request.command import Command
|
||||||
|
from iot_device_sdk_python.client.request.command_response import CommandRsp
|
||||||
|
from iot_device_sdk_python.client.request.props_set import PropSet
|
||||||
|
from iot_device_sdk_python.client.request.props_get import PropsGet
|
||||||
|
from iot_device_sdk_python.client.request.device_base_info import DeviceBaseInfo
|
||||||
|
from iot_device_sdk_python.rule.model.action_handler import ActionHandler
|
||||||
|
from iot_device_sdk_python.rule.model.actions import Action
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from iot_device_sdk_python.service.abstract_device import AbstractDevice
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceClient(RawMessageListener):
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
# SDK版本信息,不能更改
|
||||||
|
__SDK_VERSION = "Python_v1.2.0"
|
||||||
|
__SERVER_INFO_PATH = os.path.join(sys.path[0], "server_info.json")
|
||||||
|
__SERVER_URI = "server_uri"
|
||||||
|
__PORT = "port"
|
||||||
|
__SECRET = "secret"
|
||||||
|
__BOOTSTRAP_TIMEOUT = 10.0
|
||||||
|
|
||||||
|
def __init__(self, connect_auth_info: ConnectAuthInfo, mqtt_connect_conf: MqttConnectConf, device: AbstractDevice):
|
||||||
|
self.check_connect_auth_info(connect_auth_info)
|
||||||
|
self.check_mqtt_connect_conf(mqtt_connect_conf)
|
||||||
|
self.__connect_auth_info = connect_auth_info
|
||||||
|
self.__mqtt_connect_conf = mqtt_connect_conf
|
||||||
|
|
||||||
|
self._device = device
|
||||||
|
self.__connection: Optional[Connection] = None
|
||||||
|
if self.__connect_auth_info.protocol == ConnectAuthInfo.PROTOCOL_MQTT:
|
||||||
|
self.__connection = MqttConnection(connect_auth_info, mqtt_connect_conf, self)
|
||||||
|
else:
|
||||||
|
self._logger.error("Current SDK only supports PROTOCOL_MQTT.")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# 设备发放是否成功
|
||||||
|
self.__bs_flag = False
|
||||||
|
# 是否开启端侧规则
|
||||||
|
self.__enable_rule_manage = connect_auth_info.enable_rule_manage
|
||||||
|
# raw_msg_listener是原始消息接收监听器
|
||||||
|
self.__raw_msg_listener_map = dict()
|
||||||
|
# 设置原始消息监听器,用于接收平台下发的原始设备消息
|
||||||
|
self.__raw_device_msg_listener: Optional[RawDeviceMessageListener] = None
|
||||||
|
# 设置消息监听器,用于接收平台下发的设备消息
|
||||||
|
self.__device_msg_listener: Optional[DeviceMessageListener] = None
|
||||||
|
# 属性监听器,用于接收平台下发的属性读写操作
|
||||||
|
self.__property_listener: Optional[PropertyListener] = None
|
||||||
|
# 命令监听器,用于接收平台下发的命令
|
||||||
|
self.__command_listener: Optional[CommandListener] = None
|
||||||
|
# 影子监听器,用于接收平台下发的设备影子数据
|
||||||
|
self.__shadow_listener: Optional[DeviceShadowListener] = None
|
||||||
|
# 端侧规则监听器,用于自定义处理端侧规则
|
||||||
|
self.__rule_action_handler: Optional[ActionHandler] = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_connect_auth_info(connect_auth_info: ConnectAuthInfo):
|
||||||
|
"""
|
||||||
|
检查连接鉴权配置。若配置有问题,则抛出错误
|
||||||
|
|
||||||
|
Args:
|
||||||
|
connect_auth_info: 连接鉴权配置
|
||||||
|
"""
|
||||||
|
if connect_auth_info is None:
|
||||||
|
raise ValueError("ConnectAuthInfo is null")
|
||||||
|
if str_is_empty(connect_auth_info.id):
|
||||||
|
raise ValueError("ConnectAuthInfo id is invalid")
|
||||||
|
if connect_auth_info.protocol != ConnectAuthInfo.PROTOCOL_MQTT:
|
||||||
|
# 当前SDK只支持MQTT协议
|
||||||
|
raise ValueError("ConnectAuthInfo protocol is invalid, currently protocol only support MQTT")
|
||||||
|
if str_is_empty(connect_auth_info.server_uri):
|
||||||
|
raise ValueError("ConnectAuthInfo server_uri is invalid")
|
||||||
|
if connect_auth_info.auth_type not in [ConnectAuthInfo.SECRET_AUTH, ConnectAuthInfo.X509_AUTH]:
|
||||||
|
raise ValueError("ConnectAuthInfo auth_type is invalid")
|
||||||
|
if str_is_empty(connect_auth_info.secret) and (
|
||||||
|
str_is_empty(connect_auth_info.cert_path) or str_is_empty(connect_auth_info.key_path)) is None:
|
||||||
|
raise ValueError("ConnectAuthInfo secret or certificate is invalid")
|
||||||
|
if connect_auth_info.port != 1883 and connect_auth_info.port != 8883:
|
||||||
|
raise ValueError("ConnectAuthInfo port is invalid")
|
||||||
|
if connect_auth_info.port == 8883 and str_is_empty(connect_auth_info.iot_cert_path):
|
||||||
|
raise ValueError("ConnectAuthInfo iot_cert_path is invalid")
|
||||||
|
if connect_auth_info.bs_mode not in [ConnectAuthInfo.BS_MODE_DIRECT_CONNECT,
|
||||||
|
ConnectAuthInfo.BS_MODE_STANDARD_BOOTSTRAP,
|
||||||
|
ConnectAuthInfo.BS_MODE_BOOTSTRAP_WITH_SCOPEID]:
|
||||||
|
raise ValueError("ConnectAuthInfo bs_mode is invalid")
|
||||||
|
if connect_auth_info.bs_mode == ConnectAuthInfo.BS_MODE_BOOTSTRAP_WITH_SCOPEID and str_is_empty(
|
||||||
|
connect_auth_info.scope_id):
|
||||||
|
raise ValueError("ConnectAuthInfo scope_id is invalid")
|
||||||
|
if connect_auth_info.check_timestamp not in ["0", "1"]:
|
||||||
|
raise ValueError("ConnectAuthInfo check_timestamp is invalid")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_mqtt_connect_conf(mqtt_connect_conf: MqttConnectConf):
|
||||||
|
"""
|
||||||
|
检查mqtt配置。若配置有问题,则抛出错误
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mqtt_connect_conf: mqtt配置
|
||||||
|
"""
|
||||||
|
if mqtt_connect_conf is None:
|
||||||
|
raise ValueError("MqttConnectConf is null")
|
||||||
|
if not isinstance(mqtt_connect_conf.keep_alive_time, int) \
|
||||||
|
or mqtt_connect_conf.keep_alive_time < 30 \
|
||||||
|
or mqtt_connect_conf.keep_alive_time > 1200:
|
||||||
|
raise ValueError("MqttConnectConf keep_alive_time is invalid")
|
||||||
|
if not isinstance(mqtt_connect_conf.qos, int) or mqtt_connect_conf.qos not in [0, 1]:
|
||||||
|
raise ValueError("MqttConnectConf qos is invalid")
|
||||||
|
if not isinstance(mqtt_connect_conf.timeout, float):
|
||||||
|
raise ValueError("MqttConnectConf timeout is invalid")
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
"""
|
||||||
|
和平台建立连接。连接成功时,SDK将自动向平台订阅系统定义的topic
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 结果码,0表示连接成功,其他表示连接失败
|
||||||
|
"""
|
||||||
|
if self.__connect_auth_info.bs_mode == ConnectAuthInfo.BS_MODE_STANDARD_BOOTSTRAP or \
|
||||||
|
self.__connect_auth_info.bs_mode == ConnectAuthInfo.BS_MODE_BOOTSTRAP_WITH_SCOPEID:
|
||||||
|
# 设备发放场景
|
||||||
|
if os.path.exists(self.__SERVER_INFO_PATH):
|
||||||
|
server_info_dict = dict()
|
||||||
|
try:
|
||||||
|
# 已成功进行过设备发放,从文件中读取iot平台连接信息
|
||||||
|
with open(self.__SERVER_INFO_PATH, 'r') as server_info:
|
||||||
|
server_info_dict: dict = json.load(server_info)
|
||||||
|
except Exception:
|
||||||
|
self._logger.error("load server_info failed, traceback: %s", traceback.format_exc())
|
||||||
|
|
||||||
|
if "server_uri" in server_info_dict.keys() and "port" in server_info_dict.keys():
|
||||||
|
server_uri = server_info_dict.get(self.__SERVER_URI)
|
||||||
|
port = server_info_dict.get(self.__PORT)
|
||||||
|
secret = server_info_dict.get(self.__SECRET)
|
||||||
|
self.__connect_auth_info.server_uri = server_uri
|
||||||
|
self.__connect_auth_info.port = port
|
||||||
|
if secret:
|
||||||
|
self.__connect_auth_info.secret = secret
|
||||||
|
else:
|
||||||
|
# 进行设备发放
|
||||||
|
rc = self.__bootstrap()
|
||||||
|
if rc != 0:
|
||||||
|
# 发放失败
|
||||||
|
self._logger.error("bootstrap device failed.")
|
||||||
|
return rc
|
||||||
|
else:
|
||||||
|
# 进行设备发放
|
||||||
|
rc = self.__bootstrap()
|
||||||
|
if rc != 0:
|
||||||
|
# 发放失败
|
||||||
|
self._logger.error("bootstrap device failed.")
|
||||||
|
return rc
|
||||||
|
# 建立设备到iot平台的连接, 将连接模式设置为直连。
|
||||||
|
self.__connect_auth_info.bs_mode = ConnectAuthInfo.BS_MODE_DIRECT_CONNECT
|
||||||
|
rc = self.__connect()
|
||||||
|
if rc != 0:
|
||||||
|
return rc
|
||||||
|
if self.__connect_auth_info.auto_report_device_info:
|
||||||
|
# 建链成功后,SDK自动上报版本号,软固件版本号由设备上报
|
||||||
|
self.report_device_info(DeviceBaseInfo())
|
||||||
|
return rc
|
||||||
|
|
||||||
|
def __connect(self):
|
||||||
|
"""
|
||||||
|
和平台建立连接。连接成功时,SDK将自动向平台订阅系统定义的topic
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 结果码,0表示连接成功,其他表示连接失败
|
||||||
|
"""
|
||||||
|
return self.__connection.connect()
|
||||||
|
|
||||||
|
def __bootstrap(self):
|
||||||
|
"""
|
||||||
|
进行设备发放流程,返回 0表示成功,返回其它表示失败
|
||||||
|
"""
|
||||||
|
rc = self.__connect()
|
||||||
|
if rc != 0:
|
||||||
|
return rc
|
||||||
|
bs_topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/bootstrap/down"
|
||||||
|
self.__connection.subscribe_topic(bs_topic, 0)
|
||||||
|
topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/bootstrap/up"
|
||||||
|
raw_message = RawMessage(topic, self.__connect_auth_info.bs_message)
|
||||||
|
self.publish_raw_message(raw_message)
|
||||||
|
start_time = time.time()
|
||||||
|
while True:
|
||||||
|
# 等待设备发放成功
|
||||||
|
time.sleep(1)
|
||||||
|
if self.__bs_flag:
|
||||||
|
break
|
||||||
|
now = time.time()
|
||||||
|
if now - start_time > self.__BOOTSTRAP_TIMEOUT:
|
||||||
|
self._logger.error("bootstrap failed, timeout.")
|
||||||
|
return -1
|
||||||
|
# 释放设备到发放服务端的连接
|
||||||
|
self.close()
|
||||||
|
return rc
|
||||||
|
|
||||||
|
def _get_connection(self):
|
||||||
|
return self.__connection
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
""" 释放connection连接 """
|
||||||
|
self.__connection.close()
|
||||||
|
|
||||||
|
def on_message_received(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
收到原始消息后,依据topic的不同,调用不同的方法
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
topic = message.topic
|
||||||
|
|
||||||
|
# 若订阅了自定义的topic,这里先检查接收到的topic是否是自定义的
|
||||||
|
raw_msg_listener = self.__raw_msg_listener_map[topic] if topic in self.__raw_msg_listener_map else None
|
||||||
|
if raw_msg_listener is not None:
|
||||||
|
raw_msg_listener.on_message_received(message)
|
||||||
|
return
|
||||||
|
|
||||||
|
if "/messages/down" in topic:
|
||||||
|
self.on_device_msg(message) # 平台下发消息到设备测
|
||||||
|
elif "sys/commands/request_id" in topic:
|
||||||
|
self.on_command(message) # 平台下发指令到设备侧
|
||||||
|
elif "/sys/properties/set/request_id" in topic:
|
||||||
|
self.on_properties_set(message) # 处理写属性操作
|
||||||
|
elif "/sys/properties/get/request_id" in topic:
|
||||||
|
self.on_properties_get(message) # 处理读属性操作
|
||||||
|
elif "/sys/shadow/get/response" in topic:
|
||||||
|
self.on_device_shadow(message) # 处理获取平台设备影子数据
|
||||||
|
elif "/sys/events/down" in topic:
|
||||||
|
self.on_event(message) # 处理平台下发事件
|
||||||
|
elif "/sys/bootstrap/down" in topic:
|
||||||
|
self.on_bootstrap(message)
|
||||||
|
else:
|
||||||
|
self._logger.warning("unknown topic: %s", topic)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("on_message_received error, tracback: %s", traceback.format_exc())
|
||||||
|
self._logger.error("on_message_received error: %s", str(e))
|
||||||
|
|
||||||
|
def report_device_message(self, device_message: DeviceMessage, listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
上报设备消息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device_message: 设备消息
|
||||||
|
listener: 发布监听器,若不设置监听器则设为None
|
||||||
|
"""
|
||||||
|
topic = '$oc/devices/' + self.__connect_auth_info.id + '/sys/messages/up'
|
||||||
|
try:
|
||||||
|
payload = json.dumps(device_message.to_dict())
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
|
||||||
|
def report_properties(self, services: List[ServiceProperty], listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
上报设备属性
|
||||||
|
|
||||||
|
Args:
|
||||||
|
services: 设备属性列表
|
||||||
|
listener: 发布监听器,若不设置监听器则设为None
|
||||||
|
"""
|
||||||
|
topic = '$oc/devices/' + self.__connect_auth_info.id + '/sys/properties/report'
|
||||||
|
service_list = list()
|
||||||
|
for service in services:
|
||||||
|
service_list.append(service.to_dict())
|
||||||
|
try:
|
||||||
|
payload = json.dumps({"services": service_list})
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
"""
|
||||||
|
处理端侧规则
|
||||||
|
"""
|
||||||
|
if self.__enable_rule_manage:
|
||||||
|
self._device.get_rule_manage_service().handle_rule(services)
|
||||||
|
|
||||||
|
def get_device_shadow(self, request_id: str, service_id: Optional[str] = None,
|
||||||
|
object_device_id: Optional[str] = None, listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
设备侧获取平台的设备影子数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id
|
||||||
|
service_id: 服务id
|
||||||
|
object_device_id: device_id
|
||||||
|
listener: 发布监听器,若不设置监听器则设为None
|
||||||
|
"""
|
||||||
|
if object_device_id is not None:
|
||||||
|
topic = "$oc/devices/" + object_device_id + "/sys/shadow/get/request_id=" + request_id
|
||||||
|
else:
|
||||||
|
topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/shadow/get/request_id=" + request_id
|
||||||
|
|
||||||
|
payload_dict = dict()
|
||||||
|
if service_id is not None:
|
||||||
|
payload_dict["service_id"] = service_id
|
||||||
|
try:
|
||||||
|
payload = json.dumps(payload_dict)
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
|
||||||
|
def report_event(self, device_event: DeviceEvent, listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
事件上报
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device_event: 事件
|
||||||
|
listener: 发布监听器,若不设置监听器则设为None
|
||||||
|
"""
|
||||||
|
device_events = DeviceEvents()
|
||||||
|
device_events.device_id = self.__connect_auth_info.id
|
||||||
|
device_events.services = [device_event]
|
||||||
|
|
||||||
|
topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/events/up"
|
||||||
|
try:
|
||||||
|
payload = json.dumps(device_events.to_dict())
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
|
||||||
|
def report_sub_event(self, sub_device_id: str, device_event: DeviceEvent,
|
||||||
|
listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
子设备事件上报
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sub_device_id: 子设备ID
|
||||||
|
device_event: 事件
|
||||||
|
listener: 发布监听器,若不设置监听器则设为None
|
||||||
|
"""
|
||||||
|
device_events = DeviceEvents()
|
||||||
|
device_events.device_id = self.__connect_auth_info.id
|
||||||
|
if sub_device_id is not None:
|
||||||
|
device_events.device_id = sub_device_id
|
||||||
|
device_events.services = [device_event]
|
||||||
|
|
||||||
|
topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/events/up"
|
||||||
|
try:
|
||||||
|
payload = json.dumps(device_events.to_dict())
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
|
||||||
|
def respond_command(self, request_id: str, command_response: CommandRsp, listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
上报命令响应
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id,响应的请求id必须和请求的一致
|
||||||
|
command_response: 命令响应
|
||||||
|
listener: 发布监听器
|
||||||
|
"""
|
||||||
|
topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/commands/response/request_id=" + request_id
|
||||||
|
try:
|
||||||
|
payload = json.dumps(command_response.to_dict())
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
|
||||||
|
def publish_raw_message(self, raw_message: RawMessage, listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
发布消息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw_message: 消息
|
||||||
|
listener: 发布监听器,若不设置监听器则设为None
|
||||||
|
"""
|
||||||
|
self.__connection.publish_message(raw_message, listener)
|
||||||
|
|
||||||
|
def on_device_msg(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
处理平台消息下发。若当前DeviceClient设置了消息监听器,则执行此消息监听器的on_device_message()方法。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
self._logger.debug(f"receive message from platform, topic = %s, msg = %s", message.topic, message.payload)
|
||||||
|
|
||||||
|
raw_device_message = RawDeviceMessage(message.payload)
|
||||||
|
device_msg = raw_device_message.to_device_message()
|
||||||
|
|
||||||
|
if self.__raw_device_msg_listener is not None:
|
||||||
|
self.__raw_device_msg_listener.on_raw_device_message(raw_device_message)
|
||||||
|
|
||||||
|
if device_msg is not None:
|
||||||
|
is_current_device = device_msg.device_id is None \
|
||||||
|
or len(device_msg.device_id) == 0 \
|
||||||
|
or device_msg.device_id == self.__connect_auth_info.id
|
||||||
|
if self.__device_msg_listener is not None and is_current_device:
|
||||||
|
self.__device_msg_listener.on_device_message(device_msg)
|
||||||
|
else:
|
||||||
|
self._device.on_device_message(device_msg)
|
||||||
|
|
||||||
|
def on_command(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
处理平台命令下发。若当前DeviceClient设置了命令监听器,则执行此命令监听器的on_command()方法。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
request_id = get_request_id_from_msg(message)
|
||||||
|
try:
|
||||||
|
self._logger.debug("receive command from platform, topic = %s, msg = %s", message.topic,
|
||||||
|
str(message.payload))
|
||||||
|
cmd = json.loads(message.payload)
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.loads failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
command = Command()
|
||||||
|
command.convert_from_dict(cmd)
|
||||||
|
if self.__command_listener is not None:
|
||||||
|
self.__command_listener.on_command(request_id, command.service_id, command.command_name,
|
||||||
|
command.paras)
|
||||||
|
else:
|
||||||
|
self._device.on_command(request_id, command)
|
||||||
|
|
||||||
|
def on_rule_command(self, request_id: str, command: Command):
|
||||||
|
if self.__command_listener is not None:
|
||||||
|
self.__command_listener.on_command(request_id, command.service_id, command.command_name, command.paras)
|
||||||
|
return
|
||||||
|
self._logger.warning("command listener was not config for rules.")
|
||||||
|
|
||||||
|
def on_device_shadow(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
处理平台设备影子数据下发。若当前DeviceClient设置了影子监听器,则执行此命令监听器的on_shadow_get()方法。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
request_id = get_request_id_from_msg(message)
|
||||||
|
try:
|
||||||
|
payload: dict = json.loads(message.payload)
|
||||||
|
device_id: str = payload.get("object_device_id")
|
||||||
|
shadow_list: List[ShadowData] = list()
|
||||||
|
shadow_dict_list: list = payload.get("shadow")
|
||||||
|
for shadow_dict in shadow_dict_list:
|
||||||
|
shadow = ShadowData()
|
||||||
|
shadow.convert_from_dict(shadow_dict)
|
||||||
|
shadow_list.append(shadow)
|
||||||
|
if self.__shadow_listener is not None:
|
||||||
|
self.__shadow_listener.on_shadow_get(request_id, device_id, shadow_list)
|
||||||
|
else:
|
||||||
|
# 没有设置影子监听器,这里不做处理
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("handle device shadow failed, Exception: %s", str(e))
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_properties_set(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
处理平台设置设备属性。若当前DeviceClient设置了属性监听器,则执行此命令监听器的on_property_set()方法。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
request_id = get_request_id_from_msg(message)
|
||||||
|
try:
|
||||||
|
self._logger.debug("receive properties_set from platform, topic = %s, msg = %s",
|
||||||
|
message.topic, str(message.payload))
|
||||||
|
payload: dict = json.loads(message.payload)
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.loads failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
prop_set: PropSet = PropSet()
|
||||||
|
service_list: list = payload["services"]
|
||||||
|
service_property_list = [ServiceProperty(service_id=a["service_id"],
|
||||||
|
properties=a["properties"]) for a in service_list]
|
||||||
|
prop_set.services = service_property_list
|
||||||
|
if self.__property_listener is not None:
|
||||||
|
self.__property_listener.on_property_set(request_id, prop_set.services)
|
||||||
|
else:
|
||||||
|
self._device.on_properties_set(request_id, prop_set)
|
||||||
|
|
||||||
|
def on_properties_get(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
处理平台查询设备属性。若当前DeviceClient设置了属性监听器,则执行此命令监听器的on_property_get()方法。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
request_id = get_request_id_from_msg(message)
|
||||||
|
try:
|
||||||
|
self._logger.debug("receive properties_get from platform, topic = %s, msg = %s", message.topic,
|
||||||
|
str(message.payload))
|
||||||
|
obj = json.loads(message.payload)
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.loads failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
prop_get = PropsGet()
|
||||||
|
prop_get.convert_from_dict(obj)
|
||||||
|
if self.__property_listener is not None:
|
||||||
|
self.__property_listener.on_property_get(request_id, prop_get.service_id)
|
||||||
|
else:
|
||||||
|
self._device.on_properties_get(request_id, prop_get)
|
||||||
|
|
||||||
|
def on_event(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
处理平台事件下发
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self._logger.debug("receive events from platform, topic = %s, msg = %s", message.topic,
|
||||||
|
str(message.payload))
|
||||||
|
payload: dict = json.loads(message.payload)
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.loads failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
device_events = DeviceEvents()
|
||||||
|
device_events.convert_from_dict(payload)
|
||||||
|
if not device_events:
|
||||||
|
self._logger.error("device events invalid, payload: %s", str(payload))
|
||||||
|
return
|
||||||
|
self._device.on_event(device_events)
|
||||||
|
|
||||||
|
def on_rule_action_handler(self, action: List[Action]):
|
||||||
|
"""
|
||||||
|
处理端侧规则
|
||||||
|
|
||||||
|
Args:
|
||||||
|
action: 原始数据
|
||||||
|
"""
|
||||||
|
if self.__rule_action_handler is not None:
|
||||||
|
self.__rule_action_handler.handle_rule_action(action)
|
||||||
|
return
|
||||||
|
self._device.on_rule_action_handler(action)
|
||||||
|
|
||||||
|
def on_bootstrap(self, message: RawMessage):
|
||||||
|
"""
|
||||||
|
处理设备发放信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 原始数据
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self._logger.debug("receive bootstrap info from platform, topic = %s, msg = %s", message.topic,
|
||||||
|
str(message.payload))
|
||||||
|
payload: dict = json.loads(message.payload)
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.loads failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
address = str(payload.get("address"))
|
||||||
|
device_secret = payload.get("deviceSecret")
|
||||||
|
self.__connect_auth_info.server_uri = address.split(":")[0]
|
||||||
|
self.__connect_auth_info.port = int(address.split(":")[-1])
|
||||||
|
if device_secret:
|
||||||
|
self.__connect_auth_info.secret = device_secret
|
||||||
|
# 设备发放成功,保存获取的iot平台地址和端口
|
||||||
|
if os.path.exists(self.__SERVER_INFO_PATH):
|
||||||
|
os.remove(self.__SERVER_INFO_PATH)
|
||||||
|
server_info_dict = {self.__SERVER_URI: self.__connect_auth_info.server_uri,
|
||||||
|
self.__PORT: self.__connect_auth_info.port,
|
||||||
|
self.__SECRET: device_secret}
|
||||||
|
flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
|
||||||
|
modes = stat.S_IWUSR | stat.S_IRUSR
|
||||||
|
with os.fdopen(os.open(self.__SERVER_INFO_PATH, flags, modes), 'w') as server_info:
|
||||||
|
json.dump(server_info_dict, server_info)
|
||||||
|
self._logger.info("bootstrap success, change server address to %s", address)
|
||||||
|
self.__bs_flag = True
|
||||||
|
|
||||||
|
def respond_properties_get(self, request_id: str, services: List[ServiceProperty],
|
||||||
|
listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
上报读属性响应
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id,响应的请求id必须和请求的一致
|
||||||
|
services: 设备属性列表
|
||||||
|
listener: 发布监听器
|
||||||
|
"""
|
||||||
|
topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/properties/get/response/request_id=" + request_id
|
||||||
|
service_list = list()
|
||||||
|
for service in services:
|
||||||
|
service_list.append(service.to_dict())
|
||||||
|
try:
|
||||||
|
payload = json.dumps({"services": service_list})
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
|
||||||
|
def respond_properties_set(self, request_id: str, iot_result: IotResult, listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
上报写属性响应
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id,响应的请求id必须和请求的一致
|
||||||
|
iot_result: 写属性结果
|
||||||
|
listener: 发布监听器
|
||||||
|
"""
|
||||||
|
topic = "$oc/devices/" + self.__connect_auth_info.id + "/sys/properties/set/response/request_id=" + request_id
|
||||||
|
try:
|
||||||
|
payload = json.dumps(iot_result.to_dict())
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error("json.dumps failed, Exception: %s", str(e))
|
||||||
|
raise e
|
||||||
|
self.publish_raw_message(RawMessage(topic, payload, self.__mqtt_connect_conf.qos), listener)
|
||||||
|
|
||||||
|
def set_raw_device_msg_listener(self, raw_device_msg_listener: RawDeviceMessageListener):
|
||||||
|
"""
|
||||||
|
设置原始消息监听器,用于接收平台下发的消息,消息保持为二进制格式。
|
||||||
|
需要通过IoTDevice的getClient方法获取DeviceClient实例后,调用此方法设置消息监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw_device_msg_listener: 消息监听器
|
||||||
|
"""
|
||||||
|
if not isinstance(raw_device_msg_listener, RawDeviceMessageListener):
|
||||||
|
self._logger.error("device_msg_listener should be RawDeviceMessageListener type")
|
||||||
|
return
|
||||||
|
self.__raw_device_msg_listener = raw_device_msg_listener
|
||||||
|
|
||||||
|
def set_device_msg_listener(self, device_msg_listener: DeviceMessageListener):
|
||||||
|
"""
|
||||||
|
设置消息监听器,用于接收平台下发的消息。
|
||||||
|
需要通过IoTDevice的getClient方法获取DeviceClient实例后,调用此方法设置消息监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device_msg_listener: 消息监听器
|
||||||
|
"""
|
||||||
|
if not isinstance(device_msg_listener, DeviceMessageListener):
|
||||||
|
self._logger.error("device_msg_listener should be DeviceMessageListener type")
|
||||||
|
return
|
||||||
|
self.__device_msg_listener = device_msg_listener
|
||||||
|
|
||||||
|
def set_properties_listener(self, property_listener: PropertyListener):
|
||||||
|
"""
|
||||||
|
设置属性监听器,用于接收平台下发的属性读写
|
||||||
|
需要通过IoTDevice的getClient方法获取DeviceClient实例后,调用此方法设置消息监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
property_listener: 属性监听器
|
||||||
|
"""
|
||||||
|
if not isinstance(property_listener, PropertyListener):
|
||||||
|
self._logger.error("property_listener should be PropertyListener")
|
||||||
|
return
|
||||||
|
self.__property_listener = property_listener
|
||||||
|
|
||||||
|
def set_command_listener(self, command_listener: CommandListener):
|
||||||
|
"""
|
||||||
|
设置命令监听器,用于接收平台下发的命令。
|
||||||
|
需要通过IoTDevice的getClient接口获取DeviceClient实例后,调用此方法设置命令监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command_listener: 命令监听器
|
||||||
|
"""
|
||||||
|
if not isinstance(command_listener, CommandListener):
|
||||||
|
self._logger.error("command_listener should be CommandListener")
|
||||||
|
return
|
||||||
|
self.__command_listener = command_listener
|
||||||
|
|
||||||
|
def set_device_shadow_listener(self, device_shadow_listener: DeviceShadowListener):
|
||||||
|
"""
|
||||||
|
设置影子监听器,用于接收平台下发的设备影子数据
|
||||||
|
需要通过IoTDevice的getClient方法获取DeviceClient实例后,调用此方法设置消息监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device_shadow_listener: 影子监听器
|
||||||
|
"""
|
||||||
|
if not isinstance(device_shadow_listener, DeviceShadowListener):
|
||||||
|
self._logger.error("device_shadow_listener should be DeviceShadowListener")
|
||||||
|
return
|
||||||
|
self.__shadow_listener = device_shadow_listener
|
||||||
|
|
||||||
|
def set_rule_action_handler(self, rule_action_handler: ActionHandler):
|
||||||
|
"""
|
||||||
|
设置端侧规则监听器,用于自定义处理端侧规则
|
||||||
|
需要通过IoTDevice的getClient方法获取DeviceClient实例后,调用此方法设置消息监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
rule_action_handler: 端侧规则监听器
|
||||||
|
"""
|
||||||
|
if not isinstance(rule_action_handler, ActionHandler):
|
||||||
|
self._logger.error("rule_action_handler should be ActionHandler")
|
||||||
|
return
|
||||||
|
self.__rule_action_handler = rule_action_handler
|
||||||
|
|
||||||
|
def subscribe_topic(self, topic: str, qos: int, message_listener):
|
||||||
|
"""
|
||||||
|
订阅自定义topic。此接口只能用于订阅自定义topic
|
||||||
|
需要通过IoTDevice的getClient方法获取DeviceClient实例后,调用此方法设置消息监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
topic: 自定义topic
|
||||||
|
qos: qos
|
||||||
|
message_listener: 接收自定义消息的监听器
|
||||||
|
"""
|
||||||
|
self.__connection.subscribe_topic(topic, qos)
|
||||||
|
self.__raw_msg_listener_map[topic] = message_listener
|
||||||
|
|
||||||
|
def add_connect_listener(self, connect_listener):
|
||||||
|
"""
|
||||||
|
设置链路监听器,用户接收链路建立和断开事件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
connect_listener: 链路监听器
|
||||||
|
"""
|
||||||
|
self.__connection.add_connect_listener(connect_listener)
|
||||||
|
|
||||||
|
def set_connect_action_listener(self, connect_action_listener):
|
||||||
|
"""
|
||||||
|
设置连接动作监听器,用户接受连接成功或失败的事件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
connect_action_listener: 连接动作监听器
|
||||||
|
"""
|
||||||
|
self.__connection.set_connect_action_listener(connect_action_listener)
|
||||||
|
|
||||||
|
def report_device_info(self, device_info: DeviceBaseInfo, listener: Optional[ActionListener] = None):
|
||||||
|
"""
|
||||||
|
上报设备信息,包括:软件版本,硬件版本以及SDK版本
|
||||||
|
需要通过IoTDevice的getClient方法获取DeviceClient实例后,调用此方法设置消息监听器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device_info: 设备信息
|
||||||
|
listener: 发布监听器,若不设置监听器则设为None
|
||||||
|
"""
|
||||||
|
device_event = DeviceEvent()
|
||||||
|
device_event.service_id = "$sdk_info"
|
||||||
|
device_event.event_type = "sdk_info_report"
|
||||||
|
device_event.event_time = get_event_time()
|
||||||
|
paras: dict = {"device_sdk_version": self.__SDK_VERSION,
|
||||||
|
"sw_version": device_info.sw_version,
|
||||||
|
"fw_version": device_info.fw_version}
|
||||||
|
device_event.paras = paras
|
||||||
|
self.report_event(device_event, listener)
|
||||||
|
|
||||||
|
def enable_rule_manage(self):
|
||||||
|
return self.__enable_rule_manage
|
BIN
IoT/iot_device_sdk_python/client/device_client.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/device_client.pyc
Normal file
Binary file not shown.
53
IoT/iot_device_sdk_python/client/iot_result.py
Normal file
53
IoT/iot_device_sdk_python/client/iot_result.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class IotResult:
|
||||||
|
"""
|
||||||
|
处理结果
|
||||||
|
"""
|
||||||
|
def __init__(self, result_code: int, result_desc: str):
|
||||||
|
self._result_code: int = result_code
|
||||||
|
self._result_desc: str = result_desc
|
||||||
|
|
||||||
|
@property
|
||||||
|
def result_code(self):
|
||||||
|
"""
|
||||||
|
结果码,0表示成功,其他为失败
|
||||||
|
"""
|
||||||
|
return self._result_code
|
||||||
|
|
||||||
|
@result_code.setter
|
||||||
|
def result_code(self, value):
|
||||||
|
self._result_code = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def result_desc(self):
|
||||||
|
"""
|
||||||
|
结果描述
|
||||||
|
"""
|
||||||
|
return self._result_desc
|
||||||
|
|
||||||
|
@result_desc.setter
|
||||||
|
def result_desc(self, value):
|
||||||
|
self._result_desc = value
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {"result_code": self._result_code, "result_desc": self._result_desc}
|
||||||
|
|
||||||
|
|
||||||
|
SUCCESS = IotResult(0, "Success")
|
||||||
|
FAIL = IotResult(1, "Fail")
|
||||||
|
TIMEOUT = IotResult(2, "Timeout")
|
||||||
|
|
BIN
IoT/iot_device_sdk_python/client/iot_result.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/iot_result.pyc
Normal file
Binary file not shown.
BIN
IoT/iot_device_sdk_python/client/listener/__init__.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/listener/__init__.pyc
Normal file
Binary file not shown.
@ -0,0 +1,35 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from abc import abstractmethod, ABCMeta
|
||||||
|
|
||||||
|
|
||||||
|
class CommandListener(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
命令监听器,用于接收平台下发的命令。
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_command(self, request_id: str, service_id: str, command_name: str, paras: dict):
|
||||||
|
"""
|
||||||
|
命令处理
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id
|
||||||
|
service_id: 服务id
|
||||||
|
command_name: 命令名
|
||||||
|
paras: 命令参数
|
||||||
|
"""
|
BIN
IoT/iot_device_sdk_python/client/listener/command_listener.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/listener/command_listener.pyc
Normal file
Binary file not shown.
@ -0,0 +1,36 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from iot_device_sdk_python.transport.action_listener import ActionListener
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultPublishActionListener(ActionListener):
|
||||||
|
"""
|
||||||
|
默认发布监听器,用户可自行实现ActionListener类
|
||||||
|
"""
|
||||||
|
def on_success(self, message: str):
|
||||||
|
"""
|
||||||
|
发布成功
|
||||||
|
"""
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
def on_failure(self, message: str, e: Optional[Exception]):
|
||||||
|
"""
|
||||||
|
发布失败
|
||||||
|
"""
|
||||||
|
print(message)
|
Binary file not shown.
@ -0,0 +1,33 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from abc import abstractmethod, ABCMeta
|
||||||
|
from iot_device_sdk_python.client.request.device_message import DeviceMessage
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceMessageListener(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
设备消息监听器,用于接收平台下发的设备消息
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_device_message(self, message: DeviceMessage):
|
||||||
|
"""
|
||||||
|
处理平台下发的设备消息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 设备消息内容
|
||||||
|
"""
|
Binary file not shown.
@ -0,0 +1,37 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from abc import abstractmethod, ABCMeta
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.request.shadow_data import ShadowData
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceShadowListener(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
影子数据下发监听器
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_shadow_get(self, request_id: str, object_device_id: str, shadow: List[ShadowData]):
|
||||||
|
"""
|
||||||
|
处理平台下发的设备影子数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id
|
||||||
|
object_device_id: 设备id
|
||||||
|
shadow: 影子数据
|
||||||
|
"""
|
Binary file not shown.
@ -0,0 +1,47 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import List
|
||||||
|
from abc import abstractmethod, ABCMeta
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.request.service_property import ServiceProperty
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyListener(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
属性监听器,用于接收平台下发的属性读写操作
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_property_set(self, request_id: str, services: List[ServiceProperty]):
|
||||||
|
"""
|
||||||
|
处理写属性操作
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id
|
||||||
|
services: 服务属性列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_property_get(self, request_id: str, service_id: str):
|
||||||
|
"""
|
||||||
|
处理读属性操作
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request_id: 请求id
|
||||||
|
service_id: 服务id,可选
|
||||||
|
"""
|
||||||
|
|
BIN
IoT/iot_device_sdk_python/client/listener/property_listener.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/listener/property_listener.pyc
Normal file
Binary file not shown.
@ -0,0 +1,35 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from abc import abstractmethod, ABCMeta
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.request.raw_device_message import RawDeviceMessage
|
||||||
|
|
||||||
|
|
||||||
|
class RawDeviceMessageListener(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
设备消息监听器,用于接收平台下发的设备消息
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_raw_device_message(self, message: RawDeviceMessage):
|
||||||
|
"""
|
||||||
|
处理平台下发的设备消息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message: 设备消息内容
|
||||||
|
"""
|
Binary file not shown.
58
IoT/iot_device_sdk_python/client/mqtt_connect_conf.py
Normal file
58
IoT/iot_device_sdk_python/client/mqtt_connect_conf.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
|
||||||
|
class MqttConnectConf:
|
||||||
|
"""
|
||||||
|
mqtt 配置
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
""" 保活时间,仅MQTT协议,sdk默认填写120(单位:秒)。可选30~1200(秒)范围 """
|
||||||
|
self._keep_alive_time: int = 120
|
||||||
|
|
||||||
|
""" 客户端qos,0或1,默认为1 """
|
||||||
|
self._qos: int = 1
|
||||||
|
|
||||||
|
""" 连接超时时间 """
|
||||||
|
self._timeout: float = 1.0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def keep_alive_time(self):
|
||||||
|
""" 保活时间,仅MQTT协议,sdk默认填写120(单位:秒)。可选30~1200(秒)范围 """
|
||||||
|
return self._keep_alive_time
|
||||||
|
|
||||||
|
@keep_alive_time.setter
|
||||||
|
def keep_alive_time(self, value):
|
||||||
|
self._keep_alive_time = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def qos(self):
|
||||||
|
""" 客户端qos,0或1,默认为1 """
|
||||||
|
return self._qos
|
||||||
|
|
||||||
|
@qos.setter
|
||||||
|
def qos(self, value):
|
||||||
|
self._qos = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timeout(self):
|
||||||
|
""" 连接超时时间 """
|
||||||
|
return self._timeout
|
||||||
|
|
||||||
|
@timeout.setter
|
||||||
|
def timeout(self, value):
|
||||||
|
self._timeout = value
|
BIN
IoT/iot_device_sdk_python/client/mqtt_connect_conf.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/mqtt_connect_conf.pyc
Normal file
Binary file not shown.
BIN
IoT/iot_device_sdk_python/client/request/__init__.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/__init__.pyc
Normal file
Binary file not shown.
96
IoT/iot_device_sdk_python/client/request/command.py
Normal file
96
IoT/iot_device_sdk_python/client/request/command.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class Command:
|
||||||
|
"""
|
||||||
|
设备命令
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._service_id: str = ""
|
||||||
|
self._command_name: str = ""
|
||||||
|
self._device_id: str = ""
|
||||||
|
self._paras: dict = dict()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_id(self):
|
||||||
|
"""
|
||||||
|
设备的服务ID,在设备关联的产品模型中定义
|
||||||
|
"""
|
||||||
|
return self._service_id
|
||||||
|
|
||||||
|
@service_id.setter
|
||||||
|
def service_id(self, value):
|
||||||
|
self._service_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def command_name(self):
|
||||||
|
"""
|
||||||
|
设备命令名称,在设备关联的产品模型中定义
|
||||||
|
"""
|
||||||
|
return self._command_name
|
||||||
|
|
||||||
|
@command_name.setter
|
||||||
|
def command_name(self, value):
|
||||||
|
self._command_name = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_id(self):
|
||||||
|
"""
|
||||||
|
命令对应的目标设备ID,命令下发对应的最终目标设备,没有携带则表示目标设备即topic中指定的设备
|
||||||
|
"""
|
||||||
|
return self._device_id
|
||||||
|
|
||||||
|
@device_id.setter
|
||||||
|
def device_id(self, value):
|
||||||
|
self._device_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def paras(self):
|
||||||
|
"""
|
||||||
|
设备命令的执行参数,具体字段在设备关联的产品模型中定义
|
||||||
|
"""
|
||||||
|
return self._paras
|
||||||
|
|
||||||
|
@paras.setter
|
||||||
|
def paras(self, value):
|
||||||
|
self._paras = value
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""
|
||||||
|
将请求内容放到字典中
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 字典形式的请求
|
||||||
|
"""
|
||||||
|
return {"service_id": self._service_id,
|
||||||
|
"command_name": self._command_name,
|
||||||
|
"object_device_id": self._device_id,
|
||||||
|
"paras": self._paras}
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["service_id", "command_name", "object_device_id", "paras"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "service_id":
|
||||||
|
self.service_id = json_dict.get(key)
|
||||||
|
elif key == "command_name":
|
||||||
|
self.command_name = json_dict.get(key)
|
||||||
|
elif key == "object_device_id":
|
||||||
|
self.device_id = json_dict.get(key)
|
||||||
|
elif key == "paras":
|
||||||
|
self.paras = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
BIN
IoT/iot_device_sdk_python/client/request/command.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/command.pyc
Normal file
Binary file not shown.
101
IoT/iot_device_sdk_python/client/request/command_response.py
Normal file
101
IoT/iot_device_sdk_python/client/request/command_response.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class CommandRsp:
|
||||||
|
"""
|
||||||
|
命令响应
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._result_code: int = 0
|
||||||
|
self._response_name: str = ""
|
||||||
|
self._paras: dict = dict()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def result_code(self):
|
||||||
|
"""
|
||||||
|
标识命令的执行结果,0表示成功,其他表示失败。不带默认认为成功。
|
||||||
|
"""
|
||||||
|
return self._result_code
|
||||||
|
|
||||||
|
@result_code.setter
|
||||||
|
def result_code(self, value):
|
||||||
|
self._result_code = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def response_name(self):
|
||||||
|
"""
|
||||||
|
命令的响应名称,在设备关联的产品模型中定义
|
||||||
|
"""
|
||||||
|
return self._response_name
|
||||||
|
|
||||||
|
@response_name.setter
|
||||||
|
def response_name(self, value):
|
||||||
|
self._response_name = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def paras(self):
|
||||||
|
"""
|
||||||
|
命令的响应参数,具体字段在设备关联的产品模型中定义
|
||||||
|
"""
|
||||||
|
return self._paras
|
||||||
|
|
||||||
|
@paras.setter
|
||||||
|
def paras(self, value):
|
||||||
|
self._paras = value
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""
|
||||||
|
将响应内容放到字典中
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 字典形式的响应
|
||||||
|
"""
|
||||||
|
return {"result_code": self._result_code,
|
||||||
|
"response_name": self._response_name,
|
||||||
|
"paras": self._paras}
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["result_code", "response_name", "paras"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "result_code":
|
||||||
|
self.result_code = json_dict.get(key)
|
||||||
|
elif key == "response_name":
|
||||||
|
self.response_name = json_dict.get(key)
|
||||||
|
elif key == "paras":
|
||||||
|
self.paras = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def success_code():
|
||||||
|
"""
|
||||||
|
返回成功的结果码
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 成功的结果码
|
||||||
|
"""
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fail_code():
|
||||||
|
"""
|
||||||
|
返回失败的结果码
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 失败的结果码
|
||||||
|
"""
|
||||||
|
return -1
|
BIN
IoT/iot_device_sdk_python/client/request/command_response.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/command_response.pyc
Normal file
Binary file not shown.
41
IoT/iot_device_sdk_python/client/request/device_base_info.py
Normal file
41
IoT/iot_device_sdk_python/client/request/device_base_info.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class DeviceBaseInfo:
|
||||||
|
def __init__(self):
|
||||||
|
self._fw_version: str = ""
|
||||||
|
self._sw_version: str = ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fw_version(self):
|
||||||
|
"""
|
||||||
|
固件版本
|
||||||
|
"""
|
||||||
|
return self._fw_version
|
||||||
|
|
||||||
|
@fw_version.setter
|
||||||
|
def fw_version(self, value):
|
||||||
|
self._fw_version = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sw_version(self):
|
||||||
|
"""
|
||||||
|
软件版本
|
||||||
|
"""
|
||||||
|
return self._sw_version
|
||||||
|
|
||||||
|
@sw_version.setter
|
||||||
|
def sw_version(self, value):
|
||||||
|
self._sw_version = value
|
BIN
IoT/iot_device_sdk_python/client/request/device_base_info.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/device_base_info.pyc
Normal file
Binary file not shown.
108
IoT/iot_device_sdk_python/client/request/device_event.py
Normal file
108
IoT/iot_device_sdk_python/client/request/device_event.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class DeviceEvent:
|
||||||
|
"""
|
||||||
|
服务的事件
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._service_id: str = ""
|
||||||
|
self._event_type: str = ""
|
||||||
|
self._event_time: str = ""
|
||||||
|
self._event_id: str = ""
|
||||||
|
self._paras: dict = dict()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_id(self):
|
||||||
|
"""
|
||||||
|
事件所属的服务
|
||||||
|
"""
|
||||||
|
return self._service_id
|
||||||
|
|
||||||
|
@service_id.setter
|
||||||
|
def service_id(self, value):
|
||||||
|
self._service_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event_type(self):
|
||||||
|
"""
|
||||||
|
事件类型
|
||||||
|
"""
|
||||||
|
return self._event_type
|
||||||
|
|
||||||
|
@event_type.setter
|
||||||
|
def event_type(self, value):
|
||||||
|
self._event_type = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event_time(self):
|
||||||
|
"""
|
||||||
|
事件发生的时间
|
||||||
|
"""
|
||||||
|
return self._event_time
|
||||||
|
|
||||||
|
@event_time.setter
|
||||||
|
def event_time(self, value):
|
||||||
|
self._event_time = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event_id(self):
|
||||||
|
"""
|
||||||
|
事件id,通过该参数关联对应的事件请求
|
||||||
|
"""
|
||||||
|
return self._event_id
|
||||||
|
|
||||||
|
@event_id.setter
|
||||||
|
def event_id(self, value):
|
||||||
|
self._event_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def paras(self):
|
||||||
|
"""
|
||||||
|
事件具体的参数
|
||||||
|
"""
|
||||||
|
return self._paras
|
||||||
|
|
||||||
|
@paras.setter
|
||||||
|
def paras(self, value):
|
||||||
|
self._paras = value
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""
|
||||||
|
将请求内容放到字典中
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 字典形式的请求
|
||||||
|
"""
|
||||||
|
return {"service_id": self._service_id, "event_type": self._event_type, "event_time": self._event_time,
|
||||||
|
"event_id": self._event_id, "paras": self._paras}
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["service_id", "event_type", "event_time", "event_id", "paras"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "service_id":
|
||||||
|
self.service_id = json_dict.get(key)
|
||||||
|
elif key == "event_type":
|
||||||
|
self.event_type = json_dict.get(key)
|
||||||
|
elif key == "event_time":
|
||||||
|
self.event_time = json_dict.get(key)
|
||||||
|
elif key == "event_id":
|
||||||
|
self.event_id = json_dict.get(key)
|
||||||
|
elif key == "paras":
|
||||||
|
self.paras = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
BIN
IoT/iot_device_sdk_python/client/request/device_event.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/device_event.pyc
Normal file
Binary file not shown.
78
IoT/iot_device_sdk_python/client/request/device_events.py
Normal file
78
IoT/iot_device_sdk_python/client/request/device_events.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.request.device_event import DeviceEvent
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceEvents:
|
||||||
|
"""
|
||||||
|
设备事件
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._device_id: str = ""
|
||||||
|
self._services: List[DeviceEvent] = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_id(self):
|
||||||
|
"""
|
||||||
|
事件对应的最终目标设备,没有携带则表示目标设备即topic中指定的设备
|
||||||
|
"""
|
||||||
|
return self._device_id
|
||||||
|
|
||||||
|
@device_id.setter
|
||||||
|
def device_id(self, value: str):
|
||||||
|
self._device_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def services(self):
|
||||||
|
"""
|
||||||
|
事件服务列表
|
||||||
|
"""
|
||||||
|
return self._services
|
||||||
|
|
||||||
|
@services.setter
|
||||||
|
def services(self, value):
|
||||||
|
self._services = value
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""
|
||||||
|
将请求内容放到字典中
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 字典形式的请求
|
||||||
|
"""
|
||||||
|
service_list = list()
|
||||||
|
for service in self._services:
|
||||||
|
service_list.append(service.to_dict())
|
||||||
|
return {"object_device_id": self._device_id, "services": service_list}
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["object_device_id", "services"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "object_device_id":
|
||||||
|
self.device_id = json_dict.get(key)
|
||||||
|
elif key == "services":
|
||||||
|
device_event_dict_list = json_dict.get(key)
|
||||||
|
for device_event_dict in device_event_dict_list:
|
||||||
|
device_event = DeviceEvent()
|
||||||
|
device_event.convert_from_dict(device_event_dict)
|
||||||
|
self._services.append(device_event)
|
||||||
|
else:
|
||||||
|
pass
|
BIN
IoT/iot_device_sdk_python/client/request/device_events.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/device_events.pyc
Normal file
Binary file not shown.
94
IoT/iot_device_sdk_python/client/request/device_message.py
Normal file
94
IoT/iot_device_sdk_python/client/request/device_message.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class DeviceMessage:
|
||||||
|
"""
|
||||||
|
设备消息
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._object_device_id: str = ""
|
||||||
|
self._id: str = ""
|
||||||
|
self._name: str = ""
|
||||||
|
self._content: str = ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_id(self):
|
||||||
|
"""
|
||||||
|
消息对应的最终目标设备,没有携带则表示目标设备即topic中指定的设备
|
||||||
|
"""
|
||||||
|
return self._object_device_id
|
||||||
|
|
||||||
|
@device_id.setter
|
||||||
|
def device_id(self, value):
|
||||||
|
self._object_device_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
"""
|
||||||
|
消息id,消息的唯一标识
|
||||||
|
"""
|
||||||
|
return self._id
|
||||||
|
|
||||||
|
@id.setter
|
||||||
|
def id(self, value):
|
||||||
|
self._id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""
|
||||||
|
消息名称
|
||||||
|
"""
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, value):
|
||||||
|
self._name = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content(self):
|
||||||
|
"""
|
||||||
|
消息内容
|
||||||
|
"""
|
||||||
|
return self._content
|
||||||
|
|
||||||
|
@content.setter
|
||||||
|
def content(self, value):
|
||||||
|
self._content = value
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""
|
||||||
|
将请求内容放到字典中
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 字典形式的请求
|
||||||
|
"""
|
||||||
|
return {"object_device_id": self._object_device_id, "id": self._id, "name": self._name,
|
||||||
|
"content": self._content}
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["object_device_id", "name", "id", "content"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "object_device_id":
|
||||||
|
self.device_id = json_dict.get(key)
|
||||||
|
elif key == "id":
|
||||||
|
self.id = json_dict.get(key)
|
||||||
|
elif key == "name":
|
||||||
|
self.name = json_dict.get(key)
|
||||||
|
elif key == "content":
|
||||||
|
self.content = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
BIN
IoT/iot_device_sdk_python/client/request/device_message.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/device_message.pyc
Normal file
Binary file not shown.
53
IoT/iot_device_sdk_python/client/request/properties_data.py
Normal file
53
IoT/iot_device_sdk_python/client/request/properties_data.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class PropertiesData:
|
||||||
|
"""
|
||||||
|
属性数据
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._properties: dict = dict()
|
||||||
|
self._event_time: str = ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def properties(self):
|
||||||
|
"""
|
||||||
|
设备服务的属性列表,具体字段在设备关联的产品模型里定义,可以设置多个字段
|
||||||
|
"""
|
||||||
|
return self._properties
|
||||||
|
|
||||||
|
@properties.setter
|
||||||
|
def properties(self, value):
|
||||||
|
self._properties = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event_time(self):
|
||||||
|
return self._event_time
|
||||||
|
|
||||||
|
@event_time.setter
|
||||||
|
def event_time(self, value):
|
||||||
|
self._event_time = value
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["properties", "event_time"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "properties":
|
||||||
|
self.properties = json_dict.get(key)
|
||||||
|
elif key == "event_time":
|
||||||
|
self.event_time = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
BIN
IoT/iot_device_sdk_python/client/request/properties_data.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/properties_data.pyc
Normal file
Binary file not shown.
56
IoT/iot_device_sdk_python/client/request/props_get.py
Normal file
56
IoT/iot_device_sdk_python/client/request/props_get.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class PropsGet:
|
||||||
|
"""
|
||||||
|
读属性操作
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._device_id: str = ""
|
||||||
|
self._service_id: str = ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_id(self):
|
||||||
|
"""
|
||||||
|
命令对应的目标设备ID,命令下发对应的最终目标设备,没有携带则表示目标设备即topic中指定的设备
|
||||||
|
"""
|
||||||
|
return self._device_id
|
||||||
|
|
||||||
|
@device_id.setter
|
||||||
|
def device_id(self, value):
|
||||||
|
self._device_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_id(self):
|
||||||
|
"""
|
||||||
|
设备的服务ID,在设备关联的产品模型中定义
|
||||||
|
"""
|
||||||
|
return self._service_id
|
||||||
|
|
||||||
|
@service_id.setter
|
||||||
|
def service_id(self, value):
|
||||||
|
self._service_id = value
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["object_device_id", "service_id"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "object_device_id":
|
||||||
|
self.device_id = json_dict.get(key)
|
||||||
|
elif key == "service_id":
|
||||||
|
self.service_id = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
BIN
IoT/iot_device_sdk_python/client/request/props_get.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/props_get.pyc
Normal file
Binary file not shown.
50
IoT/iot_device_sdk_python/client/request/props_set.py
Normal file
50
IoT/iot_device_sdk_python/client/request/props_set.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.request.service_property import ServiceProperty
|
||||||
|
|
||||||
|
|
||||||
|
class PropSet:
|
||||||
|
"""
|
||||||
|
写属性操作
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._device_id: str = ""
|
||||||
|
self._services: List[ServiceProperty] = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_id(self):
|
||||||
|
"""
|
||||||
|
命令对应的目标设备ID,命令下发对应的最终目标设备,没有携带则表示目标设备即topic中指定的设备
|
||||||
|
"""
|
||||||
|
return self._device_id
|
||||||
|
|
||||||
|
@device_id.setter
|
||||||
|
def device_id(self, value):
|
||||||
|
self._device_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def services(self):
|
||||||
|
"""
|
||||||
|
设备服务数据列表
|
||||||
|
"""
|
||||||
|
return self._services
|
||||||
|
|
||||||
|
@services.setter
|
||||||
|
def services(self, value):
|
||||||
|
self._services = value
|
BIN
IoT/iot_device_sdk_python/client/request/props_set.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/props_set.pyc
Normal file
Binary file not shown.
@ -0,0 +1,70 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
from json import JSONDecodeError
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.request.device_message import DeviceMessage
|
||||||
|
|
||||||
|
|
||||||
|
class RawDeviceMessage:
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
__SYSTEM_MESSAGE_KEYS = {"name", "id", "content", "object_device_id"}
|
||||||
|
|
||||||
|
"""
|
||||||
|
设备消息
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, payload: bytes):
|
||||||
|
self._payload = payload
|
||||||
|
|
||||||
|
@property
|
||||||
|
def payload(self):
|
||||||
|
"""
|
||||||
|
message下发的原始数据
|
||||||
|
"""
|
||||||
|
return self._payload
|
||||||
|
|
||||||
|
@payload.setter
|
||||||
|
def payload(self, payload: bytes):
|
||||||
|
self._payload = payload
|
||||||
|
|
||||||
|
def to_utf8_string(self):
|
||||||
|
""""
|
||||||
|
尝试将原始消息以utf-8格式decode,如无法decode,则raise UnicodeDecodeError
|
||||||
|
"""
|
||||||
|
return self._payload.decode('utf-8')
|
||||||
|
|
||||||
|
def to_device_message(self):
|
||||||
|
try:
|
||||||
|
device_msg_dict = json.loads(self.to_utf8_string())
|
||||||
|
except (JSONDecodeError, UnicodeDecodeError):
|
||||||
|
self._logger.debug("device message is not in system format")
|
||||||
|
return None # can't convert the system format
|
||||||
|
|
||||||
|
if any(map(lambda a: a not in self.__SYSTEM_MESSAGE_KEYS, device_msg_dict.keys())):
|
||||||
|
self._logger.debug("device message is not in system format because contain unexpected keys")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if any(map(lambda a: a is not None and not isinstance(a, str), device_msg_dict.values())):
|
||||||
|
self._logger.debug("device message is not in system format because some values are not str")
|
||||||
|
return None
|
||||||
|
|
||||||
|
device_msg = DeviceMessage()
|
||||||
|
device_msg.convert_from_dict(device_msg_dict)
|
||||||
|
return device_msg
|
BIN
IoT/iot_device_sdk_python/client/request/raw_device_message.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/raw_device_message.pyc
Normal file
Binary file not shown.
83
IoT/iot_device_sdk_python/client/request/service_property.py
Normal file
83
IoT/iot_device_sdk_python/client/request/service_property.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
class ServiceProperty:
|
||||||
|
"""
|
||||||
|
服务属性
|
||||||
|
"""
|
||||||
|
def __init__(self, service_id: str = "", properties: dict = None, event_time: str = None):
|
||||||
|
self._service_id: str = service_id
|
||||||
|
self._properties: dict = properties
|
||||||
|
self._event_time: str = event_time
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_id(self):
|
||||||
|
"""
|
||||||
|
设备的服务ID,在设备关联的产品模型中定义
|
||||||
|
"""
|
||||||
|
return self._service_id
|
||||||
|
|
||||||
|
@service_id.setter
|
||||||
|
def service_id(self, value):
|
||||||
|
self._service_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def properties(self):
|
||||||
|
"""
|
||||||
|
属性值,具体字段由设备模型定义
|
||||||
|
"""
|
||||||
|
return self._properties
|
||||||
|
|
||||||
|
@properties.setter
|
||||||
|
def properties(self, value):
|
||||||
|
self._properties = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event_time(self):
|
||||||
|
"""
|
||||||
|
设备采集数据UTC时间(格式为毫秒级别:yyyy-MM-dd'T'HH:mm:ss.SSS'Z'),
|
||||||
|
如:20161219T114920Z或者2020-08-12T12:12:12.333Z。
|
||||||
|
|
||||||
|
设备上报数据不带该参数或参数格式错误时,则数据上报时间以平台时间为准。
|
||||||
|
"""
|
||||||
|
return self._event_time
|
||||||
|
|
||||||
|
@event_time.setter
|
||||||
|
def event_time(self, value):
|
||||||
|
self._event_time = value
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""
|
||||||
|
将请求内容放到字典中
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 字典形式的请求
|
||||||
|
"""
|
||||||
|
return {"service_id": self._service_id, "properties": self._properties, "event_time": self._event_time}
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["service_id", "properties", "event_time"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "service_id":
|
||||||
|
self.service_id = json_dict.get(key)
|
||||||
|
elif key == "properties":
|
||||||
|
self.properties = json_dict.get(key)
|
||||||
|
elif key == "event_time":
|
||||||
|
self.event_time = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
BIN
IoT/iot_device_sdk_python/client/request/service_property.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/service_property.pyc
Normal file
Binary file not shown.
94
IoT/iot_device_sdk_python/client/request/shadow_data.py
Normal file
94
IoT/iot_device_sdk_python/client/request/shadow_data.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from iot_device_sdk_python.client.request.properties_data import PropertiesData
|
||||||
|
|
||||||
|
|
||||||
|
class ShadowData:
|
||||||
|
"""
|
||||||
|
影子数据
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._service_id: str = ""
|
||||||
|
self._desired: Optional[PropertiesData] = None
|
||||||
|
self._reported: Optional[PropertiesData] = None
|
||||||
|
self._version: Optional[int] = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def service_id(self):
|
||||||
|
"""
|
||||||
|
服务id
|
||||||
|
"""
|
||||||
|
return self._service_id
|
||||||
|
|
||||||
|
@service_id.setter
|
||||||
|
def service_id(self, value):
|
||||||
|
self._service_id = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def desired(self):
|
||||||
|
"""
|
||||||
|
设备影子desired区的属性列表
|
||||||
|
"""
|
||||||
|
return self._desired
|
||||||
|
|
||||||
|
@desired.setter
|
||||||
|
def desired(self, value):
|
||||||
|
self._desired = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reported(self):
|
||||||
|
"""
|
||||||
|
设备影子reported区的属性列表
|
||||||
|
"""
|
||||||
|
return self._reported
|
||||||
|
|
||||||
|
@reported.setter
|
||||||
|
def reported(self, value):
|
||||||
|
self._reported = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def version(self):
|
||||||
|
"""
|
||||||
|
设备影子版本信息
|
||||||
|
"""
|
||||||
|
return self._version
|
||||||
|
|
||||||
|
@version.setter
|
||||||
|
def version(self, value):
|
||||||
|
self._version = value
|
||||||
|
|
||||||
|
def convert_from_dict(self, json_dict: dict):
|
||||||
|
json_name = ["service_id", "desired", "reported", "version"]
|
||||||
|
for key in json_dict.keys():
|
||||||
|
if key not in json_name:
|
||||||
|
continue
|
||||||
|
if key == "service_id":
|
||||||
|
self.service_id = json_dict.get(key)
|
||||||
|
elif key == "desired":
|
||||||
|
desired = PropertiesData()
|
||||||
|
desired.convert_from_dict(json_dict.get(key))
|
||||||
|
self.desired = desired
|
||||||
|
elif key == "reported":
|
||||||
|
reported = PropertiesData()
|
||||||
|
reported.convert_from_dict(json_dict.get(key))
|
||||||
|
self.reported = reported
|
||||||
|
elif key == "version":
|
||||||
|
self.version = json_dict.get(key)
|
||||||
|
else:
|
||||||
|
pass
|
BIN
IoT/iot_device_sdk_python/client/request/shadow_data.pyc
Normal file
BIN
IoT/iot_device_sdk_python/client/request/shadow_data.pyc
Normal file
Binary file not shown.
0
IoT/iot_device_sdk_python/devicelog/__init__.py
Normal file
0
IoT/iot_device_sdk_python/devicelog/__init__.py
Normal file
BIN
IoT/iot_device_sdk_python/devicelog/__init__.pyc
Normal file
BIN
IoT/iot_device_sdk_python/devicelog/__init__.pyc
Normal file
Binary file not shown.
137
IoT/iot_device_sdk_python/devicelog/device_log_service.py
Normal file
137
IoT/iot_device_sdk_python/devicelog/device_log_service.py
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import Optional
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
|
from iot_device_sdk_python.service.abstract_service import AbstractService
|
||||||
|
from iot_device_sdk_python.client.request.device_event import DeviceEvent
|
||||||
|
from iot_device_sdk_python.utils.iot_util import get_event_time
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceLogService(AbstractService):
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
_LOG_CONFIG = "log_config"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self._log_switch = True # 默认为True
|
||||||
|
self._end_time = None
|
||||||
|
self._connect_lost_dict: Optional[dict] = None
|
||||||
|
self._connect_failed_dict: Optional[dict] = None
|
||||||
|
|
||||||
|
def on_event(self, device_event: DeviceEvent):
|
||||||
|
"""
|
||||||
|
设备日志服务的事件处理方法
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device_event: 设备事件
|
||||||
|
"""
|
||||||
|
if device_event.event_type == self._LOG_CONFIG:
|
||||||
|
# 平台下发日志收集通知
|
||||||
|
paras: dict = device_event.paras
|
||||||
|
if "switch" in paras.keys():
|
||||||
|
str_switch = paras.get("switch")
|
||||||
|
else:
|
||||||
|
self._logger.warning("event.paras doesn't contain key: switch. paras: %s", str(paras))
|
||||||
|
return
|
||||||
|
if "end_time" in paras.keys():
|
||||||
|
end_time = paras.get("end_time")
|
||||||
|
self.end_time = end_time
|
||||||
|
else:
|
||||||
|
self._logger.debug("event.paras doesn't contain key: end_time, paras: %s", str(paras))
|
||||||
|
if str_switch == "on":
|
||||||
|
self.log_switch = True
|
||||||
|
elif str_switch == "off":
|
||||||
|
self.log_switch = False
|
||||||
|
|
||||||
|
def report_device_log(self, timestamp: str, log_type: str, content: str):
|
||||||
|
"""
|
||||||
|
设备上报日志内容
|
||||||
|
|
||||||
|
Args:
|
||||||
|
timestamp: 日志产生的时间戳,精确到秒
|
||||||
|
log_type: 日志类型,总共有如下几种:
|
||||||
|
|
||||||
|
DEVICE_STATUS: 设备状态
|
||||||
|
|
||||||
|
DEVICE_PROPERTY: 设备属性
|
||||||
|
|
||||||
|
DEVICE_MESSAGE: 设备消息
|
||||||
|
|
||||||
|
DEVICE_COMMAND: 设备命令
|
||||||
|
content: 日志内容
|
||||||
|
"""
|
||||||
|
device_event = DeviceEvent()
|
||||||
|
device_event.service_id = self.service_id
|
||||||
|
device_event.event_type = "log_report"
|
||||||
|
device_event.event_time = get_event_time()
|
||||||
|
paras: dict = {"timestamp": timestamp,
|
||||||
|
"type": log_type,
|
||||||
|
"content": content}
|
||||||
|
device_event.paras = paras
|
||||||
|
self.get_iot_device().get_client().report_event(device_event)
|
||||||
|
|
||||||
|
def can_report_log(self):
|
||||||
|
"""
|
||||||
|
根据平台上设置的开关和结束时间来判断能否上报日志
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True为能上报日志;False为不具备上报的条件;
|
||||||
|
"""
|
||||||
|
end_time: str = self.end_time
|
||||||
|
if end_time is not None:
|
||||||
|
end_time = end_time.replace("T", "")
|
||||||
|
end_time = end_time.replace("Z", "")
|
||||||
|
|
||||||
|
current_time = time.strftime("%Y%m%d%H%M%S", time.localtime())
|
||||||
|
|
||||||
|
if self.log_switch and (end_time is None or current_time < end_time):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def log_switch(self):
|
||||||
|
return self._log_switch
|
||||||
|
|
||||||
|
@log_switch.setter
|
||||||
|
def log_switch(self, value):
|
||||||
|
self._log_switch = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_time(self):
|
||||||
|
return self._end_time
|
||||||
|
|
||||||
|
@end_time.setter
|
||||||
|
def end_time(self, value):
|
||||||
|
self._end_time = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def connect_lost_dict(self):
|
||||||
|
return self._connect_lost_dict
|
||||||
|
|
||||||
|
@connect_lost_dict.setter
|
||||||
|
def connect_lost_dict(self, value):
|
||||||
|
self._connect_lost_dict = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def connect_failed_dict(self):
|
||||||
|
return self._connect_failed_dict
|
||||||
|
|
||||||
|
@connect_failed_dict.setter
|
||||||
|
def connect_failed_dict(self, value):
|
||||||
|
self._connect_failed_dict = value
|
BIN
IoT/iot_device_sdk_python/devicelog/device_log_service.pyc
Normal file
BIN
IoT/iot_device_sdk_python/devicelog/device_log_service.pyc
Normal file
Binary file not shown.
BIN
IoT/iot_device_sdk_python/devicelog/listener/__init__.pyc
Normal file
BIN
IoT/iot_device_sdk_python/devicelog/listener/__init__.pyc
Normal file
Binary file not shown.
@ -0,0 +1,64 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from iot_device_sdk_python.transport.connect_action_listener import ConnectActionListener
|
||||||
|
from iot_device_sdk_python.devicelog.device_log_service import DeviceLogService
|
||||||
|
from iot_device_sdk_python.utils.iot_util import get_gmt_timestamp
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultConnActionLogListener(ConnectActionListener):
|
||||||
|
def __init__(self, device_log_service: DeviceLogService):
|
||||||
|
self._device_log_service = device_log_service
|
||||||
|
|
||||||
|
def on_success(self, token: int):
|
||||||
|
"""
|
||||||
|
首次建链成功
|
||||||
|
|
||||||
|
Args:
|
||||||
|
token: 返回token
|
||||||
|
"""
|
||||||
|
# 只有当connect_failed_dict不为空时report一次设备日志,上报建链失败的原因
|
||||||
|
# 若建链成功,这里不上报任何设备日志。因为会与DefaultConnLogListener的connect_complete()上报重复的日志,造成浪费
|
||||||
|
if self._device_log_service.connect_failed_dict is not None:
|
||||||
|
tmp = list(self._device_log_service.connect_failed_dict.keys())
|
||||||
|
timestamp = tmp[0]
|
||||||
|
self._device_log_service.report_device_log(timestamp, "DEVICE_STATUS",
|
||||||
|
self._device_log_service.connect_failed_dict.get(timestamp))
|
||||||
|
|
||||||
|
def on_failure(self, token: int, err: Optional[Exception]):
|
||||||
|
"""
|
||||||
|
首次建链失败
|
||||||
|
|
||||||
|
Args:
|
||||||
|
token: 返回token
|
||||||
|
err: 失败异常
|
||||||
|
"""
|
||||||
|
failed_dict = dict()
|
||||||
|
failed_dict[str(get_gmt_timestamp())] = "connect failed, the reason is " + str(err)
|
||||||
|
self._device_log_service.connect_failed_dict = failed_dict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,67 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023-2024 Huawei Cloud Computing Technology Co., Ltd. All rights reserved.
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from iot_device_sdk_python.transport.connect_listener import ConnectListener
|
||||||
|
from iot_device_sdk_python.devicelog.device_log_service import DeviceLogService
|
||||||
|
from iot_device_sdk_python.utils.iot_util import get_gmt_timestamp
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultConnLogListener(ConnectListener):
|
||||||
|
def __init__(self, device_log_service: DeviceLogService):
|
||||||
|
self._device_log_service = device_log_service
|
||||||
|
|
||||||
|
def connection_lost(self, cause: str):
|
||||||
|
"""
|
||||||
|
连接丢失通知
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cause: 连接丢失原因
|
||||||
|
"""
|
||||||
|
lost_dict = dict()
|
||||||
|
str_current_time_millis = str(get_gmt_timestamp())
|
||||||
|
lost_dict[str_current_time_millis] = "connect lost"
|
||||||
|
self._device_log_service.connect_lost_dict = lost_dict
|
||||||
|
|
||||||
|
def connect_complete(self, reconnect: bool, server_uri: str):
|
||||||
|
"""
|
||||||
|
连接成功通知,如果是断链重连的情景,重连成功会上报断链的时间戳
|
||||||
|
|
||||||
|
Args:
|
||||||
|
reconnect: 是否为重连(当前此参数没有作用)
|
||||||
|
server_uri: 服务端地址
|
||||||
|
"""
|
||||||
|
self._device_log_service.report_device_log(str(get_gmt_timestamp()), "DEVICE_STATUS",
|
||||||
|
"connect complete, the uri is " + str(server_uri))
|
||||||
|
if self._device_log_service.connect_lost_dict is not None:
|
||||||
|
key_list = list(self._device_log_service.connect_lost_dict.keys())
|
||||||
|
timestamp = key_list[0]
|
||||||
|
self._device_log_service.report_device_log(timestamp, "DEVICE_STATUS",
|
||||||
|
self._device_log_service.connect_lost_dict.get(timestamp))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
0
IoT/iot_device_sdk_python/filemanager/__init__.py
Normal file
0
IoT/iot_device_sdk_python/filemanager/__init__.py
Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user