系统优化-服务封装
现在我们调用modbustcp和mqtt都直接在Program,所有加载和功能都混合在一起,比较难以维护
类似asp.net core项目的Program.cs代码如下,构建服务配置和启动
要实现的效果,Main方法中就是一个服务启动,只需要几行代码
分析代码
这里分成两部分,一部分是配置文件加载,另一部分是各种功能调用和启动
优化封装
配置封装
在DAqOption增加List<RegisterPoint>
数据点位集合,让配置信息都在一个Option中,他将作为参数传递到后续的服务中去
public class DAqOption
{
public DeviceLink DeviceLink { get; set; }
public MqttConfig MqttConfig { get; set; }
public List<RegisterPoint> Points { get; set; }
}
创建一个DAqOptionBuilder
用来加载和创建配置文件
传入一个路径来定位配置文件路径,然后增加一个Build方法,进行配置文件,返回配置类
public class DAqOptionBuilder
{
private string _path;
public DAqOptionBuilder(string path = "Config")
{
_path = path;
}
public DAqOption Build()
{
var str = File.ReadAllText($"{_path}\\Config.json");
var option = JsonSerializer.Deserialize<DAqOption>(str);
var lines = File.ReadAllLines($"{_path}\\AllPoint.csv", Encoding.UTF8).ToList();
lines.RemoveAt(0);
List<RegisterPoint> points = new List<RegisterPoint>();
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]),
};
points.Add(point);
}
option.Points = points;
return option;
}
}
服务封装
创建一个DAqService类用于存放数据采集的相关服务操作
传入配置类对象,完成各个属性赋值
public class DAqService
{
private DAqOption _option;
private DeviceLink deviceLink;
private List<RegisterPoint> points;
public DAqService(DAqOption option)
{
_option = option;
deviceLink = option.DeviceLink;
points = option.Points;
}
}
添加各个模块的对象和Start启动程序,将代码迁移过来
//模块对象
private MqttControllor MqttControllor;
private ModbusTcp _modbusTcp;
//方法
/// <summary>
/// 启动服务
/// </summary>
public void Start()
{
MqttControllor = new MqttControllor(_option.MqttConfig);
ModbusTcp modbusTcp = new ModbusTcp(deviceLink, points);
modbusTcp.DoMonitor();
modbusTcp.ValueUpdated += ModbusTcp_ValueUpdated;
}
private void ModbusTcp_ValueUpdated(RegisterPoint point, object value)
{
try
{
DeviceMessage device = new DeviceMessage {
DeviceId = deviceLink.UID };
device.Data.Add(point.UID, value);
var data = JsonSerializer.Serialize(device);
MqttControllor.Publish($"Device/{
deviceLink.UID}/Update", data); //采集立刻推送
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine($"Point:{
point.UID}-->Value:{
value}");
}
推送功能改用定时器,定时推送
C# 中有好几个种定时器,我们这里使用System.Timers.Timer
来使用
private System.Timers.Timer timer;
public DAqService(DAqOption option)
{
//...
timer = new System.Timers.Timer(1000);
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
{
try
{
DeviceMessage device = new DeviceMessage {
DeviceId = deviceLink.UID };
foreach (RegisterPoint point in points)
{
// Console.WriteLine($"Point:{point.UID}-->Value:{point.Value}");
device.Data.Add(point.UID, point.Value);
}
var data = JsonSerializer.Serialize(device);
MqttControllor.Publish($"Device/{
deviceLink.UID}/Time", data); //定时推送
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
net6中默认全局引用
默认就引用了System.Threading
,可以把ImplicitUsings直接删掉,在项目自己引用需要的命名空间即可,但是这样就得在所以项目都删掉。
在主程序中使用
仅需四行代码
internal class Program
{
static void Main(string[] args)
{
DAqOptionBuilder builder = new DAqOptionBuilder();
var option = builder.Build();
DAqService dAqService = new DAqService(option);
dAqService.Start();
}
}
完整服务代码
public class DAqService
{
private MqttControllor MqttControllor;
private ModbusTcp _modbusTcp;
private DAqOption _option;
private DeviceLink deviceLink;
private List<RegisterPoint> points;
private System.Timers.Timer timer;
public DAqService(DAqOption option)
{
_option = option;
deviceLink = option.DeviceLink;
points = option.Points;
timer = new System.Timers.Timer(1000);
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
{
try
{
DeviceMessage device = new DeviceMessage {
DeviceId = deviceLink.UID };
foreach (RegisterPoint point in points)
{
// Console.WriteLine($"Point:{point.UID}-->Value:{point.Value}");
device.Data.Add(point.UID, point.Value);
}
var data = JsonSerializer.Serialize(device);
MqttControllor.Publish($"Device/{
deviceLink.UID}/Time", data); //定时推送
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 启动服务
/// </summary>
public void Start()
{
MqttControllor = new MqttControllor(_option.MqttConfig);
ModbusTcp modbusTcp = new ModbusTcp(deviceLink, points);
modbusTcp.DoMonitor();
modbusTcp.ValueUpdated += ModbusTcp_ValueUpdated;
}
private void ModbusTcp_ValueUpdated(RegisterPoint point, object value)
{
try
{
DeviceMessage device = new DeviceMessage {
DeviceId = deviceLink.UID };
device.Data.Add(point.UID, value);
var data = JsonSerializer.Serialize(device);
MqttControllor.Publish($"Device/{
deviceLink.UID}/Update", data); //采集立刻推送
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine($"Point:{
point.UID}-->Value:{
value}");
}
}