<
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)
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;
return false;
public byte[] ReadKeepRegByteArr(string iAddress, string iLength)
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)
ushort[] des = master.ReadHoldingRegisters(ushort.Parse(iAddress), ushort.Parse(iLength));
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);
private NModBusHelper objTcp;
private void FrmMain_Load(object? sender, EventArgs e)
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;
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);
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;
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;
CommonMethods.CurrentPLCValue.Add(variable.Name, variable.Value);
CommonMethods.ErrorTimes++;
if (CommonMethods.ErrorTimes >= int.Parse(dev.MaxErrorTimes))
CommonMethods.IsConnected = false;
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);
CommonMethods.CurrentPLCVariable[variable.Name] = variable;
if (bool.Parse(variable.ArchiveEnable))
CommonMethods.ArchiveVarList.Add(variable);
foreach (var variable in CommonMethods.ArchiveVarList)
if (!CommonMethods.CurrentPLCNote.ContainsKey(variable.Name))
CommonMethods.CurrentPLCNote.Add(variable.Name, variable.Description);
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);
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;
start = 0;
offset = 0;
return false;
offset = 0;
return int.TryParse(address, out start);
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)
private void btnIn_Click(object sender, EventArgs e)
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;
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>();
DateTime dt = DateTime.Now;
foreach (var item in CommonMethods.AllVarList)
string varName = item.Name;
string description = item.Description;
double value = 0;
if (!CommonMethods.CurrentPLCValue.ContainsKey(varName))
value = 0;
value = double.Parse(item.Value);
if (actualDataArray.Count <= 1000)
actualDataArray.Add(new ActualData()
InsertTime = dt,
Name = varName,
Value = value.ToString("f2"),
Description = description
});
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>();
public static Dictionary<string, Variable> CurrentPLCVariable = new Dictionary<string, Variable>();
public static Dictionary<string, string> CurrentPLCNote = new Dictionary<string, string>();
public static bool IsConnected = false;
public static int CacheCount = 600;
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; }
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();
public MyDbContext()
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);
protected override void OnModelCreating(ModelBuilder modelBuilder)
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
* 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EF6Demon
public class SysAdminConfig : IEntityTypeConfiguration<SysAdmin>
public void Configure(EntityTypeBuilder<SysAdmin> builder)
builder.ToTable("SysAdmins");
builder.HasKey(a => a.Id);
通过外键, 建立各设备组之间的关系,生成服务类
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()
IEnumerable<ActualData> actualData1 = db.ActualDatas;
actualData1.Where(a => a.Id > 10).OrderByDescending(i => i.Id).Take(20);
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
所用的包:<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net6.0-windows</TargetFramework> <Nullable>enable</Nullable> <UseWindowsForms>
private ModbusFactory modbusFactory;
private IModbusMaster master;
private TcpClient tcpClient;
public string IPAdress { get; set; }
public int Port { get; set; }
public bo
Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP。Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。
ModbusTCP的数据帧可分为两部分:MBAP+PDU。
MBAP为报文头,长度为7字节,组成如下:事务处理标识+协议标识+长度+单元标识
Tips:
1、目前NetCore下与
Modbus通信的框架主要选择了
Modbus.Net https://github.com/parallelbgls/
Modbus.Net
2、
modbus是常用的工业通信协议,在软件调试时可以通过
modbus poll+slave模拟通信通过达到调试目的,下图是我使用软件
1)为串口模拟工具
NModbus is a C# implementation of the Modbus protocol. Provides connectivity to Modbus slave compatible devices and applications. Supports serial ASCII, serial RTU, TCP, and UDP protocols. NModbus4 it's a fork of NModbus(https://code.google.com/p/nmodbus). NModbus4 differs from original NModbus in following:
1.removed USB support(FtdAdapter.dll)
2.removed log4net dependency
3.removed Unme.Common.dll dependency
4.assembly renamed to NModbus4.dll
5.target framework changed to .NET 4
警告:
DataConversionWarning:
Data was
converted to boolean for metric jaccard。warnings.warn(msg,
DataConversionWarning)
解释:
DataConversionWarning:数据已转换为度量jaccard的布尔值警告.warn(消息,数据转换警告)
MODBUS TCP 03功能码报文解析
初识
Modbus TCP-------------
C#编写
Modbus TCP客户端程序(一)
初识
Modbus TCP-------------
C#编写
Modbus TCP客户端程序(二)
0. 软件描述
目前此上位机软件一共有四个版本:
上位机软件v1.0版本功能:可以设置服务器的IP地址与端口号。客户端只能发送固定的报文,并接收服务器返回的报文,若要改变发送的报文,需要在程序中进行更改。
上位机软件v1.1版本功能:在v1.0基础上增加了
二、Modbus
1.最近在做Modbus有关的工作,根据杨更更的 Modbus软件开发实战 里面都是基于VS的很适合我这种C#开发人员,首先根据书里面的介绍LiModbus直接敲代码就OK,敲完自行测试哈,这里就暂时不多缀余。这个是基于C++
2.Nmodbus这个是基于C#开源的代码 网上也有先下载下来再说https://git...
web 编写遵循的核心协议就是http/tcp 协议。而这个核心的内容是就Socket编程。
Socket 是点对点的通讯模式,是全双工的。是靠IP地址进行寻址访问的。
根据设计又几种模式: 点对点 (适合两者之间大文件的传输) 服务器模式(聊天,webapi等)
这里主要讨论: 服务器模式
Socket 编程需要引用
using System.Net;using System.Ne...