详解.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; 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); this.configRoot = cfgBuilder.Build(); 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()) //{ // this.nodeClass = configRoot.GetSection("NodeClass").Get<NodeClass>(); // this.modbusNode = configRoot.GetSection("NodeClass:ModbusNode").Get<ModbusNode>(); // this.modbusGroup = configRoot.GetSection("NodeClass:ModbusNode:ModbusGroup").Get<ModbusGroup>(); // dbContext.NodeClasses.AddAsync(this.nodeClass); // dbContext.ModbusNodes.AddAsync(this.modbusNode); // dbContext.ModbusGroups.AddAsync(this.modbusGroup); // 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) { InsertActualData(); } } private void InsertActualData() { if (CommonMethods.CurrentPLCValue != null && CommonMethods.CurrentPLCValue.Count > 0) { List<ActualData> actualDataArray = new List<ActualData>(); //List<ReportData> reportDataArray = new List<ReportData>(); DateTime dt = DateTime.Now; foreach (var item in CommonMethods.AllVarList) //FileVarModbusList归档集合 { string varName = item.Name;//modbus 点表中的名称 string description = item.Description; //注释 double value = 0; if (!CommonMethods.CurrentPLCValue.ContainsKey(varName)) { value = 0; } else { value = double.Parse(item.Value); //value = Convert.ToDouble(CommonMethods.CurrentPLCValue[varName]); } if (actualDataArray.Count <= 1000) { actualDataArray.Add(new ActualData() { InsertTime = dt, Name = varName, Value = value.ToString("f2"), Description = description }); } else { actualDataArray.RemoveAt(0); } } var db = new ModelsResponsitory(); db.AddActualData(actualDataArray); } } } }
通用类
using Microsoft.EntityFrameworkCore.Query; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class CommonMethods { public static Dictionary<string, object> CurrentPLCValue = new Dictionary<string, object>(); //归档变量集合 public static List<Variable> ArchiveVarList = new List<Variable>(); //所有 public static List<Variable> AllVarList = new List<Variable>(); /// <summary> /// 键值对,键是变量名称,值是其对应的变量实体对象 用来写数据 /// </summary> public static Dictionary<string, Variable> CurrentPLCVariable = new Dictionary<string, Variable>(); /// <summary> /// 变量名称和变量地址的键值对 /// </summary> public static Dictionary<string, string> CurrentPLCNote = new Dictionary<string, string>(); public static bool IsConnected = false; public static int CacheCount = 600;//10分钟, 每秒一条 public static IIncludableQueryable<NodeClass, IEnumerable<Variable>> ModbusTCPList; public static int ErrorTimes = 0; public static bool FirstConnect = true; public static string Ip; public static string Port; public static string VarNum; } }
EFcore的配置
using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Sqlite; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; namespace EF6Demon { public class MyDbContext:DbContext { public DbSet<ActualData> ActualDatas { get; set; } //API中为复数, 而不是数据库表 public DbSet<NodeClass> NodeClasses { get; set; } public DbSet<ModbusNode> ModbusNodes { get; set; } public DbSet<ModbusGroup> ModbusGroups { get; set; } public DbSet<Variable> Variables { get; set; } public DbSet<SysAdmin> SysAdmins { get; set; } private ConfigurationBuilder cfgBuilder = new ConfigurationBuilder(); //private IConfiguration configuration; //private string connString; public MyDbContext() { //configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("Ipcfg.json").Build(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); cfgBuilder.AddJsonFile("VariableNode.json", optional: true, reloadOnChange: true); IConfigurationRoot configRoot = cfgBuilder.Build(); string connString = configRoot.GetSection("ConnectionStrings:SqliteConnectionString").Value; optionsBuilder.UseSqlite(connString); //configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("Ipcfg.json").Build(); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //ConfigurationBuilder cfg1 = new ConfigurationBuilder(); //cfg1.AddJsonFile("VariableNode.json", optional: true, reloadOnChange: true); //IConfigurationRoot configRoot = cfg1.Build(); //string varNum = configRoot.GetSection("NodeClass:ModbusNode:VarNum").Value; //IList<Variable> iniVariableList = new List<Variable>(); //for (int i = 0; i < int.Parse(varNum); i++) //{ // Variable variable = configRoot.GetSection($"NodeClass:ModbusNode:ModbusGroup:Variable:{i}").Get<Variable>(); // iniVariableList.Add(variable); //} var iniActualData = File.ReadAllText(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"/Database/Variable.json"); IList<ActualData> iniActualList = JsonConvert.DeserializeObject<IList<ActualData>>(iniActualData); //modelBuilder.Entity<Variable>().HasData(iniVariableList); modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly); } } } //VS终端下 // 视图-其他窗口-程序包控制台 //选择默认项目 //add-migration initialMigration //创建数据迁移 //add-migration initialMigration1 //创建数据迁移 // update-database //Remove-migration 删除最后一次脚本 //Script-Migration 显示迁移的sql脚本 //DBfirst // Scaffold-DbContext "server=192.168.207.107; database=Demon1; uid=root; pwd=123456" Pomelo.EntityFrameworkCore.MySql //根据已有数据库创建数据模型。在 NuGet 的程序包管理(Package Manager)控制台中(PowerShell)执行命令: //Scaffold-DbContext "server=数据库服务器;uid=数据库用户名;pwd=数据库密码;database=数据库名;" Pomelo.EntityFrameworkCore.MySql -OutputDir Data -Force //.Net Core CLi:dotnet ef dbcontext scaffold "server=数据库服务器;uid=数据库用户名;pwd=数据库密码;database=数据库名;" Pomelo.EntityFrameworkCore.MySql -o Data -f //CMD 命令下 安装EF工具: //dotnet tool install --global dotnet-ef //数据迁移: //dotnet ef migrations add DataSeeding //数据更新: //dotnet ef database update /* * cmd命令: Mysql数据库: docker run --name mysqltest -p 3306:3306 -v /usr/local/mysql/data:/var/lib/mysql -v /usr/local/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql dotnet ef migrations add MySQLInit dotnet ef database update dotnet ef database update MySQLUpdate3 回滚 对应版本 */
模型:
using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class Variable { public long Id { get; set; } public string Number { get; set; } public string Name { get; set; } public string Description { get; set; } public string Type { get; set; } public string VarAddress { get; set; } public string Scale { get; set; } public string Offset { get; set; } public string Start { get; set; } public string AccessProperty { get; set; } public string AlarmEnable { get; set; } public string ArchiveEnable { get; set; } public string SetLimitEnable { get; set; } public string AlarmType { get; set; } public string DiscreteAlarmType { get; set; } public string DiscreteAlarmPriority { get; set; } public string DiscreteAlarmNote { get; set; } public string LoLoAlarmEnable { get; set; } public string LoLoAlarmValue { get; set; } public string LoLoAlarmPriority { get; set; } public string LoLoAlarmNote { get; set; } public string LowAlarmEnable { get; set; } public string LowAlarmValue { get; set; } public string LowAlarmPriority { get; set; } public string LowAlarmNote { get; set; } public string HighAlarmEnable { get; set; } public string HighAlarmValue { get; set; } public string HighAlarmPriority { get; set; } public string HighAlarmNote { get; set; } public string HiHiAlarmEnable { get; set; } public string HiHiAlarmValue { get; set; } public string HiHiAlarmPriority { get; set; } public string HiHiAlarmNote { get; set; } public string ArchivePeriod { get; set; } public string SetLimitMax { get; set; } public string SetLimitMin { get; set; } public string VarType { get; set; } public string StoreType { get; set; } public string InsertTime { get; set; } public string Value { get; set; } public long ModbusGroupId { get; set; } public ModbusGroup ModbusGroup { get; set; } } }
using System.Collections.Generic; namespace EF6Demon { public class ModbusGroup { public long Id { get; set; } public string Name { get; set; } public string Description { get; set; } public string Type { get; set; } public string StoreArea { get; set; } public string Length { get; set; } public string Start { get; set; } public string SlaveID { get; set; } public string IsActive { get; set; } public long ModbusNodeId { get; set; } public ModbusNode ModbusNode { get; set; } public List<Variable> Variables { get; set; } = new List<Variable>(); } }
using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class ModbusNode { public ModbusNode() { } public long Id { get; set; } public string Name { get; set; } public string Description { get; set; } public string ModbusType { get; set; } public string ConnectTimeOut { get; set; } public string CreateTime { get; set; } public string ReConnectTime { get; set; } public string IsActive { get; set; } public string MaxErrorTimes { get; set; } public string KeyWay { get; set; } public string UseAlarmCheck { get; set; } public string ServerURL { get; set; } public string Port { get; set; } public string DataFormat { get; set; } public string VarNum { get; set; } public long NodeClassId { get; set; } public List<ModbusGroup> ModbusGroups { get; set; } = new List<ModbusGroup>(); public NodeClass NodeClass { get; set; } } }
using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class NodeClass { public long Id { get; set; } public string Name { get; set; } public string Description { get; set; } public List<ModbusNode> ModbusNodes { get; set; } = new List<ModbusNode>(); } }
using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class ActualData { public long Id { get; set; } public string Description { get; set; } public string Name { get; set; } public string Value { get; set; } public DateTime InsertTime { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF6Demon { public class SysAdmin { public long Id { get; set; } public string LoginName { get; set; } public string Pwd { get; set; } public string HandCtrl { get; set; } public string AutoCtrl { get; set; } public string SysSet { get; set; } public string SysLog { get; set; } public string Report { get; set; } public string Trend { get; set; } public string UserManage { get; set; } } }
模型配置:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { internal class NodeClassConfig : IEntityTypeConfiguration<NodeClass> { public void Configure(EntityTypeBuilder<NodeClass> builder) { builder.ToTable("NodeClass"); builder.HasKey(a => a.Id); builder.Property(a => a.Description).HasMaxLength(100); builder.HasMany<ModbusNode>(n=>n.ModbusNodes).WithOne(m=> m.NodeClass); } } }
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class ModbusNodeConfig : IEntityTypeConfiguration<ModbusNode> { public void Configure(EntityTypeBuilder<ModbusNode> builder) { builder.ToTable("ModbusNode"); builder.HasKey(a => a.Id); builder.Property(a => a.Description).HasMaxLength(100); builder.HasOne<NodeClass>(m => m.NodeClass) .WithMany(n => n.ModbusNodes) .HasForeignKey(c => c.NodeClassId); } } }
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class ModbusGroupConfig : IEntityTypeConfiguration<ModbusGroup> { public void Configure(EntityTypeBuilder<ModbusGroup> builder) { builder.ToTable("ModbusGroup"); builder.HasKey(a => a.Id); builder.Property(a => a.Description).HasMaxLength(100); builder.HasOne<ModbusNode>(c => c.ModbusNode) .WithMany(a => a.ModbusGroups) .HasForeignKey(c => c.ModbusNodeId); } } }
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class VariableConfig : IEntityTypeConfiguration<Variable> { public void Configure(EntityTypeBuilder<Variable> builder) { builder.ToTable("Variable"); builder.HasKey(v => v.Id); builder.Property(v => v.Description).HasMaxLength(100); builder.HasOne<ModbusGroup>(v => v.ModbusGroup).WithMany(m=>m.Variables).HasForeignKey(v=>v.ModbusGroupId); } } }
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class ActualDataConfig : IEntityTypeConfiguration<ActualData> { public void Configure(EntityTypeBuilder<ActualData> builder) { builder.ToTable("ActualData"); builder.HasKey(a => a.Id); builder.Property(a => a.Description).HasMaxLength(100); } } }
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public class ModbusGroupConfig : IEntityTypeConfiguration<ModbusGroup> { public void Configure(EntityTypeBuilder<ModbusGroup> builder) { builder.ToTable("ModbusGroup"); builder.HasKey(a => a.Id); builder.Property(a => a.Description).HasMaxLength(100); builder.HasOne<ModbusNode>(c => c.ModbusNode) .WithMany(a => a.ModbusGroups) .HasForeignKey(c => c.ModbusNodeId); } } }
通过外键, 建立各设备组之间的关系,生成服务类
using Microsoft.EntityFrameworkCore.Query; using System; using System.Collections.Generic; using System.Text; namespace EF6Demon { public interface IProvider { List<ActualData> GetActualData(); void AddActualData(List<ActualData> actualData); IIncludableQueryable<NodeClass, IEnumerable<Variable>> GetAllVariable(); } }
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace EF6Demon { public class ModelsResponsitory : IProvider { private MyDbContext db = new MyDbContext(); public MyDbContext Db { get { return db; } set { db = value; } } public void AddActualData(List<ActualData> actualData) { db.ActualDatas.AddRangeAsync(actualData); db.SaveChangesAsync(); } public List<ActualData> GetActualData() { //IQueryable<ActualData> actualData = db.ActualDatas.Where(a=>a.Id>10); //return actualData; IEnumerable<ActualData> actualData1 = db.ActualDatas; //IEnumerable<TSource> IOrderedEnumerable<TSource> OrderByDescending 全部取出,在内存中比较Where(a => a.Id > 10) actualData1.Where(a => a.Id > 10).OrderByDescending(i => i.Id).Take(20); //IQueryable<TSource> Where IOrderedQueryable<TSource> OrderByDescending, 给服务器发sql语句 Where(a => a.Id > 10) //加上toList 把数据全部取回本地, 不占用带宽 IQueryable<ActualData> actualData =db.ActualDatas; return actualData.Where(a => a.Id > 10).OrderByDescending(i => i.Id).Take(20).ToList(); } public IIncludableQueryable<NodeClass, IEnumerable<Variable>> GetAllVariable() { return db.NodeClasses. Include(n => n.ModbusNodes.Where(nodes => nodes.NodeClassId == 1)) .ThenInclude(m => m.ModbusGroups.Where(groups => groups.ModbusNodeId == 1)) .ThenInclude(gp => gp.Variables.Where(v => v.ModbusGroupId == 1)); } } }
本地配置文件:
{ "ConnectionStrings": { "SqliteConnectionString": "Data Source=E:\\Csharp\\EF6Demon\\EF6Demon\\bin\\Debug\\net6.0-windows\\Database\\DbSqlite.db", "MySQLConnectionString": "server=192.168.85.102; database=OneToMany; uid=root; pwd=123456;" }, "NodeClass": { "Id": 1, "Name": "ModbusClent", "Description": "Modbus相关客户端", "ModbusNode": { "Id": 1, "NodeClassId": 1, "Name": "ModbusTCPClient", "Description": "1#ZG上位机测试", "ModbusType": "2000", "ConnectTimeOut": "2000", "CreateTime": "0", "ReConnectTime": "5000", "IsActive": "True", "MaxErrorTimes": "1", "KeyWay": "VarName", "UseAlarmCheck": "True", "ServerURL": "127.0.0.1", "Port": "502", "DataFormat": "ABCD", "VarNum": "6", "ModbusGroup": { "Id": 1, "Name": "保持寄存器长度为寄存器个数", "Description": "40001-40010", "Type": "ModbusTCP", "StoreArea": "40000", "Length": "10", "Start": "0", "SlaveID": "1", "IsActive": "true", "ModbusNodeId": 1, "Variable": [ { "Id": 1, "Number": "1", "Name": "Float1", "Description": "40001-40002", "Type": "ModbusTCP", "VarAddress": 0, "Scale": "1", "Offset": "0", "Start": "0", "AccessProperty": "读写", "AlarmEnable": "True", "ArchiveEnable": "True", "SetLimitEnable": "True", "AlarmType": "True", "DiscreteAlarmType": "False", "DiscreteAlarmPriority": "0", "DiscreteAlarmNote": "null", "LoLoAlarmEnable": "True", "LoLoAlarmValue": "0", "LoLoAlarmPriority": "0", "LoLoAlarmNote": "40001-40002低低报警", "LowAlarmEnable": "True", "LowAlarmValue": "20", "LowAlarmPriority": "0", "LowAlarmNote": "40001-40002低报警", "HighAlarmEnable": "True", "HighAlarmValue": "80", "HighAlarmPriority": "0", "HighAlarmNote": "40001-40002高报警", "HiHiAlarmEnable": "True", "HiHiAlarmValue": "100", "HiHiAlarmPriority": "0", "HiHiAlarmNote": "40001-40002高高报警", "ArchivePeriod": "80", "SetLimitMax": "100", "SetLimitMin": "0", "VarType": "Float", "StoreType": "03 Holding Register(4x)", "InsertTime": "0", "Value": "0", "ModbusGroupId": 1 }, { "Id": 2, "Number": "2", "Name": "Float2", "Description": "40003-40004", "Type": "ModbusTCP", "VarAddress": 2, "Scale": "1", "Offset": "0", "Start": "0", "AccessProperty": "读写", "AlarmEnable": "True", "ArchiveEnable": "True", "SetLimitEnable": "True", "AlarmType": "True", "DiscreteAlarmType": "False", "DiscreteAlarmPriority": "0", "DiscreteAlarmNote": "null", "LoLoAlarmEnable": "True", "LoLoAlarmValue": "0", "LoLoAlarmPriority": "0", "LoLoAlarmNote": "40003-40004低低报警", "LowAlarmEnable": "True", "LowAlarmValue": "20", "LowAlarmPriority": "0", "LowAlarmNote": "40003-40004低报警", "HighAlarmEnable": "True", "HighAlarmValue": "80", "HighAlarmPriority": "0", "HighAlarmNote": "40003-40004高报警", "HiHiAlarmEnable": "True", "HiHiAlarmValue": "100", "HiHiAlarmPriority": "0", "HiHiAlarmNote": "40003-40004高高报警", "ArchivePeriod": "80", "SetLimitMax": "100", "SetLimitMin": "0", "VarType": "Float", "StoreType": "03 Holding Register(4x)", "InsertTime": "0", "Value": "0", "ModbusGroupId": 1 }, { "Id": 3, "Number": "3", "Name": "Float3", "Description": "40005-40006", "Type": "ModbusTCP", "VarAddress": 4, "Scale": "1", "Offset": "0", "Start": "0", "AccessProperty": "读写", "AlarmEnable": "True", "ArchiveEnable": "True", "SetLimitEnable": "True", "AlarmType": "True", "DiscreteAlarmType": "False", "DiscreteAlarmPriority": "0", "DiscreteAlarmNote": "null", "LoLoAlarmEnable": "True", "LoLoAlarmValue": "0", "LoLoAlarmPriority": "0", "LoLoAlarmNote": "40005-40006低低报警", "LowAlarmEnable": "True", "LowAlarmValue": "20", "LowAlarmPriority": "0", "LowAlarmNote": "40005-40006低报警", "HighAlarmEnable": "True", "HighAlarmValue": "80", "HighAlarmPriority": "0", "HighAlarmNote": "40005-40006高报警", "HiHiAlarmEnable": "True", "HiHiAlarmValue": "100", "HiHiAlarmPriority": "0", "HiHiAlarmNote": "40005-40006高高报警", "ArchivePeriod": "80", "SetLimitMax": "100", "SetLimitMin": "0", "VarType": "Float", "StoreType": "03 Holding Register(4x)", "InsertTime": "0", "Value": "0", "ModbusGroupId": 1 }, { "Id": 4, "Number": "4", "Name": "Float4", "Description": "40007-40008", "Type": "ModbusTCP", "VarAddress": 6, "Scale": "1", "Offset": "0", "Start": "0", "AccessProperty": "读写", "AlarmEnable": "True", "ArchiveEnable": "True", "SetLimitEnable": "True", "AlarmType": "True", "DiscreteAlarmType": "False", "DiscreteAlarmPriority": "0", "DiscreteAlarmNote": "null", "LoLoAlarmEnable": "True", "LoLoAlarmValue": "0", "LoLoAlarmPriority": "0", "LoLoAlarmNote": "40003-40004低低报警", "LowAlarmEnable": "True", "LowAlarmValue": "20", "LowAlarmPriority": "0", "LowAlarmNote": "40003-40004低报警", "HighAlarmEnable": "True", "HighAlarmValue": "80", "HighAlarmPriority": "0", "HighAlarmNote": "40003-40004高报警", "HiHiAlarmEnable": "True", "HiHiAlarmValue": "100", "HiHiAlarmPriority": "0", "HiHiAlarmNote": "40003-40004高高报警", "ArchivePeriod": "80", "SetLimitMax": "100", "SetLimitMin": "0", "VarType": "Float", "StoreType": "03 Holding Register(4x)", "InsertTime": "0", "Value": "0", "ModbusGroupId": 1 }, { "Id": 5, "Number": "5", "Name": "Ushort1", "Description": "40009", "Type": "ModbusTCP", "VarAddress": 8, "Scale": "1", "Offset": "0", "Start": "0", "AccessProperty": "读写", "AlarmEnable": "True", "ArchiveEnable": "True", "SetLimitEnable": "True", "AlarmType": "True", "DiscreteAlarmType": "False", "DiscreteAlarmPriority": "0", "DiscreteAlarmNote": "null", "LoLoAlarmEnable": "True", "LoLoAlarmValue": "0", "LoLoAlarmPriority": "0", "LoLoAlarmNote": "40009低低报警", "LowAlarmEnable": "True", "LowAlarmValue": "20", "LowAlarmPriority": "0", "LowAlarmNote": "40009低报警", "HighAlarmEnable": "True", "HighAlarmValue": "80", "HighAlarmPriority": "0", "HighAlarmNote": "40009高报警", "HiHiAlarmEnable": "True", "HiHiAlarmValue": "100", "HiHiAlarmPriority": "0", "HiHiAlarmNote": "40009高高报警", "ArchivePeriod": "80", "SetLimitMax": "100", "SetLimitMin": "0", "VarType": "UShort", "StoreType": "03 Holding Register(4x)", "InsertTime": "0", "Value": "0", "ModbusGroupId": 1 }, { "Id": 6, "Number": "6", "Name": "Ushort2", "Description": "40010", "Type": "ModbusTCP", "VarAddress": 9, "Scale": "1", "Offset": "0", "Start": "0", "AccessProperty": "读写", "AlarmEnable": "True", "ArchiveEnable": "True", "SetLimitEnable": "True", "AlarmType": "True", "DiscreteAlarmType": "False", "DiscreteAlarmPriority": "0", "DiscreteAlarmNote": "null", "LoLoAlarmEnable": "True", "LoLoAlarmValue": "0", "LoLoAlarmPriority": "0", "LoLoAlarmNote": "40009低低报警", "LowAlarmEnable": "True", "LowAlarmValue": "20", "LowAlarmPriority": "0", "LowAlarmNote": "40009低报警", "HighAlarmEnable": "True", "HighAlarmValue": "80", "HighAlarmPriority": "0", "HighAlarmNote": "40009高报警", "HiHiAlarmEnable": "True", "HiHiAlarmValue": "100", "HiHiAlarmPriority": "0", "HiHiAlarmNote": "40009高高报警", "ArchivePeriod": "80", "SetLimitMax": "100", "SetLimitMin": "0", "VarType": "UShort", "StoreType": "03 Holding Register(4x)", "InsertTime": "0", "Value": "0", "ModbusGroupId": 1 } ] } } } }
到此这篇关于.NET6下的Modbus通讯 和数据库记录的文章就介绍到这了,更多相关.NET6下的Modbus通讯 和数据库记录内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
赞 (0)