华为云用户手册

  • 属性上报 以下消息转换为IoTDA平台的属性,应用可以通过查询设备影子或者数据转发接收属性上报消息。 上报位置信息 对应的消息ID:0x0200 推送样例: { "resource": "device.property", "event": "report", "event_time": "20151212T121212Z", "notify_data": { "header": { "device_id": "00000000000012345678", "product_id": "ABC123456789", "app_id": "d4922d8a-6c8e-4396-852c-164aefa6638f", "gateway_id": "00000000000012345678", "node_id": "00000000000012345678", "tags": [ { "tag_value": "testTagValue", "tag_key": "testTagName" } ] }, "body": { "services": [ { "service_id": "Location", "properties": { "alarm": { "emergencyAlarm": 0, "overSpeedAlarm": 0, "fatigueDrivingAlarm": 0, "dangerousDrivingAlarm": 0, "powerVoltageAlarm": 0, "powerOffAlarm": 0, "cameraErrorAlarm": 0, "overSpeedWarning": 0, "fatigueDrivingWarning": 0, "violationDrivingAlarm": 0, "tirePressureWarning": 0, "rightTurnErrorAlarm": 0, "overDrivingTimeAlarm": 0, "overParkAlarm": 0, "drivingAreaAlarm": 0, "drivingRouteAlarm": 0, "drivingTimeAbnormalAlarm": 0, "offCourseAlarm": 0, "gasolineAlarm": 0, "stolenAlarm": 0, "startingAbnormalAlarm": 0, "displacementAbnormalAlarm": 0, "rolloverAlarm": 0, "rolloverWarning": 0, "icerrorAlarm": 0, "lcderrorAlarm": 0, "ttserrorAlarm": 1, "gnssantennaShortCircuitAlarm": 0, "gnsserrorAlarm": 0, "gnssantennaNotConnectedAlarm": 0, "vssalarm": 0 }, "status": { "accStatus": 0, "positioningStatus": 0, "latitudeStatus": 0, "longitudeStatus": 0, "businessStatus": 0, "encryptedStatus": 0, "forwardCollisionWarningStatus": 0, "laneDeviationAlarmStatus": 0, "loadStatus": 0, "oilStatus": 0, "powerStatus": 1, "doorStatus": 0, "firstDoorStatus": 0, "secondDoorStatus": 0, "thirdDoorStatus": 0, "fourthDoorStatus": 0, "fifthDoorStatus": 0, "galileoStatus": 0, "vehicleStatus": 0, "gpsstatus": 0, "glonassstatus": 0, "bdsstatus": 0 }, "longitude": 116.307629, "latitude": 40.058359, "height": 312, "speed": 3, "direction": 99, "dateTime": "200707192359", "extend": [ ] }, "event_time": "20151212T121212Z" } ] } } } 表1 协议报文字段与属性对应表 起始字节 字段 数据类型 对应属性 0 报警标志 DWORD alarm 4 状态 DWORD status 8 纬度 DWORD longitude 12 经度 DWORD latitude 16 高程 WORD height 18 速度 WORD speed 20 方向 WORD direction 21 时间 BCD[6] dateTime 表2 报警预警标志位与alarm属性对应表 位 定义 对应属性 0 1:紧急报警 emergencyAlarm 1 1:超速报警 overSpeedAlarm 2 1:疲劳驾驶报警 fatigueDrivingAlarm 3 1:危险驾驶行为报警 dangerousDrivingAlarm 4 1:GNSS模块发生故障报警 gnsserrorAlarm 5 1:GNSS天线未接或被剪断报警 gnssantennaNotConnectedAlarm 6 1:GNSS天线短路报警 gnssantennaShortCircuitAlarm 7 1:终端主电源欠压报警 powerVoltageAlarm 8 1:终端主电源掉电报警 powerOffAlarm 9 1:终端LCD或显示器故障报警 lcderrorAlarm 10 1: TTS 模块故障报警 ttserrorAlarm 11 1:摄像头故障报警 cameraErrorAlarm 12 1:道路运输证IC卡模块故障报警 icerrorAlarm 13 1:超速预警 overSpeedWarning 14 1:疲劳驾驶预警 fatigueDrivingWarning 15 1:违规行驶报警 violationDrivingAlarm 16 1:胎压预警 tirePressureWarning 17 1:右转盲区异常报警 rightTurnErrorAlarm 18 1:当天累计驾驶超时报警 overDrivingTimeAlarm 19 1:超时停车报警 overParkAlarm 20 1:进出区域报警 drivingAreaAlarm 21 1:进出路线报警 drivingRouteAlarm 22 1:路段行驶时间不足/过长报警 drivingTimeAbnormalAlarm 23 1:路线偏离报警 offCourseAlarm 24 1:车辆VSS故障 vssalarm 25 1:车辆油量异常报警 gasolineAlarm 26 1:车辆被盗报警(通过车辆防盗器) stolenAlarm 27 1:车辆非法点火报警 startingAbnormalAlarm 28 1:车辆非法位移报警 displacementAbnormalAlarm 29 1:碰撞侧翻报警 rolloverAlarm 30 1:侧翻预警 rolloverWarning 31 保留 - 表3 状态标志位与status属性对应表 位 定义 对应属性 0 0:ACC关;1:ACC开 accStatus 1 0:未定位;1:定位 positioningStatus 2 0:北纬;1:南纬 latitudeStatus 3 0:东经;1:西经 longitudeStatus 4 0:运营状态;1:停运状态 businessStatus 5 0:经纬度未经保密插件加密;1:经纬度已经保密插加密 encryptedStatus 6 1:紧急刹车系统采集的前撞预警 forwardCollisionWarningStatus 7 1:车道偏移预警 laneDeviationAlarmStatus 8~9 00:空车;01:半载;10:保留;11:满载 loadStatus 10 0:车辆油路正常;1:车辆油路断开 oilStatus 11 0:车辆电路正常;1:车辆电路断开 powerStatus 12 0:车门解锁;1:车门加锁 doorStatus 13 0:门1关;1:门1开(前门) firstDoorStatus 14 0:门2关;1:门2开(中门) secondDoorStatus 15 0:门3关;1:门3开(后门) thirdDoorStatus 16 0:门4关;1:门4开(驾驶席门) fourthDoorStatus 17 0:门5关;1:门5开(自定义) fifthDoorStatus 18 0:未使用GPS卫星进行定位;1:使用GPS卫星进行定位 gpsstatus 19 0:未使用北斗卫星进行定位;1:使用北斗卫星进行定位 bdsstatus 20 0:未使用GLONASS卫星进行定位;1:使用GLONASS卫星进行定位 glonassstatus 21 0:未使用Galileo卫星进行定位;1:使用Galileo卫星进行定位 galileoStatus 22 0:车辆处于停止状态;1:车辆处于行驶状态 vehicleStatus 23~31 保留 -
  • 方案架构 方案总体架构框图如下: 图1 总体架构图 各种不同协议类型的设备,通过泛协议插件,最终以MQTT协议和华为云 物联网平台 进行链接。泛协议插件是各种不同协议类型设备和华为云物联网平台之间的中间层,用以屏蔽各种不同协议之间的差异。泛协议插件由三部分组成: “泛协议设备接入层”:用于以特定网络协议与泛协议设备建链。 “协议桥接适配层”:负责完成第三方协议数据和平台格式数据的互相转换。 上行:把第三方协议数据转成平台格式数据,并调用泛协议SDK接口进行上报。 下行:收到平台下行数据时,将平台格式数据转换为第三方协议数据转发给第三方协议设备。 “泛协议SDK”:即平台提供的泛协议接入接入SDK,提供了网桥的通用功能实现。
  • 部署插件 访问 设备接入服务 ,单击“管理控制台 ”进入设备接入控制台。 单击“IoTDA实例 ”,单击具体实例“详情”按钮,选择“泛协议接入”。 图1 泛协议-泛协议接入 选择“云网关”,单击“新增云网关” 。端口填写为“8898”。镜像选择镜像名称为“protocol-plugin-sl651”的镜像。 图2 泛协议-部署成功SL651 防火墙和安全组需要放通8898端口(TCP)。 父主题: SL651协议接入
  • 部署插件 具体操作: 访问设备接入服务,单击“管理控制台 ”进入设备接入控制台。 单击“IoTDA实例 ”,单击具体实例“详情”按钮,选择“泛协议接入”。 图1 泛协议-泛协议接入 选择“云网关”,单击“新增云网关” 。端口填写为“8890”。镜像选择镜像名称为“protocol-plugin-hj212”的镜像。 图2 泛协议-部署成功HJ212 防火墙放通8890端口(TCP)。 父主题: HJ212协议接入
  • 入门实践 我们整理了从队列网络连通、不同类型的作业分析、数据迁移场景的常用开发指南和最佳实践内容,帮助您更好的使用 DLI 进行大数据分析和处理。 表1 DLI常用开发指南与最佳实践 场景 操作指导 描述 队列网络连通 配置DLI队列与内网数据源的网络连通 DLI在创建运行作业需要连接外部其他数据源,本节操作介绍队列与外部数据源之间的网络连通方法,如:DLI连接 MRS 、RDS、 CSS 、Kafka、DWS时,需要打通DLI和外部数据源之间的网络。 配置DLI 队列与公网网络连通 介绍DLI队列在公网访问场景下网络连通的方法。通过配置SNAT规则,添加到公网的路由信息,可以实现队列到和公网的网络打通。 Spark SQL作业开发 使用Spark SQL作业分析OBS数据 介绍使用Spark SQL作业创建OBS表、导入OBS表数据、插入和查询OBS表数据等操作。 Flink OpenSource SQL作业开发 从Kafka读取数据写入到RDS 介绍使用Flink OpenSource SQL作业从Kafka读取数据写入到RDS的开发示例。 从Kafka读取数据写入到DWS 介绍使用Flink OpenSource SQL作业从Kafka读取数据写入到DWS的开发示例。 从Kafka读取数据写入到Elasticsearch 介绍使用Flink OpenSource SQL作业从Kafka读取数据写入到Elasticsearch的开发示例。 从MySQL CDC源表读取数据写入到DWS 介绍使用Flink OpenSource SQL作业从MySQL CDC源表读取数据写入到DWS的开发示例。 从PostgreSQL CDC源表读取数据写入到DWS 介绍使用Flink OpenSource SQL作业从PostgreSQL CDC源表读取数据写入到DWS的开发示例。 Flink Jar作业开发 Flink Jar作业开发基础样例 通过自定义作业与MRS进行交互为例进行介绍Flink Jar作业开发样例。 使用Flink Jar写入数据到OBS开发指南 介绍将kafka数据处理后写入到OBS的操作样例。 使用Flink Jar连接开启SASL_SSL认证的Kafka 介绍使用Flink OpenSource SQL连接开启SASL_SSL认证的Kafka。 使用Flink Jar读写DIS开发指南 介绍Flink Jar作业读写DIS数据的操作方法。 Spark Jar作业开发 使用Spark Jar作业读取和查询OBS数据 介绍从编写Spark程序代码读取和查询OBS数据、编译打包到提交Spark Jar作业的开发样例。 数据迁移 迁移Hive数据至DLI 介绍如何通过 CDM 数据同步功能,迁移MRS Hive数据至DLI。 迁移Kafka数据至DLI 介绍如何通过CDM数据同步功能,迁移MRS Kafka数据至DLI。 迁移Elasticsearch数据至DLI 介绍如何通过CDM数据同步功能,迁移Elasticsearch类型的 CS S集群数据至DLI。 迁移RDS数据至DLI 介绍如何通过CDM数据同步功能,迁移关系型数据库RDS数据至DLI。 迁移DWS数据至DLI 介绍如何通过CDM数据同步功能,迁移 数据仓库 服务DWS数据至DLI。
  • 后续指引 完成增强型跨源连接访问RDS快速入门操作后,如果您想了解更多关于跨源连接的相关操作,建议您参考以下指引阅读。 分类 文档 说明 界面操作 跨源连接和跨源分析 提供跨源连接、分析相关的功能介绍和操作指导。 开发指南 跨源访问其他数据源 提供跨源访问CSS、DWS、HBase、OpenTSDB、RDS、Redis、Mongo等样例代码和开发指导。 增强型跨源API参考 提供增强型跨源相关API接口指导。
  • 步骤6:提交SQL作业 本节示例以SQL作业为例说明如何跨源访问RDS表。 在DLI管理控制台的左侧导航栏中,单击“SQL编辑器”,进入SQL作业编辑器页面。 在“SQL编辑器”页面右侧的编辑窗口中,输入如下SQL语句创建数据库db1,单击“执行”。 create database db1; 在编辑窗口中,选择队列“dli_queue_01”和数据库“db1”。输入如下SQL语句创建表,向RDS表插入数据,以及查询数据,单击“执行”。 根据界面显示的执行结果查询RDS表数据信息,整个操作完成。 CREATE TABLE IF NOT EXISTS rds_test USING JDBC OPTIONS ( 'url' = 'jdbc:mysql://{{ip}}:{{port}}', //RDS内网地址及端口 'driver' = 'com.mysql.jdbc.Driver', 'dbtable' = 'dli_demo.tabletest', //在RDS创建的库名及表名 'passwdauth'="xxxxx" // DLI侧创建的Password类型的跨源认证名称。使用跨源认证则无需在作业中配置账号和密码。 ) insert into rds_test VALUES ('123','abc'); SELECT * from rds_test;
  • 步骤2:创建RDS数据库表 登录RDS管理控制台。 在管理控制台左上角选择区域和项目。 在“实例管理页面”,找到您已经创建的RDS实例,记录并保存RDS实例的内网地址。 图2 内网地址 单击所创建RDS实例的“登录”,跳转至“数据管理服务-DAS”。输入相关账户信息,单击“测试连接”。显示连接成功后,单击“登录”,进入“实例登录”页面。 图3 登录RDS 图4 实例登录 登录RDS实例后,单击“新建数据库”,创建名称为“dli_demo”的数据库。 单击“SQL查询”,执行如下SQL创建表。 CREATE TABLE `dli_demo`.`tabletest` ( `id` VARCHAR(32) NOT NULL, `name` VARCHAR(32) NOT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4;
  • 操作流程 使用DLI提交SQL作业查询RDS MySQL数据操作流程如表1所示。 开始进行如下操作前,请务必参考准备工作完成必要操作。 表1 使用DLI提交SQL作业查询RDS MySQL数据的操作流程 操作步骤 说明 步骤1:创建RDS MySQ L实例 样例场景需要创建RDS MySQL实例。 步骤2:创建RDS数据库表 登录RDS实例创建数据库和表。 步骤3:创建弹性资源池并添加队列 创建提交作业所需的计算资源。 步骤4:创建增强型跨源连接 通过增强型跨源连接建立DLI弹性资源池与RDS实例的网络连通。 步骤5:创建跨源认证 使用跨源认证保存DLI读写RDS数据的访问凭证。 步骤6:提交SQL作业 使用标准SQL语句进行数据的查询和分析。
  • 步骤1:创建RDS MySQL实例 本样例中,假设作业名称为“JobSample”,采用RDS服务作为数据源,创建RDS MySQL实例,具体操作请参见《 云数据库MySQL 快速入门》中的“MySQL快速入门”章节。 登录RDS管理控制台。 在管理控制台左上角选择区域和项目。 在“实例管理”页面,单击“购买数据库实例”。 在购买数据库实例页面,选择计费模式,填写并选择实例相关信息后,单击“立即购买”。 根据业务规划配置参数信息,本例参数配置信息如所示。 更多RDS实例的参数配置信息请参考购买RDS实例。 表2 RDS MySQL实例参数配置信息 参数名称 参数说明 取值样例 计费模式 选择RDS实例的计费模式。 按需计费 区域 资源所在的区域。 华东-上海二 实例名称 实例名称。 rds-demo 数据库引擎 MySQL MySQL 数据库版本 选用RDS for MySQL数据库时,请根据实际业务需求选择合适的数据库引擎版本。建议您选择当前可用的最高版本数据库,因其性能更稳定,安全性更高,使用更可靠。 8.0 实例类型 选择实例的主备类型。 单机 存储类型 实例的存储类型决定实例的读写速度。最大吞吐量越高,读写速度越快。 SSD云盘 可用区 对于单机实例,仅需选择单个可用区。 - 时区 由于世界各国家与地区经度不同,地方时也有所不同,因此会划分为不同的时区。时区可在创建实例时选择,后期可修改。 默认 性能规格 实例的CPU和内存。不同性能规格对应不同连接数和最大IOPS。 2vCPUs | 4GB 存储空间 如果存储类型为SSD云盘或极速型SSD,可设置存储空间自动扩容,当存储空间可用率过小时,会自动扩容存储空间。 40GB 磁盘加密 选择是否开启磁盘加密功能。 不加密 虚拟私有云 选择已有的虚拟私有云。 如需重新创建VPC和子网,请参考创建虚拟私有云和子网。 说明: 跨源场景数据源网段和弹性资源池的网段不能重合。 - 数据库端口 默认使用3306端口。 3306 安全组 安全组限制实例的安全访问规则,加强云数据库RDS服务与其他服务间的安全访问。 数据源的安全组需放通DLI弹性资源池的网段。 - 设置密码 设置实例的登录密码。 - 管理员账号 root root 管理员密码 设置管理员密码。 - 参数模板 数据库参数模板就像是数据库引擎配置值的容器,参数模板中的参数可应用于一个或多个相同类型的数据库实例。 系统默认模板:Default-MySQL-5.7 表名大小写 配置表名不区分大小写。 不区分大小写 企业项目 对于已成功关联企业项目的用户,仅需在“企业项目”下拉框中选择目标项目。 default 购买数量 实例购买数量 1 只读实例 为了实现读取能力的弹性扩展,分担数据库压力,您可以在某个区域中创建一个或多个只读实例。 暂不购买 单击“立即购买”,进入规格确认页面。 单击“提交”,完成购买RDS MySQL实例。 实例创建成功后,用户可以在“实例管理”页面对其进行查看和管理。 创建实例过程中,状态显示为“创建中”,创建完成的实例状态显示为“正常”。您可以通过“任务中心”查看详细进度和结果。
  • 快速入门 如果您是首次使用华为云Flexus云服务,您可以根据快速入门快速了解并使用华为云Flexus云服务。本文介绍华为云Flexus云服务各产品的快速入门内容以及文档索引。 产品类型 内容说明 文档索引 Flexus应用服务器L实例 入门指引 介绍Flexus L实例产品基础知识、计费方式、使用流程、了解控制台以及新用户常见问题等,帮助您快速了解并使用Flexus L实例。 使用WordPress应用镜像搭建网站 为您介绍如何使用Flexus L实例的WordPress应用镜像三步快速搭建网站。 使用CentOS系统镜像部署Nginx服务器 介绍如何使用Flexus L实例的CentOS系统镜像部署Nginx服务器。 Flexus L实例快速入门 Flexus云服务器X实例 入门指引 介绍Flexus X实例产品基础知识、计费方式、使用流程、了解控制台以及新用户常见问题等,帮助您快速了解并使用Flexus X实例。 购买并登录Flexus X实例 介绍如何在管理控制台快速购买并登录Flexus X实例。 Flexus X实例快速入门 Flexus云数据库RDS 购买并登录Flexus云数据库RDS 介绍如何购买到Flexus数据库并通过DAS连接Flexus数据库。 Flexus数据库快速入门
  • 发布Topic 发布Topic是指设备主动向平台上报自己的属性或消息,详细见设备属性上报接口文档。 在FrmMqttDemo中实现了上报Topic、属性上报功能。 1 2 3 4 5 6 7 8 var appMsg = new MqttApplicationMessage(); appMsg.Payload = Encoding.UTF8.GetBytes(inputString); appMsg.Topic = topic; appMsg.QualityOfServiceLevel = int.Parse(cbOosSelect.SelectedValue.ToString()) == 0 ? MqttQualityOfServiceLevel.AtMostOnce : MqttQualityOfServiceLevel.AtLeastOnce; appMsg.Retain = false; // 上行响应 client.PublishAsync(appMsg).Wait(); 发布Topic后,Demo界面显示如下: 设备上报属性成功后可在设备详情页面查看到上报的属性: 图2 查看上报数据-Demo_smokeDetector 如果在“设备详情”页面没有最新上报数据,请修改产品模型中服务和属性的内容,确保设备上报的服务/属性和产品模型中的服务/属性一致,或者进入“产品基本信息”页面,删除所有服务。 由于是同步命令需要端侧回复响应可参考接口。
  • 操作步骤 访问设备接入服务,单击“管理控制台”进入“设备接入”控制台。选择您的实例,单击实例卡片进入。 单击左侧导航栏的“产品”,在产品列表中,找到对应的产品,单击产品进入产品详情页。 在产品详情基本信息页面,单击“自定义模型”,添加服务。 输入“服务ID”、“服务类型”和“服务描述”,然后单击“确定”。 “服务ID”:采用首字母大写的命名方式。比如:WaterMeter、StreetLight。 “服务类型”:建议和服务ID保持一致。 “服务描述”:比如路灯上报的环境光强度和路灯开关状态的属性。 添加服务后,在“添加服务”区域,对属性和命令进行定义。每个服务下,可以包含属性和命令,也可以只包含其中之一,请根据此类设备的实际情况进行配置。 单击步骤4新增的服务ID,在展开的页面单击“新增属性”,在弹出窗口中配置属性的各项参数,然后单击“确定”。 参数 说明 属性名称 建议采用驼峰形式,如batteryLevel、internalTemperature。 数据类型 int:当上报的数据为整数时,可配置为此类型。 long: 当上报的数据为长整型时,可配置为此类型。 decimal:当上报的数据为小数时,可配置为此类型。配置“经纬度”属性时,数据类型建议使用“decimal”。 string:当上报的数据为字符串、枚举值时,可以配置为此类型。如果为枚举值,值之间需要用英文逗号(“,”)分隔。 dateTime:当上报的数据为日期时,可以配置为此类型。 此类型属性上报格式推荐样例:2020-09-01T18:50:20Z或者2020-09-01T18:50:20.200Z jsonObject:当上报的数据为JSON结构体时,可以配置为此类型。 enum: 当上报的数据为枚举值时,可配置为此类型。 搭配参数enumList格式填写,比如状态属性的enumList填写为OPEN,CLOSE,那么属性上报格式样例为"OPEN"或者"CLOSE" boolean: 当上报的数据为布尔值时,可配置为此类型。 此类型属性上报推荐格式样例:true/false 或者 0/1 stringList: 当上报的数据为字符串数组时,可配置为此类型。 此类型属性上报推荐格式样例:["str1","str2","str3"] 访问权限 可读:通过接口可以查询该属性。 可写:通过接口可以修改该属性值。 取值范围 请根据此类设备的实际情况进行配置。 步长 单位 图1 新增属性-batteryLevel 单击“添加命令”,在弹出窗口中配置命令。 “命令名称”:建议采用全大写形式,单词间用下划线连接的命名方式,如DISCOVERY,CHANGE_STATUS。 “下发参数”:单击“新增输入参数”,在弹出窗口中配置下发命令字段的各项参数,然后“确定”。 参数 说明 参数名称 建议采用第一个单词首字母小写,其余单词的首字母大写的命名方式,比如valueChange 数据类型 请根据此类设备的实际情况进行配置。 取值范围 步长 单位 图2 新增命令CHANGE_STATUS 如果要添加命令响应,单击“新增响应参数”,在弹出窗口中配置响应命令字段的各项参数,然后单击“确定”。 参数 说明 参数名称 建议采用第一个单词首字母小写,其余单词的首字母大写的命名方式,比如valueResult 数据类型 请根据此类设备的实际情况进行配置。 取值范围 步长 单位 图3 新增命令响应参数-valueAResult
  • 概述 在线开发产品模型前需要创建产品。创建产品需要输入产品名称、协议类型、数据格式、所属行业和设备类型等信息,产品模型会使用这些信息作为设备能力字段取值。物联网平台提供了标准模型和厂商模型,这些模型涉及多个领域,模型中提供了已经编辑好的产品模型文件,您可以根据自己的需要对产品模型中的字段进行修改和增删;如果选择自定义产品模型,则需要完整定义产品模型。 本节定义包含一个服务的产品模型为示例,该产品模型包含设备上报数据、下发命令、下发命令响应等场景的服务和字段。
  • 上报升级结果 根据PCP协议约定的交互流程,设备在执行完软件升级后,将会向物联网平台上报升级的结果。 设备发送的请求消息 根据PCP消息结构的定义可以得出,设备向物联网平台上报升级结果,各个消息字段的填写如下: 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致,为18。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段的数据类型得出数据区长度为17字节,转换为十六进制为:0011。 数据区:结果码,以上报升级成功为例,结果码为00。当前版本号:升级完成后的版本号,与物联网平台下发的软件版本一致,即v1.0,转换为十六进制为:56312E30000000000000000000000000。 字段 数据类型 描述及要求 结果码 BYTE 0X00升级成功。 0X01设备使用中。 0X04电量不足。 0X05剩余空间不足。 0X09内存不足。 0X0A安装升级包失败。 0X7F内部异常。 当前版本号 BYTE[16] 设备当前版本号。 设备向物联网平台上报升级结果的消息为:FFFE 01 18 0000 0011 0056312E30000000000000000000000000(CRC16校验前),经CRC16计算得到校验码为:C7D2。则替换校验码后设备向物联网平台上报升级结果码流为:FFFE0118C7D200110056312E30000000000000000000000000。 物联网平台发送的应答消息 物联网平台收到设备上报的升级结果消息后,将对设备进行应答,各个消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致:18。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段定义得出该数据长度为1个字节,转换为十六进制为:0001。 数据区:处理成功,则返回00,升级任务不存在80。本示例以返回00处理成功为例进行说明。 字段 数据类型 描述及要求 结果码 BYTE 0X00处理成功。 0X80升级任务不存在。 物联网平台向设备的应答消息为:FFFE 01 18 0000 0001 00 (CRC16校验前),经CRC16计算得到校验码为:AFA1。则替换校验码后物联网平台返回的应答消息为:FFFE0118AFA1000100 。
  • 上报下载结果 根据PCP协议约定的交互流程,设备接收完所有分片数据并组装完软件包后,需要向物联网平台上报软件包的下载结果。 设备发送的请求消息 根据PCP消息结构的定义可以得出,设备向物联网平台发送的上报软件包下载结果消息,各个消息字段的填写如下: 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致,为16。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段的数据类型得出数据区长度为1个字节,转换为十六进制为:0001。 数据区:上报软件包的下载结果,比如下载成功,设备侧上报00。 字段 数据类型 描述及要求 下载状态 BYTE 0X00下载成功。 0X05剩余空间不足。 0X06下载超时。 0X07升级包校验失败。 0X08升级包类型不支持。 设备向物联网平台发送升级包下载结果的消息为:FFFE 01 16 0000 0001 00(CRC16校验前),经CRC16计算得到校验码为:850E。则替换校验码后设备发送的升级包下载结果的消息为:FFFE0116850E000100。 物联网平台的应答消息 物联网平台收到设备上报的软件包下载结果后,将会向设备返回应答消息,各个消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致:16。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段定义得出该数据长度为1个字节,转换为十六进制为:0001。 数据区:处理成功,则返回00,处理失败返回80。本示例以返回00处理成功为例进行说明。 字段 数据类型 描述及要求 结果码 BYTE 0X00处理成功。 0X80升级任务不存在。 物联网平台向设备应答的消息为:FFFE 01 16 0000 0001 00 (CRC16校验前),经CRC16计算得到校验码为:850E。则替换校验码后物联网平台向设备应答的消息为:FFFE0116850E000100。
  • 执行软件升级 根据PCP协议约定的交互流程,物联网平台收到设备发送的软件包下载结果通知后,需要通知设备进行升级操作。 物联网平台发送的请求消息 根据PCP消息结构的定义可以得出,物联网平台向设备发送执行软件升级消息,各个消息字段的填写如下: 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致,为17。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段的数据类型得出无数据区,即为0字节,转换为十六进制为:0000。 数据区:无数据区,无需携带该字段。 字段 数据类型 描述及要求 无数据区 物联网平台向设备下发的执行软件升级的消息为:FFFE 01 17 0000 0000(CRC16校验前),经CRC16计算得到校验码为:CF90。则替换校验码后物联网平台向设备发送的消息为:FFFE0117CF900000。 设备发送的应答消息 设备收到物联网平台下发的执行升级消息后,将对收到消息后的执行动作进行应答,各消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致:17。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段定义得出该数据长度为1个字节,转换为十六进制为:0001。 数据区:处理成功,则返回00,其它处理结果请参考数据区定义。本示例以返回00处理成功为例进行说明。 字段 数据类型 描述及要求 结果码 BYTE 0X00处理成功。 0X01设备使用中。 0X04电量不足。 0X05剩余空间不足。 0X09内存不足。 设备向物联网平台应答的消息为:FFFE 01 17 0000 0001 00 (CRC16校验前),经CRC16计算得到校验码为:B725。则替换校验码后设备返回的响应消息为:FFFE0117B725000100 。
  • 下载升级包 根据PCP协议约定的交互流程,物联网平台通知设备有新的软件版本时,设备向物联网平台请求下载软件包,按照分片的序号进行下载。 设备发送的请求消息 根据PCP消息结构的定义可以得出,设备向物联网平台发送的请求软件包分片的第一条消息,各消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:查询消息码表可知请求升级包的消息码为21,转换为十六进制为:15。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段的数据类型得出数据区长度为18个字节,转换为十六进制为:0012。 数据区:目标版本号为平台下发的新版本通知版本号,即v1.0,转换为十六进制为56312E30000000000000000000000000,分片序号为第0个分片,即0000。 字段 数据类型 描述及要求 目的版本号 BYTE[16] 目的版本号,由ASCII字符组成,位数不足时,后补“0X00”。 分片序号 WORD 表示请求获取的分片序号,从0开始计算,分片的总数为软件包大小除以每个分片的大小并向上取整获得。设备可以保存已经收到的分片,下次直接从缺失的分片开始请求,达到断点续传的效果。 设备向物联网平台发送请求软件包分片的第一条消息为:FFFE 01 15 0000 0012 56312E30000000000000000000000000 0000(CRC16校验前),经CRC16计算得到校验码为:5618。则替换校验码后设备发送的第一条请求分片消息为:FFFE01155618001256312E300000000000000000000000000000。 其它分片请求的消息流只需要替换分片序号后,重新计算并替换CRC16校验码即可,此处就不再展开。 物联网平台的应答消息 物联网平台收到设备的请求软件包分片消息后,将会给设备下发分片的数据。物联网平台向设备响应的第一条请求分片的消息,各消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致:15。 校验码:CRC16计算前先用0000替代。 数据区:先讲数据区再讲数据区长度。结果码:00,分片序号:第0个分片:0000,分片数据:跟软件包定义的内容有关,我们假设软件包内容为HELLO, IoT SOTA!,经ASCII码转换为十六进制为:48454C4C4F2C20496F5420534F544121,共16字节。用户上传软件包时手动输入升级包分片大小为500byte,即最大长度为500字节。这种情况下,无需在数据的后面补充0。 数据区长度:根据数据区的字段定义得出该数据长度为19,转换为十六进制为:0013。 字段 数据类型 描述及要求 结果码 BYTE 0X00处理成功。 0X80升级任务不存在。 0X81指定的分片不存在。 分片序号 WORD 表示返回的分片序号。 分片数据 BYTE[n] 分片的内容,n为实际的分片大小。如果结果码不为0,则不带此字段。 物联网平台向设备发送的第一个软件包分片消息为:FFFE 01 15 0000 0013 00 0000 48454C4C4F2C20496F5420534F544121(CRC16校验前),经CRC16计算得到校验码为:E107。则替换校验码后物联网平台向设备发送的第一个软件包分片消息为:FFFE0115E107001300000048454C4C4F2C20496F5420534F544121。 其它软件包分片的消息流只需要替换分片序号和分片数据后,重新计算并替换CRC16校验码即可,此处就不再展开。
  • 下载新版本软件包通知 根据PCP协议约定的交互流程,查询完版本号后,物联网平台下发指令让设备下载新版本的软件包。 物联网平台发送消息 根据PCP消息结构的定义可以得出,物联网平台向设备下发下载新版本软件包通知时,各消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:此处为新版本通知,查询消息码表可以知道新版本通知为20,转换为十六进制为14。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的消息字段可以得出,数据区长度为22个字节,转换为十六进制为:0016。 数据区:根据数据区的定义可知。 目标版本号:由16个字节组成,假设升级的目标版本号为v1.0版本,转换为十六进制并在后面14个字节补充0后得到:56312E30000000000000000000000000。 升级包分片大小:由2个字节组成,单位为byte,用户上传软件包时可以手动输入升级包分片大小,如果不设置默认为500byte,大小为32~500之间。假设为500byte,转换为十六进制后为:01F4。 升级包分片总数:由2个字节组成,由软件包大小除以每个分片的大小并向上取整获得。假设软件包大小为500byte,则分片数量为1,转换为十六进制后为:0001。 检验码:由2个字节组成,目前已废弃,固定为:0000。 字段 数据类型 描述及要求 目的版本号 BYTE[16] 目的版本号,由ASCII字符组成,位数不足时,后补“0X00”。 升级包分片大小 WORD 每个分片的大小 升级包分片总数 WORD 升级包分片总数 升级包校验码 WORD 固定为:0000 将下载新版本软件包通知的消息流组合起来得到:FFFE 01 14 0000 0016 56312E30000000000000000000000000 01F4 0001 0000。前面说了,还要将消息流进行CRC16算法计算得到校验码为02F7。因此,物联网平台向设备通知下载新版本软件包的信息,物联网平台向设备发送的消息流为FFFE011402F7001656312E3000000000000000000000000001F400010000。 设备返回的应答消息 设备收到下载新版本软件包通知后,设备向物联网平台返回应答消息,是否允许设备进行升级,各消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致,为14。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段的数据类型得出数据区长度为1个字节,转换为十六进制为:0001。 数据区:设备根据自身的情况对平台下发的新版本通知进行响应,本示例以设备应答“允许升级”为例进行介绍,得出数据区为:00。其它应答消息请根据应答消息字段进行适配。 字段 数据类型 描述及要求 结果码 BYTE “0X00”允许升级 “0X01”设备使用中 “0X02”信号质量差 “0X03”已经是最新版本 “0X04”电量不足 “0X05”剩余空间不足 “0X09”内存不足 “0X7F”内部异常 将设备给物联网平台的应答消息流组合起来得到:FFFE 01 14 0000 0001 00。前面说了,还要将消息流进行CRC16算法计算得到校验码为D768。因此,设备向平台返回的应答消息流为FFFE0114D768000100。
  • 概述 设备的OTA软件升级是基于华为定义的PCP协议进行的,设备侧需根据PCP协议定义的交互流程进行适配开发。下面我们将结合物联网平台与设备的软件升级交互流程,介绍终端设备将如何基于PCP协议构建交互过程中的请求消息和应答消息,帮助您更好的根据PCP协议进行终端侧的软件升级功能开发。 下面我们先了解下PCP消息的结构,PCP协议的请求消息和应答消息都遵循相同的消息结构,主要由这几部分组成: PCP协议消息由:起始标识位、版本号、消息码、校验码、数据区长度和数据区组成,各字段的要求和描述如下表所示。 字段名 字段类型 描述和要求 起始标识 WORD 起始标识,固定为0XFFFE。 版本号 BYTE 高四位预留;低四位表示协议版本号,当前为1。 消息码 BYTE 标识物联网平台与设备之间的请求消息类型,应答消息的消息码和请求消息相同。消息码的定义为: 0-18:预留消息码,暂未使用。 19:查询设备版本。 20:下载新版本软件包通知。 21:请求下载升级包。 22:上报升级包下载结果。 23:执行软件升级。 24:上报升级结果。 25-127:预留消息码,暂未使用。 校验码 WORD 从起始标识到数据区的最后一个字节的CRC16校验值,计算前先把校验码字段置为0,计算完成后把结果写到校验码字段。 说明: CRC16算法:CRC16/CCITT x16+x12+x5+1 数据区长度 WORD 数据区的长度。 数据区 BYTE[n] 可变长度,具体由各个指令定义,可参考下面介绍的各个指令对应的请求消息和应答消息定义。 数据类型 描述 BYTE 无符号一字节整数 WORD 无符号二字节整数 DWORD 无符号四字节整数 BYTE[n] n字节的十六进制数 STRING 字符串
  • 查询设备版本号 从设备的软件升级流程(本流程只描述物联网平台与设备基于PCP协议交互的流程)可以看到,首先物联网平台向设备下发查询版本号信息,设备进行应答。 物联网平台发送消息 根据PCP消息结构的定义可以得出,物联网平台向设备下发查询版本号时,各消息字段的填写如下: 起始标识:固定为消息流的前2个字节,固定为FFFE。 版本号:数据类型为1个字节整数,且固定为1,即在消息流中为01。 消息码:数据类型为1个字节整数,查询设备版本的消息码为19,转换为十六进制为13。 校验码:数据类型为2个字节整数,先将校验码置为0000,然后将完整的消息码流进行CRC16的算法计算得到校验码,再将得到的校验码替换原消息中的0000。 数据区长度:数据类型为2个字节整数,代表数据区的消息长度,根据数据区的数据结构可以得出该条消息无数据区,即数据区长度为0000。 数据区:数据区代表要真正发送给设备的数据,根据查询版本信息的数据区定义,该条消息是没有实际要传送的数据的,即无需数据区字段。 字段 数据类型 描述及要求 无数据区 因此将查询版本消息的码流组合起来得到:FFFE 01 13 0000 0000。前面的校验码时讲了,需要将组合后的消息码流进行CRC16算法(物联网平台提供了基于JAVA和C语言的CRC16算法代码样例,您可以直接使用)得到校验码4C9A,然后将该校验码替换原码流中的0000后得到FFFE01134C9A0000,该消息码流即为物联网平台发送给设备的查询版本信息的消息码流。 设备返回的应答消息 设备收到物联网平台要查询设备的软件版本号消息,设备要向物联网平台反馈查询的结果,各消息字段的填写如下。 起始标识固定为:FFFE。 版本号固定为:01。 消息码:与请求的消息码一致,为13。 校验码:CRC16计算前先用0000替代。 数据区长度:根据数据区的字段的数据类型得出数据区长度为17个字节,转换为十六进制为:0011。 数据区:根据数据区的定义可知,处理成功的结果码为00,版本号信息假设为V0.9,将V0.9进行ASCII转码得到56302E39,由于版本号的数据类型为BYTE[16],即16个字节,当前只有4个字节,因此需要在版本号数据后面补0,得到56302E39000000000000000000000000。因此,数据区合并后为0056302E39000000000000000000000000。 字段 数据类型 描述及要求 结果码 BYTE “0X00”处理成功 当前版本号 BYTE[16] 当前版本号,由ASCII字符组成,位数不足时,后补“0X00”。 将查询版本信息的消息流组合起来得到:FFFE 01 13 0000 0011 0056302E39000000000000000000000000。前面讲到,还要将消息流进行CRC16算法计算得到校验码为8DE3。因此,物联网平台向设备查询版本号信息,设备向平台返回的消息流为FFFE01138DE300110056302E39000000000000000000000000。
  • 数组及可变长数组数据类型 如果该烟感设备需要支持描述信息上报功能,描述信息描述信息支持数组和可变长度数组两种类型,则按照以下步骤创建消息。 产品模型定义 在烟感产品的开发空间完成产品模型定义。 图40 模型定义-smokedetector携带other_info 编解码插件开发 在烟感产品的开发空间,选择“插件开发”,单击“图形化开发”。 单击“新增消息”,新增消息“other_info”,上报数组类型的描述信息。配置此步骤的主要目的是,将设备上传的数组二进制码流消息解码成JSON格式,以便物联网平台理解。配置示例如下: 消息名:other_info 消息类型:数据上报 添加响应字段:是。添加响应字段后,物联网平台在收到设备上报的数据后,会下发用户设置的响应数据到设备。 响应数据:AAAA0000(默认) 图41 插件开发-新增消息other_info 单击“添加字段”,添加messageId字段,表示消息种类。在本场景中,0x0用于标识上报火灾等级和温度的消息,0x1用于标识只上报温度的消息,0x2用于标识上报描述信息(数组类型)的消息。messageId、数据类型、长度、默认值、偏移值的说明可参考1。 图42 插件开发-添加字段messageId(0x2) 添加other_info字段,“数据类型”选择“array”,表示数组类型的描述信息。在本场景中,“长度”配置为5个字节。字段名、默认值、偏移值的说明可参考2。 图43 插件开发-添加字段other_info为array 单击“新增消息”,新增“other_info2”消息,上报可变长度数组类型的描述信息。配置此步骤的主要目的是,将设备上传的可变长度数组二进制码流消息解码成JSON格式,以便物联网平台理解。配置示例如下: 消息名:other_info2 消息类型:数据上报 添加响应字段:是。添加响应字段后,物联网平台在收到设备上报的数据后,会下发用户设置的响应数据到设备。 响应数据:AAAA0000(默认) 图44 插件开发-新增消息other_info2 单击“添加字段”,添加messageId字段,表示消息种类。在本场景中,0x0用于标识上报火灾等级和温度的消息,0x1用于标识只上报温度的消息,0x3用于标识上报描述信息(可变长度数组类型)的消息。messageId、数据类型、长度、默认值、偏移值的说明可参考1。 图45 插件开发-添加字段messageId(0x3) 添加length字段,表示数组长度。“数据类型”根据可变长度数组的长度进行配置,长度在255以内,配置为“int8u”。长度、默认值、偏移值的说明可参考2。 图46 插件开发-添加字段length 添加other_info字段,数据类型选择“variant”,表示可变长度数组类型的描述信息。“长度关联字段”选择“length”,表示当前可变长数组的长度由上报的length的值决定。“掩码”默认为“0xff”,用来计算该数组实际生效的长度,例如:“长度关联字段”length的值为5,其对应的二进制为:00000101,此时若掩码为0xff,对应的二进制为:11111111,那么两者进行“与“运算之后的结果为00000101,即十进制的5,那么该数组实际生效的长度为5。如上报数据为03051234567890,表示当前上报的数据对应的是messageId为03的的message,可变长数组长度为5,可变长参数other_info对应的码流为1234567890。 图47 插件开发-添加字段other_info为variant 拖动右侧“设备模型”区域的属性字段,与数据上报消息的相应字段建立映射关系。 图48 插件开发-数据上报字段映射关系other_info为varint 单击“保存”,并在插件保存成功后单击“部署”,将编解码插件部署到物联网平台。 图49 插件开发-部署插件 调测编解码插件 在烟感产品的开发空间,选择“在线调试”,并单击“新增测试设备”。 用户可根据自己的业务场景,选择使用真实设备或者虚拟设备进行调测。具体调测步骤请参考在线调试。本文以虚拟设备为例,调测编解码插件。 在弹出的“新增测试设备”窗口,选择“虚拟设备”,单击“确定”,创建一个虚拟设备。虚拟设备名称包含 “DeviceSimulator”字样,每款产品下只能创建一个虚拟设备。 图50 在线调试-创建虚拟设备 单击“调试”,进入调试界面。 图51 在线调试-进入调试 使用设备模拟器上报数组类型的描述信息。 十六进制码流示例:0211223344。02表示messageId,此消息上报数组类型的描述信息;11223344表示描述信息,长度为4个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=null}。描述信息不足5个字节,编解码插件无法解析。 图52 在线调试-模拟数据上报other_info数组1 十六进制码流示例:021122334455。02表示messageId,此消息上报数组类型的描述信息;1122334455表示描述信息,长度为5个字节。 在“应用模拟器”区域查看数据上报的结果:{serviceId: smokedetector, data: {"other_info":"ESIzRFU="}}。描述信息长度为5个字节,编解码插件解析成功。 图53 在线调试-模拟数据上报other_info数组2 十六进制码流示例:02112233445566。02表示messageId,此消息上报数组类型的描述信息;112233445566表示描述信息,长度为6个字节。 在“应用模拟器”区域查看数据上报的结果:{serviceId: smokedetector, data: {"other_info":"ESIzRFU="}}。描述信息长度超过5个字节,编解码插件截取前5个字节进行解析。 图54 在线调试-模拟数据上报other_info数组3 使用设备模拟器上报可变长度数组类型的描述信息。 十六进制码流示例:030101。03表示messageId,此消息上报可变长度数组类型的描述信息;01表示描述信息长度(1个字节),长度为1个字节;01表示描述信息,长度为1个字节。 在“应用模拟器”区域查看数据上报的结果:{serviceId: smokedetector, data: {"other_info":"AQ=="}}。AQ==是01经过base64编码后的值。 图55 在线调试-模拟数据上报other_info可变长数组1 十六进制码流示例:03020102。03表示messageId,此消息上报可变长度数组类型的描述信息;02表示描述信息长度(2个字节),长度为1个字节;0102表示描述信息,长度为2个字节。 在“应用模拟器”区域查看数据上报的结果:{serviceId: smokedetector, data: {"other_info":"AQI="}}。AQI=是01经过base64编码后的值。 图56 在线调试-模拟数据上报other_info可变长数组2 十六进制码流示例:03030102。03表示messageId,此消息上报可变长度数组类型的描述信息;03表示描述信息长度(3个字节),长度为1个字节;0102表示描述信息,长度为2个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=null}。描述信息长度不足3个字节,编解码插件解析失败。 图57 在线调试-模拟数据上报other_info可变长数组3 十六进制码流示例:0303010203。03表示messageId,此消息上报可变长度数组类型的描述信息;03表示描述信息长度(3个字节),长度为1个字节;010203表示描述信息,长度为3个字节。 在“应用模拟器”区域查看数据上报的结果:{serviceId: smokedetector, data: {"other_info":"AQID"}}。AQID是010203经过base64编码后的值。 图58 在线调试-模拟数据上报other_info可变长数组4 十六进制码流示例:030301020304。03表示messageId,此消息上报可变长度数组类型的描述信息;03表示描述信息长度(3个字节),长度为1个字节;01020304表示描述信息,长度为4个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=AQID}。描述信息长度超过3个字节,编解码插件截取前3个字节进行解析,AQID是010203经过base64编码后的值。 图59 在线调试-模拟数据上报other_info可变长数组5 base64编码方式说明 base64编码方式会把3个8位字节(3*8=24)转化为4个6位字节(4*6=24),并在每个6位字节前补两个0,构成4个8位字节的形式。如果要进行编码的码流不足3个字节,则在码流后用0填充,使用0填充的字节经编码输出的字符为“=”。 base64可以将16进制码流当做字符或者数值进行编码,两种方式获得的编码结果不同。以16进制码流01为例进行说明: 把01当作字符,不足3个字符,补1个0,得到010。通过查询ASCII码表,将字符转换为8位二进制数,即:0转换为00110000、1转换为00110001,因此010可以转换为001100000011000100110000(3*8=24)。再转换为4个6位字节:001100、000011、000100、110000,并在每个6位字节前补两个0,得到:00001100、00000011、00000100、00110000。这4个8位字节对应的10进制数分别为12、3、4、48,通过查询base64编码表,获得M(12)、D(3)、E(4),由于3个字符中,最后一个字符通过补0获得,因此第4个8位字节使用“=”表示。最终,把01当做字符,通过base64编码得到MDE=。 把01当作数值(即1),不足3个字符,补两个0,得到100。将数值转换为8位2进制数,即:0转换为00000000、1转换为00000001,因此100可以转换为000000010000000000000000(3*8=24)。在转换为4个6位字节:000000、010000、000000、000000,并在每个6位字节前补两个0,得到:00000000、00010000、00000000、00000000。这4个8位字节对应的10进制数分别为:0、16、0、0,通过查询base64编码表,获得A(0)、Q(16),由于3个数值中,最后两个数值通过补0获得,因此第3、4个8位字节使用“=”表示。最终,把01当作数值,通过base64编码得到AQ==。 总结 当数据类型为数组或可变长度数组时,插件是按照base64进行编解码的:上报数据时,将16进制码流进行base64编码,比如:01编码为“AQ==”;命令下发时,将字符进行base64解码,比如:“AQ==”解码为01。 当某字段的数据类型为可变长度数组时,该字段需要关联长度字段,长度字段的数据类型必须为int。 针对可变长度数组,命令下发和数据上报的编解码插件开发方式相同。 图形化开发的编解码插件使用base64进行编码时,是将16进制码流当做数值进行编码。
  • 字符串及可变长字符串的编解码插件 如果该烟感设备需要支持描述信息上报功能,描述信息支持字符串和可变长度字符串两种类型,则按照以下步骤创建消息。 产品模型定义 重新创建一个烟感产品,并在烟感产品的开发空间完成产品模型定义。 图20 模型定义-smokedetector携带other_info 编解码插件开发 在烟感产品的开发空间,选择“插件开发”,单击“图形化开发”。 单击“新增消息”,新增消息“other_info”,上报字符串类型的描述信息。配置此步骤的主要目的是,将设备上传的字符串二进制码流消息解码成JSON格式,以便物联网平台理解。配置示例如下: 消息名:other_info 消息类型:数据上报 添加响应字段:是。添加响应字段后,物联网平台在收到设备上报的数据后,会下发用户设置的响应数据到设备。 响应数据:AAAA0000(默认) 图21 插件开发-新增消息other_info 单击“添加字段”,添加messageId字段,表示消息种类。在本场景中,0x0用于标识上报火灾等级和温度的消息,0x1用于标识只上报温度的消息,0x2用于标识上报描述信息(字符串类型)的消息。messageId、数据类型、长度、默认值、偏移值的说明可参考1。 图22 插件开发-添加字段messageId(0x2) 添加other_info字段,表示字符串类型的描述信息。在本场景中,字符串类型的字段数据类型选择“string”,“长度”配置 6个字节。字段名、默认值、偏移值的说明可参考2。 图23 插件开发-添加字段other_info 单击“新增消息”,新增“other_info2”消息名,配置数据上报消息,上报可变长度字符串类型的描述信息。配置此步骤的主要目的是,将设备上传的可变长度字符串二进制码流消息解码成JSON格式,以便物联网平台理解。配置示例如下: 消息名:other_info2 消息类型:数据上报 添加响应字段:是。添加响应字段后,物联网平台在收到设备上报的数据后,会下发用户设置的响应数据到设备。 响应数据:AAAA0000(默认) 图24 插件开发-新增消息other_info2 添加messageId字段,表示消息种类。在本场景中,0x0用于标识上报火灾等级和温度的消息,0x1用于标识只上报温度的消息,0x3用于标识上报描述信息(可变长度字符串类型)的消息。messageId、数据类型、长度、默认值、偏移值的说明可参考1。 图25 插件开发-添加字段messageId(0x3) 添加length字段,表示可变字符串长度。“数据类型”根据可变长度字符串的长度进行配置,此场景可变字符串长度在255以内,配置为“int8u”。长度、默认值、偏移值的说明可参考2。 图26 插件开发-添加字段length 添加other_info字段,数据类型选择“varstring”,表示可变长度字符串类型的描述信息。“长度关联字段”选择“length”,表示当前可变长字符串的长度由上报的length的值决定。“掩码”默认为“0xff”,用来计算该字段实际生效的长度,例如:“长度关联字段”length的值为5,其对应的二进制为:00000101,此时若掩码为0xff,对应的二进制为:11111111,那么两者进行“与“运算之后的结果为00000101,即十进制的5,那么该字段实际生效的长度为5个字节。如上报数据为03051234567890,表示当前上报的数据对应的是messageId为03的的message,可变长字符串长度为5个字节,可变长参数other_info对应的码流为1234567890。 图27 插件开发-添加字段other_info为varstring 拖动右侧“设备模型”区域的属性字段,与数据上报消息的相应字段建立映射关系。 图28 插件开发-数据上报字段映射关系 单击“保存”,并在插件保存成功后单击“部署”,将编解码插件部署到物联网平台。 图29 插件开发-部署插件 调测编解码插件 在烟感产品的开发空间,选择“在线调试”,并单击“新增测试设备”。 用户可根据自己的业务场景,选择使用真实设备或者虚拟设备进行调测。具体调测步骤请参考在线调试。本文以虚拟设备为例,调测编解码插件。 在弹出的“新增测试设备”窗口,选择“虚拟设备”,单击“确定”,创建一个虚拟设备。虚拟设备名称包含 “DeviceSimulator”字样,每款产品下只能创建一个虚拟设备。 图30 在线调试-创建虚拟设备 单击“调试”,进入调试界面。 图31 在线调试-进入调试 使用设备模拟器上报字符串类型的描述信息。 十六进制码流示例:0231。02表示messageId,此消息上报字符串类型的描述信息;31表示描述信息,长度为1个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=null}。描述信息不足6个字节,编解码插件无法解析。 图32 在线调试-模拟数据上报other_info长度不足 十六进制码流示例:02313233343536。02表示messageId,此消息上报字符串类型的描述信息;313233343536表示描述信息,长度为6个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=123456}。描述信息长度为6个字节,编解码插件解析成功。 图33 在线调试-模拟数据上报other_info长度合适 十六进制码流示例:023132333435363738。02表示messageId,此消息上报字符串类型的描述信息;3132333435363738表示描述信息,长度为8个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=123456}。描述信息长度超过6个字节,编解码插件截取前6个字节进行解析。 图34 在线调试-模拟数据上报other_info长度过长 十六进制码流示例:02013132333435。02表示messageId,此消息上报字符串类型的描述信息;013132333435表示描述信息,长度为6个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=\u000112345}。01在ASCII码表里表示“标题开始”,无法用具体字符表示,因此编解码插件解析为\u0001。 图35 在线调试-模拟数据上报other_info ASCII码 使用设备模拟器上报可变长度字符串类型的描述信息。 十六进制码流示例:030141。03表示messageId,此消息上报可变长度字符串类型的描述信息;01表示描述信息长度;41表示描述信息,长度为1个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=A}。41是A的十六进制ASCII码。 图36 在线调试-模拟数据上报other_info可变长字符串1 十六进制码流示例:03024142。03表示messageId,此消息上报可变长度字符串类型的描述信息;02表示描述信息的长度;4142表示描述信息,长度为2个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=AB}。4142是AB的十六进制ASCII码。 图37 在线调试-模拟数据上报other_info可变长字符串2 十六进制码流示例:030341424344。03表示messageId,此消息上报可变长度字符串类型的描述信息;03表示描述信息长度;41424344表示描述信息,长度为4个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=ABC}。描述信息长度超过3个字节,编解码插件截取前3个字节进行解析,414243是ABC的十六进制ASCII码。 图38 在线调试-模拟数据上报other_info可变长字符串3 十六进制码流示例:0304414243。03表示messageId,此消息上报可变长度字符串类型的描述信息;04表示字符串长度;414243表示描述信息,长度为4个字节。 在“应用模拟器”区域查看数据上报的结果:{other_info=null}。描述信息长度不足4个字节,编解码插件解析失败。 图39 在线调试-模拟数据上报other_info可变长字符串4 总结 当数据类型为字符串或可变长度字符串时,插件是按照ASCII码进行编解码的:上报数据时,将16进制码流解码为对应字符串,比如:21解析为“!”、31解析为“1”、41解析为“A”;下发命令时,将字符串编码对应的16进制码流,比如:“!”编码为21,“1”编码为31,“A”编码为41。 当某字段的数据类型为可变长度字符串时,该字段需要关联长度字段,长度字段的数据类型必须为int。 针对可变长度字符串,命令下发和数据上报的编解码插件开发方式相同。 图形化开发的编解码插件使用ASCII码16进制的标准表对字符串和可变长度字符串进行编解码。解码时(数据上报),如果解析结果无法使用具体字符表示,如:标题开始、正文开始、正文结束等,则使用\u+2字节码流值表示(例如:01解析为\u0001,02解析为\u0002);如果解析结果可以使用具体字符表示,则使用具体字符。
  • 数据上报和命令下发 场景说明 有一款烟感设备,具有如下特征: 具有烟雾报警功能(火灾等级)和温度上报功能。 支持远程控制命令,可远程打开报警功能。比如火灾现场温度,远程打开烟雾报警,提醒住户疏散。 支持上报命令执行结果。 产品模型定义 在烟感产品的开发空间,完成产品模型定义。 level:火灾级别,用于表示火灾的严重程度。 temperature:温度,用于表示火灾现场温度。 SET_ALARM:打开或关闭告警命令,value=0表示关闭,value=1表示打开。 图1 模型定义-smokedetector 编解码插件开发 在烟感产品的开发空间,选择“插件开发”,单击“图形化开发”。 单击“新增消息”,新增“smokerinfo”消息。配置此步骤的主要目的是,将设备上传的二进制码流消息解码成JSON格式,以便物联网平台理解。配置示例如下: 消息名:smokerinfo 消息类型:数据上报。 添加响应字段:是。添加响应字段后,物联网平台在收到设备上报的数据后,会下发用户设置的响应数据到设备。 响应数据:AAAA0000(默认) 图2 插件开发-新增消息smokerinfo 单击“添加字段”,勾选“标记为地址域”,添加messageId字段,表示消息类型。在本场景中,上报火灾等级和温度的消息类型是0x0。设备上报消息时,每条消息首个字段就是messageId。如设备上报消息为0001013A,第一个字段00就是表示此条消息是上报火灾级别和温度的消息。后续字段01和013A分别代表火灾级别和温度。如果只有一条数据上报消息和一条命令下发消息,可以不添加messageId字段。 “数据类型”根据数据上报消息种类的数量进行配置。messageId字段默认的数据类型为int8u。 “偏移值”是根据字段位置和字段的字节数的配置自动填充的。messageId为此消息的第一个字段,起始位置为0,字节长度为1,终点位置为1。所以偏移值为0-1。 “长度”是根据“数据类型”的配置自动填充的。 “默认值”可以修改,但必须为十六进制格式,且设备数据上报消息的对应字段必须和此处的默认值保持一致。 图3 插件开发-添加字段messageId 添加level字段,表示火灾级别。 “字段名”只能输入包含字母、数字、_和$,且不能以数字开头的字符。 “数据类型”根据设备上报数据的实际情况进行配置,需要和产品模型相应字段的定义相匹配。产品模型中定义的火灾级别level属性的数据类型为int,最大值为9。所以选择的数据类型为int8u。 “偏移值”是根据字段位置和字段的字节数的配置自动填充的。“level”字段的起始位置就是前一字段的终点,前一字段“messageId”的终点位置为1,所以“level”字段的起始位置为1。“level”字段长度为1个字节,终点为2。所以“偏移值”为1-2。 “长度”根据“数据类型”的配置自动填充。 “默认值”不填。此处火灾级别level不固定,无默认值。 图4 插件开发-添加字段level 添加temperature字段,表示温度。 “数据类型”,在产品模型中,temperature属性的“数据类型”为int,最大值1000,因此在插件中定义temperature字段的“数据类型”为“int16u”,以满足temperature属性的取值范围。 “偏移值”是根据与首字段的间隔的字符数自动配置的。“temperature”字段的起始位置就是前一字段的终点,前一字段“level”的终点位置为2,所以“temperature”字段的起始位置为2。“temperature”字段长度为2个字节,终点为4。所以“偏移值”为2-4。 “长度”根据数据类型的配置自动填充。 “默认值”不填,此处温度temperature的值不固定,无默认值。 图5 插件开发-添加字段temperature 单击“新增消息”,新增“SET_ALARM”消息,设置火灾告警的温度阈值。例如超过60摄氏度,设备上报告警。配置此步骤的主要目的是,将平台下发的JSON格式命令消息编码成二进制数据,以便烟感设备理解。配置示例如下: 消息名:SET_ALARM 消息类型:命令下发 添加响应字段:是。添加响应字段后,设备在接收命令后,可以上报命令执行结果。您可以根据自己的需求,选择是否添加响应字段。 图6 插件开发-新增消息SET_ALARM 单击“添加字段”,添加messageId字段,表示消息类型。例如,设置火灾告警阈值的消息类型为0x3。messageId、数据类型、长度、默认值、偏移值的说明可参考1。 图7 插件开发-添加命令字段messageId(0x3) 添加mid字段。这里的mid字段是由平台生成和下发的,用于将下发的命令和命令下发响应消息关联。mid字段的数据类型默认为int16u。长度、默认值、偏移值的说明可参考2。 图8 插件开发-添加命令字段mid 添加value字段,表示下发命令的参数值。例如,下发火灾告警的温度阈值。数据类型、长度、默认值、偏移值的说明可以参考2。 图9 插件开发-添加命令字段value 单击“添加响应字段”,添加“messageId”字段,表示消息类型。命令下发响应消息为上行消息,需要通过messageId和数据上报消息进行区分。上报火灾告警温度阈值的消息类型为0x4。messageId、数据类型、长度、默认值、偏移值的说明可参考1。 图10 插件开发-添加响应字段messageId(0x4) 添加mid字段。这里的mid字段需要跟平台下发的命令里的mid字段保持一致,用于将下发的命令和命令执行结果进行关联。mid字段的数据类型默认为int16u。长度、默认值、偏移值的说明可参考2。 图11 插件开发-添加响应字段mid 添加errcode字段,用于表示命令执行状态:00表示成功,01表示失败,如果未携带该字段,则默认命令执行成功。errcode字段的数据类型默认为int8u。长度、默认值、偏移值的说明可参考2。 图12 插件开发-添加响应字段errcode 添加result字段,用于表示命令执行结果。例如,设备向平台返回当前的告警阈值。 图13 插件开发-添加响应字段result 拖动右侧“设备模型”区域的属性字段和命令字段,数据上报消息和命令下发消息的相应字段建立映射关系。 图14 插件开发-在线开发插件smokerdetector 单击“保存”,并在插件保存成功后单击“部署”,将编解码插件部署到物联网平台。 图15 插件开发-部署插件 调测编解码插件 在烟感产品的开发空间,选择“在线调试”,并单击“新增测试设备”。 用户可根据自己的业务场景,选择使用真实设备或者虚拟设备进行调测。具体调测步骤请参考在线调试。本文以虚拟设备为例,调测编解码插件。 在弹出的“新增测试设备”窗口,选择“虚拟设备”,单击“确定”,创建一个虚拟设备。虚拟设备名称包含 “DeviceSimulator”字样,每款产品下只能创建一个虚拟设备。 图16 在线调试-创建虚拟设备 单击“调试”,进入调试界面。 图17 在线调试-进入调试 使用设备模拟器进行数据上报。十六进制码流示例:0008016B。00为地址域messageId,08表示火灾级别level,长度为1个字节;016B表示温度,长度为2个字节。 在“应用模拟器”区域查看数据上报的结果:{level=8, temperature=363}。8为十六进制数08转换为十进制的数值;363为十六进制数016B转换为十进制的数值。 在设备模拟器区域看到平台下发的响应数据AAAA0000。 图18 在线调试-模拟数据上报smokerdetector 使用应用模拟器进行命令下发,输入value值为1,可看到应用模拟下发命令{ "serviceId": "Smokeinfo", "method": "SET_ALARM", "paras": "{\"value\":1}" }。 在“设备模拟器”区域查看命令接收的结果:03000101。03为地址域messageId,0001为mid字段,01为十进制数1转换为十六进制的数值。 图19 在线调试-模拟命令下发smokerdetector 使用CoAP的虚拟设备在线调试时,若下发命令后设备模拟器未接收到对应的命令,可以先上报一次属性后,再下发。 总结 如果插件需要对命令执行结果进行解析,则必须在命令和命令响应中定义mid字段。 命令下发的mid是2个字节,对于每个设备来说,mid从1递增到65535,对应码流为0001到FFFF。 设备执行完命令,命令执行结果上报中的mid要与收到命令中的mid保持一致,这样平台才能刷新对应命令的状态。
  • 如何开发网关 网关是一个特殊的设备,除具备一般设备功能之外,还具有子设备管理、子设备消息转发的功能。SDK提供了AbstractGateway抽象类来简化网关的实现。该类提供了子设备管理功能,需要从平台获取子设备信息并保存(需要子类提供子设备持久化接口)、子设备下行消息转发功能(需要子类实现转发处理接口)、以及上报子设备列表、上报子设备属性、上报子设备状态、上报子设备消息等接口。 使用AbstractGateway类 继承该类,在构造函数里提供子设备信息持久化接口,实现其下行消息转发的抽象接口: 1 2 3 4 5 6 7 public abstract void onSubdevCommand(String requestId, Command command); public abstract void onSubdevPropertiesSet(String requestId, PropsSet propsSet); public abstract void onSubdevPropertiesGet(String requestId, PropsGet propsGet); public abstract void onSubdevMessage(DeviceMessage message); iot-gateway-demo代码介绍 工程iot-gateway-demo基于AbstractGateway实现了一个简单的网关,它提供tcp设备接入能力。关键类: SimpleGateway:继承自AbstractGateway,实现子设备管理和下行消息转发 StringTcpServer:基于netty实现一个TCP server,本例中子设备采用TCP协议,并且首条消息为鉴权消息 SubDevicesFilePersistence:子设备信息持久化,采用json文件来保存子设备信息,并在内存中做了缓存 Session:设备会话类,保存了设备id和TCP的channel的对应关系 SimpleGateway类 添加或删除子设备处理 添加子设备:AbstractGateway的onAddSubDevices接口已经完成了子设备信息的保存。我们不需要再增加额外处理,因此SimpleGateway不需要重写onAddSubDevices接口 删除子设备:我们不仅需要修改持久化信息,还需要断开当前子设备的连接。所以我们重写了onDeleteSubDevices接口,增加了拆链处理,然后调用父类的onDeleteSubDevices。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override public int onDeleteSubDevices(SubDevicesInfo subDevicesInfo) { for (DeviceInfo subdevice : subDevicesInfo.getDevices()) { Session session = nodeIdToSesseionMap.get(subdevice.getNodeId()); if (session != null) { if (session.getChannel() != null) { session.getChannel().close(); channelIdToSessionMap.remove(session.getChannel().id().asLongText()); nodeIdToSesseionMap.remove(session.getNodeId()); } } } return super.onDeleteSubDevices(subDevicesInfo); } 下行消息处理 网关收到平台下行消息时,需要转发给子设备。平台下行消息分为三种:设备消息、属性读写、命令。 设备消息:这里我们需要根据deviceId获取nodeId,从而获取session,从session里获取channel,就可以往channel发送消息。在转发消息时,可以根据需要进行一定的转换处理。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Override public void onSubdevMessage(DeviceMessage message) { //平台接口带的都是deviceId,deviceId是由nodeId和productId拼装生成的,即 //deviceId = productId_nodeId String nodeId = IotUtil.getNodeIdFromDeviceId(message.getDeviceId()); if (nodeId == null) { return; } //通过nodeId获取session,进一步获取channel Session session = nodeIdToSesseionMap.get(nodeId); if (session == null) { log.error("subdev is not connected " + nodeId); return; } if (session.getChannel() == null){ log.error("channel is null " + nodeId); return; } //直接把消息转发给子设备 session.getChannel().writeAndFlush(message.getContent()); log.info("writeAndFlush " + message); } 属性读写: 属性读写包括属性设置和属性查询。 属性设置: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Override public void onSubdevPropertiesSet(String requestId, PropsSet propsSet) { if (propsSet.getDeviceId() == null) { return; } String nodeId = IotUtil.getNodeIdFromDeviceId(propsSet.getDeviceId()); if (nodeId == null) { return; } Session session = nodeIdToSesseionMap.get(nodeId); if (session == null) { return; } //这里我们直接把对象转成string发给子设备,实际场景中可能需要进行一定的编解码转换 session.getChannel().writeAndFlush(JsonUtil.convertObject2String(propsSet)); //为了简化处理,我们在这里直接回响应。更合理做法是在子设备处理完后再回响应 getClient().respondPropsSet(requestId, IotResult.SUC CES S); log.info("writeAndFlush " + propsSet); } 属性查询: 1 2 3 4 5 6 7 @Override public void onSubdevPropertiesGet(String requestId, PropsGet propsGet) { //不建议平台直接读子设备的属性,这里直接返回失败 log.error("not supporte onSubdevPropertiesGet"); deviceClient.respondPropsSet(requestId, IotResult.FAIL); } 命令:处理流程和消息类似,实际场景中可能需要不同的编解码转换。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override public void onSubdevCommand(String requestId, Command command) { if (command.getDeviceId() == null) { return; } String nodeId = IotUtil.getNodeIdFromDeviceId(command.getDeviceId()); if (nodeId == null) { return; } Session session = nodeIdToSesseionMap.get(nodeId); if (session == null) { return; } //这里我们直接把command对象转成string发给子设备,实际场景中可能需要进行一定的编解码转换 session.getChannel().writeAndFlush(JsonUtil.convertObject2String(command)); //为了简化处理,我们在这里直接回命令响应。更合理做法是在子设备处理完后再回响应 getClient().respondCommand(requestId, new CommandRsp(0)); log.info("writeAndFlush " + command); } 上行消息处理 上行处理在StringTcpServer的channelRead0接口里。如果会话不存在,需要先创建会话: 如果子设备信息不存在,这里会创建会话失败,直接拒绝连接 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { Channel incoming = ctx.channel(); log.info("channelRead0" + incoming.remoteAddress() + " msg :" + s); //如果是首条消息,创建session //如果是首条消息,创建session Session session = simpleGateway.getSessionByChannel(incoming.id().asLongText()); if (session == null) { String nodeId = s; session = simpleGateway.createSession(nodeId, incoming); //创建会话失败,拒绝连接 if (session == null) { log.info("close channel"); ctx.close(); } } 如果会话存在,则进行消息转发: 1 2 3 4 5 6 7 else { //如果需要上报属性则调用reportSubDeviceProperties DeviceMessage deviceMessage = new DeviceMessage(s); deviceMessage.setDeviceId(session.getDeviceId()); simpleGateway.reportSubDeviceMessage(deviceMessage, null); } 到这里,网关的关键代码介绍完了,其他的部分看源代码。整个demo是开源的,用户可以根据需要进行扩展。比如修改持久化方式、转发中增加消息格式的转换、实现其他子设备接入协议。 iot-gateway-demo的使用 创建子设备的产品,步骤可参考创建产品。 在创建的产品中定义模型,添加服务,服务ID为parameter。并且新增alarm和temperature两个属性,如下图所示 图9 模型定义-子设备产品 修改StringTcpServer的main函数,替换构造参数,然后运行该类。 1 2 3 simpleGateway = new SimpleGateway(new SubDevicesFilePersistence(), "ssl://iot-acc.cn-north-4.myhuaweicloud.com:8883", "5e06bfee334dd4f33759f5b3_demo", "mysecret"); 在平台上看到该网关在线后,添加子设备。 图10 设备-添加子设备 表1 子设备参数 参数名称 参数描述 所属产品 子设备所属的产品,选择步骤1创建的产品。 设备名称 即device_name,可自定义,如subdev_name 设备标识码 即node_id,填写subdev。 设备ID 即devicee_id,可不填写,自动生成。 此时网关上日志打印: 2024-04-16 21:00:01 INFO SubDevicesFilePersistence:112 - add subdev, the nodeId is subdev 运行TcpDevice类,建立连接后,输入步骤3中注册的子设备的nodeId,如subdev。 图11 子设备连接 此时网关设备日志打印: 2024-04-16 21:00:54 INFO StringTcpServer:196 - initChannel: /127.0.0.1:21889 2024-04-16 21:01:00 INFO StringTcpServer:137 - channelRead0 is /127.0.0.1:21889, the msg is subdev 2024-04-16 21:01:00 INFO SimpleGateway:100 - create new session ok, the session is Session{nodeId='subdev', channel=[id: 0xf9b89f78, L:/127.0.0.1:8080 - R:/127.0.0.1:21889], deviceId='subdev_deviceId'} 在平台上看到子设备上线。 图12 设备列表-设备在线 子设备上报消息 图13 子设备上报消息 查看日志看到上报成功 2024-04-16 21:02:36 INFO StringTcpServer:137 - channelRead0 is /127.0.0.1:21889, the msg is hello 2024-04-16 21:02:36 INFO MqttConnection:299 - publish message topic is $oc/devices/5e06bfee334dd4f33759f5b3_demo/sys/messages/up, msg = {"name":null,"id":null,"content":"hello","object_device_id":"subdev_deviceId"] 2024-04-16 21:02:36 INFO MqttConnection:299 - publish message topic is $oc/devices/5e06bfee334dd4f33759f5b3_demo/sys/gateway/sub_devices/properties/report, msg = {"devices":[{"services":[{"properties":{"temprature":2,"alarm":1},"service_id":"parameter","event_time":null}],"device_id":"subdev_deviceId"}]] 查看消息跟踪 在平台上找到网关,选择 设备详情-消息跟踪,打开消息跟踪。继续让子设备发送数据,等待片刻后看到消息跟踪: 图14 消息跟踪-直连设备
  • 设备初始化 创建设备时,需要写入在注册设备时获取的设备ID、密码,以及1中获取的设备对接信息,注意格式为ssl:// 域名 信息:端口号 或 ssl://IP地址:端口号 1 2 3 4 5 6 // 获取证书路径:加载iot平台的ca证书,进行服务端校验,使用sdk默认的ca.jks即可。 URL resource = MessageSample.class.getClassLoader().getResource("ca.jks"); File file = new File(resource.getPath()); //例如在iot-device-demo文件 MessageSample.java中修改以下参数 IoTDevice device = new IoTDevice("ssl://域名信息:8883", "5e06bfee334dd4f33759f5b3_demo", "mysecret", file); 所有涉及设备ID和密码的文件均需要修改成对应的信息。 建立连接。调用init接口,该接口是阻塞调用,如果建立连接成功会返回0。 1 2 3 if (device.init() != 0) { return; } 如果连接成功就会打印: 1 2023-07-17 17:22:59 INFO MqttConnection:105 - Mqtt client connected. address :ssl://域名信息:8883 创建设备并连接成功后,可以开始使用设备进行通信。调用IoT Device 的getClient接口获取设备客户端,客户端提供了消息、属性、命令等通讯接口。
  • 创建产品 为了方便体验,我们提供了一个烟感的产品模型,烟感会上报烟雾值、温度、湿度、烟雾报警、还支持响铃报警命令。以烟感例,体验消息上报、属性上报等功能。 访问设备接入服务,单击“管理控制台”进入设备接入控制台,选择您的实例,单击实例卡片进入。查看MQTTS设备接入域名,保存该地址。 单击左侧导航栏“产品”,单击页面左侧的“创建产品”。 根据页面提示填写参数,然后单击“确定”完成产品的创建。 基本信息 所属资源空间 平台自动将新创建的产品归属在默认资源空间下。如需归属在其他资源空间下,下拉选择所属的资源空间。如无对应的资源空间,请先创建资源空间。 产品名称 自定义。支持字母、数字、下划线(_)、连字符(-)的字符组合。 协议类型 选择“MQTT”。 数据格式 选择“JSON”。 设备类型选择 选择”自定义类型” 设备类型 填写“smokeDetector” 高级配置 产品ID 不填写 产品描述 请根据实际情况填写。
  • 准备工作 开发环境要求:已经安装JDK(版本1.8以上)和maven 访问SDK下载页面,下载SDK,整个工程包含以下子工程: iot-device-sdk-java:sdk代码 iot-device-demo:普通直连设备的demo代码 iot-gateway-demo:网关设备的demo代码 iot-bridge-sdk:网桥的sdk代码 iot-bridge-demo:网桥的demo代码,用来演示如何将tcp设备桥接到平台 iot-bridge-sample-tcp-protocol:子设备使用tcp协议链接网桥的样例 iot-device-code-generator:设备代码生成器,可以根据产品模型自动生成设备代码 编译安装:进入到SDK根目录,执行mvn install
  • 操作步骤 访问设备接入服务,单击“管理控制台”进入设备接入控制台。选择您的实例,单击实例卡片进入。 单击左侧导航栏“产品”,单击页面左侧的“创建产品”。根据页面提示填写参数,然后单击“确定”,完成产品的创建。 基本信息 所属资源空间 下拉选择所属的资源空间。如无对应的资源空间,请先创建资源空间。 产品名称 为产品命名。产品名称在相同资源空间有唯一性。长度不超过64,只允许中文、字母、数字、以及_?'#().,&%@!-字符的组合。 协议类型 MQTT:使用MQTT协议接入平台的设备,数据格式可以是二进制也可以是JSON格式,采用二进制时需要部署编解码插件。 LwM2M/CoAP:使用在资源受限(包括存储、功耗等)的NB-IoT设备,数据格式是二进制,需要部署编解码插件才能与物联网平台交互。 HTTPS:HTTPS是基于HTTP协议,通过SSL加密的一种安全通信协议。物联网平台支持HTTPS协议通信。 Modbus:物联网平台支持使用Modbus协议接入,使用Modbus协议的设备接入IoT边缘节点的方式为非直连。直连设备和非直连设备差异说明,请参考这里。 HTTP(TLS加密)、ONVIF、OPC-UA、OPC-DA、Other,TCP,UDP:通过边缘接入。 数据格式 JSON:平台和设备之间的通信协议采用JSON格式。 二进制码流:您需在控制台开发编解码插件,将设备上报的二进制码流数据转换为JSON格式,将平台下发的JSON格式数据解析为二进制码流格式,设备才能与平台进行通信。 所属行业 请根据实际情况选择。 设备类型 请根据实际情况选择。 高级配置 产品ID 定制ProductID,用于唯一标识一个产品。如果携带此参数,平台将产品ID设置为该参数值;如果不携带此参数,产品ID在物联网平台创建产品后由平台分配获得。 产品描述 产品描述。请根据实际情况填写。 产品创建成功后,您可以单击“更多-删除”删除不再使用的产品。删除产品后,该产品下的产品模型、编解码插件等资源将被清空,请谨慎操作。
  • 导入产品模型 当您已经有完备的产品模型时(线下开发或从其他项目/平台导出),或者使用excel编辑开发产品模型时,可以将产品模型直接导入“物联网平台”。 通过本地导入的产品模型不含编解码插件,如果设备上报采用的是二进制码流,请前往控制台进行插件开发或导入插件。 上传模型文件 访问设备接入服务,单击“管理控制台”进入设备接入控制台。选择您的实例,单击实例卡片进入。 单击左侧导航栏的“产品”,在产品列表中,找到对应的产品,单击产品进入产品界面。 在基本信息页面,单击“上传模型文件”,在弹框中加载本地的产品模型文件,然后单击“确定”。 图2 产品-上传产品模型 Excel导入 访问设备接入服务,单击“管理控制台”进入设备接入控制台。选择您的实例,单击实例卡片进入。 单击左侧导航栏的“产品”,在产品列表中,找到相应的产品,单击产品进入产品界面。 单击“Excel导入”,在产品模板表格中,填写“设备”页签的服务ID,以及“参数”页签的属性、命令、事件等参数。导入Excel表格后,然后单击“确定”。 图3 产品-Excel导入产品模型
共100000条