C#实现数据采集系统-多设备采集

系统功能升级-多设备采集

数据采集系统在网络环境下,性能足够,可以实现1对多采集,需要支持多个设备进行同时采集功能,现在就开发多设备采集功能

修改多设备配置

设备配置

  1. DeviceLink 改成List集合的DeviceLinks
  2. 删掉Points,将点位集合放到对应的设备中去
csharp 复制代码
    public class DaqOption
    {
        //单设备
        //public DeviceLink DeviceLink { get; set; }
        //多设备
        public List<DeviceLink> DeviceLinks { get; set; }

        public MqttConfig MqttConfig { get; set; }

        public ServiceConfig ServiceConfig { get; set; }
        
        //public List<RegisterPoint> Points { get; set; }

        public DaqOption() { }
    }
    
    
/// <summary>
 /// 设备链路类
 /// </summary>
 public class DeviceLink
 {
     public string UID { get; set; }
     public string Ip { get; set; }

     public int Port { get; set; }

     public int SlaveId { get; set; } = 1;

     /// <summary>
     /// 采集周期 单位:S   200ms 0.2s
     /// </summary>
     public double AcqTimeSpan { get; set; }
     
     
      //增加
     public List<RegisterPoint> Points { get; set; }

     public DeviceLink()
     {
         Points = new List<RegisterPoint>();
     }
 }

同时配置文件也跟着变化,DeviceLinks改成数组形式,变成两个设备的配置

json 复制代码
{
  "DeviceLinks": [
    {
      "UID": "device01",
      "Ip": "127.0.0.1",
      "Port": 502,
      "SlaveId": 1,
      "AcqTimeSpan": 1
    },
    {
      "UID": "device02",
      "Ip": "127.0.0.1",
      "Port": 503,
      "SlaveId": 1,
      "AcqTimeSpan": 1
    }
  ],
  "MqttConfig": {
   //...
  },
  "ServiceConfig": {
  //...
  }
}

数据点位配置

RegisterPoint中增加设备Id的属性,用于区分,这个数据点位属于哪个设备

csharp 复制代码
    public class RegisterPoint
    {
        //...

        public string DeviceId { get; set; }
    }

配置加载

DaqOptionBuilder修改配置加载,主要就是点位的加载,多设备配置的加载,按上面的配置修改后,自动反序列化加载。

点位的加载,需要读入新加的设备Id,然后根据设备id在DeviceLinks中查找到对应的设备,然后将点位加入到对应设备的点位集合Points中去。

csharp 复制代码
 public class DaqOptionBuilder
 {
     //...

     public DaqOption Build()
     {
         var str = File.ReadAllText(_path + "\\Config.json");
         var option = JsonSerializer.Deserialize<DaqOption>(str);

         List<RegisterPoint> points = new List<RegisterPoint>();
         var lines = File.ReadAllLines(_path + "\\AllPoint.csv").ToList();
         lines.RemoveAt(0);
         foreach (var line in lines)
         {
             var values = line.Split(',');
             var point = new RegisterPoint
             {
                 UID = values[0],
                 Name = values[1],
                 Type = Type.GetType("System." + values[2]),
                 RegisterType = values[3],
                 Address = int.Parse(values[4]),
                 Length = int.Parse(values[5]),
                 DeviceId = values[6] //读入点位对应的设备ID
             };
             //查找对应的设备,将点位加入进去
             option.DeviceLinks.FirstOrDefault(x => x.UID == point.DeviceId)?.Points.Add(point);
         }

         return option;
     }
 }

主服务修改

多设备属性修改

修改DaqService服务类中,原来设备对象_deviceLink_points,改成设备集合_deviceLinks,然后对应的服务类中同步修改

csharp 复制代码
 public class DaqService
 {
     // 原来
     // private DeviceLink _deviceLink;
     // private List<RegisterPoint> _points;
     
     //新
     private List<DeviceLink> _deviceLinks;
     
     
      public DaqService(DaqOption option)
     {
        
         //...
         //修改
         _deviceLinks = option.DeviceLinks;
         //...
     }
 }

功能修改

在启动和定时推送中,都改成循环_deviceLinks来实现功能

