Skip to main content

数据接入驱动开发

本文将会详细介绍如何使用 Dotnet SDK 开发自定义数据接入驱动.

介绍

数据接入驱动 是为实现从不同的协议、设备或其它平台系统采集数据而开发的特定程序. 每个 数据接入驱动 程序需要根据协议的特点实现数据采集功能,然后将采集到的数据通过 Dotnet SDK 提供的接口发送到平台.

Dotnet SDK 提供了 数据接入驱动 开发的相关内容. 包括驱动的接口定义, 以及与平台交互功能. 开发者只需要实现接口中的方法.

开发步骤

1. 创建项目

  1. 创建项目C#控制台程序
  2. 创建 Programs.cs 文件

2. 引入SDK

  1. 添加nuget包,详细步骤见Dotnet sdk介绍-使用方式
  2. 引用命名空间
    using AiriotSDK.Data;
using AiriotSDK.Driver;
using AiriotSDK.Tools;

3. 定义schema

数据接入驱动 需要定义一个 schema 用于描述驱动的配置信息. schema 是一个类似于 json 格式的对象, 详细格式说明见 数据接入驱动schema说明. 以下是一个简单的示例:

({
"title": "netcore-driver",
"key": "netcore-driver",
"model": {
"properties": {
"settings": {
"title": "设备配置",
"type": "object",
"properties": {
"interval": {
"type": "number",
"title": "采集周期"
},
"port": {
"type": "number",
"title": "端口"
}
}
},
"tags": {
"title": "数据点",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "名称"
},
"id": {
"type": "string",
"title": "标识"
},
"unit": {
"type": "string",
"title": "单位"
},
"fixed": {
"type": "number",
"title": "小数位数"
},
"mod": {
"type": "number",
"title": "缩放比例"
}
}
}
},
"commands": {
"title": "命令",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "名称"
},
"form": {
"type": "array",
"title": "表单项",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "参数名"
},
"type": {
"type": "string",
"title": "数据类型",
"enum": [
"string",
"number",
"boolean"
],
"enum_title": [
"字符串",
"数字",
"布尔型"
]
},
"format": {
"type": "string",
"title": "表单类型",
"enum": [
"",
"date",
"datetime",
"email",
"upload_file_input"
],
"enum_title": [
"默认",
"日期选择器",
"时间选择器",
"电子邮件输入框",
"文件上传"
]
},
"enum": {
"type": "array",
"title": "选择项值",
"items": {
"type": "string"
}
},
"enum_title": {
"type": "array",
"title": "选择项文字",
"items": {
"type": "string"
}
},
"required": {
"type": "boolean",
"title": "是否必填"
},
"default": {
"type": "string",
"title": "默认值"
},
"mod": {
"type": "number",
"title": "缩放比例"
},
"tagValue": {
"type": "object",
"title": "数值定义",
"properties": {
"minValue": {
"title": "最小值",
"type": "number"
},
"maxValue": {
"title": "最大值",
"type": "number"
},
"minRaw": {
"title": "原始最小值",
"type": "number"
},
"maxRaw": {
"title": "原始最大值",
"type": "number"
}
}
}
}
}
},
"ops": {
"title": "指令",
"type": "array",
"items": {
"type": "object",
"properties": {
"action": {
"type": "string",
"title": "布/撤防",
"enum": [
"arming",
"unArming",
"queryState"
],
"enum_title": [
"系统全布防",
"系统全撤防",
"查询模块状态"
]
},
"modelNo": {
"type": "number",
"title": "模块编号",
"description": "查询模块状态指令填写"
}
}
}
}
}
}
}
}
},
"device": {
"properties": {
"settings": {
"title": "设备配置",
"type": "object",
"properties": {
"interval": {
"type": "number",
"title": "采集周期"
}
}
},
"tags": {
"title": "数据点",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "名称"
},
"id": {
"type": "string",
"title": "标识"
},
"unit": {
"type": "string",
"title": "单位"
},
"fixed": {
"type": "number",
"title": "小数位数"
},
"mod": {
"type": "number",
"title": "缩放比例"
}
}
}
}
}
}
})

4. 根据schema返回对应配置

在上一步骤中, 通过 schema 定义了驱动的相关配置, 包括 驱动配置数据点配置指令配置.

整体格式说明

驱动从平台接收到的配置信息整体格式如下:

{
"id": "645b4249b4f5349780d205d5",
"name": "netcore-driver",
"driverType": "netcore-driver",
"device": {
"commands": [],
"settings": {}
},
"tables": [{
"id": "演示表001",
"device": {
"driver": "netcore-driver",
"groupId": "645b4249b4f5349780d205d5",
"settings": {
"interval": 10
},
"tags": [{
"id": "csdata001",
"name": "csdata001"
}, {
"id": "csdata002",
"name": "csdata002"
}],
"commands": [],
"events": null
},
"devices": [{
"id": "cstable001",
"name": "cstable001",
"device": {
"driver": "",
"groupId": "",
"settings": null,
"tags": null,
"commands": null,
"events": null
},
"disable": false,
"off": false
}]
}]
}

上述格式中的 devicetables.devicetables.devices.device 分别为 驱动实例配置模型配置(工作表的设备配置)资产配置(设备的设备配置).

其中 settings驱动配置信息, 与 schema 中的 settings 对应. tags数据点配置信息, 与 schema 中的 tags 对应. commands指令配置信息, 与 schema 中的 commands 对应.

info

驱动实例模型资产 中的 settings 可以不相同, 但 tagscommands 必须相同. 例如, 可以把统一的配置信息放在 驱动实例 中, 把不同的配置信息放在 模型资产 中.

