using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using xktComm.Common;
using xktComm.DataConvert;
using xktNodeSettings;
using xktNodeSettings.Node.Modbus;
using xktNodeSettings.Node.Variable;
namespace CMStestMdbus
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
modbusTCPList = ModbusTCPCFG.LoadXmlFile(settingPath);
SqlSugarService.SetConnectionStr("Data Source=" + Application.StartupPath + str2);
InitialInfo();
Communication();
}
string str2 = "\\config\\ZgTestData.db;Pooling=true;FailIfMissing=false";
//配置文件路径
private string settingPath = Application.StartupPath + "\\settings\\settingsss.xml";
InsertDataSQLite objInsert = new InsertDataSQLite(10000);//10秒1次
private string ipAddress = "127.0.0.1";
private int port = 502;
//private CancellationTokenSource cts = new CancellationTokenSource();
/// <summary>
/// 通讯函数
/// </summary>
private void Communication()
{
if (modbusTCPList.Count>0)//有modbusTCP节点
{
foreach (var dev in modbusTCPList) //遍历modbusTCP节点
{
if (dev.IsActive)
{
dev.cts = new CancellationTokenSource();
Task.Run(async () =>
{
while (!dev.cts.IsCancellationRequested)//默认是false
{
if (dev.IsConnected) //放解析
{
CommonMethods.TCPisConnected = dev.IsConnected;
foreach (var gp in dev.ModbusTCPGroupList)//遍历每一个组
{
if (gp.IsActive)
{
//读取数据
byte[] res = null;
//线圈存储区
if (gp.StoreArea == ModbusStoreArea.输入线圈 || gp.StoreArea == ModbusStoreArea.输出线圈)
{
//读取
switch (gp.StoreArea)
{
case ModbusStoreArea.输出线圈:
res = dev.modtcp.ReadOutputStatus(gp.Start, gp.Length);
break;
case ModbusStoreArea.输入线圈:
res = dev.modtcp.ReadInputStatus(gp.Start, gp.Length);
break;
default:
break;
}
//解析
//判断
if (res != null && res.Length == ((gp.Length % 8 == 0) ? gp.Length / 8 : gp.Length / 8 + 1))
{
dev.ErrorTimes = 0;
foreach (var variable in gp.varList)
{
//验证地址并解析地址
if (VerifyModbusAddress(true, variable.VarAddress, out int start, out int offset))
{
//真正的地址偏移
start -= gp.Start;
switch (variable.VarType)
{
case DataType.Bool:
variable.Value = BitLib.GetBitArrayFromByteArray(res, false)[start];
break;
default:
break;
}
//包含就替换,否则就添加
if (CommonMethods.CurrentPLCValue.ContainsKey(variable.Name))
{
CommonMethods.CurrentPLCValue[variable.Name] = variable.Value;
}
else
{
CommonMethods.CurrentPLCValue.Add(variable.Name, variable.Value);
}
}
}
}
else
{
dev.ErrorTimes++;
if (dev.ErrorTimes >= dev.MaxErrorTimes)
{
dev.IsConnected = false;
CommonMethods.TCPisConnected = dev.IsConnected;
}
}
}
//寄存器存储区
else
{
//读取
switch (gp.StoreArea)
{
case ModbusStoreArea.保持寄存器:
res = dev.modtcp.ReadKeepReg(gp.Start, gp.Length);
break;
case ModbusStoreArea.输入寄存器:
res = dev.modtcp.ReadInputReg(gp.Start, gp.Length);
break;
default:
break;
}
if (res != null && res.Length == gp.Length * 2)
{
dev.ErrorTimes = 0;
foreach (var variable in gp.varList)
{
if (VerifyModbusAddress(false, variable.VarAddress, out int start, out int offset))
{
start -= gp.Start;
start *= 2;
//2开始读取50个寄存器
//第一个变量地址是2,索引是0 (2-2)*2
//第二个变量地址是4,索引是4 (4-2)*2
//第三个变量地址是6,索引是8 (6-2)*2
switch (variable.VarType)
{
case DataType.Bool:
variable.Value = BitLib.GetBitFrom2ByteArray(res, start, offset, true);
break;
case DataType.Byte:
variable.Value = ByteLib.GetByteFromByteArray(res, start);
break;
case DataType.Short:
variable.Value = ShortLib.GetShortFromByteArray(res, start, dev.DataFormat);
break;
case DataType.UShort:
variable.Value = UShortLib.GetUShortFromByteArray(res, start, dev.DataFormat);
break;
case DataType.Int:
variable.Value = IntLib.GetIntFromByteArray(res, start, dev.DataFormat);
break;
case DataType.UInt:
variable.Value = UIntLib.GetUIntFromByteArray(res, start, dev.DataFormat);
break;
case DataType.Float:
variable.Value = FloatLib.GetFloatFromByteArray(res, start, dev.DataFormat);
break;
case DataType.Double:
variable.Value = DoubleLib.GetDoubleFromByteArray(res, start, dev.DataFormat);
break;
case DataType.Long:
variable.Value = LongLib.GetLongFromByteArray(res, start, dev.DataFormat);
break;
case DataType.ULong:
variable.Value = ULongLib.GetULongFromByteArray(res, start, dev.DataFormat);
break;
case DataType.String:
variable.Value = StringLib.GetStringFromByteArray(res, start, offset, Encoding.ASCII);
break;
case DataType.ByteArray:
variable.Value = StringLib.GetHexStringFromByteArray(res, start, offset);
break;
case DataType.HexString:
variable.Value = StringLib.GetHexStringFromByteArray(res, start, offset);
break;
default:
break;
}
//包含就替换,否则就添加
if (CommonMethods.CurrentPLCValue.ContainsKey(variable.Name))
{
CommonMethods.CurrentPLCValue[variable.Name] = variable.Value;
}
else
{
CommonMethods.CurrentPLCValue.Add(variable.Name, variable.Value);
}
}
}
}
else
{
dev.ErrorTimes++;
if (dev.ErrorTimes >= dev.MaxErrorTimes)
{
dev.IsConnected = false;
CommonMethods.TCPisConnected = dev.IsConnected;
}
}
}
}
}
}
else
{
//延时
if (!dev.FirstConnect)//如果不是第一次连接
{
await Task.Delay(dev.ReConnectTime);
dev.modtcp?.DisConnect();
}
//第一次 连接
//初始化通信对象
dev.modtcp = new xktComm.Modbus.ModbusTcp();
dev.modtcp.ConnectTimeOut = dev.ConnectTimeOut;//设置连接超时时间
//设置间隔时间
await Task.Delay(200);
//设置数据格式
dev.modtcp.DataFormat = dev.DataFormat;
//建立连接
dev.IsConnected = dev.modtcp.Connect(dev.ServerURL, dev.Port);
dev.FirstConnect = false;
await Task.Delay(200);
}
}
}, dev.cts.Token);
}
}
}
}
/// <summary>
/// 验证IP地址函数
/// </summary>
/// <param name="isBit"></param>
/// <param name="address"></param>
/// <param name="start"></param>
/// <param name="offset"></param>
/// <returns></returns>
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);
}
}
}
//设备集合
private List<NodeModbusTCP> modbusTCPList = new List<NodeModbusTCP>();
/// <summary>
/// 初始化相关信息
/// </summary>
private void InitialInfo()
{
foreach (var dev in modbusTCPList)
{
foreach (var gp in dev.ModbusTCPGroupList)
{
foreach (var variable in gp.varList)
{
if (variable.Config.ArchiveEnable)//API改变
{
CommonMethods.storeVariList.Add(variable);
}
}
}
}
//自己修改IP地址
//modbusTCPList[0].ServerURL = ipAddress;
//....
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using xktNodeSettings.Node.Modbus;
using xktNodeSettings.Node.Variable;
namespace CMStestMdbus
{
public class CommonMethods
{
public static Dictionary<string, object> CurrentPLCValue = new Dictionary<string, object>();
//TCP标志位
public static bool TCPisConnected = false;
public static int CacheCount = 600;//10分钟, 每秒一条
//归档变量集合
public static List<ModbusTCPVariable> storeVariList = new List<ModbusTCPVariable>();
public static List<List<Cache>> CacheList = new List<List<Cache>>();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CMStestMdbus
{
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.TCPisConnected)
{
InsertActualData();
//if (DateTime.Now.Minute == 0 && DateTime.Now.Second == 0)//整点插入
//{
// InsertDataHourReport();
//}
}
}
#region 插入实时数据
private void InsertActualData()
{
if (CommonMethods.CurrentPLCValue != null && CommonMethods.CurrentPLCValue.Count > 0)
{
List<ActualData> actualDataArray = new List<ActualData>();
List<Cache> cache = new List<Cache>();
////FileVarModbusList归档变量集合 在commonMethos里创建的静态变量, 归档, 意味着存入数据库
//归档信息在json里面存储
foreach (var item in CommonMethods.storeVariList)//FileVarModbusList归档集合
{
string varName = item.Name;//modbus 点表中的名称
string remark = item.Description; //注释
double value = 0.0;
if (!CommonMethods.CurrentPLCValue.ContainsKey(varName))
{
value = 0.0;
}
else
{
value = Convert.ToDouble(CommonMethods.CurrentPLCValue[varName]);
}
DateTime dt = DateTime.Now;
actualDataArray.Add(new ActualData()
{
InsertTime = dt,
VarName = varName,
Value = Convert.ToString(value),
Remark = remark
});
cache.Add(new Cache()
{
InsertTime = dt,
VarName = varName,
Value = value.ToString(),
Remark = remark
});
}
var count = new ActualDataProvider().Insert(actualDataArray); //向数据库插入数据
if (CommonMethods.CacheList.Count <= count)//如果Count小于600
{
CommonMethods.CacheList.Add(cache);//集合的集合
}
else
{
CommonMethods.CacheList.RemoveAt(0);//把第一个去掉
CommonMethods.CacheList.Add(cache);//继续添加
}
}
}
#endregion
#region 插入小时数据
//private void InsertDataHourReport()
//{
// List<string> array = new List<string>();
// foreach (var item in CommonMethods.storeVariList)
// {//ModbusTCPVariable
// double value = 0.0;
// if (CommonMethods.CurrentPLCValue.ContainsKey(item.Name))
// {
// string Res = CommonMethods.CurrentPLCValue[item.Name].ToString();//键值对,a[key]为值,存了19个变量的值
// if (Res.Length == 0)
// {
// value = 0.0;
// }
// else
// {
// value = Convert.ToDouble(Res);
// }
// array.Add(value.ToString("f1"));
// }
// ReportData reportData = new ReportData()
// {
// J0GCB11CF101 = array[0],
// J0GCB12CF101 = array[1],
// J0GCB13CF101 = array[2],
// J0GCB20CT101 = array[3],
// J0GCB20CQ101_NTU = array[4],
// J0GCB10CP102 = array[5],
// J0GCB21CF101 = array[6],
// J0GCB21CF102 = array[7],
// J0GCB21CP101 = array[8],
// J0GCB21CP102 = array[9],
// J0GCB21CQ101_NTU = array[10],
// J0GCB22CF101 = array[11],
// J0GCB22CF102 = array[12],
// J0GCB22CP101 = array[13],
// J0GCB22CP102 = array[14],
// J0GCB22CQ101_NTU = array[15],
// J0GCB31CL101 = array[16],
// J0GCB32CL101 = array[17],
// J0GCB50CP101 = array[18]
// };
// var conut = new ReportDataProvider().Insert(reportData);
// }
//}
#endregion
}
}
<?xml version="1.0" encoding="utf-8"?>
<Settings>
<NodeClass Name="PLC设备" Description="各种PLC控制设备">
<DeviceNode Name="西门子PLC" Description="空压系统1#PLC" DeviceType="30" ConnectTimeOut="2000" ReConnectTime="5000" CreateTime="2022/1/26 5:03:03" InstallationDate="2022/1/26 5:03:03" IsActive="True" MaxErrorTimes="1" KeyWay="VarName" UseAlarmCheck="False" IpAddress="192.168.10.134" Port="502" PlcType="S71500" Rack="0" Slot="0" IsUseMultiRead="false" />
</NodeClass>
<NodeClass Name="OPC客户端" Description="OPC相关客户端" />
<NodeClass Name="Modbus客户端" Description="Modbus相关客户端">
<ModbusNode Name="Modbus TCP Client" Description="1#软水系统" ModbusType="2000" ConnectTimeOut="2000" CreateTime="2022/1/26 7:01:52" ReConnectTime="5000" InstallationDate="2022/1/26 7:01:52" IsActive="True" MaxErrorTimes="1" KeyWay="VarName" UseAlarmCheck="False" ServerURL="192.168.10.134" Port="502" DataFormat="ABCD">
<ModbusGroup Name="读_读写" Description="Float_Bool" Type="ModbusTCP" StoreArea="保持寄存器" Length="15" Start="0" SlaveID="1" IsActive="true">
<Variable Name="J0GCB11CF101" Description="1号活性碳过滤器入口水流量" Type="ModbusTCP" VarAddress="0" Scale="1" Offset="0" Start="0" AccessProperty="只读" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="Float" />
<Variable Name="J0GCB12CF101" Description="2号活性碳过滤器入口水流量" Type="ModbusTCP" VarAddress="2" Scale="1" Offset="0" Start="0" AccessProperty="只读" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="Float" />
<Variable Name="J0GCB13CF101" Description="3号活性碳过滤器入口水流量" Type="ModbusTCP" VarAddress="4" Scale="1" Offset="0" Start="0" AccessProperty="只读" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="Float" />
<Variable Name="J0GCB20CT101" Description="超滤装置进口母管水温度" Type="ModbusTCP" VarAddress="6" Scale="1" Offset="0" Start="0" AccessProperty="只读" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="Float" />
<Variable Name="J0GCB20CQ101_NTU" Description="超滤装置进口母管浊度" Type="ModbusTCP" VarAddress="8" Scale="1" Offset="0" Start="0" AccessProperty="只读" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="Float" />
<Variable Name="J0GCB31CL101" Description="1号超滤出水水箱水位" Type="ModbusTCP" VarAddress="10" Scale="1" Offset="0" Start="0" AccessProperty="读写" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="UShort" />
<Variable Name="J0GCB32CL101" Description="2号超滤出水水箱水位" Type="ModbusTCP" VarAddress="11" Scale="1" Offset="0" Start="0" AccessProperty="读写" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="UShort" />
<Variable Name="J0GCB50CP101" Description="超滤出水升压泵出口母管压" Type="ModbusTCP" VarAddress="12" Scale="1" Offset="0" Start="0" AccessProperty="读写" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="UShort" />
<Variable Name="J0GCB60CF101" Description="超滤反洗水泵出口母管流量" Type="ModbusTCP" VarAddress="13" Scale="1" Offset="0" Start="0" AccessProperty="读写" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="UShort" />
<Variable Name="J0GCB60CP101" Description="超滤反洗水泵出口母管压力" Type="ModbusTCP" VarAddress="14" Scale="1" Offset="0" Start="0" AccessProperty="读写" AlarmEnable="False" ArchiveEnable="True" SetLimitEnable="False" ArchivePeriod="2" VarType="UShort" />
</ModbusGroup>
</ModbusNode>
</NodeClass>
<NodeClass Name="Custom客户端" Description="Custom相关客户端" />
<NodeClass Name="服务器" Description="自定义服务器" />
</Settings>
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CMStestMdbus
{
public class ActualDataProvider
{
public int Delete(ActualData t)
{
if (t == null) return 0;
ActualData model = SqlSugarHelper.db.Queryable<ActualData>().Where(item => item.Id == t.Id).First();
if (model == null) return 0;
int count = SqlSugarHelper.db.Deleteable<ActualData>(model).ExecuteCommand();
return count;
}
//public int Insert(ActualData t)
//{
// int count = SqlSugarHelper.db.Insertable<ActualData>(t).ExecuteCommand();
// return count;
//}
/// <summary>
/// 批量插入
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
///
public int Insert(List<ActualData> t)
{
if (t == null) return 0;
////if (t.Value == null) return 0;
////方法1
//foreach (var item in t.ToArray())
//{
// SqlSugarHelper.db.Insertable<ActualData>(item).ExecuteCommand();
//}
////方法2
int count = SqlSugarHelper.db.Insertable(t.ToArray()).ExecuteCommand();//官方推荐的
return count;
}
public List<ActualData> Select()
{
DateTime day = DateTime.Now.AddDays(-1);
return SqlSugarHelper.db.Queryable<ActualData>().Where(u => SqlFunc.Between(u.InsertTime, day,DateTime.Now)).ToList();
//return SqlSugarHelper.db.Queryable<ActualData>().ToList();
}
public int Update(ActualData t)
{
if (t == null) return 0;
ActualData model = SqlSugarHelper.db.Queryable<ActualData>().Where(item => item.Id == t.Id).First();
if (model == null) return 0;
model.Value = t.Value;
model.Remark = t.Remark;
model.VarName = t.VarName;
int count = SqlSugarHelper.db.Updateable<ActualData>(model).ExecuteCommand();
return count;
}
}
}
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CMStestMdbus
{
public class SqlSugarHelper
{
public static string ConnectionString = string.Empty; //必填, 数据库连接字符串
public static SqlSugarClient db
{
get => new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = ConnectionString,
DbType = SqlSugar.DbType.Sqlite, //必填, 数据库类型
IsAutoCloseConnection = true, //默认false, 时候知道关闭数据库连接, 设置为true无需使用using或者Close操作
InitKeyType = InitKeyType.SystemTable //默认SystemTable, 字段信息读取, 如:该属性是不是主键,是不是标识列等等信息
});
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CMStestMdbus
{
public class SqlSugarService
{
/// <summary>
/// 设置连接字符串
/// </summary>
/// <param name="ConnectionStr"></param>
public static void SetConnectionStr(string ConnectionStr)
{
SqlSugarHelper.ConnectionString = ConnectionStr;
}
}
}
//SqlSugarService.SetConnectionStr("Data Source=" + Application.StartupPath + "\\Config\\ScadaData.db;Pooling=true;FailIfMissing=false");
本文详细介绍了如何在C#项目中利用Sqlsugar库进行数据库操作,涵盖了连接配置、实体映射、CRUD操作以及 LINQ 查询的使用方法,旨在提升开发效率并简化数据访问层的代码。
912

被折叠的 条评论
为什么被折叠?