csharp 复制代码
 public void Start()
 {
     foreach (var item in _deviceLinks)
     {
         ModbusTcp modbusTcp = new ModbusTcp(item);
         modbusTcp.ValueUpdated += ModbusTcp_ValueUpdated;
         modbusTcp.DoMitor();
     }

     mqttControllor = new MqttControllor(_option.MqttConfig);
     mqttControllor.MqttConnect();
     if (_serviceConfig.IsPushScheduled)
     {
         _timer.Start();
     }
 }
 
     private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
    {
        foreach (var link in _deviceLinks)
        {
            try
            {
                DeviceMessage deviceMessage = new DeviceMessage() { DeviceId = link.UID };
                foreach (var point in link.Points)
                {
                    Console.WriteLine($"Point:{point.UID}-->Value:{point.Value}");
                    deviceMessage.Data.Add(point.UID, point.Value);
                }
                var str1 = JsonSerializer.Serialize(deviceMessage);
                mqttControllor.Publish("Device/" + link.UID + "/Time", str1);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

在变化推送中,可以直接使用点位中DeviceId 替代原设备ID(_deviceLink.UID

csharp 复制代码
 //事件方法
 private void ModbusTcp_ValueUpdated(RegisterPoint point, object value)
 {
     if (_serviceConfig.IsPushChanged)
     {
         try
         {
             DeviceMessage device = new DeviceMessage { DeviceId = point.DeviceId };
             device.Data.Add(point.UID, value);
             var data = JsonSerializer.Serialize(device);
             mqttControllor.Publish($"Device/{point.DeviceId}/Update", data); //采集立刻推送
         }
         catch (Exception ex)
         {
             Console.WriteLine(ex.Message);
         }
         Console.WriteLine($"Point:{point.UID}-->Value:{value}");
     }
 }

完整的服务代码

csharp 复制代码
 public class DaqService
 {
     private DaqOption _option;
     private List<DeviceLink> _deviceLinks;
     private ServiceConfig _serviceConfig;

     MqttControllor mqttControllor { get; set; }

     private Timer _timer;

     public DaqService(DaqOption option)
     {
         _option = option;
         _deviceLinks = option.DeviceLinks;
         _serviceConfig = option.ServiceConfig;
         if (_serviceConfig.IsPushScheduled)
         {
             _timer = new Timer(_serviceConfig.PushTimeSpan * 1000);
             _timer.Elapsed += Timer_Elapsed;
         }
     }

     public void Start()
     {
         foreach (var item in _deviceLinks)
         {
             ModbusTcp modbusTcp = new ModbusTcp(item);
             modbusTcp.ValueUpdated += ModbusTcp_ValueUpdated;
             modbusTcp.DoMitor();
         }

         mqttControllor = new MqttControllor(_option.MqttConfig);
         mqttControllor.MqttConnect();
         if (_serviceConfig.IsPushScheduled)
         {
             _timer.Start();
         }
     }

     private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
     {
         foreach (var link in _deviceLinks)
         {
             try
             {
                 DeviceMessage deviceMessage = new DeviceMessage() { DeviceId = link.UID };
                 foreach (var point in link.Points)
                 {
                     Console.WriteLine($"Point:{point.UID}-->Value:{point.Value}");
                     deviceMessage.Data.Add(point.UID, point.Value);
                 }
                 var str1 = JsonSerializer.Serialize(deviceMessage);
                 mqttControllor.Publish("Device/" + link.UID + "/Time", str1);
             }
             catch (Exception ex)
             {
                 Console.WriteLine(ex.Message);
             }
         }
     }

     //事件方法
     private void ModbusTcp_ValueUpdated(RegisterPoint point, object value)
     {
         if (_serviceConfig.IsPushChanged)
         {
             try
             {
                 DeviceMessage device = new DeviceMessage { DeviceId = point.DeviceId };
                 device.Data.Add(point.UID, value);
                 var data = JsonSerializer.Serialize(device);
                 mqttControllor.Publish($"Device/{point.DeviceId}/Update", data); //采集立刻推送
             }
             catch (Exception ex)
             {
                 Console.WriteLine(ex.Message);
             }
             Console.WriteLine($"Point:{point.UID}-->Value:{value}");
         }
     }
 }

最终实现效果

相关推荐
IT规划师14 分钟前
C#|.net core 基础 - 扩展数组添加删除性能最好的方法
c#·.netcore·数组
时光追逐者1 小时前
分享6个.NET开源的AI和LLM相关项目框架
人工智能·microsoft·ai·c#·.net·.netcore
friklogff1 小时前
【C#生态园】提升C#开发效率:深入了解自然语言处理库与工具
开发语言·c#·区块链
__water10 小时前
『功能项目』回调函数处理死亡【54】
c#·回调函数·unity引擎
__water10 小时前
『功能项目』眩晕图标显示【52】
c#·unity引擎·动画事件
程序猿小D10 小时前
第二百三十五节 JPA教程 - JPA Lob列示例
java·数据库·windows·oracle·jdk·jpa
__water11 小时前
『功能项目』第二职业法师的平A【57】
c#·unity引擎·魔法球伤害传递
iummature12 小时前
ZLMediaKit Windows编译以及使用
windows
__water13 小时前
『功能项目』战士的伤害型技能【45】
c#·unity引擎·战士职业伤害型技能
君莫愁。14 小时前
【Unity】检测鼠标点击位置是否有2D对象
unity·c#·游戏引擎