5. 实现驱动接口

SDK 中定义了 数据接入驱动接口, 该接口是平台控制驱动的桥梁. 开发者需要实现这个接口.

    /// <summary>
/// 驱动实力接口
/// </summary>
public interface IDriver
{
/// <summary>
/// 启动方法
/// </summary>
ErrorInfo Start(IDriverApp app, byte[] bytes);

/// <summary>
/// 驱动重载方法
/// </summary>
ErrorInfo Reload(IDriverApp app, byte[] bytes);

/// <summary>
/// 执行指令方法
/// </summary>
CommResult Run(IDriverApp app, Command cmd);

/// <summary>
/// 批量执行指令方法
/// </summary>
CommResult BatchRun(IDriverApp app, BatchCommand cmd);

/// <summary>
/// 数据点写入
/// </summary>
CommResult WriteTag(IDriverApp app, Command cmd);

/// <summary>
/// 调试驱动方法
/// </summary>
CommResult Debug(IDriverApp app, byte[] bytes);

/// <summary>
/// 停止驱动方法
/// </summary>
ErrorInfo Stop(IDriverApp app);

/// <summary>
/// 获取驱动schema
/// </summary>
CommResult Schema(IDriverApp app);
}

/// <summary>
/// 返回结果
/// </summary>
public class CommResult
{
public CommResult(bool status, string message, object data = null)
{
Data = data;
if (status)
{
Error = null;
}
else
{
Error = new ErrorInfo()
{
Code = -1,
Message = message
};
}
}
public ErrorInfo Error;
public object Data;

/// <summary>
/// 失败方法
/// </summary>
/// <param name="msg">错误提示信息</param>
/// <returns></returns>
public static CommResult Failure(string msg)
{
return new CommResult(false, msg);
}

/// <summary>
/// 成功方法
/// </summary>
/// <param name="msg">成功提示信息</param>
/// <param name="data">成功时返回的数据</param>
/// <returns></returns>
public static CommResult Success(string msg, object data = null)
{
return new CommResult(true, msg, data);
}
}

/// <summary>
/// 错误消息
/// </summary>
public class ErrorInfo
{
/// <summary>
/// 错误码
/// </summary>
public int Code { get; set; }

/// <summary>
/// 错误提示信息
/// </summary>
public string Message { get; set; }

/// <summary>
/// 生成一条新的错误消息
/// </summary>
/// <param name="msg">错误提示信息</param>
/// <returns></returns>
public static ErrorInfo New(string msg)
{
return new ErrorInfo()
{
Code = -1,
Message = msg
};
}
}
info

注: 向平台上报采集到的数据时, 必须通过 驱动与平台交互接口 中的 writePoint 方法发送, 不能直接调用 MQTT 客户端发送. 因为 SDK 会对发送的数据进行一些处理, 包括有效范围处理、数值映射、缩放比例、小数位等处理.

6. 配置驱动

这里所说 驱动配置 主要是一些静态配置信息(与 schema 中定义的配置无关), 其中包括 平台配置信息, 驱动配置信息自定义配置信息. 这些信息一般通过配置文件(rc)、环境变量、命令行参数等方式传入. 其中一些配置信息由平台启动驱动时通过命令行参数传入.

这些配置信息, 在开发过程中可以根据实际情况进行调整. 但是在打包时必须按照平台的要求进行配置. 打包时的配置信息见 驱动配置说明.

平台配置信息

平台配置信息 主要为平台的连接信息. 包括: MQTT 连接信息, 驱动管理服务 连接信息. 内容如下:

mq:
type: mqtt
mqtt:
host: 平台mqtt服务器ip地址
port: 平台mqtt服务器端口

serviceId: 所属项目ID
project: 驱动实例ID

driver:
id: 驱动ID
name: 驱动名称

driverGrpc:
host: 驱动管理服务ip地址
port: 驱动管理服务端口
info

相关服务的端口号可在运维管理系统中查看.

驱动配置信息

驱动配置信息 主要包括 驱动ID, 驱动名称, 驱动实例ID, 所属项目ID.

  • 驱动ID 为驱动的唯一标识, 必须在平台中唯一.
  • 驱动名称 为该驱动在平台中的显示名称.
  • 驱动实例ID 为该驱动实例的唯一标识. 同一个驱动可以创建多个实例, 每个实例的 驱动ID 相同但 驱动实例ID 唯一. 该信息由平台在 驱动管理 中创建驱动实例时生成.
  • 所属项目ID 每个驱动实例都属于一个项目, 该驱动实例只会拿到该项目中的模型和设备信息.
serviceId: 所属项目ID
project: 驱动实例ID

driver:
id: 驱动ID
name: 驱动名称
info
  1. 驱动ID驱动名称 需要在配置中手动定义.

  2. 驱动实例ID所属项目ID 在开发过程中, 需要将这些信息手动配置. 在打包时无须定义, 在平台中安装驱动时这些信息会由平台通过命令行参数传入.

驱动配置说明

以下是完整的驱动配置文件, 请参考该配置文件进行配置.

mq:
type: mqtt
mqtt:
host: 127.0.0.1
port: 1883

serviceId: 所属项目ID
project: 驱动实例ID

driver:
id: 驱动ID
name: 驱动名称

driverGrpc:
host: 127.0.0.1
port: 9224

windows系统打包发布时的驱动配置

driverGrpc:
host: 127.0.0.1
port: 9224

mq:
type: mqtt
mqtt:
host: 127.0.0.1
port: 1883

driver:
id: netcore-driver
name: dotnet驱动例子

linux系统打包发布时的驱动配置

driver:
id: netcore-driver
name: dotnet驱动例子