详解.NET6下的Modbus通讯和数据库记录

2022-04-18 15:05:11

所用的包:

<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();    www.easck.com  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) //FileVarModbuw 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.0JyBGNF.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":www.easck.com "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     }    ]   }  } }}