协议插件开发
# 协议插件开发
# 概述
协议插件是基于敢为 IoTCenter 平台、用以实现协议对接的最小组件,其交付物的常见文件格式为".dll",由于协议插件可对接的对象通常会称为“设备”,所以协议插件也被称为“设备动态库”。
本节内容较多,囊括很多基础性的知识,必须细致了解,后面章节的内容以本节为基础。
# 设备是什么?
众所周知,在类似于智慧家居这种场景的物联网系统中,最常见是一眼就可以看明白、具有连通性(及其和系统间的互联性和关联性)的设备,所以我们可能会习以为常的将IoTCenter平台理解为面向硬件设备的物联网接入系统,事实上并非如此。对于企业级物联网系统而言,所要管理的物联网设备,可能并不仅仅只包括这些硬件,可能还包括更加复杂的业务领域,所以,我们有必要先了解在IoTCenter平台中,对于"设备"这个名词的理解。
物联网系统与传统的面向Web的业务系统存在的最大区别就在于设备在其中担任着非常重要的作用。通常而言,设备指的是一种”物“,它上面搭载着一种名为传感器的电子原件,并与网络相连接。比如,大家使用的手机,具有烟雾传感器,监控摄像头等,都是设备的一种。不仅如此,具有联网能力的其他设备,如雨伞或我们佩戴的手环,也同样是”设备“。但不同的设备可能有不同的接入方式,可能会使用不同的技术手段。
若IoTCenter部署某台服务器上,我们以其为视角,去观察与之相联通的各种硬件,大体可以识别为如下几种情形:
- 通过常见协议直接连接的硬件:可以通过蓝牙、TCP、UDP协议与服务器直接连接的硬件。
- 不能直接连接的硬件:网络设备中,有一些设备不能直接连接到服务器,而是通过一种负责连接设备的机器或软件与服务器连接。 通俗而言,这种组件被称为”网关“,包括硬网关和软网关两种类型。
- 通过物联网系统连接:由于企业级市场有别于家用市场,通常在项目中,某些特定的硬件会通过专用物联网系统来访问,这种物联网系统一般称为”物联网感知系统“。
- 不通过局域网连接,而是通过互联网连接的设备:有一些设备,它们虽然部署在内网,但事实上不具备内网连接端口,而是通过内置sim卡(物联卡)的形式,先连接到互联网,然后服务器再通过互联网与之相连。
# 设备的类型
根据上述四种情形,IoTCenter将可连接的设备细分为直连设备和子系统、虚拟设备三种类型:
- 直连设备
通过协议机制与服务器直接连接的设备,称为”直连设备“。具体而言,可能包括的协议包括有线类的串口、以太网,无线类的蓝牙,wifi,小功率无线收发器,zigbee等协议。
- 子系统
通过网关或物联网感知平台与服务器相连的设备,称为”子系统“。子系统既包括网关,也包括物联网感知系统。
- 虚拟设备:
由网关、物联网感知系统所管理的子设备,对于IoTCenter平台来说,看似真实存在,实际上无需关心其是否真实存在,可以理解为虚拟设备。事实上虚拟设备不一定是子设备,也有可能是由多个直连设备、子设备的某些属性值,按照业务逻辑组合起来的逻辑设备。
# 协议插件
在IoTCenter开发中,最基础最常见的组件当属协议插件莫属了,协议插件的主要作用包括:
# 协议插件基础
# 开发协议插件的基本流程
开发协议插件,又称【协议对接】,该步骤是物联网开发的首要关键步骤。单纯从技术层面来说,协议对接似乎只是简单的将数据从A平台转换到敢为物联网平台,简单的实现数据采集,事实上这个步骤依然存在不少需要注意的技术细节。
优雅的开发者总善于将各类复杂问题抽象化为共性问题,并站在更高的抽象用解决通用问题的方法来解决某些具体问题。总体而言,敢为认为协议对接流程大体经历三个基本环节:
需求分析设计
协议解析
提取项目需求,并获得由客户或供应商提供的协议文本,对该协议进行分析,提取与当前项目需求匹配的业务接口。
必要时,根据业务分析当前协议文本与实际需求的差异之处,依托团队沟通手段,对相关问题进行澄清,减少不必要的浪费,确保协议插件开发的有序开展。
设计物模型
根据业务接口,梳理协议插件需要具备的基础要素,设计物模型。
对接开发
根据设计的物模型,设计和开发协议插件所需要具备的基础能力,并通过自测,验证其功能可用性。
集成调试
在IoTCenter平台中部署协议插件,并通过平台中查看该设备的实际数据,验证功能闭环,完成项目功能上线。
由于物联网领域多与硬件或子系统打交道,在实际商业项目中硬件或子系统的采购、安装、部署的周期非常长,使得开发出来的成果往往不能第一时间得到验证。而当项目上线时,有可能会要求在较短的时间内快速完成协议对接,这可能要耗费大量的时间和精力。
建议开发者多依托自己的开发环境,通过模拟工具的方式,创造更多的测试条件,提前验证代码的可用性,降低项目交付的成本。
由于本章节主要侧重于提供协议插件开发的示例,上述环节可简单了解,后续将通过多个实战练习使读者形成肌肉记忆。
# 选择开发框架
.NET 框架目前有 .NET Framework、.NET Core、Mono等,开发动态库,可根据需要选择最佳框架,例如,如果开发的协议插件需要在windows 版本下运行,可选择 .NET 6.0。
选择何种.NET框架
目前由于IoTCenter基于 .NET 6.0开发,建议协议插件开发时,默认版本可选择 .NET 6.0,若后续IoTCenter版本升级,则将会给出推荐的 .NET Core版本。
.NET Core 的开发目标是跨平台的.NET平台,因此 .NET Core 会包含 .NET Framework的类别库,但与 .NET Framework 不同的是 .NET Core 采用包化 (Packages) 的管理方式,应用程序只需要获取需要的组件即可,与 .NET Framework 大包式安装的作法截然不同,同时各包亦有独立的版本线 (Version line),不再硬性要求应用程序跟随主线版本。
何时选择 .NET Standard框架
微软为了实现跨平台、多架构,所以会出现多种类型的框架,.NET Standard 不是框架,而是一种 API 标准,所有的 .NET 框架都必须按照规范设计,目前 .NET Standard 共有 9 个版本。
.NET Standard 的类库,可以同时被 .NET Framework 、 .NET Core 、Xamain 等项目引用。 .NET Framework 、 .NET Core 、Xamain 各自创建的类库、项目,不能被其他类型的项目引用。
由于 .NET Strandard在 .NET 5以后版本中已经停止维护,不再更新,目前仅推荐需要同时兼容早期版本AlarmCenter产品和IoTCenter产品的项目中中开发相应协议插件时采用。
# 保持连接
设备通过常用协议机制与IoTCenter连接,并通过协议向其发送各种数据。在这种情况下,实现具体连接能力的的基础组件,就是协议插件。IoTCenter将给每个协议插件分配相应的线程维护其运行状态,并可通过设定的规则定期与设备进行主动通信机制,避免由于连接中断而导致功能不可用的问题。
# 接收、采集和处理数据
设备将数据转发给IoTCenter服务,由于为了数据传输的方便,可能会发送二进制格式。协议插件负责接收这种二进制格式的原始数据,并按照约定的规则,将数据编解码为数值数据和字符串的格式。
备注:BCD码是一种二进制的数字编码形式,用二进制编码编码十进制代码。
有时,每台设备发送的数据不会直接发送给服务器,而是将大量数据整合为一个完整的数据包后再发给服务器,这样可以通过整合数据减少数据的附加信息,也能减少网络带宽消耗,减少对服务器的负担。协议插件也承担了对该数据包的解包功能。
此外,设备向服务器发送的频率可能并非实时,而是按照一定的时延定期发送,或根据数据产生量,不定期发送,那么协议插件内部也需要具备这种处理功能。
# 数据存储
物联网系统接收到的数据可分为结构化和非结构化两种,IoTCenter具备存储物联网实时非结构化数据的能力,如果处理后的结构化数据需要存储,则需要由协议插件开发相应的存储功能。
# 物模型
# 定义
协议插件的运行依赖于开发者对其进行领域建模,而在IoTCenter平台中对设备使用了通用建模结构,这种建模结构又称为“物模型”。这种模型是对物理空间中的实体(如传感器、车载装置、楼宇、工厂等)在云端的数字化表示,从基本属性、遥测属性、遥信属性、设置四个方面,分别描述了该实体是什么、能做什么、如何实现对其的控制。
以下对这四个方面进行了说明。
功能类型 | 说明 |
---|---|
设备基本属性 | 描述设备的基本定义。包括连接方式,采用的协议通信机制,通信时间参数等基本信息。 |
遥测属性 | 设备可读取的能力中,以读数表示的部分。一般用于描述设备运行时的读数,如环境监测设备所读取的当前环境温度等。 |
遥信属性 | 设备可读取的能力中,以状态值表示的部分。例如开关机状态,是否触发何种报警等。 |
设置 | 设备运行时,可由接入方触发的某种事件,如对某个读数进行设置,对设备进行开机,关机操作等。 |
理解设备的通用建模结构,是进行IoTCenter协议插件开发的基础。IoTCenter平台定义的物模型有别于其他平台的物模型,附录有一篇《IoTCenter物模型与其他平台物模型的区别》专题介绍。
# 常见属性字段
# 设备基本属性
配置与设备进行连接的常见参数及数据采集周期。必备属性包括以下字段:
- 所属产品
产品是具有业务含义的实际对象,可选择当前设备关联的产品类型,在本文档的历史版本中,被定义为【设备模板】。
- 设备名称
定义当前设备的名称。主要用于与其他设备进行区分。
- 通信刷新周期
协议插件是通过独立线程的机制与远端设备保持连接,该刷新周期字段用于协议插件的数据采集频率,单位为毫秒。
- 驱动文件
即实际协议插件可执行程序文件。
- 设备地址
如果远端设备使用了串口或Tcp通信的服务端,设备地址为其实际的IP地址加端口号,如192.168.0.1:2206,表示当前协议插件内部将创建到远端192.168.0.1:2206的连接客户端。如果远端设备为http地址,则可通过此字段定义远端服务的地址,如http://192.168.0.1/httpserver。
- 通讯端口
如果远端设备为客户端,IoTCenter为服务端,使用通讯端口作为本机与远端通信的端口。例如为当前主机IP加端口号,如127.0.0.1:2206,则表示协议插件内部需要创建该Tcp的服务端,客户端直接连接到此服务端。同时,通讯端口也定义了本机在运行协议插件时的线程分组标识,相同的通讯端口,将使用同一个线程来运行协议插件。
- 通讯时间参数
使用modbus、串口、tcp等机制中,如果将IoTCenter定义为客户端,可通过定义通讯时间参数来刷新与目标服务端设备的连接状态。该参数的格式为500/4/3/1000,指发送通讯请求500ms后,4ms内没有回应算作一次通讯失败,上一次失败后,等待1000ms后进行下一次通讯, 允许通讯连续失败3次,如果连续失败4次则判定为通讯故障。
- 其他参数
# 遥测属性
物联网属性,侧重于读数,包括文本型,数值型,时间型。例如天气预报过程中的温度,湿度,降水概率等。
- 设备号
当前遥测所关联的设备编号。
- 遥测号
当前设备下遥测的唯一编号。
- 遥测编码
不同设备间,若具有相同的遥测字段,可用相同的遥测编码表示。例如温湿度感应器具有温度和湿度两个属性,而某个电器(如电冰箱)也有温度和湿度两个属性,则可以使用相同的编码表示。
- 遥测名称
遥测的中文显示名称。
- 单位
以天气预报的温度为例,其单位可以为℃(摄氏度)或℉(华氏度)。
- 操作命令
用于从远端设备获取指定测点时的指标名称。例如,通过Http接口获取天气预报数据时,可通过定义Temp的字段来关联该天气预报接口的指定属性值。
- 操作参数
如果提取到的原始数据需要经过一些计算规则,可通过定义操作参数来实现。例如,若天气预报返回的为摄氏度,而业务需求需要转换为华氏度,则可定义一个转换方式(ToF),表示在提取到摄氏度的天气预报时,使用该转换方式,将天气预报转化为华氏度。
- 报警范围
对于物联网设备来说,报警是基本需求,以天气预报为例,若气温超过35摄氏度,则可能要触发报警。因此,还可根据需要设计遥测的报警范围。
该范围包括最小值(触发报警时的最小温度值),最大值(触发报警时的最大温度值),恢复下限值(温度达到多少恢复为正常状态的下限值),恢复上限值(温度达到多少恢复为正常状态时的最大值)。
# 遥信属性
物联网属性,侧重于布尔状态值。如开关状态,是否触发了火警报警等。若以天气预报为例,可设置
- 设备号
当前遥测所关联的设备编号。
- 遥信号
当前遥信所关联的唯一编号。
- 遥信编码
不同设备间,若具有相同的遥信属性值,可用相同的遥信编码表示。例如温湿度感应器具有过热报警属性,而某个电器(如电冰箱)也有过热报警属性,则可以使用相同的编码表示。
- 遥信名称
遥测的中文显示名称。
- 操作命令
用于从远端设备获取指定测点时的指标名称。例如,通过Http接口获取天气预报数据时,可通过定义IsRain的字段来关联该天气预报接口的指定属性值(Rain)。
- 操作参数
如果提取到的原始数据需要经过一些计算规则,可通过定义操作参数来实现。例如,若天气预报返回的为Rain为整形数据,而业务需求需要转换为华氏度,则可定义一个转换方式(ToBoolean),表示在提取到整形或其他类型的天气预报时,使用该转换方式,将天气预报转化为布尔量。
以Modbus为例的数据协议,有时需要通过一组关键词和参数来提取寄存器的内存数值,可通过操作命令和操作参数来定义提取条件。
- 0-1级别
由于遥信一般为布尔量,则表示从布尔量的0,切换到布尔量的1时,设备测点显示的状态。例如,一般可定义从0-1为正常状态。
- 1-0级别
由于遥信一般为布尔量,则表示从布尔量的1,切换到布尔量的0时,设备测点显示的状态。例如,一般可定义从0-1为非正常状态。
# 设置
设置一般为对远端物联网设备或终端,或子系统采取的某些交互性操作,例如触发电灯回路打开开关,对空调等进行温度调节等。
- 设备号
当前设置所关联的设备编号。
- 设置编码
若对不同的物联网设备,可采取一类操作,可用唯一的编码表示。例如,定义空调的温度控制,和对新风机进行温度控制等。
- 设置名称
设置的中文名称。
- 操作命令
对远端设备进行某些操作时,定义的操作标识。例如,如果操作命令为“OpenLight",表示对某个电灯回路进行开灯操作。
- 操作参数
与遥测、遥信的操作参数类似,一般可用于某些复杂场景需要多种规则组合执行操作的情况。
- 设置类型
不同的设置,通过不同的设置类型代码来定义不同操作类型,包括如下几种:
有输入的设置 V:需要由用户或外部接口传入设置的具体数据。 遥测属性设置 C:对遥测属性值进行设置。 遥信属性设置 X:对遥信属性值进行设置。 系统命令 S:通过协议插件机制实现命令下发。 场景命令 J:通过场景控制协议插件实现场景指令下发。
- 值
对设备进行某些操作时,需要设置的具体数值,也包括可传输到远端的数据结构。例如在Http接口中,可能通过Post方法向接口传输数据,则可通过预先定义json数据体的方式实现。
设置的具体参数,可参见《设置参数详解》.
接下来将通过开发一些具体的协议插件来探究协议插件的运行机制,实际代码开发时,属性与IoTCenter提供的物联网开发Api相结合的的接口或参数对照表,可参见下表。
# 设备属性对照表
表
序号 | 字段名称 | 数据类型 | 允许Null值 | 字段说明 | 是否主键 |
---|---|---|---|---|---|
1 | sta_n | int | Yes | 站点号 | 否 |
2 | equip_no | int | No | 设备编码 | 是 |
3 | equip_nm | nvarchar(64) | No | 设备名称 | 否 |
4 | equip_detail | nvarchar(255) | Yes | 设备属性 | 否 |
5 | acc_cyc | int | Yes | 通讯刷新周期 | 否 |
6 | related_pic | nvarchar(255) | Yes | 关联页面 | 否 |
7 | proc_advice | nvarchar(254) | Yes | 通讯故障处理意见 | 否 |
8 | out_of_contact | nvarchar(64) | No | 故障信息 | 否 |
9 | contacted | nvarchar(64) | Yes | 故障恢复提示 | 否 |
10 | event_wav | nvarchar(64) | Yes | 报警声音文件 | 否 |
11 | communication_drv | nvarchar(128) | Yes | 驱动文件 | 否 |
12 | local_addr | nvarchar(64) | Yes | 通讯端口 | 否 |
13 | equip_addr | nvarchar(128) | Yes | 设备地址 | 否 |
14 | communication_param | nvarchar(MAX) | Yes | 通讯参数 | 否 |
15 | communication_time_param | nvarchar(32) | Yes | 通讯时间参数 | 否 |
16 | raw_equip_no | int | Yes | 模板设备号 | 否 |
17 | tabname | nvarchar(15) | Yes | 附表名称 | 否 |
18 | alarm_scheme | int | Yes | 报警方式 | 否 |
19 | attrib | int | Yes | 属性 | 否 |
20 | sta_IP | nvarchar(255) | Yes | 站点IP | 否 |
21 | AlarmRiseCycle | int | Yes | 报警升级周期(分钟) | 否 |
22 | Reserve1 | nvarchar(MAX) | Yes | 扩展字段1 | 否 |
23 | Reserve2 | nvarchar(MAX) | Yes | 扩展字段2 | 否 |
24 | Reserve3 | nvarchar(MAX) | Yes | 扩展字段3 | 否 |
25 | related_video | nvarchar(255) | Yes | 关联视频 | 否 |
26 | ZiChanID | nvarchar(255) | Yes | 资产编号 | 否 |
27 | PlanNo | nvarchar(255) | Yes | 预案编号 | 否 |
28 | SafeTime | nvarchar(MAX) | Yes | 安全时段 | 否 |
# 遥测属性对照表
表
序号 | 字段名称 | 数据类型 | 允许Null值 | 字段说明 | 是否主键 |
---|---|---|---|---|---|
1 | sta_n | smallint | Yes | 站点号 | 否 |
2 | equip_no | smallint | No | 设备号 | 是 |
3 | yc_no | smallint | No | 遥测号 | 是 |
4 | yc_nm | nvarchar(80) | Yes | 遥测名称 | 否 |
5 | mapping | bit | No | 是否进行比例变换 | 否 |
6 | yc_min | real | Yes | 最小值 | 否 |
7 | yc_max | real | Yes | 最大值 | 否 |
8 | physic_min | real | Yes | 实测最小值 | 否 |
9 | physic_max | real | Yes | 实测最大值 | 否 |
10 | val_min | real | Yes | 下限值 | 否 |
11 | restore_min | real | Yes | 回复下限值 | 否 |
12 | restore_max | real | Yes | 回复上限值 | 否 |
13 | val_max | real | Yes | 上限值 | 否 |
14 | val_trait | int | Yes | 属性值 | 否 |
15 | main_instruction | nvarchar(128) | Yes | 操作命令 | 否 |
16 | minor_instruction | nvarchar(128) | Yes | 操作参数 | 否 |
17 | safe_bgn | datetime | Yes | 安全时段(始) | 否 |
18 | safe_end | datetime | Yes | 安全时段(末) | 否 |
19 | alarm_acceptable_time | smallint | Yes | 越线滞纳时间(秒) | 否 |
20 | restore_acceptable_time | smallint | Yes | 恢复滞纳时间(秒) | 否 |
21 | alarm_repeat_time | smallint | Yes | 重复报警时间(分钟) | 否 |
22 | proc_advice | nvarchar(254) | Yes | 处理意见 | 否 |
23 | lvl_level | smallint | No | 报警级别 | 否 |
24 | outmin_evt | nvarchar(64) | Yes | 越下限事件 | 否 |
25 | outmax_evt | nvarchar(64) | Yes | 越上限事件 | 否 |
26 | wave_file | nvarchar(64) | Yes | 声音文件 | 否 |
27 | related_pic | nvarchar(255) | Yes | 弹出页面 | 否 |
28 | alarm_scheme | int | Yes | 报警方式 | 否 |
29 | curve_rcd | bit | No | 是否曲线记录 | 否 |
30 | curve_limit | real | Yes | 曲线记录阈值 | 否 |
31 | alarm_shield | ntext | Yes | 报警记录级别(报警屏蔽) | 否 |
32 | unit | nvarchar(50) | Yes | 单位 | 否 |
33 | AlarmRiseCycle | int | Yes | 报警升级周期 | 否 |
34 | Reserve1 | ntext | Yes | 扩展字段1 | 否 |
35 | Reserve2 | ntext | Yes | 扩展字段2 | 否 |
36 | Reserve3 | ntext | Yes | 扩展字段3 | 否 |
37 | related_video | nvarchar(255) | Yes | 关联视频 | 否 |
38 | ZiChanID | nvarchar(255) | Yes | 资产编号 | 否 |
39 | PlanNo | nvarchar(255) | Yes | 预案号 | 否 |
40 | SafeTime | ntext | Yes | 安全时段 | 否 |
# 遥测属性对照表
表
序号 | 字段名称 | 数据类型 | 允许Null值 | 字段说明 | 是否主键 |
---|---|---|---|---|---|
1 | sta_n | smallint | Yes | 站点号 | 否 |
2 | equip_no | smallint | No | 设备号 | 是 |
3 | yx_no | smallint | No | 遥信号 | 是 |
4 | yx_nm | nvarchar(80) | Yes | 遥信名称 | 否 |
9 | proc_advice_r | nvarchar(254) | Yes | 处理意见0-1 | 否 |
10 | proc_advice_d | nvarchar(254) | Yes | 处理意见1-0 | 否 |
11 | level_r | smallint | Yes | 0-1事件级别 | 否 |
12 | level_d | smallint | Yes | 1-0事件级别 | 否 |
13 | evt_01 | nvarchar(64) | Yes | 0-1事件描述 | 否 |
14 | evt_10 | nvarchar(64) | Yes | 1-0事件描述 | 否 |
15 | main_instruction | nvarchar(128) | Yes | 操作命令 | 否 |
16 | minor_instruction | nvarchar(128) | Yes | 操作参数 | 否 |
17 | safe_bgn | datetime | Yes | 安全时段(始) | 否 |
18 | safe_end | datetime | Yes | 安全时段(末) | 否 |
19 | alarm_acceptable_time | smallint | Yes | 越线滞纳时间(秒) | 否 |
20 | restore_acceptable_time | smallint | Yes | 恢复滞纳时间(秒) | 否 |
21 | alarm_repeat_time | smallint | Yes | 重复报警时间(分钟) | 否 |
26 | wave_file | nvarchar(64) | Yes | 声音文件 | 否 |
27 | related_pic | nvarchar(255) | Yes | 弹出页面 | 否 |
28 | alarm_scheme | int | Yes | 报警方式 | 否 |
29 | inversion | bit | No | 是否取反 | 否 |
30 | initval | smallint | Yes | 初始状态(值) | 否 |
31 | val_trait | ntext | Yes | 属性值 | 否 |
32 | alarm_shield | ntext | Yes | 报警屏蔽 | 否 |
33 | AlarmRiseCycle | int | Yes | 报警升级周期 | 否 |
34 | Reserve1 | ntext | Yes | 扩展字段1 | 否 |
35 | Reserve2 | ntext | Yes | 扩展字段2 | 否 |
36 | Reserve3 | ntext | Yes | 扩展字段3 | 否 |
37 | related_video | nvarchar(255) | Yes | 关联视频 | 否 |
38 | ZiChanID | nvarchar(255) | Yes | 资产编号 | 否 |
39 | PlanNo | nvarchar(255) | Yes | 预案号 | 否 |
40 | SafeTime | ntext | Yes | 安全时段 | 否 |
# 设置属性对照表
表
序号 | 字段名称 | 数据类型 | 允许Null值 | 字段说明 | 是否主键 |
---|---|---|---|---|---|
1 | sta_n | smallint | Yes | 站点号 | 否 |
2 | equip_no | smallint | No | 设备号 | 是 |
3 | set_no | smallint | No | 设置号 | 是 |
4 | set_nm | ntext | Yes | 设置名称 | 否 |
5 | set_type | nvarchar(1) | Yes | 设置类型 | 否 |
6 | main_instruction | nvarchar(64) | Yes | 操作命令 | 否 |
7 | minor_instruction | nvarchar(255) | Yes | 参照参数 | 否 |
8 | record | bit | Yes | 记录 | 否 |
9 | action | nvarchar(16) | Yes | 动作 | 否 |
10 | value | nvarchar(255) | Yes | 值 | 否 |
11 | canexecution | bit | Yes | 是否执行 | 否 |
12 | VoiceKeys | ntext | Yes | 语音命令 | 否 |
13 | EnableVoice | bit | Yes | 是否支持语音 | 否 |
14 | Reserve1 | ntext | Yes | 保留字段1 | 否 |
15 | Reserve2 | ntext | Yes | 保留字段2 | 否 |
16 | Reserve3 | ntext | Yes | 保留字段3 | 否 |
17 | qr_equip_no | smallint | Yes | 二维码 | 否 |