
# 代码解析
开发自定义驱动，进行OT数采。
```
using IoT.SDK.Edge.Interface;
using IoT.SDK.Edge.Client;
using IoT.SDK.Edge.Utils;
using IoT.SDK.Edge.Dto;
using System.Collections.Generic;
namespace ModuleSDK_Demo
{
    public class DcDriver : IPointsCallback, IModuleShadowCallback
    {
        private DcClient dcClient;
        public DcDriver()
        {
            // 创建数采客户端
            dcClient = DcClient.CreateFromEnv();
        }
        public void Start()
        {
            // 打开数采客户端
            dcClient.Open();
            // 设置点位读写回调
            dcClient.IPointsCallback = this;
            // 同步模块影子
            dcClient.StartModuleShadow(this);
        }
        /*
         * 收到点位读取请求的处理
         */
        public PointsGetRsp OnPointGet(string requestId, PointsGetReq pointsGetReq)
        {
            // TODO 伙伴需要根据OnModuleShadowReceived获取的数采配置实现读取opcua服务器的点位信息
            // PointsGetReq的Points属性结构为[pointId1,pointId2,...]的列表
            // 此处示例，读取到的点位数据均为1
            PointsGetRsp response = new PointsGetRsp();
            foreach(string pointId in pointsGetReq.Points)
            {
                response.Points.TryAdd(pointId, 1);
            }
            return response;
        }
        /*
         * 收到点位设置请求的处理
         */
        public PointsSetRsp OnPointSet(string requestId, PointsSetReq pointsSetReq)
        {
            // TODO 伙伴需要根据OnModuleShadowReceived获取的数采配置实现写opcua服务器的点位信息
            // PointsSetReq的Points属性结构为[pointId:value]的键值对
            // 此处示例，直接返回成功响应
            return new PointsSetRsp(0, "success");
        }
        /*
         * 模块影子回调，收到模块下行数采配置，消息需要缓存或持久化
         * 进入边缘节点详细->数采配置->下发配置
         */
        public void OnModuleShadowReceived(ModuleShadow shadow)
        {
            // 伙伴需要对影子进行缓存或持久化，可根据影子属性的更新时间进行增量同步
            var briefModuleShadow = JsonUtil.FromJson<BriefModuleShadowDto>(
                JsonUtil.ToJson(shadow.Properties));
            // 此处示例，只要收到模块影子，则重新连接数据源，再收集数据并主动上报
            ConnectDatasource(briefModuleShadow.ConnectionInfo);
            CollectAndReportData(briefModuleShadow.Points);
        }
        /*
         * 收集数据并上报
         */
        public void CollectAndReportData(Dictionary<string, object> points)
        {
            var reportData = new Dictionary<string, object>();
            foreach (string key in points.Keys)
            {
                PointConfig pointConfig = JsonUtil.FromJson<PointConfig>(
                    JsonUtil.ToJson(points.GetValueOrDefault(key)));
                // 伙伴可根据pointConfig中的信息读取点位数据
                // 此处示例，读取到的点位数据为10
                object value = 10;
                reportData.TryAdd(key, value);
            }
            // 调用数采应用端的接口上报数据
            PointsReport pointsReport = new PointsReport(reportData);
            dcClient.PointReport(pointsReport);
        }
        /*
         * 根据数采配置的数据源连接参数完成数据源连接
         */
        private void ConnectDatasource(Dictionary<string, string> connectionInfo)
        {
            // 以Opcua服务器为例，获取服务器连接地址
            string endPoint = connectionInfo.GetValueOrDefault("endpoint");
            // 伙伴根据endpoint实现连接数据源动作
        }
    }
}
```
下发配置对象
```
public class BriefModuleShadowDto
    {
        // 数据源id
        [JsonProperty("ds_id")]
        public string DsId { get; set; }
        // 数采模板默认参数
        [JsonProperty("default_values")]
        public Dictionary<string, string> DefaultValues { get; set; }
        // 数据源附加参数
        [JsonProperty("collection_paras")]
        public Dictionary<string, int> CollectionParas { get; set; }
        // 数据源连接信息
        [JsonProperty("connection_info")]
        public Dictionary<string, string> ConnectionInfo { get; set; }
        // 点位信息
        [JsonProperty("points")]
        public Dictionary<string, object> Points { get; set; }
    }
```
点位信息对象
```
public class PointConfig
    {
        // 点位地址，opcua地址：address = "ns=3;i=1002"
        [JsonProperty("address")]
        public string Address { get; set; }
        // 数据类型，int、int32、float、double、bool等
        [JsonProperty("data_type")]
        public string DataType { get; set; }
        // 点位采集周期单位毫秒
        [JsonProperty("cycle")]
        public int Cycle { get; set; }
        // 点位更新时间
        [JsonProperty("update_time")]
        public long UpdateTime { get; set; }
    }
```
