详解.NET6下的Modbus通讯和数据库记录所⽤的包: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NModbus4.NetCore" Version="2.0.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />
</ItemGroup>
<ItemGroup>
<None Update="VariableNode.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
通信库:
using Modbus.Device;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using thinger.DataConvertLib;
namespace EF6Demon
{
public class NModBusHelper
{
private TcpClient tcpClient = null;
private ModbusIpMaster master;
public bool Connect(string ip, string port)
{
try
{
tcpClient = new TcpClient();
tcpClient.Connect(IPAddress.Parse(ip), int.Parse(port));
master = ModbusIpMaster.CreateIp(tcpClient);
}
catch (Exception)
{
return false;
}
return tcpClient.Connected;
}
public bool Disconnect()
{
if (tcpClient != null)
{
tcpClient.Close();
return true;
}
else
{
return false;
}
}
public byte[] ReadKeepRegByteArr(string iAddress, string iLength)//偏移量,寄存器数量 {
try
{
ushort[] des = master.ReadHoldingRegisters(ushort.Parse(iAddress), ushort.Parse(iLength));
byte[] res = ByteArrayLib.GetByteArrayFromUShortArray(des);
return res;
}
catch (Exception)
呼伦贝尔学院学报
{
return null;
}
}
public ushort[] ReadKeepRegUshort(string iAddress, string iLength)//偏移量,寄存器数量
{
try
公共产品理论{
ushort[] des = master.ReadHoldingRegisters(ushort.Parse(iAddress), ushort.Parse(iLength));
//byte[] res = ByteArrayLib.GetByteArrayFromUShortArray(des);
return des;
}
catch (Exception)
{
return null;
}
}
public List<float> AnalyseData_4x(ushort[] des, string iAddress)
{
int StartByte;
StartByte = int.Parse(iAddress) * 2;
List<float> floatArray = new List<float>();
byte[] byteArray = ByteArrayLib.GetByteArrayFromUShortArray(des);
for (int i = StartByte; i < byteArray.Length; i += 4)
{
floatArray.Add(FloatLib.GetFloatFromByteArray(byteArray, i));
}
return floatArray;
}
}
}
主程序:
using Microsoft.Extensions.Configuration;
using thinger.DataConvertLib;
namespace EF6Demon
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
this.Load += FrmMain_Load;
}
private ModelsResponsitory dbContext = new ModelsResponsitory();
private ConfigurationBuilder cfgBuilder = new ConfigurationBuilder();
private IConfigurationRoot configRoot;
private CancellationTokenSource cts = new CancellationTokenSource();
ushort[] res;N电信
string iAddress = "0";
string iLenth; //寄存器个数
private List<float> floatList = new List<float>();
private CancellationTokenSource cts1 = new CancellationTokenSource();
InsertDataSQLite objInsert = new InsertDataSQLite(10000);//10秒1次
private NModBusHelper objTcp;
private void FrmMain_Load(object? sender, EventArgs e)
{
//读取IP;
cfgBuilder.AddJsonFile("VariableNode.json", optional: true, reloadOnChange: true);
CommonMethods.Ip = configRoot.GetSection("NodeClass:ModbusNode:ServerURL").Value;
CommonMethods.Port = configRoot.GetSection("NodeClass:ModbusNode:Port").Value;
CommonMethods.VarNum = configRoot.GetSection("NodeClass:ModbusNode:VarNum").Value;
//读取点表信息
//for (int i = 0; i < int.Parse(CommonMethods.VarNum); i++)
//{
// Variable variable = configRoot.GetSection($"NodeClass:ModbusNode:ModbusGroup:Variable:{i}").Get<Variable>();
// CommonMethods.AllVarList.Add(variable);
//}
this.iLenth = configRoot.GetSection("NodeClass:ModbusNode:ModbusGroup:Length").Value;
CommonMethods.ModbusTCPList = dbContext.GetAllVariable();
foreach (var item in CommonMethods.ModbusTCPList)
{
foreach (var item1 in item.ModbusNodes)
{
foreach (var item2 in item1.ModbusGroups)
{
CommonMethods.AllVarList.AddRange(item2.Variables);
}
}
}
InsertDataSQLite objInsert = new InsertDataSQLite(10000);//10秒1次
ModbusTCPInitialInfo();
Communication();
}
private void Communication()
{
if (CommonMethods.ModbusTCPList.Count() > 0)
{
foreach (var t in CommonMethods.ModbusTCPList)
{
foreach (var dev in t.ModbusNodes)
{
if (bool.Parse(dev.IsActive))
{
Task.Run(async () =>
{
while (!cts1.IsCancellationRequested)
{
if (CommonMethods.IsConnected)
{
await Task.Delay(500);
foreach (var gp in dev.ModbusGroups)
{
if (bool.Parse(gp.IsActive))
{
//读取数据
byte[] res = null;
if (int.Parse(gp.StoreArea) == 40000)
{
res = objTcp.ReadKeepRegByteArr(gp.Start, gp.Length);
}
if (res != null && res.Length == int.Parse(gp.Length) * 2)
{
CommonMethods.ErrorTimes = 0;
foreach (var variable in gp.Variables)
{
if (VerifyModbusAddress(false, variable.VarAddress, out int start, out int offset))
{
start -= int.Parse(gp.Start);
start *= 2;
// ABCD = 0,BADC = 1, CDAB = 2, DCBA = 3,
switch (variable.VarType)
{
case "Float":
variable.Value = FloatLib.GetFloatFromByteArray(res, start, DataFormat.ABCD).ToString();
break;
case "UShort":
variable.Value = UShortLib.GetUShortFromByteArray(res, start, DataFormat.ABCD).ToString(); break;
default:
break;
}
if (CommonMethods.CurrentPLCValue.ContainsKey(variable.Name))
{
CommonMethods.CurrentPLCValue[variable.Name] = variable.Value;
}
else
{
CommonMethods.CurrentPLCValue.Add(variable.Name, variable.Value);
}
}
}
梁晓声}
else
{
CommonMethods.ErrorTimes++;
if (CommonMethods.ErrorTimes >= int.Parse(dev.MaxErrorTimes))
{
CommonMethods.IsConnected = false;
}
}
}
}
}
else
{
if (!CommonMethods.FirstConnect)
{
/
/延时
await Task.Delay(int.Parse(dev.ReConnectTime));
objTcp?.Disconnect();
}
//第⼀次连接
//初始化通信对象
objTcp = new NModBusHelper();
CommonMethods.IsConnected = objTcp.Connect(dev.ServerURL, dev.Port); CommonMethods.FirstConnect = false;
await Task.Delay(200);
}
}
}, cts1.Token);
}
}
}
}
}
private void ModbusTCPInitialInfo()
{
foreach (var variable in CommonMethods.AllVarList)
{
if (!CommonMethods.CurrentPLCVariable.ContainsKey(variable.Name))
{
船长教学设计CommonMethods.CurrentPLCVariable.Add(variable.Name, variable);
}
else
{
CommonMethods.CurrentPLCVariable[variable.Name] = variable;
}
遥望宋朝
//存储的归档变量
if (bool.Parse(variable.ArchiveEnable))
{
CommonMethods.ArchiveVarList.Add(variable);
}
}
//归档变量, ⽤来查询实时数据, ArchiveEnable的数据要与配置⽂件SystemSet⼀致
foreach (var variable in CommonMethods.ArchiveVarList)
{
if (!CommonMethods.CurrentPLCNote.ContainsKey(variable.Name))
{
CommonMethods.CurrentPLCNote.Add(variable.Name, variable.Description);
}
else
{
CommonMethods.CurrentPLCNote[variable.Name] = variable.Description;
}
}
}
private bool VerifyModbusAddress(bool isBit, string address, out int start, out int offset)
{
if (isBit)
{
offset = 0;
return int.TryParse(address, out start);
}
else
{
if (address.Contains('.'))
{
string[] result = address.Split('.');
if (result.Length == 2)
{
bool val = true;
int res = 0;
val = val && int.TryParse(result[0], out res);
start = res;
val = val && int.TryParse(result[1], out res);
offset = res;
return val;
}
else
{
start = 0;
offset = 0;
return false;
}
}
else
{
offset = 0;
return int.TryParse(address, out start);
}
}
}
//设置ListBox
private void Addinfo(string info)
{
this.isInfo.Items.Insert(
0, DateTime.Now.ToString("HH:mm:ss") + " " + info + Environment.NewLine);
}
private void btnConn_Click(object sender, EventArgs e)
{
}
private NodeClass nodeClass = new NodeClass();
private ModbusNode modbusNode = new ModbusNode();
private ModbusGroup modbusGroup = new ModbusGroup();
private void btnInsert_Click(object sender, EventArgs e)
{
//using (MyDbContext dbContext = new MyDbContext())
/
/{
// deClass = configRoot.GetSection("NodeClass").Get<NodeClass>();
// dbusNode = configRoot.GetSection("NodeClass:ModbusNode").Get<ModbusNode>();
// dbusGroup = configRoot.GetSection("NodeClass:ModbusNode:ModbusGroup").Get<ModbusGroup>();
// dbContext.NodeClasses.deClass);
// dbContext.ModbusNodes.dbusNode);
// dbContext.ModbusGroups.dbusGroup);
// List<Variable> variables = new List<Variable>();
// for (int i = 0; i < int.Parse(CommonMethods.VarNum); i++)
// {
/
/ Variable variable = configRoot.GetSection($"NodeClass:ModbusNode:ModbusGroup:Variable:{i}").Get<Variable>(); // variables.Add(variable);
// }
// dbContext.Variables.AddRangeAsync(variables);
// dbContext.SaveChangesAsync();
//}
}
private void btnIn_Click(object sender, EventArgs e)
{
//List<ActualData> list = new List<ActualData>();
ModelsResponsitory db = new ModelsResponsitory();
this.Dgv.DataSource= db.GetActualData();
}
}
}
插⼊数据库
using System;
using System.Collections.Generic;
using System.Text;
namespace EF6Demon
{
public class InsertDataSQLite
{
System.Timers.Timer t;
int count = 0;
public InsertDataSQLite(int Interval)
{
t = new System.Timers.Timer(Interval);
t.Elapsed += T_Elapsed;
t.AutoReset = true;
t.Enabled = true;
t.Start();
count = CommonMethods.CacheCount; //默认为600
}
private void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (CommonMethods.IsConnected)