diff --git a/SlnMesnac.Business/SlnMesnac.Business.csproj b/SlnMesnac.Business/SlnMesnac.Business.csproj
new file mode 100644
index 0000000..4e2cf5e
--- /dev/null
+++ b/SlnMesnac.Business/SlnMesnac.Business.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Business/base/BaseBusiness.cs b/SlnMesnac.Business/base/BaseBusiness.cs
new file mode 100644
index 0000000..4dd7e89
--- /dev/null
+++ b/SlnMesnac.Business/base/BaseBusiness.cs
@@ -0,0 +1,115 @@
+using Microsoft.Extensions.DependencyInjection;
+using SlnMesnac.Plc;
+using SlnMesnac.Rfid;
+using SlnMesnac.Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Business.base
+* 唯一标识:b00d95c1-a164-43a3-9f34-2a5d2efb3f34
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-12 17:36:19
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Business.@base
+{
+ internal class BaseBusiness
+ {
+ private readonly List _plcFactories;
+
+ private readonly List _rfidFactories;
+
+ private IServiceProvider _serviceProvider;
+
+ public BaseBusiness(IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+
+ using (var scope = _serviceProvider.CreateScope())
+ {
+ _plcFactories = scope.ServiceProvider.GetRequiredService>();
+ _rfidFactories = scope.ServiceProvider.GetRequiredService>();
+ }
+ }
+
+ ///
+ /// 根据Key获取PLC连接信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ public PlcAbsractFactory GetPlcByKey(string key)
+ {
+ if(_plcFactories == null)
+ {
+ throw new ArgumentNullException($"根据Key获取PLC连接信息异常:PLC 连接信息为空");
+ }
+
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("根据Key获取PLC连接信息异常:设备Key参数为空");
+ }
+
+ try
+ {
+ var info = _plcFactories.Where(x => x.ConfigKey == key).FirstOrDefault();
+
+ return info;
+ }catch(Exception ex)
+ {
+ throw new InvalidOperationException($"根据Key获取PLC连接信息异常:{ex.Message}");
+ }
+ }
+
+
+ ///
+ /// 根据Key获取Rfid连接信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RfidAbsractFactory GetRfidByKey(string key)
+ {
+ if (_rfidFactories == null)
+ {
+ throw new ArgumentNullException($"根据Key获取RFID连接信息异常:PLC 连接信息为空");
+ }
+
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("根据Key获取RFID连接信息异常:设备Key参数为空");
+ }
+
+ try
+ {
+ var info = _rfidFactories.Where(x => x.ConfigKey == key).FirstOrDefault();
+
+ return info;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据Key获取RFID连接信息异常:{ex.Message}");
+ }
+ }
+ }
+}
diff --git a/SlnMesnac.Common/ExpressionExtensions.cs b/SlnMesnac.Common/ExpressionExtensions.cs
new file mode 100644
index 0000000..a5348c0
--- /dev/null
+++ b/SlnMesnac.Common/ExpressionExtensions.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Linq;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Common
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Common
+{
+ ///
+ /// 谓词表达式构建器
+ ///
+ public static class ExpressionExtensions
+ {
+ ///
+ /// 创建一个值恒为 true 的表达式。
+ ///
+ /// 表达式方法类型
+ /// 一个值恒为 true 的表达式。
+ public static Expression> True() { return p => true; }
+
+ ///
+ /// 创建一个值恒为 false 的表达式。
+ ///
+ /// 表达式方法类型
+ /// 一个值恒为 false 的表达式。
+ public static Expression> False() { return f => false; }
+
+ ///
+ /// 使用 Expression.OrElse 的方式拼接两个 System.Linq.Expression。
+ ///
+ /// 表达式方法类型
+ /// 左边的 System.Linq.Expression 。
+ /// 右边的 System.Linq.Expression。
+ /// 拼接完成的 System.Linq.Expression。
+ public static Expression Or(this Expression left, Expression right)
+ {
+ return MakeBinary(left, right, Expression.OrElse);
+ }
+
+ ///
+ /// 使用 Expression.AndAlso 的方式拼接两个 System.Linq.Expression。
+ ///
+ /// 表达式方法类型
+ /// 左边的 System.Linq.Expression 。
+ /// 右边的 System.Linq.Expression。
+ /// 拼接完成的 System.Linq.Expression。
+ public static Expression And(this Expression left, Expression right)
+ {
+ return MakeBinary(left, right, Expression.AndAlso);
+ }
+
+ ///
+ /// 使用自定义的方式拼接两个 System.Linq.Expression。
+ ///
+ /// 表达式方法类型
+ /// 左边的 System.Linq.Expression 。
+ /// 右边的 System.Linq.Expression。
+ ///
+ /// 拼接完成的 System.Linq.Expression。
+ private static Expression MakeBinary(this Expression left, Expression right, Func func)
+ {
+ return MakeBinary((LambdaExpression)left, right, func) as Expression;
+ }
+
+ ///
+ /// 拼接两个
+ /// System.Linq.Expression
+ /// ,两个
+ /// System.Linq.Expression
+ /// 的参数必须完全相同。
+ ///
+ /// 左边的
+ /// System.Linq.Expression
+ ///
+ /// 右边的
+ /// System.Linq.Expression
+ ///
+ /// 表达式拼接的具体逻辑
+ /// 拼接完成的
+ /// System.Linq.Expression
+ ///
+ private static LambdaExpression MakeBinary(this LambdaExpression left, LambdaExpression right, Func func)
+ {
+ var data = Combinate(right.Parameters, left.Parameters).ToArray();
+
+ right = ParameterReplace.Replace(right, data) as LambdaExpression;
+
+ return Expression.Lambda(func(left.Body, right.Body), left.Parameters.ToArray());
+ }
+
+ ///
+ /// 合并参数
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static IEnumerable> Combinate(IEnumerable left, IEnumerable right)
+ {
+ var a = left.GetEnumerator();
+ var b = right.GetEnumerator();
+ while (a.MoveNext() && b.MoveNext())
+ yield return new KeyValuePair(a.Current, b.Current);
+ }
+ }
+
+ internal sealed class ParameterReplace : ExpressionVisitor
+ {
+ public static Expression Replace(Expression e, IEnumerable> paramList)
+ {
+ var item = new ParameterReplace(paramList);
+ return item.Visit(e);
+ }
+
+ private readonly Dictionary _parameters;
+
+ public ParameterReplace(IEnumerable> paramList)
+ {
+ _parameters = paramList.ToDictionary(p => p.Key, p => p.Value, new ParameterEquality());
+ }
+
+ protected override Expression VisitParameter(ParameterExpression p)
+ {
+ ParameterExpression result;
+ if (_parameters.TryGetValue(p, out result))
+ return result;
+ return base.VisitParameter(p);
+ }
+
+ #region class: ParameterEquality
+ private class ParameterEquality : IEqualityComparer
+ {
+ public bool Equals(ParameterExpression x, ParameterExpression y)
+ {
+ if (x == null || y == null)
+ return false;
+
+ return x.Type == y.Type;
+ }
+
+ public int GetHashCode(ParameterExpression obj)
+ {
+ if (obj == null)
+ return 0;
+
+ return obj.Type.GetHashCode();
+ }
+ }
+ #endregion
+ }
+}
diff --git a/SlnMesnac.Common/SlnMesnac.Common.csproj b/SlnMesnac.Common/SlnMesnac.Common.csproj
new file mode 100644
index 0000000..d031ec1
--- /dev/null
+++ b/SlnMesnac.Common/SlnMesnac.Common.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Common/StringChange.cs b/SlnMesnac.Common/StringChange.cs
new file mode 100644
index 0000000..6c4ff13
--- /dev/null
+++ b/SlnMesnac.Common/StringChange.cs
@@ -0,0 +1,225 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Common
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Common
+{
+ public class StringChange
+ {
+ ///
+ /// 将字符串强制转换成int,转换失败则返回0
+ ///
+ ///
+ ///
+ public int ParseToInt(string str)
+ {
+ int returnInt = 0;
+ if (str == null || str.Trim().Length < 1)
+ {
+ return returnInt;
+ }
+ if (int.TryParse(str, out returnInt))
+ {
+ return returnInt;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ ///
+ /// char数组转Array
+ ///
+ ///
+ ///
+ ///
+ public string CharArrayToString(char[] cha, int len)
+ {
+ string str = "";
+ for (int i = 0; i < len; i++)
+ {
+ str += string.Format("{0}", cha[i]);
+ }
+
+ return str;
+ }
+
+ public string bytesToHexStr(byte[] bytes, int iLen)//e.g. { 0x01, 0x01} ---> " 01 01"
+ {
+ string returnStr = "";
+ if (bytes != null)
+ {
+ for (int i = 0; i < iLen; i++)
+ {
+ returnStr += bytes[i].ToString("X2");
+ }
+ }
+ return returnStr;
+ }
+
+ public byte[] HexStrTorbytes(string strHex)//e.g. " 01 01" ---> { 0x01, 0x01}
+ {
+ strHex = strHex.Replace(" ", "");
+ if ((strHex.Length % 2) != 0)
+ strHex += " ";
+ byte[] returnBytes = new byte[strHex.Length / 2];
+ for (int i = 0; i < returnBytes.Length; i++)
+ returnBytes[i] = Convert.ToByte(strHex.Substring(i * 2, 2), 16);
+ return returnBytes;
+ }
+
+ public string StringToHexString(string s, Encoding encode)
+ {
+ byte[] b = encode.GetBytes(s); //按照指定编码将string编程字节数组
+ string result = string.Empty;
+ for (int i = 0; i < b.Length; i++) //逐字节变为16进制字符,以%隔开
+ {
+ result += "%" + Convert.ToString(b[i], 16);
+ }
+ return result;
+ }
+
+ public string HexStringToString(string hs, Encoding encode)
+ {
+ //以%分割字符串,并去掉空字符
+ string[] chars = hs.Split(new char[] { '%' }, StringSplitOptions.RemoveEmptyEntries);
+ byte[] b = new byte[chars.Length];
+ //逐个字符变为16进制字节数据
+ for (int i = 0; i < chars.Length; i++)
+ {
+ b[i] = Convert.ToByte(chars[i], 16);
+ }
+ //按照指定编码将字节数组变为字符串
+ return encode.GetString(b);
+ }
+
+ public byte[] Swap16Bytes(byte[] OldU16)
+ {
+ byte[] ReturnBytes = new byte[2];
+ ReturnBytes[1] = OldU16[0];
+ ReturnBytes[0] = OldU16[1];
+ return ReturnBytes;
+ }
+
+
+ /// 64Base码
+ /// 保存路径
+ /// 文件名称
+ ///
+ public bool Base64ToImage(string strbase64, string path, string filename)
+ {
+ bool Flag = false;
+ try
+ {
+ //base64编码的文本 转为 图片
+ //图片名称
+ byte[] arr = Convert.FromBase64String(strbase64);//将指定的字符串(它将二进制数据编码为 Base64 数字)转换为等效的 8 位无符号整数数组。
+ using (MemoryStream ms = new MemoryStream(arr))
+ {
+ Bitmap bmp = new Bitmap(ms);//加载图像
+ if (!Directory.Exists(path))//判断保存目录是否存在
+ {
+ Directory.CreateDirectory(path);
+ }
+ bmp.Save((path + "\\" + filename + ".png"), System.Drawing.Imaging.ImageFormat.Png);//将图片以JPEG格式保存在指定目录(可以选择其他图片格式)
+ ms.Close();//关闭流并释放
+ if (File.Exists(path + "\\" + filename + ".png"))//判断是否存在
+ {
+ Flag = true;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("图片保存失败:" + ex.Message);
+ }
+ return Flag;
+ }
+
+ ///
+ /// 获取时间戳
+ ///
+ ///
+ public long GetTimeStamp()
+ {
+ TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
+ return Convert.ToInt64(ts.TotalSeconds);
+ }
+
+ public byte[] ConvertFloatToINt(byte[] floatBytes)
+ {
+ byte[] intBytes = new byte[floatBytes.Length / 2];
+ for (int i = 0; i < intBytes.Length; i++)
+ {
+ intBytes[i] = floatBytes[i * 2];
+ }
+ return intBytes;
+ }
+
+ //CRC异或校验
+ public byte CalculateVerify(byte[] pMessage, int iLength)
+ {
+ UInt16 i;
+ byte iVerify = 0;
+
+ iVerify = pMessage[0];
+ for (i = 1; i < iLength; i++)
+ {
+ iVerify = (byte)(iVerify ^ pMessage[i]);
+ }
+ return iVerify;
+ }
+
+ public int HexStringToNegative(string strNumber)
+ {
+
+ int iNegate = 0;
+ int iNumber = Convert.ToInt32(strNumber, 16);
+ if (iNumber > 127)
+ {
+ int iComplement = iNumber - 1;
+ string strNegate = string.Empty;
+ char[] binchar = Convert.ToString(iComplement, 2).PadLeft(8, '0').ToArray();
+ foreach (char ch in binchar)
+ {
+ if (Convert.ToInt32(ch) == 48)
+ {
+ strNegate += "1";
+ }
+ else
+ {
+ strNegate += "0";
+ }
+ }
+ iNegate = -Convert.ToInt32(strNegate, 2);
+ }
+ return iNegate;
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Config/AppConfig.cs b/SlnMesnac.Config/AppConfig.cs
new file mode 100644
index 0000000..d2b0de6
--- /dev/null
+++ b/SlnMesnac.Config/AppConfig.cs
@@ -0,0 +1,87 @@
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Config
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Config
+{
+ ///
+ /// 系统配置
+ ///
+ #pragma warning disable CS8618 // Non-nullable field 'Data' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
+ public class AppConfig : IOptions
+ {
+ ///
+ /// 日志文件路径
+ ///
+ public string logPath { get; set; }
+
+ ///
+ /// Sql连接配置
+ ///
+ public List sqlConfig { get; set; }
+
+ ///
+ /// PLC连接配置
+ ///
+ public List plcConfig { get; set; }
+
+ ///
+ /// RFID连接配置
+ ///
+ public List rfidConfig { get; set; }
+
+
+ ///
+ /// Redis配置
+ ///
+ public string redisConfig { get; set; }
+
+ ///
+ /// 修改配置文件
+ ///
+ ///
+ public void SetValue(AppConfig appConfig)
+ {
+ var jsonObject = JsonConvert.SerializeObject(new
+ {
+ AppConfig = new
+ {
+ logPath = appConfig.logPath,
+ SqlConfig = appConfig.sqlConfig,
+ PlcConfig = appConfig.plcConfig,
+ RfidConfig = appConfig.rfidConfig,
+ RedisConfig = appConfig.redisConfig,
+ }
+ }, Newtonsoft.Json.Formatting.Indented);
+ var appSettingsPath = Path.Combine(AppContext.BaseDirectory, "appsettings.json");
+ File.WriteAllText(appSettingsPath, jsonObject);
+ }
+
+ public AppConfig Value => this;
+ }
+}
diff --git a/SlnMesnac.Config/PlcConfig.cs b/SlnMesnac.Config/PlcConfig.cs
new file mode 100644
index 0000000..6be7fb7
--- /dev/null
+++ b/SlnMesnac.Config/PlcConfig.cs
@@ -0,0 +1,61 @@
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Config
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Config
+{
+ ///
+ /// PLC配置,通过AppConfig进行获取
+ ///
+ #pragma warning disable CS8618 // Non-nullable field 'Data' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
+ public class PlcConfig
+ {
+ ///
+ /// PLC配置ID
+ ///
+ public int configId { get; set; }
+
+ ///
+ /// PIC类型
+ ///
+ public string plcType { get; set; }
+
+ ///
+ /// PLC IP
+ ///
+ public string plcIp { get; set; }
+
+ ///
+ /// PLC Port
+ ///
+ public int plcPort { get; set; }
+
+ ///
+ /// PLC Key
+ ///
+ public string plcKey { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ public bool isFlage { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Config/RfidConfig.cs b/SlnMesnac.Config/RfidConfig.cs
new file mode 100644
index 0000000..87622ea
--- /dev/null
+++ b/SlnMesnac.Config/RfidConfig.cs
@@ -0,0 +1,52 @@
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Config
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Config
+{
+ public class RfidConfig
+ {
+ ///
+ /// 配置ID
+ ///
+ public int configId { get; set; }
+
+ ///
+ /// 设备 IP
+ ///
+ public string? equipIp { get; set; }
+
+ ///
+ /// 设备 Port
+ ///
+ public int equipPort { get; set; }
+
+ ///
+ /// 设备 Key
+ ///
+ public string? equipKey { get; set; }
+
+ ///
+ /// 是否启用
+ ///
+ public bool isFlage { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Config/SlnMesnac.Config.csproj b/SlnMesnac.Config/SlnMesnac.Config.csproj
new file mode 100644
index 0000000..daf8195
--- /dev/null
+++ b/SlnMesnac.Config/SlnMesnac.Config.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Config/SqlConfig.cs b/SlnMesnac.Config/SqlConfig.cs
new file mode 100644
index 0000000..cc3de31
--- /dev/null
+++ b/SlnMesnac.Config/SqlConfig.cs
@@ -0,0 +1,46 @@
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Config
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Config
+{
+ ///
+ /// Sql连接配置
+ ///
+ #pragma warning disable CS8618 // Non-nullable field 'Data' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
+ public class SqlConfig
+ {
+ ///
+ /// Sql 配置ID,实体通过该ID关联数据源
+ ///
+ public string configId { get; set; }
+
+ ///
+ /// 数据库类型,MySql-0;SqlServer-1;Sqlite-2;Oracle-3
+ ///
+ public int dbType { get; set; }
+
+ ///
+ /// 连接字符串
+ ///
+ public string connStr { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Extensions/PlcFactorySetup.cs b/SlnMesnac.Extensions/PlcFactorySetup.cs
new file mode 100644
index 0000000..3298593
--- /dev/null
+++ b/SlnMesnac.Extensions/PlcFactorySetup.cs
@@ -0,0 +1,131 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Serilog;
+using SlnMesnac.Config;
+using SlnMesnac.Plc;
+using SlnMesnac.Plc.Factory;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Extensions
+* 唯一标识:9bf604b4-3937-476a-adb0-27adc6fbea28
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-12 15:25:47
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Extensions
+{
+ ///
+ /// PLC工厂
+ ///
+ public static class PlcFactorySetup
+ {
+
+ public static void AddPlcFactorySetup(this IServiceCollection services)
+ {
+ services.AddSingleton>(x =>
+ {
+ AppConfig appConfig = x.GetService();
+
+ List absractFactories = new List();
+
+ try
+ {
+ do
+ {
+ if (!HslCommunication.Authorization.SetAuthorizationCode("1839541f-8fb4-42c4-a13f-733b027fe5af"))
+ {
+ Log.Information("HslCommunication激活失败,可用时长为24小时");
+ break;
+ }
+ else
+ {
+ Log.Information("HslCommunication激活成功");
+ }
+
+ if (appConfig.plcConfig != null)
+ {
+ foreach (var item in appConfig.plcConfig)
+ {
+ if (item.isFlage)
+ {
+ PlcAbsractFactory _plc = InitPlc(x, item.plcType);
+
+ var connectResult = _plc.Connect(item.plcIp, item.plcPort);
+ if (connectResult)
+ {
+ Log.Information($"PLC:{item.plcIp}:{item.plcPort};连接成功,时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
+ _plc.ConfigKey = item.plcKey;
+
+ if (absractFactories.Contains(_plc))
+ {
+ absractFactories.Remove(_plc);
+ }
+
+ absractFactories.Add(_plc);
+ }
+ else
+ {
+ Log.Information($"PLC:{item.plcIp}:{item.plcPort};连接失败,时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
+ }
+ }
+ }
+ }
+ }while(false);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"PLC初始化连接异常:{e.Message}");
+ }
+
+ return absractFactories;
+ });
+ }
+
+ private static PlcAbsractFactory InitPlc(IServiceProvider serviceProvider,string plcType)
+ {
+ PlcAbsractFactory _plc = null;
+ var _inovance = serviceProvider.GetRequiredService();
+ var _melsecBinary = serviceProvider.GetRequiredService();
+ var _omronNj = serviceProvider.GetRequiredService();
+ var _siemens = serviceProvider.GetRequiredService();
+
+ switch (plcType)
+ {
+ case "InovancePlc":
+ _plc = _inovance;
+ break;
+ case "MelsecBinaryPlc":
+ _plc = _melsecBinary;
+ break;
+ case "OmronNJPlc":
+ _plc = _omronNj;
+ break;
+ case "SiemensPlc":
+ _plc = _siemens;
+ break;
+ default:
+ break;
+ }
+
+ return _plc;
+ }
+ }
+}
diff --git a/SlnMesnac.Extensions/RfidFactorySetup.cs b/SlnMesnac.Extensions/RfidFactorySetup.cs
new file mode 100644
index 0000000..ac5e29f
--- /dev/null
+++ b/SlnMesnac.Extensions/RfidFactorySetup.cs
@@ -0,0 +1,87 @@
+using Microsoft.Extensions.DependencyInjection;
+using Serilog;
+using SlnMesnac.Config;
+using SlnMesnac.Plc;
+using SlnMesnac.Rfid;
+using SlnMesnac.Rfid.Factory;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Extensions
+* 唯一标识:007aaf92-2adf-42a1-8b64-4e02925e3d5b
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-12 17:08:27
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Extensions
+{
+ public static class RfidFactorySetup
+ {
+ public static void AddRfidFactorySetup(this IServiceCollection services)
+ {
+ services.AddSingleton>(x =>
+ {
+ AppConfig appConfig = x.GetService();
+ List absractFactories = new List();
+
+ try
+ {
+ if (appConfig.rfidConfig != null)
+ {
+ foreach (var item in appConfig.rfidConfig)
+ {
+ if (item.isFlage)
+ {
+ RfidAbsractFactory _rfid = x.GetService();
+ bool connectResult = _rfid.Connect(item.equipIp, item.equipPort);
+ if (connectResult)
+ {
+ Log.Information($"RFID:{item.equipIp}:{item.equipPort};连接成功,时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
+ _rfid.ConfigKey = item.equipKey;
+
+ if (absractFactories.Contains(_rfid))
+ {
+ absractFactories.Remove(_rfid);
+ }
+
+ absractFactories.Add(_rfid);
+ }
+ else
+ {
+ Log.Information($"RFID:{item.equipIp}:{item.equipPort};连接失败,时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
+ }
+ }
+ }
+ }
+ else
+ {
+ Log.Error("RFID配置信息为空");
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Error($"RFID初始化连接异常:{e.Message}");
+ }
+
+ return absractFactories;
+ });
+ }
+ }
+}
diff --git a/SlnMesnac.Extensions/SlnMesnac.Extensions.csproj b/SlnMesnac.Extensions/SlnMesnac.Extensions.csproj
new file mode 100644
index 0000000..cd6c9bd
--- /dev/null
+++ b/SlnMesnac.Extensions/SlnMesnac.Extensions.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Extensions/SqlsugarSetup.cs b/SlnMesnac.Extensions/SqlsugarSetup.cs
new file mode 100644
index 0000000..8761bea
--- /dev/null
+++ b/SlnMesnac.Extensions/SqlsugarSetup.cs
@@ -0,0 +1,69 @@
+using Microsoft.Extensions.DependencyInjection;
+using SlnMesnac.Config;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Extensions
+* 唯一标识:bbb46406-e99d-4205-8046-ad954cf88315
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-12 17:31:43
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Extensions
+{
+ public static class SqlsugarSetup
+ {
+ ///
+ /// 注册SqlSugar
+ ///
+ ///
+ public static void AddSqlSugarSetup(this IServiceCollection services)
+ {
+ services.AddSingleton(x =>
+ {
+ var appConfig = x.GetService();
+
+ var connectConfigList = new List();
+ if (appConfig.sqlConfig != null)
+ {
+ foreach (var item in appConfig.sqlConfig)
+ {
+ var config = new ConnectionConfig()
+ {
+ ConfigId = item.configId,
+ DbType = (DbType)item.dbType,
+ ConnectionString = item.connStr,
+ InitKeyType = InitKeyType.Attribute,
+ IsAutoCloseConnection = true,
+ };
+ connectConfigList.Add(config);
+ }
+ }
+ SqlSugarScope Db = new SqlSugarScope(connectConfigList, db =>
+ {
+ db.Aop.OnLogExecuting = (sql, pars) => { };
+ });
+
+ return Db;
+ });
+ }
+ }
+}
diff --git a/SlnMesnac.Generate/GenerateCode.cs b/SlnMesnac.Generate/GenerateCode.cs
new file mode 100644
index 0000000..812b0f9
--- /dev/null
+++ b/SlnMesnac.Generate/GenerateCode.cs
@@ -0,0 +1,113 @@
+using SlnMesnac.Generate.Templates.Service;
+using SlnMesnac.Generate.Templates.Service.Impl;
+using SqlSugar;
+using System;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Generate
+* 唯一标识:78595105-fab6-40f0-97b4-1272dc3e0e86
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-11 13:35:01
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Generate
+{
+ ///
+ /// 生成代码
+ ///
+ public class GenerateCode
+ {
+ private readonly ISqlSugarClient _sqlSugarClient;
+
+ public GenerateCode(ISqlSugarClient sqlSugarClient)
+ {
+ _sqlSugarClient = sqlSugarClient;
+ }
+
+ public bool CreateCode(string configId,string tableName,string savePath,string nameSpace)
+ {
+ if (string.IsNullOrEmpty(configId))
+ {
+ throw new ArgumentNullException($"代码生成异常:configId参数为空");
+ }
+
+ if (string.IsNullOrEmpty(tableName))
+ {
+ throw new ArgumentNullException($"代码生成异常:表格名称参数为空");
+ }
+
+ if (string.IsNullOrEmpty(savePath))
+ {
+ throw new ArgumentNullException($"代码生成异常:文件存储路径参数为空");
+ }
+
+ if (string.IsNullOrEmpty(nameSpace))
+ {
+ throw new ArgumentNullException($"代码生成异常:命名空间参数为空");
+ }
+
+ try
+ {
+ savePath += $"\\{tableName}";
+
+ var scope = _sqlSugarClient.AsTenant().GetConnectionScope(configId);
+
+ scope.DbFirst.IsCreateAttribute()
+ .FormatPropertyName(it=> ToCamelCase(it)).Where(p => p == tableName).CreateClassFile($"{savePath}\\Entity", nameSpace);
+
+ var isc = new IServiceCreate();
+ bool iscRes = isc.Create(tableName, nameSpace, savePath);
+ if (!iscRes)
+ {
+ throw new InvalidOperationException($"Service接口生成失败");
+ }
+
+ var sc = new ServiceCreate();
+ var scRes = sc.Create(tableName, nameSpace, savePath);
+
+ if (!scRes)
+ {
+ throw new InvalidOperationException($"Service实现类生成失败");
+ }
+
+ return true;
+ }catch (Exception ex)
+ {
+ throw new InvalidOperationException($"代码生成异常:{ex.Message}");
+ }
+ }
+
+ private static string ToCamelCase(string input)
+ {
+ // 将字符串转换为驼峰格式,但保持每个单词的首字母大写
+ string[] words = input.Split('_');
+ for (int i = 0; i < words.Length; i++)
+ {
+ if (i > 0)
+ {
+ words[i] = char.ToUpper(words[i][0]) + words[i].Substring(1).ToLower();
+ }
+ else
+ {
+ words[i] = words[i].ToLower();
+ }
+ }
+ return string.Join("", words);
+ }
+ }
+}
diff --git a/SlnMesnac.Generate/SlnMesnac.Generate.csproj b/SlnMesnac.Generate/SlnMesnac.Generate.csproj
new file mode 100644
index 0000000..7e094ef
--- /dev/null
+++ b/SlnMesnac.Generate/SlnMesnac.Generate.csproj
@@ -0,0 +1,16 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Generate/Templates/Service/IServiceCreate.cs b/SlnMesnac.Generate/Templates/Service/IServiceCreate.cs
new file mode 100644
index 0000000..1306e4c
--- /dev/null
+++ b/SlnMesnac.Generate/Templates/Service/IServiceCreate.cs
@@ -0,0 +1,78 @@
+using Commons.Collections;
+using NVelocity.App;
+using NVelocity.Runtime;
+using NVelocity;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Generate.Templates
+* 唯一标识:4dbafd45-d689-4d1a-b54d-b936dae7d17c
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-11 13:28:04
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Generate.Templates.Service
+{
+ public class IServiceCreate
+ {
+ private static readonly string templateDir = @"F:\桌面\SlnMesnac\SlnMesnac.Generate\Templates\Service";
+
+ public bool Create(string tableName, string NameSpace, string outdir)
+ {
+
+ try
+ {
+ VelocityEngine velocityEngine = new VelocityEngine();
+ ExtendedProperties props = new ExtendedProperties();
+ props.AddProperty(RuntimeConstants.RESOURCE_LOADER, @"file");
+ props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, templateDir);
+ props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");
+ props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
+ //模板的缓存设置
+ props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, true); //是否缓存
+ props.AddProperty("file.resource.loader.modificationCheckInterval", (Int64)30); //缓存时间(秒)
+ velocityEngine.Init(props);
+ //为模板变量赋值
+ VelocityContext context = new VelocityContext();
+ context.Put("tableName", tableName);
+ context.Put("NameSpace", NameSpace);
+ context.Put("outdir", outdir);
+ //从文件中读取模板
+ Template template = velocityEngine.GetTemplate(@"\IServices.vm");
+ if (!Directory.Exists(outdir + "\\IServices"))
+ {
+ Directory.CreateDirectory(outdir + "\\IServices");
+ }
+ //合并模板
+ using (StreamWriter writer = new StreamWriter(outdir + $"\\IServices\\I{tableName.Substring(0, 1).ToUpper()}{tableName.Substring(1)}Service.cs", false))
+ {
+ template.Merge(context, writer);
+ }
+ return true;
+ }catch(Exception ex)
+ {
+ throw new InvalidOperationException($"Service接口模板创建异常:{ex.Message}");
+ }
+ }
+
+
+ }
+}
diff --git a/SlnMesnac.Generate/Templates/Service/IServices.vm b/SlnMesnac.Generate/Templates/Service/IServices.vm
new file mode 100644
index 0000000..a5b8992
--- /dev/null
+++ b/SlnMesnac.Generate/Templates/Service/IServices.vm
@@ -0,0 +1,13 @@
+using SlnMesnac.Model.domain;
+using SlnMesnac.Repository.service.@base;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ${NameSpace}.service
+{
+ public interface I${tableName}Services: IBaseService<${tableName}>
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Generate/Templates/Service/Impl/ServiceCreate.cs b/SlnMesnac.Generate/Templates/Service/Impl/ServiceCreate.cs
new file mode 100644
index 0000000..0aa6838
--- /dev/null
+++ b/SlnMesnac.Generate/Templates/Service/Impl/ServiceCreate.cs
@@ -0,0 +1,75 @@
+using Commons.Collections;
+using NVelocity.App;
+using NVelocity.Runtime;
+using NVelocity;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Generate.Templates
+* 唯一标识:4acc596a-6223-4156-b16c-952c225eff25
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-11 13:27:33
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Generate.Templates.Service.Impl
+{
+ public class ServiceCreate
+ {
+ private static readonly string templateDir = @"F:\桌面\SlnMesnac\SlnMesnac.Generate\Templates\Service\Impl\";
+
+ public bool Create(string tableName, string NameSpace, string outdir)
+ {
+ try
+ {
+ VelocityEngine velocityEngine = new VelocityEngine();
+ ExtendedProperties props = new ExtendedProperties();
+ props.AddProperty(RuntimeConstants.RESOURCE_LOADER, @"file");
+ props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, templateDir);
+ props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");
+ props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
+ //模板的缓存设置
+ props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, true); //是否缓存
+ props.AddProperty("file.resource.loader.modificationCheckInterval", (Int64)30); //缓存时间(秒)
+ velocityEngine.Init(props);
+ //为模板变量赋值
+ VelocityContext context = new VelocityContext();
+ context.Put("tableName", tableName);
+ context.Put("NameSpace", NameSpace);
+ context.Put("outdir", outdir);
+ //从文件中读取模板
+ Template template = velocityEngine.GetTemplate(@"\Services.vm");
+ if (!Directory.Exists(outdir + "\\Services"))
+ {
+ Directory.CreateDirectory(outdir + "\\Services");
+ }
+ //合并模板
+ using (StreamWriter writer = new StreamWriter(outdir + $"\\Services\\{tableName.Substring(0, 1).ToUpper()}{tableName.Substring(1)}ServiceImpl.cs", false))
+ {
+ template.Merge(context, writer);
+ }
+ return true;
+ }catch(Exception ex)
+ {
+ throw new InvalidOperationException($"Service实现类模板创建异常:{ex.Message}");
+ }
+ }
+ }
+}
diff --git a/SlnMesnac.Generate/Templates/Service/Impl/Services.vm b/SlnMesnac.Generate/Templates/Service/Impl/Services.vm
new file mode 100644
index 0000000..bcf9a49
--- /dev/null
+++ b/SlnMesnac.Generate/Templates/Service/Impl/Services.vm
@@ -0,0 +1,14 @@
+using SlnMesnac.Model.domain;
+using SlnMesnac.Repository.service.@base;
+using System;
+using System.Collections.Generic;
+
+namespace ${NameSpace}.service.Impl
+{
+ public class ${tableName}ServiceImpl : BaseServiceImpl<${tableName}>, I${tableName}Service
+ {
+ public ${tableName}ServiceImpl(Repository<${tableName}> repository):base(repository)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Library/GRreader.dll b/SlnMesnac.Library/GRreader.dll
new file mode 100644
index 0000000..70ee539
Binary files /dev/null and b/SlnMesnac.Library/GRreader.dll differ
diff --git a/SlnMesnac.Library/HslCommunication.dll b/SlnMesnac.Library/HslCommunication.dll
new file mode 100644
index 0000000..7082ca2
Binary files /dev/null and b/SlnMesnac.Library/HslCommunication.dll differ
diff --git a/SlnMesnac.Model/SlnMesnac.Model.csproj b/SlnMesnac.Model/SlnMesnac.Model.csproj
new file mode 100644
index 0000000..4f9d9b5
--- /dev/null
+++ b/SlnMesnac.Model/SlnMesnac.Model.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Model/domain/BaseMaterialInfo.cs b/SlnMesnac.Model/domain/BaseMaterialInfo.cs
new file mode 100644
index 0000000..c62d5aa
--- /dev/null
+++ b/SlnMesnac.Model/domain/BaseMaterialInfo.cs
@@ -0,0 +1,309 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Xml.Linq;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Model.domain
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Model.domain
+{
+
+
+ [SugarTable("BasMaterial"), TenantAttribute("mes")]
+ [DataContract(Name = "BasMaterial 物料信息")]
+ #pragma warning disable CS8618 // Non-nullable field 'Data' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
+ public class BaseMaterialInfo
+ {
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ObjID", IsPrimaryKey = true)]
+ public int ObjID { get; set; }
+ ///
+ /// 大类+小类+规格+胶代码或最后4顺序号
+ ///
+ [SugarColumn(ColumnName = "MaterialCode")]
+ public string MaterialCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MajorTypeID")]
+ public int? MajorTypeID { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MinorTypeID")]
+ public string MinorTypeID { get; set; }
+ ///
+ ///
+ /// 默认值: ('')
+ ///
+ [SugarColumn(ColumnName = "RubCode")]
+ public string RubCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MaterialName")]
+ public string MaterialName { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MaterialOtherName")]
+ public string MaterialOtherName { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MaterialSimpleName")]
+ public string MaterialSimpleName { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ProductMaterialCode")]
+ public string ProductMaterialCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MaterialLevel")]
+ public string MaterialLevel { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MaterialGroup")]
+ public string MaterialGroup { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "UserCode")]
+ public string UserCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "PlanPrice")]
+ public decimal? PlanPrice { get; set; }
+ ///
+ /// 具体到县级市,长度为6,国外的只具体国家
+ ///
+ [SugarColumn(ColumnName = "ProductArea")]
+ public string ProductArea { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MinStock")]
+ public decimal? MinStock { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "MaxStock")]
+ public decimal? MaxStock { get; set; }
+ ///
+ /// 千克,克,块,桶,升
+ ///
+ [SugarColumn(ColumnName = "UnitID")]
+ public int? UnitID { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "StaticUnitID")]
+ public int? StaticUnitID { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "StaticUnitCoefficient")]
+ public decimal? StaticUnitCoefficient { get; set; }
+ ///
+ /// 显为百分比
+ ///
+ [SugarColumn(ColumnName = "CheckPermitError")]
+ public decimal? CheckPermitError { get; set; }
+ ///
+ /// 按小时计算
+ ///
+ [SugarColumn(ColumnName = "MaxParkTime")]
+ public decimal? MaxParkTime { get; set; }
+ ///
+ /// 小时计算
+ ///
+ [SugarColumn(ColumnName = "MinParkTime")]
+ public decimal? MinParkTime { get; set; }
+ ///
+ ///
+ /// 默认值: (getdate())
+ ///
+ [SugarColumn(ColumnName = "DefineDate")]
+ public DateTime? DefineDate { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "StandardCode")]
+ public string StandardCode { get; set; }
+ ///
+ ///
+ /// 默认值: ((1))
+ ///
+ [SugarColumn(ColumnName = "StaticClass")]
+ public int? StaticClass { get; set; }
+ ///
+ ///
+ /// 默认值: ((0))
+ ///
+ [SugarColumn(ColumnName = "IsEqualMaterial")]
+ public string IsEqualMaterial { get; set; }
+ ///
+ ///
+ /// 默认值: ((0))
+ ///
+ [SugarColumn(ColumnName = "IsPutJar")]
+ public string IsPutJar { get; set; }
+ ///
+ ///
+ /// 默认值: ((1))
+ ///
+ [SugarColumn(ColumnName = "IsQualityRateCount")]
+ public string IsQualityRateCount { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ERPCode")]
+ public string ERPCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "Remark")]
+ public string Remark { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "DeleteFlag")]
+ public string DeleteFlag { get; set; }
+ ///
+ ///
+ /// 默认值: ((0))
+ ///
+ [SugarColumn(ColumnName = "ValidDate")]
+ public decimal ValidDate { get; set; }
+ ///
+ ///
+ /// 默认值: ((0))
+ ///
+ [SugarColumn(ColumnName = "ValidDateB")]
+ public decimal ValidDateB { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "SAPMaterialCode")]
+ public string SAPMaterialCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "SAPMaterialShortCode")]
+ public string SAPMaterialShortCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ERPCode_Bak")]
+ public string ErpcodeBak { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "OperSourceTemp")]
+ public string OperSourceTemp { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "IsQualityrateCountBak")]
+ public int? IsQualityrateCountBak { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "CMaterialLevel")]
+ public string CMaterialLevel { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "CMaterialGroup")]
+ public string CMaterialGroup { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "XBStock")]
+ public decimal? XBStock { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "HFCode")]
+ public string HFCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "HFCode2")]
+ public string HFCode2 { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "UNITName")]
+ public string UNITName { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "KFACSTATUS")]
+ public string Kfacstatus { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "Ordertype")]
+ public string Ordertype { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "CreateDate")]
+ public string CreateDate { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "UpdateDate")]
+ public string UpdateDate { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "UnAudit")]
+ public string UnAudit { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ChkStand")]
+ public string ChkStand { get; set; }
+ ///
+ /// 1 KG 2 PC 3 标准KG
+ /// 默认值: ((1))
+ ///
+ [SugarColumn(ColumnName = "SapUpUnit")]
+ public int? SapUpUnit { get; set; }
+ ///
+ /// 是否为轨道事业部物料:0:不是,1:是
+ ///
+ [SugarColumn(ColumnName = "IsGDMaterial")]
+ public int? IsGDMaterial { get; set; }
+ }
+}
diff --git a/SlnMesnac.Model/domain/BaseUser.cs b/SlnMesnac.Model/domain/BaseUser.cs
new file mode 100644
index 0000000..04dd56f
--- /dev/null
+++ b/SlnMesnac.Model/domain/BaseUser.cs
@@ -0,0 +1,131 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Security.Principal;
+using System.Text;
+using System.Xml.Linq;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Model.domain
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Model.domain
+{
+ ///
+ /// 系统基础资料-人员基础资料 yuany
+ ///
+ [SugarTable("BasUser"), TenantAttribute("mes")]
+ [DataContract(Name = "BaseUser 人员基础资料")]
+ #pragma warning disable CS8618 // Non-nullable field 'Data' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
+ public class BaseUser
+ {
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ObjID", IsPrimaryKey = true, IsIdentity = true)]
+ public int ObjID { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "UserName")]
+ public string UserName { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "UserPWD")]
+ public string UserPWD { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "RealName")]
+ public string RealName { get; set; }
+ ///
+ ///
+ /// 默认值: ((1))
+ ///
+ [SugarColumn(ColumnName = "Sex")]
+ public int? Sex { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "Telephone")]
+ public string Telephone { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "WorkBarcode")]
+ public string WorkBarcode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "DeptCode")]
+ public string DeptCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "WorkID")]
+ public int? WorkID { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ShiftID")]
+ public int? ShiftID { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "WorkShopID")]
+ public int? WorkShopID { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "HRCode")]
+ public string HRCode { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "ERPCode")]
+ public string ERPCode { get; set; }
+ ///
+ ///
+ /// 默认值: ((0))
+ ///
+ [SugarColumn(ColumnName = "DeleteFlag")]
+ public string DeleteFlag { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "Remark")]
+ public string Remark { get; set; }
+ ///
+ ///
+ /// 默认值: ((1))
+ ///
+ [SugarColumn(ColumnName = "IsEmployee")]
+ public string IsEmployee { get; set; }
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "RecordTime")]
+ public DateTime? RecordTime { get; set; }
+ }
+}
+
diff --git a/SlnMesnac.Model/dto/TagInfo.cs b/SlnMesnac.Model/dto/TagInfo.cs
new file mode 100644
index 0000000..d4f28b6
--- /dev/null
+++ b/SlnMesnac.Model/dto/TagInfo.cs
@@ -0,0 +1,40 @@
+using System;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Model.dto
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Model.dto
+{
+ #pragma warning disable CS8618 // Non-nullable field 'Data' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
+ public class TagInfo
+ {
+ public byte[] PC = new byte[2];
+ public int Count { get; set; }
+ public int RSSI{ get; set; }
+ public int Antana{ get; set; }
+ public byte[] EPC{ get; set; }
+ public byte[] Data{ get; set; }
+ public string PCstring = (string) null;
+ public string EPCstring = (string) null;
+ public DateTime Time{ get; set; }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Mqtt/MqttClient.cs b/SlnMesnac.Mqtt/MqttClient.cs
new file mode 100644
index 0000000..c80618e
--- /dev/null
+++ b/SlnMesnac.Mqtt/MqttClient.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using System.Threading;
+using MQTTnet.Client;
+using System.Security.Authentication;
+using MQTTnet;
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Serilog;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Mqtt
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Mqtt
+{
+ ///
+ /// MQTT客户端
+ ///
+ public class MqttClient
+ {
+ public readonly SerilogHelper _logger;
+
+ private IMqttClient _client;
+
+ public MqttClient(SerilogHelper logger)
+ {
+ _logger = logger;
+ }
+
+ ///
+ /// 链接服务器
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async void Connect(string ip, int port, string clientId, string username, string password)
+ {
+ try
+ {
+ MqttClientOptions options = new MqttClientOptionsBuilder()
+ .WithTcpServer(ip, port)
+ .WithClientId(clientId)
+ .WithCredentials(username, password)
+ .WithTls(o => //开启ssl
+ {
+ o.CertificateValidationHandler = _ => true;
+
+ o.SslProtocol = SslProtocols.Tls12;
+ })
+ .Build();
+ _client = new MqttFactory().CreateMqttClient();
+
+ _client.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceived;
+
+ MqttClientConnectResult result = await _client.ConnectAsync(options);
+
+ if (result != null)
+ {
+ if (result.ResultCode == MQTTnet.Client.MqttClientConnectResultCode.Success)
+ {
+ _logger.Info($"连接服务器成功{ip}:{port}");
+ }
+ else
+ {
+ _logger.Info($"连接服务器失败");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("连接服务器异常",ex);
+ }
+ }
+
+ ///
+ /// 断开链接
+ ///
+ public void DisConnect()
+ {
+ _client.DisconnectAsync();
+ _logger.Info($"断开连接");
+ }
+
+ ///
+ /// 订阅主题
+ ///
+ ///
+ public async void SubscriptionAsync(string topic)
+ {
+ try
+ {
+ var mqttFactory = new MqttFactory();
+ var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
+ .WithTopicFilter(
+ f =>
+ {
+ f.WithTopic(topic);
+ })
+ .Build();
+
+ MqttClientSubscribeResult result = await _client.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
+
+ _logger.Info($"订阅主题:{topic}");
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("订阅主题异常",ex);
+ }
+ }
+
+ ///
+ /// 取消订阅
+ ///
+ ///
+ public void Unsubscribe(string topic)
+ {
+ _client.UnsubscribeAsync(topic);
+ _logger.Info($"取消订阅,主题:{topic}");
+ }
+
+ ///
+ /// 推送消息
+ ///
+ ///
+ ///
+ public void Publish(string topic, string message)
+ {
+ try
+ {
+ var msg = new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(message)
+ .Build();
+ _client.PublishAsync(msg, CancellationToken.None);
+ _logger.Info($"向服务端推送成功,主题:{topic};内容:{message}");
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("向服务端推送消息异常",ex);
+ }
+ }
+
+ private async Task MqttClient_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs eventArgs)
+ {
+ var info = $"接收到主题:{eventArgs.ApplicationMessage.Topic}的消息,内容:{Encoding.UTF8.GetString(eventArgs.ApplicationMessage.Payload)}";
+ _logger.Info(info);
+ }
+
+ }
+}
diff --git a/SlnMesnac.Mqtt/SlnMesnac.Mqtt.csproj b/SlnMesnac.Mqtt/SlnMesnac.Mqtt.csproj
new file mode 100644
index 0000000..659191d
--- /dev/null
+++ b/SlnMesnac.Mqtt/SlnMesnac.Mqtt.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Plc/Factory/InovanceFactory.cs b/SlnMesnac.Plc/Factory/InovanceFactory.cs
new file mode 100644
index 0000000..d9eebc1
--- /dev/null
+++ b/SlnMesnac.Plc/Factory/InovanceFactory.cs
@@ -0,0 +1,346 @@
+using System;
+using HslCommunication;
+using HslCommunication.Profinet.Inovance;
+using SlnMesnac.Common;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Plc.Factory
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Plc.Factory
+{
+ public class InovanceFactory:PlcAbsractFactory
+ {
+ private StringChange _stringChange;
+
+ private InovanceTcpNet inovanceTcp = null;
+
+ public InovanceFactory(StringChange stringChange)
+ {
+ _stringChange = stringChange;
+
+ this.inovanceTcp = new InovanceTcpNet();
+ this.inovanceTcp.ConnectTimeOut = 2000;
+ }
+
+ public override bool IsConnected { get; set; }
+
+ ///
+ /// 建立连接
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool Connect(string ip, int port)
+ {
+ try
+ {
+ inovanceTcp?.ConnectClose();
+ if (inovanceTcp != null)
+ {
+ inovanceTcp.IpAddress = ip;
+ inovanceTcp.Port = port;
+ inovanceTcp.DataFormat = HslCommunication.Core.DataFormat.CDAB;
+
+ OperateResult connect = inovanceTcp.ConnectServer();
+ this.IsConnected = connect.IsSuccess;
+ if (!connect.IsSuccess)
+ {
+ throw new InvalidOperationException($"汇川PLC连接失败:{connect.Message}");
+ }
+
+ return connect.IsSuccess;
+ }
+ else
+ {
+ throw new ArgumentException($"汇川PLC实例inovanceTcp为null");
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"汇川PLC连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 断开连接
+ ///
+ ///
+ ///
+ public override bool DisConnect()
+ {
+ try
+ {
+ OperateResult disConnect = inovanceTcp.ConnectClose();
+ this.IsConnected = false;
+ if (!disConnect.IsSuccess)
+ {
+ throw new InvalidOperationException($"汇川PLC断开连接失败:{disConnect.Message}");
+ }
+ return disConnect.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"汇川PLC断开连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取指定长度数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override byte[] readValueByAddress(string address, int len)
+ {
+ try
+ {
+ OperateResult read = inovanceTcp.Read(address, (ushort)(len));
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据失败:{read.Message}");
+ }
+ return _stringChange.ConvertFloatToINt(read.Content);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取int16数据
+ ///
+ ///
+ ///
+ ///
+ public override int readInt16ByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = inovanceTcp.ReadInt16(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址写入int16数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeInt16ByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = new OperateResult();
+ int s = 0;
+ string[] strArry = address.Split('.');
+
+ //先读取整个块的内容
+ var info = inovanceTcp.ReadInt16(strArry[0]);
+ if (info.Content == 0)
+ {
+ int length = _stringChange.ParseToInt(strArry[1]) + 1;
+ string[] array = new string[length];
+ for (int i = 0; i < length; i++)
+ {
+ if (i == _stringChange.ParseToInt(strArry[1]))
+ {
+ array[i] = value.ToString();
+ }
+ else
+ {
+ array[i] = "0";
+ }
+ }
+ //反转
+ Array.Reverse(array);
+ byte[] buffer = new byte[array.Length];
+ string result = "";
+ for (int i = 0; i < array.Length; i++)
+ {
+ result += (byte)Convert.ToInt32(array[i], 16);
+ }
+ s = Convert.ToInt32(result.Trim(), 2);
+ operateResult = inovanceTcp.Write(strArry[0], (ushort)s);
+ }
+ else
+ {
+ var inf2 = Convert.ToString(info.Content, 2);
+ string[] infoArray = new string[inf2.Length];
+ for (int i = 0; i < inf2.Length; i++)
+ {
+ infoArray[i] = inf2.Substring(i, 1);
+ }
+ Array.Reverse(infoArray);
+ infoArray[_stringChange.ParseToInt(strArry[1])] = value.ToString();
+ string result = "";
+ foreach (var item in infoArray)
+ {
+ result = result + item;
+ }
+ s = Convert.ToInt32(result.Trim(), 10);
+ operateResult = inovanceTcp.Write(strArry[0], s);
+ }
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取string类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override string readStringByAddress(string address, ushort length)
+ {
+ try
+ {
+ OperateResult read = inovanceTcp.ReadString(address, length);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入String类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeStringByAddress(string address, string value)
+ {
+ try
+ {
+ OperateResult operateResult = inovanceTcp.Write(address, value);
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ public override bool readBoolByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = inovanceTcp.ReadBool(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeBoolByAddress(string address, bool value)
+ {
+ try
+ {
+ OperateResult operateResult = inovanceTcp.Write(address, short.Parse(_stringChange.ParseToInt(value ? "1" : "0").ToString()));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Double类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeDoubleByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = inovanceTcp.Write(address, Convert.ToDouble(value));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Plc/Factory/MelsecBinaryFactory.cs b/SlnMesnac.Plc/Factory/MelsecBinaryFactory.cs
new file mode 100644
index 0000000..28b9a8e
--- /dev/null
+++ b/SlnMesnac.Plc/Factory/MelsecBinaryFactory.cs
@@ -0,0 +1,287 @@
+using System;
+using HslCommunication;
+using HslCommunication.Profinet.Melsec;
+using SlnMesnac.Common;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Plc.Factory
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Plc.Factory
+{
+ public class MelsecBinaryFactory:PlcAbsractFactory
+ {
+ private StringChange _stringChange;
+
+ private MelsecMcNet melsec_net = null;
+
+ public MelsecBinaryFactory(StringChange stringChange)
+ {
+ _stringChange = stringChange;
+
+ this.melsec_net = new MelsecMcNet();
+ this.melsec_net.ConnectTimeOut = 2000;
+ }
+
+ public override bool IsConnected { get; set; }
+
+ ///
+ /// 建立连接
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool Connect(string iP, int port)
+ {
+ try
+ {
+ melsec_net.IpAddress = iP;
+ melsec_net.Port = port;
+ OperateResult connect = melsec_net.ConnectServer();
+ this.IsConnected = connect.IsSuccess;
+ if (!connect.IsSuccess)
+ {
+ throw new InvalidOperationException($"三菱PLC连接失败:{connect.Message}");
+ }
+
+ return connect.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"三菱PLC连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 断开连接
+ ///
+ ///
+ ///
+ public override bool DisConnect()
+ {
+ try
+ {
+ OperateResult disConnect = melsec_net.ConnectClose();
+ this.IsConnected = false;
+ if (!disConnect.IsSuccess)
+ {
+ throw new InvalidOperationException($"三菱PLC断开连接失败:{disConnect.Message}");
+ }
+ return disConnect.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"三菱PLC断开连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取指定长度数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override byte[] readValueByAddress(string address, int len)
+ {
+ try
+ {
+ OperateResult read = melsec_net.Read(address, (ushort)(len));
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据失败:{read.Message}");
+ }
+ return _stringChange.ConvertFloatToINt(read.Content);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取int16数据
+ ///
+ ///
+ ///
+ ///
+ public override int readInt16ByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = melsec_net.ReadInt16(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址写入int16数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeInt16ByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = melsec_net.Write(address, Convert.ToInt16(value));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取string类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override string readStringByAddress(string address, ushort length)
+ {
+ try
+ {
+ OperateResult read = melsec_net.ReadString(address, length);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入String类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeStringByAddress(string address, string value)
+ {
+ try
+ {
+ OperateResult operateResult = melsec_net.Write(address, value);
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ public override bool readBoolByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = melsec_net.ReadBool(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeBoolByAddress(string address, bool value)
+ {
+ try
+ {
+ OperateResult operateResult = melsec_net.Write(address, short.Parse(_stringChange.ParseToInt(value ? "1" : "0").ToString()));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Double类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeDoubleByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = melsec_net.Write(address, Convert.ToDouble(value));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Plc/Factory/OmronNJFactory.cs b/SlnMesnac.Plc/Factory/OmronNJFactory.cs
new file mode 100644
index 0000000..a3812e9
--- /dev/null
+++ b/SlnMesnac.Plc/Factory/OmronNJFactory.cs
@@ -0,0 +1,290 @@
+using System;
+using HslCommunication;
+using HslCommunication.Profinet.Omron;
+using SlnMesnac.Common;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Plc.Factory
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Plc.Factory
+{
+ public class OmronNJFactory:PlcAbsractFactory
+ {
+ private StringChange _stringChange;
+
+ private OmronFinsNet omronFinsNet = null;
+
+ public OmronNJFactory(StringChange stringChange)
+ {
+ _stringChange = stringChange;
+
+ this.omronFinsNet = new OmronFinsNet();
+ this.omronFinsNet.ConnectTimeOut = 2000;
+ }
+
+ public override bool IsConnected { get; set; }
+
+ ///
+ /// 建立连接
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool Connect(string iP, int port)
+ {
+ try
+ {
+ omronFinsNet.IpAddress = iP;
+ omronFinsNet.Port = 9600;
+ omronFinsNet.SA1 = (byte)192;
+ omronFinsNet.DA1 = (byte)239;
+ omronFinsNet.DA2 = (byte)0;
+ OperateResult connect = omronFinsNet.ConnectServer();
+ this.IsConnected = connect.IsSuccess;
+ if (!connect.IsSuccess)
+ {
+ throw new InvalidOperationException($"欧姆龙PLC连接失败:{connect.Message}");
+ }
+
+ return connect.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"欧姆龙PLC连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 断开连接
+ ///
+ ///
+ ///
+ public override bool DisConnect()
+ {
+ try
+ {
+ OperateResult disConnect = omronFinsNet.ConnectClose();
+ this.IsConnected = false;
+ if (!disConnect.IsSuccess)
+ {
+ throw new InvalidOperationException($"欧姆龙PLC断开连接失败:{disConnect.Message}");
+ }
+ return disConnect.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"欧姆龙PLC断开连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取指定长度数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override byte[] readValueByAddress(string address, int len)
+ {
+ try
+ {
+ OperateResult read = omronFinsNet.Read(address, (ushort)(len));
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据失败:{read.Message}");
+ }
+ return _stringChange.ConvertFloatToINt(read.Content);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取int16数据
+ ///
+ ///
+ ///
+ ///
+ public override int readInt16ByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = omronFinsNet.ReadInt16(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址写入int16数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeInt16ByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = omronFinsNet.Write(address, Convert.ToInt16(value));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取string类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override string readStringByAddress(string address, ushort length)
+ {
+ try
+ {
+ OperateResult read = omronFinsNet.ReadString(address, length);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入String类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeStringByAddress(string address, string value)
+ {
+ try
+ {
+ OperateResult operateResult = omronFinsNet.Write(address, value);
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ public override bool readBoolByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = omronFinsNet.ReadBool(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeBoolByAddress(string address, bool value)
+ {
+ try
+ {
+ OperateResult operateResult = omronFinsNet.Write(address, short.Parse(_stringChange.ParseToInt(value ? "1" : "0").ToString()));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Double类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeDoubleByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = omronFinsNet.Write(address, Convert.ToDouble(value));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Plc/Factory/SiemensFactory.cs b/SlnMesnac.Plc/Factory/SiemensFactory.cs
new file mode 100644
index 0000000..2e0ed6d
--- /dev/null
+++ b/SlnMesnac.Plc/Factory/SiemensFactory.cs
@@ -0,0 +1,287 @@
+using System;
+using HslCommunication;
+using HslCommunication.Profinet.Siemens;
+using SlnMesnac.Common;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Plc.Factory
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Plc.Factory
+{
+ public class SiemensFactory:PlcAbsractFactory
+ {
+
+ private StringChange _stringChange;
+
+ private const SiemensPLCS type = SiemensPLCS.S200Smart;
+
+ private SiemensS7Net s7 = new SiemensS7Net(type);
+
+ public SiemensFactory(StringChange stringChange)
+ {
+ _stringChange = stringChange;
+ }
+
+ public override bool IsConnected { get; set; }
+
+ ///
+ /// 建立连接
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool Connect(string iP, int port)
+ {
+ try
+ {
+ s7.IpAddress = iP;
+ s7.Port = 102;
+ OperateResult connect = s7.ConnectServer();
+ this.IsConnected = connect.IsSuccess;
+ if (!connect.IsSuccess)
+ {
+ throw new InvalidOperationException($"西门子S系列PLC连接失败:{connect.Message}");
+ }
+
+ return connect.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"西门子S系列PLC连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 断开连接
+ ///
+ ///
+ ///
+ public override bool DisConnect()
+ {
+ try
+ {
+ OperateResult disConnect = s7.ConnectClose();
+ this.IsConnected = false;
+ if (!disConnect.IsSuccess)
+ {
+ throw new InvalidOperationException($"西门子S系列PLC断开连接失败:{disConnect.Message}");
+ }
+ return disConnect.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"西门子S系列PLC断开连接异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取指定长度数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override byte[] readValueByAddress(string address, int len)
+ {
+ try
+ {
+ OperateResult read = s7.Read(address, (ushort)(len));
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据失败:{read.Message}");
+ }
+ return _stringChange.ConvertFloatToINt(read.Content);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取指定长度数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址读取int16数据
+ ///
+ ///
+ ///
+ ///
+ public override int readInt16ByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = s7.ReadInt16(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据地址写入int16数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeInt16ByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = s7.Write(address, Convert.ToInt16(value));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入int16数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取string类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override string readStringByAddress(string address, ushort length)
+ {
+ try
+ {
+ OperateResult read = s7.ReadString(address, length);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入String类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeStringByAddress(string address, string value)
+ {
+ try
+ {
+ OperateResult operateResult = s7.Write(address, value);
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入string数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址读取Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ public override bool readBoolByAddress(string address)
+ {
+ try
+ {
+ OperateResult read = s7.ReadBool(address);
+ if (!read.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据失败:{read.Content}");
+ }
+ return read.Content;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};读取bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Bool类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeBoolByAddress(string address, bool value)
+ {
+ try
+ {
+ OperateResult operateResult = s7.Write(address, short.Parse(_stringChange.ParseToInt(value ? "1" : "0").ToString()));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入bool数据异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 通过PLC地址写入Double类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool writeDoubleByAddress(string address, int value)
+ {
+ try
+ {
+ OperateResult operateResult = s7.Write(address, Convert.ToDouble(value));
+ if (!operateResult.IsSuccess)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据失败:{operateResult.Message}");
+ }
+ return operateResult.IsSuccess;
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Plc/PlcAbsractFactory.cs b/SlnMesnac.Plc/PlcAbsractFactory.cs
new file mode 100644
index 0000000..049cf0a
--- /dev/null
+++ b/SlnMesnac.Plc/PlcAbsractFactory.cs
@@ -0,0 +1,109 @@
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Plc
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Plc
+{
+ public abstract class PlcAbsractFactory
+ {
+
+ public string ConfigKey { get;set; }
+
+ ///
+ /// 是否连接
+ ///
+ public abstract bool IsConnected { get; set; }
+
+ ///
+ /// 建立连接
+ ///
+ ///
+ ///
+ ///
+ public abstract bool Connect(string ip, int port);
+
+ ///
+ /// 断开连接
+ ///
+ ///
+ public abstract bool DisConnect();
+
+ ///
+ /// 根据地址读取指定长度数据
+ ///
+ ///
+ ///
+ ///
+ public abstract byte[] readValueByAddress(string address,int len);
+
+ ///
+ /// 通过PLC地址读取int16类型数据
+ ///
+ ///
+ ///
+ public abstract int readInt16ByAddress(string address);
+
+ ///
+ /// 通过PLC地址写入int16类型数据
+ ///
+ ///
+ ///
+ ///
+ public abstract bool writeInt16ByAddress(string address,int value);
+
+ ///
+ /// 通过PLC地址读取string类型数据
+ ///
+ ///
+ ///
+ public abstract string readStringByAddress(string address, ushort length);
+
+ ///
+ /// 通过PLC地址写入String类型数据
+ ///
+ ///
+ ///
+ ///
+ public abstract bool writeStringByAddress(string address, string value);
+
+ ///
+ /// 通过PLC地址读取Bool类型数据
+ ///
+ ///
+ ///
+ public abstract bool readBoolByAddress(string address);
+
+ ///
+ /// 通过PLC地址写入Bool类型数据
+ ///
+ ///
+ ///
+ public abstract bool writeBoolByAddress(string address, bool value);
+
+ ///
+ /// 通过PLC地址写入Double类型数据
+ ///
+ ///
+ ///
+ ///
+ public abstract bool writeDoubleByAddress(string address, int value);
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Plc/SlnMesnac.Plc.csproj b/SlnMesnac.Plc/SlnMesnac.Plc.csproj
new file mode 100644
index 0000000..4074e53
--- /dev/null
+++ b/SlnMesnac.Plc/SlnMesnac.Plc.csproj
@@ -0,0 +1,19 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Quartz/Job/Job2.cs b/SlnMesnac.Quartz/Job/Job2.cs
new file mode 100644
index 0000000..cf4623c
--- /dev/null
+++ b/SlnMesnac.Quartz/Job/Job2.cs
@@ -0,0 +1,48 @@
+using Microsoft.Extensions.Logging;
+using Quartz;
+using SlnMesnac.Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Quartz.Job
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Quartz.Job
+{
+ internal class Job2 : IJob
+ {
+ private readonly SerilogHelper _logger;
+
+ public Job2(SerilogHelper logger)
+ {
+ _logger = logger;
+ }
+
+ public Task Execute(IJobExecutionContext context)
+ {
+ _logger.Info($"执行Job2:{DateTime.Now.ToString("HH:mm:ss")}");
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/SlnMesnac.Quartz/Job/MyJob.cs b/SlnMesnac.Quartz/Job/MyJob.cs
new file mode 100644
index 0000000..e12d7ba
--- /dev/null
+++ b/SlnMesnac.Quartz/Job/MyJob.cs
@@ -0,0 +1,48 @@
+using Microsoft.Extensions.Logging;
+using Quartz;
+using SlnMesnac.Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Quartz.Job
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Quartz.Job
+{
+ public class MyJob : IJob
+ {
+ private readonly SerilogHelper _logger;
+
+ public MyJob(SerilogHelper logger)
+ {
+ _logger = logger;
+ }
+
+ public Task Execute(IJobExecutionContext context)
+ {
+ _logger.Info($"执行MyJob:{DateTime.Now.ToString("HH:mm:ss")}");
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/SlnMesnac.Quartz/QuartzSetUp.cs b/SlnMesnac.Quartz/QuartzSetUp.cs
new file mode 100644
index 0000000..1a6bb23
--- /dev/null
+++ b/SlnMesnac.Quartz/QuartzSetUp.cs
@@ -0,0 +1,54 @@
+using Microsoft.Extensions.DependencyInjection;
+using Quartz;
+using SlnMesnac.Quartz.Job;
+using System;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Quartz
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Quartz
+{
+ public static class QuartzSetUp
+ {
+ [Obsolete]
+ public static void AddQuartzSetUp(this IServiceCollection services)
+ {
+ services.AddQuartz(q =>
+ {
+ q.UseMicrosoftDependencyInjectionJobFactory();
+
+ q.ScheduleJob(trigger =>
+ trigger.WithCronSchedule("*/3 * * * * ?").WithIdentity("MyJob", "MyJobGroup") // 示例:每3s执行一次
+ );
+
+ q.ScheduleJob(trigger =>
+ trigger.WithCronSchedule("*/5 * * * * ?").WithIdentity("Job2", "Job2Group") // 示例:每5s执行一次
+ );
+ });
+
+ services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
+
+ services.AddSingleton(provider => provider.GetRequiredService().GetScheduler().Result);
+
+ }
+ }
+}
diff --git a/SlnMesnac.Quartz/SlnMesnac.Quartz.csproj b/SlnMesnac.Quartz/SlnMesnac.Quartz.csproj
new file mode 100644
index 0000000..344e515
--- /dev/null
+++ b/SlnMesnac.Quartz/SlnMesnac.Quartz.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Redis/RedisHandler.cs b/SlnMesnac.Redis/RedisHandler.cs
new file mode 100644
index 0000000..7501351
--- /dev/null
+++ b/SlnMesnac.Redis/RedisHandler.cs
@@ -0,0 +1,93 @@
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Config;
+using SlnMesnac.Serilog;
+using StackExchange.Redis;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Redis
+* 唯一标识:00418016-53c9-4f87-a13f-daa19d656bba
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-12 15:15:25
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Redis
+{
+ public class RedisHandler
+ {
+ private SerilogHelper _logger;
+
+ private readonly AppConfig _appConfig;
+
+ private readonly ISubscriber _subscriber;
+
+ private readonly ConnectionMultiplexer redis;
+
+ public RedisHandler(AppConfig appConfig, SerilogHelper logger)
+ {
+ _appConfig = appConfig;
+
+ redis = ConnectionMultiplexer.Connect(_appConfig.redisConfig);
+ _subscriber = redis.GetSubscriber();
+ _logger = logger;
+ }
+
+
+
+ ///
+ /// 推送消息
+ ///
+ ///
+ ///
+ public void PublishMessage(string channel, string message)
+ {
+ long res = _subscriber.Publish(channel, message);
+
+ _logger.Info($"向主题:{channel};推送消息:{message};结果:{res}");
+ }
+
+ ///
+ /// 订阅消息
+ ///
+ ///
+ ///
+ public void SubscribeToChannel(string channel, Action onMessageReceived)
+ {
+ _subscriber.Subscribe(channel, (ch, message) =>
+ {
+ onMessageReceived(ch, message);
+ _logger.Info($"订阅主题:{channel};收到主题:{ch};推送的消息:{message}");
+ });
+ }
+
+ public void CleanExpiredMessages(string channel)
+ {
+ var redis = _subscriber.Multiplexer.GetDatabase();
+ redis.KeyDelete(channel);
+ }
+
+ public void SetValue(string key, string message)
+ {
+ IDatabase db = redis.GetDatabase(0);
+ TimeSpan expiry = TimeSpan.FromSeconds(10);
+ db.StringSet(key, message, expiry);
+ }
+ }
+}
diff --git a/SlnMesnac.Redis/SlnMesnac.Redis.csproj b/SlnMesnac.Redis/SlnMesnac.Redis.csproj
new file mode 100644
index 0000000..9d4e6d6
--- /dev/null
+++ b/SlnMesnac.Redis/SlnMesnac.Redis.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Repository/Repository.cs b/SlnMesnac.Repository/Repository.cs
new file mode 100644
index 0000000..7216a1c
--- /dev/null
+++ b/SlnMesnac.Repository/Repository.cs
@@ -0,0 +1,42 @@
+using SqlSugar;
+using System;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Repository
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Repository
+{
+ public class Repository : SimpleClient where T : class, new()
+ {
+ public ITenant itenant = null;//多租户事务、GetConnection、IsAnyConnection等功能
+
+ public Repository(ISqlSugarClient db)
+ {
+ itenant = db.AsTenant();//用来处理事务
+ base.Context = db.AsTenant().GetConnectionScopeWithAttr();//获取子Db
+
+ //如果不想通过注入多个仓储
+ //用到ChangeRepository或者Db.GetMyRepository需要看标题4写法
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Repository/SlnMesnac.Repository.csproj b/SlnMesnac.Repository/SlnMesnac.Repository.csproj
new file mode 100644
index 0000000..50714c1
--- /dev/null
+++ b/SlnMesnac.Repository/SlnMesnac.Repository.csproj
@@ -0,0 +1,20 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Repository/service/IBaseMaterialService.cs b/SlnMesnac.Repository/service/IBaseMaterialService.cs
new file mode 100644
index 0000000..5e3e59e
--- /dev/null
+++ b/SlnMesnac.Repository/service/IBaseMaterialService.cs
@@ -0,0 +1,62 @@
+using SlnMesnac.Model.domain;
+using SlnMesnac.Repository.service.@base;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Repository.service
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Repository.service
+{
+ public interface IBaseMaterialService : IBaseService
+ {
+
+ ///
+ /// 获取所有的物料信息
+ ///
+ ///
+ List GetMaterialInfos();
+
+ ///
+ /// 通过物料编码获取物料信息
+ ///
+ ///
+ ///
+ BaseMaterialInfo GetMaterialInfoByMaterialCode(string materialCode);
+
+ ///
+ /// 通过SAP物料编码获取物料信息
+ ///
+ ///
+ ///
+ BaseMaterialInfo GetMaterialInfoBySapMaterialCode(string sapMaterialCode);
+
+ ///
+ /// 通过物料类别获取物料信息
+ ///
+ /// 物料大类
+ /// 物料细类
+ ///
+ List GetMaterialInfosByMaterialType(int majorTypeId, string minorTypeId);
+ }
+}
diff --git a/SlnMesnac.Repository/service/IBaseUserService.cs b/SlnMesnac.Repository/service/IBaseUserService.cs
new file mode 100644
index 0000000..d1ece41
--- /dev/null
+++ b/SlnMesnac.Repository/service/IBaseUserService.cs
@@ -0,0 +1,46 @@
+using SlnMesnac.Model.domain;
+using SlnMesnac.Repository.service.@base;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Repository.service
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Repository.service
+{
+ public interface IBaseUserService:IBaseService
+ {
+ ///
+ /// 获取用户信息
+ ///
+ ///
+ List GetUsers();
+
+ ///
+ /// 验证添加用户信息,有一个错误时进行回滚
+ ///
+ ///
+ ///
+ bool InsertUsers(List users);
+ }
+}
diff --git a/SlnMesnac.Repository/service/Impl/BaseMaterialServiceImpl.cs b/SlnMesnac.Repository/service/Impl/BaseMaterialServiceImpl.cs
new file mode 100644
index 0000000..71e33bc
--- /dev/null
+++ b/SlnMesnac.Repository/service/Impl/BaseMaterialServiceImpl.cs
@@ -0,0 +1,132 @@
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Model.domain;
+using SlnMesnac.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Text;
+using SlnMesnac.Repository.service.@base;
+using SlnMesnac.Serilog;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Repository.service.Impl
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Repository.service.Impl
+{
+ public class BaseMaterialServiceImpl : BaseServiceImpl, IBaseMaterialService
+ {
+ private SerilogHelper _logger;
+
+ public BaseMaterialServiceImpl(Repository repository, SerilogHelper logger) :base(repository)
+ {
+ _logger = logger;
+ }
+
+ ///
+ /// 通过物料编码获取物料信息
+ ///
+ ///
+ ///
+ public BaseMaterialInfo GetMaterialInfoByMaterialCode(string materialCode)
+ {
+ BaseMaterialInfo materialInfo = null;
+ try
+ {
+ materialInfo = base._rep.GetFirst(x => x.MaterialCode == materialCode);
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"根据物料编号获取物料信息异常:{ex.Message}");
+ }
+ return materialInfo;
+ }
+
+ ///
+ /// 通过SAP物料编码获取物料信息
+ ///
+ ///
+ ///
+ public BaseMaterialInfo GetMaterialInfoBySapMaterialCode(string sapMaterialCode)
+ {
+ BaseMaterialInfo materialInfo = null;
+ try
+ {
+ materialInfo = base._rep.GetFirst(x => x.SAPMaterialCode == sapMaterialCode);
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"根据SAP物料编号获取物料信息异常:{ex.Message}");
+ }
+ return materialInfo;
+ }
+
+ ///
+ /// 获取所有的物料信息
+ ///
+ ///
+ public List GetMaterialInfos()
+ {
+ List materialInfos = null;
+ try
+ {
+ materialInfos = base._rep.GetList();
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"获取物料信息异常:{ex.Message}");
+ }
+ return materialInfos;
+ }
+
+ ///
+ /// 通过物料类别获取物料信息
+ ///
+ /// 物料大类
+ /// 物料细类
+ ///
+ public List GetMaterialInfosByMaterialType(int majorTypeId, string minorTypeId)
+ {
+ List materialInfos = null;
+ try
+ {
+ Expression> exp = x => true;
+
+ if (majorTypeId != 0)
+ {
+ exp = exp.And(x => x.MajorTypeID == majorTypeId);
+ }
+ else if (!string.IsNullOrEmpty(minorTypeId))
+ {
+ exp = exp.And(x => x.MinorTypeID == minorTypeId);
+ }
+
+ materialInfos = base._rep.GetList(exp);
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"通过物料类型获取物料信息异常:{ex.Message}");
+ }
+ return materialInfos;
+ }
+ }
+}
+
diff --git a/SlnMesnac.Repository/service/Impl/BaseUserServiceImpl.cs b/SlnMesnac.Repository/service/Impl/BaseUserServiceImpl.cs
new file mode 100644
index 0000000..1e33e08
--- /dev/null
+++ b/SlnMesnac.Repository/service/Impl/BaseUserServiceImpl.cs
@@ -0,0 +1,76 @@
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Model.domain;
+using SlnMesnac.Repository.service.@base;
+using SlnMesnac.Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Repository.service.Impl
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Repository.service.Impl
+{
+ public class BaseUserServiceImpl : BaseServiceImpl,IBaseUserService
+ {
+ private readonly SerilogHelper _logger;
+
+ public BaseUserServiceImpl(Repository rep, SerilogHelper logger) :base(rep)
+ {
+ _logger = logger;
+ }
+
+
+ public List GetUsers()
+ {
+ List users = null;
+ try
+ {
+ users = base._rep.GetList();
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"获取用户信息异常{ex.Message}");
+ }
+ return users;
+ }
+
+ public bool InsertUsers(List users)
+ {
+ bool result = false;
+ try
+ {
+ base._rep.AsTenant().BeginTran();
+
+ result = base._rep.InsertRange(users);
+
+ base._rep.AsTenant().CommitTran();
+ }
+ catch (Exception ex)
+ {
+ base._rep.AsTenant().RollbackTran();
+ _logger.Error($"用户信息添加异常:{ex.Message}");
+ }
+ return result;
+ }
+ }
+}
diff --git a/SlnMesnac.Repository/service/base/BaseServiceImpl.cs b/SlnMesnac.Repository/service/base/BaseServiceImpl.cs
new file mode 100644
index 0000000..2227110
--- /dev/null
+++ b/SlnMesnac.Repository/service/base/BaseServiceImpl.cs
@@ -0,0 +1,358 @@
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Repository.service.@base;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Repository.service.Impl
+* 唯一标识:70cc8c3a-2c3b-4034-894b-f1a4f04aa21e
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-08 09:49:07
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Repository.service.@base
+{
+ public class BaseServiceImpl : IBaseService where T : class, new()
+ {
+ public readonly Repository _rep;
+
+ public BaseServiceImpl(Repository rep)
+ {
+ _rep = rep;
+ }
+
+ ///
+ /// 添加实体信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool Insert(T model)
+ {
+ if (model == null)
+ {
+ throw new ArgumentNullException($"添加实体信息异常:实体参数为空");
+ }
+
+ try
+ {
+ return _rep.Insert(model);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"添加实体信息异常:{ex.Message}");
+ }
+
+ }
+
+ ///
+ /// 批量添加实体集合
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool Insert(List lisT)
+ {
+ if (lisT == null)
+ {
+ throw new ArgumentNullException($"批量添加实体集合异常:实体集合参数为空");
+ }
+ try
+ {
+ _rep.AsTenant().BeginTran();
+ var info = _rep.InsertRange(lisT);
+ _rep.AsTenant().CommitTran();
+ return true;
+ }
+ catch (Exception ex)
+ {
+ _rep.AsTenant().RollbackTran();
+ throw new InvalidOperationException($"批量添加实体集合异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据id 删除信息
+ ///
+ ///
+ ///
+ ///
+ public bool DeleteById(object id)
+ {
+ if (id == null)
+ {
+ throw new ArgumentNullException($"根据id删除信息异常:Id参数为空");
+ }
+ try
+ {
+ return _rep.DeleteById(id);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据id删除信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据实体删除信息
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool Delete(T model)
+ {
+ if (model == null)
+ {
+ throw new ArgumentNullException($"根据实体删除信息异常:实体参数为空");
+ }
+ try
+ {
+ return _rep.DeleteById(model);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据实体删除信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据实体集合批量删除信息
+ ///
+ ///
+ ///
+ ///
+ public bool Deletes(List entitys)
+ {
+ if (entitys == null)
+ {
+ throw new ArgumentNullException($"根据实体集合批量删除信息异常:实体集合参数为空");
+ }
+ try
+ {
+ return _rep.Delete(entitys);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据实体集合批量删除信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据实体更新信息
+ ///
+ ///
+ ///
+ ///
+ public bool Update(T model)
+ {
+ if (model == null)
+ {
+ throw new ArgumentNullException($"根据实体更新信息异常:实体参数为空");
+ }
+ try
+ {
+ return _rep.Update(model);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据实体更新信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 批量更新实体集合信息
+ ///
+ ///
+ ///
+ ///
+ public bool Update(List entitys)
+ {
+ if (entitys == null)
+ {
+ throw new ArgumentNullException($"批量更新实体集合信息异常:实体集合参数为空");
+ }
+
+ try
+ {
+ return _rep.UpdateRange(entitys);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"批量更新实体集合信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据Where条件更新实体信息
+ ///
+ ///
+ ///
+ ///
+ public bool Update(T entity, string strWhere)
+ {
+ if (entity == null)
+ {
+ throw new ArgumentNullException($"根据Where条件更新实体信息异常:实体参数为空");
+ }
+
+ if (string.IsNullOrEmpty(strWhere))
+ {
+ throw new ArgumentNullException($"根据Where条件更新实体信息异常:Where参数为空");
+ }
+
+ try
+ {
+ return _rep.AsUpdateable(entity).Where(strWhere).ExecuteCommandHasChange();
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据Where条件更新实体信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据实体更新指定列
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool Update(T entity, List lstColumns = null, List lstIgnoreColumns = null, string strWhere = "")
+ {
+ try
+ {
+ IUpdateable up = _rep.AsUpdateable(entity);
+ if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0)
+ {
+ up = up.IgnoreColumns(lstIgnoreColumns.ToArray());
+ }
+ if (lstColumns != null && lstColumns.Count > 0)
+ {
+ up = up.UpdateColumns(lstColumns.ToArray());
+ }
+ if (!string.IsNullOrEmpty(strWhere))
+ {
+ up = up.Where(strWhere);
+ }
+ return up.ExecuteCommandHasChange();
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据实体更新指定列异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 查询所有信息
+ ///
+ ///
+ ///
+ public List Query()
+ {
+ try
+ {
+ return _rep.GetList();
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"查询所有信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据Id查询实体
+ ///
+ ///
+ ///
+ ///
+ public T Query(object objId)
+ {
+ if (objId == null)
+ {
+ throw new ArgumentNullException($"根据Id查询实体信息异常:Id参数为空");
+ }
+ try
+ {
+ return _rep.GetById(objId);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据Id查询实体信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据表达式查询
+ ///
+ ///
+ ///
+ ///
+ public List Query(Expression> whereExpression)
+ {
+ if (whereExpression == null)
+ {
+ throw new ArgumentNullException($"根据表达式查询实体信息异常:表达式参数为空");
+ }
+ try
+ {
+ return _rep.GetList(whereExpression);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据表达式查询实体信息异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据表达式排序查询
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public List Query(Expression> whereExpression, Expression> orderByExpression, bool isAsc = true)
+ {
+ if (whereExpression == null)
+ {
+ throw new ArgumentNullException($"根据表达式排序查询信息异常:条件表达式参数为空");
+ }
+
+ if (orderByExpression == null)
+ {
+ throw new ArgumentNullException($"根据表达式排序查询信息异常:排序表达式参数为空");
+ }
+
+ try
+ {
+ return _rep.AsQueryable().OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).WhereIF(whereExpression != null, whereExpression).ToList();
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException($"根据表达式排序查询信息异常:{ex.Message}");
+ }
+ }
+ }
+}
diff --git a/SlnMesnac.Repository/service/base/IBaseService.cs b/SlnMesnac.Repository/service/base/IBaseService.cs
new file mode 100644
index 0000000..029ac99
--- /dev/null
+++ b/SlnMesnac.Repository/service/base/IBaseService.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Text;
+
+namespace SlnMesnac.Repository.service.@base
+{
+ public interface IBaseService where T : class
+ {
+ ///
+ /// 添加实体信息
+ ///
+ ///
+ ///
+ bool Insert(T model);
+
+ ///
+ /// 批量添加实体集合
+ ///
+ ///
+ ///
+ bool Insert(List lisT);
+
+ ///
+ /// 根据id 删除信息
+ ///
+ ///
+ ///
+ bool DeleteById(object id);
+
+ ///
+ /// 根据实体删除信息
+ ///
+ ///
+ ///
+ bool Delete(T model);
+
+ ///
+ /// 根据实体集合批量删除信息
+ ///
+ ///
+ ///
+ bool Deletes(List entitys);
+
+ ///
+ /// 根据实体更新信息
+ ///
+ ///
+ ///
+ bool Update(T model);
+
+ ///
+ /// 批量更新实体集合信息
+ ///
+ ///
+ ///
+ bool Update(List entitys);
+
+ ///
+ /// 根据Where条件更新实体信息
+ ///
+ ///
+ ///
+ ///
+ bool Update(T entity, string strWhere);
+
+ ///
+ /// 根据实体更新指定列
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool Update(T entity, List lstColumns = null, List lstIgnoreColumns = null, string strWhere = "");
+
+ ///
+ /// 查询所有信息
+ ///
+ ///
+ List Query();
+
+ ///
+ /// 根据Id查询实体
+ ///
+ ///
+ ///
+ T Query(object objId);
+
+ ///
+ /// 根据表达式查询
+ ///
+ ///
+ ///
+ List Query(Expression> whereExpression);
+
+ ///
+ /// 根据表达式排序查询
+ ///
+ /// 查询条件
+ /// 排序条件
+ /// 是否正序
+ ///
+ List Query(Expression> whereExpression, Expression> orderByExpression, bool isAsc = true);
+ }
+}
diff --git a/SlnMesnac.Rfid/Dto/MessagePack.cs b/SlnMesnac.Rfid/Dto/MessagePack.cs
new file mode 100644
index 0000000..284d42f
--- /dev/null
+++ b/SlnMesnac.Rfid/Dto/MessagePack.cs
@@ -0,0 +1,31 @@
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Rfid.Dto
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Rfid.Dto
+{
+ public class MessagePack
+ {
+ //public byte m_beginChar1 = 0xBB; //开始包
+ public byte[] m_pData = null; //发送数据
+ //public byte m_EndChar1 = 0x0D; //结束包
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Rfid/Enum/RecvState.cs b/SlnMesnac.Rfid/Enum/RecvState.cs
new file mode 100644
index 0000000..f9f1708
--- /dev/null
+++ b/SlnMesnac.Rfid/Enum/RecvState.cs
@@ -0,0 +1,43 @@
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Rfid.Enum
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Rfid.Enum
+{
+ public enum RecvState
+ {
+ //RFly-I160 返回数据 BB DD 00 01 40 41 0D
+ WaitingBeginChar1_State = 1, //等待接收帧同步字符1 0xBB
+ WaitingBeginChar2_State = 2, //等待接收帧同步字符2 0xDD
+ WaitingForBarcodeLength_State = 3, //等待条码长度不固定
+ WaitingForCode_State = 4, //等待指令编号Code 0x02
+ WaitingForStus_State = 5, //等待接受状态码 0x00
+ WaitingForTagCount_State = 6, //等待接受标签组数不固定
+ WaitingForCount_State = 7, //等待接收第一组标签读取次数 0x01
+ WaitingForRSSI_State = 8, //等待接收读取信号强度 0xCB
+ WaitingForAnt_State = 9, //等待接收天线端口 0x01
+ WaitingForPC1_State = 10, //等待接收EPC区域 0x00
+ WaitingForPC2_State = 11, //等待接收EPC区域 0x00
+ WaitingForData_State = 12, //等待接收数据字符
+ WaitingForXor_State = 13, //等待比对校验位
+ WaitingForEndChar_State = 14, //等待接收尾字符 0x0D
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Rfid/Factory/RflyFactory.cs b/SlnMesnac.Rfid/Factory/RflyFactory.cs
new file mode 100644
index 0000000..5d9e63b
--- /dev/null
+++ b/SlnMesnac.Rfid/Factory/RflyFactory.cs
@@ -0,0 +1,484 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Common;
+using SlnMesnac.Model.dto;
+using SlnMesnac.Rfid.Dto;
+using SlnMesnac.Rfid.Enum;
+using SlnMesnac.Serilog;
+using TouchSocket.Core;
+using TouchSocket.Sockets;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Rfid.Factory
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Rfid.Factory
+{
+ public class RflyFactory:RfidAbsractFactory
+ {
+ private SerilogHelper _logger;
+ private readonly TcpClient _tcpClient = new TcpClient();
+ private readonly StringChange _stringChange;
+
+ public RflyFactory(SerilogHelper logger,StringChange stringChange)
+ {
+ _logger = logger;
+ _stringChange = stringChange;
+ }
+
+ ///
+ /// 建立连接
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool Connect(string ip, int port)
+ {
+ try
+ {
+ _tcpClient.Setup(new TouchSocketConfig().SetRemoteIPHost($"{ip}:{port}"));
+ _tcpClient.Connect();
+ return true;
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException($"设备连接异常:{e.Message}");
+ }
+ }
+
+ ///
+ /// 按时间段盘点
+ ///
+ ///
+ ///
+ ///
+ public override List TimePeriodRead(int timeout = 5000)
+ {
+ byte[] u16byte = new byte[2];
+ byte[] bCRC = new byte[4];
+ try
+ {
+ #region 指令封装
+ MessagePack pMessagePack = new MessagePack();
+ pMessagePack.m_pData = new byte[8];
+ pMessagePack.m_pData[0] = 0xAA;
+ pMessagePack.m_pData[1] = 0x55;
+ pMessagePack.m_pData[2] = 0x02;
+ pMessagePack.m_pData[3] = 0x02;
+ u16byte = BitConverter.GetBytes(timeout); //超时时间
+ u16byte = _stringChange.Swap16Bytes(u16byte); //协议里为大端在前
+ Array.Copy(u16byte, 0, pMessagePack.m_pData, 4, 2);
+ Array.Copy(pMessagePack.m_pData, 2, bCRC, 0, 4);
+ pMessagePack.m_pData[6] = _stringChange.CalculateVerify(bCRC, bCRC.Length);
+ pMessagePack.m_pData[7] = 0x0D;
+ #endregion
+
+ var waitClient = _tcpClient.CreateWaitingClient(new WaitingOptions()
+ {
+ FilterFunc = response =>
+ {
+ return true;
+ }
+ });
+
+ byte[] reciveBuffer = waitClient.SendThenReturn(pMessagePack.m_pData, timeout);
+
+ _logger.Info($"接收原始报文:{_stringChange.bytesToHexStr(reciveBuffer,reciveBuffer.Length)}");
+
+ byte[] resultBuffer = PareReceiveBufferData(reciveBuffer,reciveBuffer.Length);
+
+ List tagInfoList = Device_DealTagInfoList(resultBuffer);
+
+ return tagInfoList;
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException($"按时间段盘点异常:{e.Message}");
+ }
+ }
+
+ #region 标签解析
+
+ ///
+ /// 状态机函数
+ ///
+ ///
+ ///
+ ///
+ ///
+ private byte[] PareReceiveBufferData(byte[] buffer, int iLen)
+ {
+ RecvState enumRecvState = RecvState.WaitingBeginChar1_State;
+ int m_iPosition = 0;
+ UInt16 m_iFullMessageLength = 0;
+ int iBarcodeLength = 0;//条码长度
+ ArrayList m_FrecvData = new ArrayList();
+ byte m_iVerify = 0;
+ try
+ {
+ var bufferStr = _stringChange.bytesToHexStr(buffer, iLen);
+ byte[] m_szFullMessage = new byte[iLen];
+ for (int i = 0; i < iLen; i++)
+ {
+ switch (enumRecvState)
+ {
+ case RecvState.WaitingBeginChar1_State: //开始接受数据帧1 0xBB
+ Array.Clear(m_szFullMessage, 0, iLen);//清空为0
+ if (buffer[i] == 0xBB)
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingBeginChar2_State;
+ }
+ else
+ {
+ m_iFullMessageLength = 0;
+ m_iPosition = 0;
+ enumRecvState = RecvState.WaitingBeginChar1_State;
+ }
+ break;
+ case RecvState.WaitingBeginChar2_State: //开始接受数据帧1 0xDD
+ if (buffer[i] == 0xDD)
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingForBarcodeLength_State;
+ }
+ else
+ {
+ m_iFullMessageLength = 0;
+ m_iPosition = 0;
+ enumRecvState = RecvState.WaitingBeginChar1_State;
+ }
+ break;
+ case RecvState.WaitingForBarcodeLength_State: //开始接受数据长度(TagCount - EPC)
+ m_szFullMessage[m_iPosition] = buffer[i];
+ iBarcodeLength = buffer[i]; //单组标签:18;两组标签:35
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingForCode_State;
+ break;
+
+ case RecvState.WaitingForCode_State: //开始接受指令编号
+ if (buffer[i] == 0x02)
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingForStus_State;
+ }
+ else if (buffer[i] == 0x90) // 如果是心跳BB DD 01 90 00 1F 8E 0D
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingForEndChar_State;
+ }
+ else if (buffer[i] == 0xBF) // 如果是心跳BB DD 04 BF 00 00 00 F9 0B 49 0D
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingForEndChar_State;
+ }
+ else
+ {
+ m_iFullMessageLength = 0;
+ m_iPosition = 0;
+ enumRecvState = RecvState.WaitingBeginChar1_State;
+ }
+ break;
+ case RecvState.WaitingForStus_State: //开始接受状态码
+ if (buffer[i] == 0x00)
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingForTagCount_State;
+ }
+ else if (buffer[i] == 0x40)
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ //LogService.Instance.Debug("RFU620等待接受WaitingForEndChar_State:Noread");
+ lock (m_FrecvData)
+ {
+ m_FrecvData.Add(m_szFullMessage);
+ }
+ m_iPosition = 0;
+ i = iLen;
+ enumRecvState = RecvState.WaitingBeginChar1_State;
+ //LogService.Instance.Debug("RFly-I160状态机结束。");
+ }
+ break;
+ case RecvState.WaitingForTagCount_State: //开始接受标签组数
+ Array.Copy(buffer, i, m_szFullMessage, m_iPosition, iBarcodeLength);//m_iPosition = 5
+ byte[] tempData = new byte[iBarcodeLength];
+ Array.Clear(tempData, 0, iBarcodeLength);
+ Array.Copy(buffer, i, tempData, 0, iBarcodeLength);
+ m_iPosition = m_iPosition + iBarcodeLength; //m_iPosition = 39
+ i = i + iBarcodeLength - 1; //i = 39
+ enumRecvState = RecvState.WaitingForXor_State;
+ break;
+ case RecvState.WaitingForXor_State: //开始比对校验位 Rfly160
+ byte[] m_CRCVerify = new byte[1024]; //此数组用于校验位计算
+ Array.Clear(m_CRCVerify, 0, m_CRCVerify.Length);
+ Array.Copy(m_szFullMessage, 2, m_CRCVerify, 0, iBarcodeLength + 3); //校验位计算是从Length - EPC 结束
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iVerify = m_szFullMessage[m_iPosition];
+ if (m_iVerify == _stringChange.CalculateVerify(m_CRCVerify, m_CRCVerify.Length))
+ {
+ m_iPosition++;
+ enumRecvState = RecvState.WaitingForEndChar_State;
+ }
+ else //如果校验不成功
+ {
+ m_iFullMessageLength = 0;
+ m_iPosition = 0;
+ enumRecvState = RecvState.WaitingBeginChar1_State;
+ }
+ break;
+ case RecvState.WaitingForEndChar_State:
+ if (buffer[0] == 0xBB && buffer[1] == 0xDD && buffer[2] == 0x00 && buffer[3] != 0x90) //此处为Noread数据显示
+ {
+ m_szFullMessage[0] = 0xBB;
+ m_szFullMessage[1] = 0xDD;
+ m_szFullMessage[2] = 0x00;
+ lock (m_FrecvData)
+ {
+ m_FrecvData.Add(m_szFullMessage);
+ }
+ m_iPosition = 0;
+ i = iLen;
+ enumRecvState = RecvState.WaitingBeginChar1_State;
+ }
+ else if (buffer[0] == 0xBB && buffer[1] == 0xDD && buffer[2] == 0x04 && buffer[3] == 0xBF)
+ {
+ Array.Copy(buffer, 0, m_szFullMessage, 0, 11);
+ i = 11;
+ lock (m_FrecvData)
+ {
+ m_FrecvData.Add(m_szFullMessage);
+ }
+ i = iLen;
+ }
+ else if (buffer[i] == 0x00) //获取温度
+ {
+ Array.Copy(buffer, 0, m_szFullMessage, 0, 8);
+ i = 8;
+ lock (m_FrecvData)
+ {
+ m_FrecvData.Add(m_szFullMessage);
+ }
+ i = iLen;
+ }
+ else if (buffer[i] == 0x11)
+ {
+ Array.Copy(buffer, 0, m_szFullMessage, 0, 7);
+ i = 7;
+ lock (m_FrecvData)
+ {
+ m_FrecvData.Add(m_szFullMessage);
+ }
+ }
+ else if (buffer[i] == 0x01)
+ {
+ Array.Copy(buffer, 0, m_szFullMessage, 0, 8);
+ i = 8;
+ lock (m_FrecvData)
+ {
+ m_FrecvData.Add(m_szFullMessage);
+ }
+ }
+ else
+ {
+ m_szFullMessage[m_iPosition] = buffer[i];
+ m_iPosition++;
+ if (buffer[i] == 0x0D)
+ {
+ lock (m_FrecvData)
+ {
+ m_FrecvData.Add(m_szFullMessage);
+ }
+ }
+ }
+ m_iPosition = 0;
+ enumRecvState = RecvState.WaitingBeginChar1_State;
+ break;
+ }
+ }
+
+ return m_szFullMessage;
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException($"状态机逻辑处理异常:{e.Message}");
+ }
+ }
+
+ private Mutex mutauto = new Mutex();
+ ///
+ /// 解析函数
+ ///
+ ///
+ ///
+ ///
+ public List Device_DealTagInfoList(byte[] AutoDealReportData)
+ {
+ List tagInfoList = new List();
+ byte[] bResultEPC_Data = new byte[14];
+ byte[] m_AutoReadEPC = null;
+ int m_readEPCDataLen = 0;
+ try
+ {
+ mutauto.WaitOne();
+ int iFirstCountPos = 6; //第一次读取标签次数位置
+ int iFirstRSSIPos = 7; //第一次读取标签强度位置
+ int iFirstAnt = 8;
+ int iFirstPC = 9; //第一次读取标签天线位置
+ int iFirstLeftBarcketPos = 11;//EPC数据起始位置
+ UInt16 tempDataCount = 0;
+ int tempDataRSSI = 0;
+ UInt16 tempDataANT = 0;
+ int iBarcodeGroupCount = Convert.ToInt32(AutoDealReportData[5].ToString()); //标签组数
+ int iBarcodeLength = 16; //标签长度
+ int iCommonSecondFlag = 0;
+ for (int j = 0; j < iBarcodeGroupCount; j++)
+ {
+ TagInfo tag = new TagInfo();
+ byte[] tempPCByte = new byte[2]; //取出PC
+ Array.Clear(tempPCByte, 0, 2);
+ Array.Copy(AutoDealReportData, iFirstPC, tempPCByte, 0, 2);
+
+ int pc = Convert.ToInt32(tempPCByte[0].ToString("X"));
+ int epcLength = EPCLengthByPC(pc);
+ iBarcodeLength = epcLength;
+
+ byte[] tempDataByte = new byte[epcLength];
+ Array.Clear(tempDataByte, 0, iBarcodeLength);
+ Array.Copy(AutoDealReportData, iFirstLeftBarcketPos, tempDataByte, 0, iBarcodeLength);
+
+ byte[] tempCountByte = new byte[1]; //取出标签次数
+ Array.Clear(tempCountByte, 0, 1);
+ Array.Copy(AutoDealReportData, iFirstCountPos, tempCountByte, 0, 1);
+ tempDataCount = tempCountByte[0];
+
+ byte[] tempRSSIByte = new byte[1]; //取出标签强度
+ Array.Clear(tempRSSIByte, 0, 1);
+ Array.Copy(AutoDealReportData, iFirstRSSIPos, tempRSSIByte, 0, 1);
+
+ tempDataRSSI = _stringChange.HexStringToNegative(_stringChange.bytesToHexStr(tempRSSIByte, 1));
+
+ #region add by wenjy 20220829 取出天线号
+ byte[] tempAntByte = new byte[1]; //取出天线号
+ Array.Clear(tempAntByte, 0, 1);
+ Array.Copy(AutoDealReportData, iFirstAnt, tempAntByte, 0, 1);
+ tempDataANT = tempAntByte[0];
+ #endregion
+
+ tag.Count = tempDataCount;
+ tag.RSSI = tempDataRSSI;
+ tag.EPC = tempDataByte;
+
+ if (pc == 24)
+ {
+ tag.EPCstring = _stringChange.bytesToHexStr(tempDataByte, tempDataByte.Length).Substring(0, 7);
+ }
+ else
+ {
+ tag.EPCstring = Encoding.ASCII.GetString(tempDataByte);
+ }
+
+ tag.PC = tempPCByte;
+ tag.Antana = tempDataANT;
+ tagInfoList.Add(tag);
+ int iBarcodeListLen = tagInfoList.Count; //特别注意,必须这样,要不然会多一条数据
+
+ iFirstCountPos = iFirstCountPos + iBarcodeLength + 5; //次数
+ iFirstRSSIPos = iFirstCountPos + 1; //强度
+ iFirstAnt = iFirstRSSIPos + 1; //天线
+ iFirstPC = iFirstAnt + 1;
+ iFirstLeftBarcketPos = iFirstLeftBarcketPos + iBarcodeLength + 5;
+
+ _logger.Info("----函数调用:Device_DealTagInfoList 第[" + (iCommonSecondFlag + 1) + "]次数据解析为:" + tag.EPCstring + ",读取标签次数:[" + tempDataCount + "],标签信号强度:[" + tempDataRSSI + "],天线号:[" + tempDataANT + "]");
+ iCommonSecondFlag++;
+ if (iCommonSecondFlag == iBarcodeGroupCount)
+ {
+ mutauto.ReleaseMutex();
+ _logger.Info("《《《返回标签数据!");
+ return tagInfoList;
+ }
+ }
+ return tagInfoList;
+ }
+ catch (Exception ex)
+ {
+ mutauto.ReleaseMutex();
+ throw new InvalidOperationException($"Device_AutoDealContent 自动处理函数异常:{ex.Message}");
+ }
+ }
+
+ ///
+ /// 根据PC获取EPC长度
+ ///
+ ///
+ ///
+ private int EPCLengthByPC(int pcValue)
+ {
+ int epcLength = 0;
+ if (pcValue >= 10 && pcValue < 20)
+ {
+ epcLength = 4;
+ }
+ else if (pcValue >= 20 && pcValue < 30)
+ {
+ epcLength = 8;
+ }
+ else if (pcValue >= 30 && pcValue < 40)
+ {
+ epcLength = 12;
+ }
+ else if (pcValue >= 40 && pcValue < 50)
+ {
+ epcLength = 16;
+ }
+ else if (pcValue >= 50 && pcValue < 60)
+ {
+ epcLength = 20;
+ }
+ else if (pcValue >= 60 && pcValue < 70)
+ {
+ epcLength = 24;
+ }
+ else if (pcValue >= 70 && pcValue < 80)
+ {
+ epcLength = 28;
+ }
+ else if (pcValue >= 80 && pcValue < 90)
+ {
+ epcLength = 30;
+ }
+ return epcLength;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Rfid/RfidAbsractFactory.cs b/SlnMesnac.Rfid/RfidAbsractFactory.cs
new file mode 100644
index 0000000..2a2c1b7
--- /dev/null
+++ b/SlnMesnac.Rfid/RfidAbsractFactory.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using SlnMesnac.Model.dto;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Rfid
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Rfid
+{
+ ///
+ /// RFID抽象工厂
+ ///
+ public abstract class RfidAbsractFactory
+ {
+
+ public string ConfigKey { get; set; }
+
+ ///
+ /// 建立连接
+ ///
+ ///
+ ///
+ ///
+ public abstract bool Connect(string ip, int port);
+
+ ///
+ /// 按时间段盘点
+ ///
+ ///
+ ///
+ public abstract List TimePeriodRead(int timeout = 5000);
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Rfid/SlnMesnac.Rfid.csproj b/SlnMesnac.Rfid/SlnMesnac.Rfid.csproj
new file mode 100644
index 0000000..ac2b62d
--- /dev/null
+++ b/SlnMesnac.Rfid/SlnMesnac.Rfid.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.Serilog/SerilogExtensions.cs b/SlnMesnac.Serilog/SerilogExtensions.cs
new file mode 100644
index 0000000..87a5374
--- /dev/null
+++ b/SlnMesnac.Serilog/SerilogExtensions.cs
@@ -0,0 +1,69 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Serilog;
+using Serilog.Events;
+using SlnMesnac.Config;
+using System;
+using System.IO;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.Serilog
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Serilog
+{
+ ///
+ /// Serilog
+ ///
+ public static class SerilogExtensions
+ {
+ public static void UseSerilogExtensions(this IServiceProvider service)
+ {
+ #region 通过配置文件读取日志存放位置
+ var appConfig = service.GetService();
+ var logPath = $"{appConfig.logPath}/Logs/";
+
+ #endregion
+
+ //Log.Logger = new LoggerConfiguration().MinimumLevel.Information().WriteTo.Console()
+ // .WriteTo.File(Path.Combine(logPath, "Info.log"), LogEventLevel.Information)
+ // .WriteTo.File(Path.Combine(logPath, "Error.log"), LogEventLevel.Error)
+ // .WriteTo.File(Path.Combine(logPath, "Warn.log"), LogEventLevel.Warning)
+ // //.WriteTo.File(Path.Combine(logPath, "Debug.log"), LogEventLevel.Debug, fileSizeLimitBytes: 5 * 1024)
+ // .CreateLogger();
+
+ Log.Logger = new LoggerConfiguration().MinimumLevel.Information().WriteTo.Console()
+ .WriteTo.Logger(lc => lc
+ .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Info"))
+ .WriteTo.File(Path.Combine($"{logPath}/Info/", "Info.log"), rollingInterval: RollingInterval.Day))
+ .WriteTo.Logger(lc => lc
+ .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Plc"))
+ .WriteTo.File(Path.Combine($"{logPath}/Plc/", "Plc.log"), rollingInterval: RollingInterval.Day))
+ .WriteTo.Logger(lc => lc
+ .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Camera"))
+ .WriteTo.File(Path.Combine($"{logPath}/Camera/", "Camera.log"), rollingInterval: RollingInterval.Day))
+ .WriteTo.Logger(lc => lc
+ .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Error"))
+ .WriteTo.File(Path.Combine($"{logPath}/Error/", "Error.log"), rollingInterval: RollingInterval.Day))
+ .CreateLogger();
+ }
+ }
+}
diff --git a/SlnMesnac.Serilog/SerilogHelper.cs b/SlnMesnac.Serilog/SerilogHelper.cs
new file mode 100644
index 0000000..fc542a8
--- /dev/null
+++ b/SlnMesnac.Serilog/SerilogHelper.cs
@@ -0,0 +1,108 @@
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:T14-GEN3-7895
+* 命名空间:SlnMesnac.Serilog
+* 唯一标识:fae9d68d-1992-4a03-b299-19edd9fc786d
+*
+* 创建者:WenJY
+* 电子邮箱:
+* 创建时间:2024-12-26 8:46:21
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.Serilog
+{
+ ///
+ /// Serilog日志类
+ ///
+ public class SerilogHelper
+ {
+ private readonly ILogger? Info_logger = Log.ForContext("Module", "Info");
+ private readonly ILogger? Plc_logger = Log.ForContext("Module", "Plc");
+ private readonly ILogger? Error_logger = Log.ForContext("Module", "Error");
+ private readonly ILogger? Camera_logger = Log.ForContext("Module", "Camera");
+
+ ///
+ /// Info日志
+ ///
+ ///
+ public void Info(string msg)
+ {
+ if (Info_logger != null)
+ {
+ this.Info_logger.Information(msg);
+ }
+ }
+
+ ///
+ /// Plc日志
+ ///
+ ///
+ public void Plc(string msg)
+ {
+ if (Plc_logger != null)
+ {
+ this.Plc_logger.Information(msg);
+ }
+ }
+
+ ///
+ /// 相机日志
+ ///
+ ///
+ public void Camera(string msg)
+ {
+ if (Camera_logger != null)
+ {
+ this.Camera_logger.Information(msg);
+ }
+ }
+
+ ///
+ /// Error日志
+ ///
+ ///
+ ///
+ public void Error(string msg, Exception ex = null)
+ {
+ if (!string.IsNullOrEmpty(msg) && ex == null)
+ {
+ this.Error_logger.Information("【附加信息】 : {0}
", new object[] { msg });
+ }
+ else if (!string.IsNullOrEmpty(msg) && ex != null)
+ {
+ string errorMsg = BeautyErrorMsg(ex);
+ this.Error_logger.Information("【附加信息】 : {0}
{1}", new object[] { msg, errorMsg });
+ }
+ else if (string.IsNullOrEmpty(msg) && ex != null)
+ {
+ string errorMsg = BeautyErrorMsg(ex);
+ this.Error_logger.Information(errorMsg);
+ }
+ }
+
+ private string BeautyErrorMsg(Exception ex)
+ {
+ string errorMsg = string.Format("【异常类型】:{0}
【异常信息】:{1}
【堆栈调用】:{2}", new object[] { ex.GetType().Name, ex.Message, ex.StackTrace });
+ errorMsg = errorMsg.Replace("\r\n", "
");
+ errorMsg = errorMsg.Replace("位置", "位置");
+ return errorMsg;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.Serilog/SlnMesnac.Serilog.csproj b/SlnMesnac.Serilog/SlnMesnac.Serilog.csproj
new file mode 100644
index 0000000..2377389
--- /dev/null
+++ b/SlnMesnac.Serilog/SlnMesnac.Serilog.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.TouchSocket/ApiServer.cs b/SlnMesnac.TouchSocket/ApiServer.cs
new file mode 100644
index 0000000..d704959
--- /dev/null
+++ b/SlnMesnac.TouchSocket/ApiServer.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TouchSocket.Rpc;
+using TouchSocket.WebApi;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:T14-GEN3-7895
+* 命名空间:SlnMesnac.TouchSocket
+* 唯一标识:649766cc-308e-4bf3-8d69-dea48ec40642
+*
+* 创建者:WenJY
+* 电子邮箱:
+* 创建时间:2024-09-04 10:51:54
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.TouchSocket
+{
+ public class ApiServer: RpcServer
+ {
+
+ public delegate void RefreshScanInfoInCenterStart();
+ ///
+ /// 入库开始事件刷新
+ ///
+ public event RefreshScanInfoInCenterStart RefreshScanInfoInCenterStartEvent;
+
+ public delegate void RefreshScanInfoInCenterStop();
+ ///
+ /// 入库结束事件刷新
+ ///
+ public event RefreshScanInfoInCenterStop RefreshScanInfoInCenterStopEvent;
+
+ public delegate void RefreshScanInfoOutCenterStart();
+ ///
+ /// 出库开始事件刷新
+ ///
+ public event RefreshScanInfoOutCenterStart RefreshScanInfoOutCenterStartEvent;
+
+ public delegate void RefreshScanInfoOutCenterStop();
+ ///
+ /// 出库结束事件刷新
+ ///
+ public event RefreshScanInfoOutCenterStop RefreshScanInfoOutCenterStopEvent;
+
+ ///
+ /// 入库开始
+ ///
+ ///
+ ///
+ [EnableCors("cors")]
+ [WebApi(HttpMethodType.POST)]
+ public object getScanInfoInCenterStart(string messageHeader)
+ {
+ RefreshScanInfoInCenterStartEvent?.Invoke();
+ return true;
+ }
+
+ ///
+ /// 入库结束
+ ///
+ ///
+ ///
+ [EnableCors("cors")]
+ [WebApi(HttpMethodType.POST)]
+ public object getScanInfoInCenterStop(string messageHeader)
+ {
+ RefreshScanInfoInCenterStopEvent?.Invoke();
+ return true;
+ }
+
+ ///
+ /// 出库开始
+ ///
+ ///
+ ///
+ [WebApi(HttpMethodType.POST)]
+ public object getScanInfoOutCenterStart(string messageHeader)
+ {
+ RefreshScanInfoOutCenterStartEvent?.Invoke();
+ return true;
+ }
+
+ ///
+ /// 出库结束
+ ///
+ ///
+ ///
+ [WebApi(HttpMethodType.POST)]
+ public object getScanInfoOutCenterStop(string messageHeader)
+ {
+ RefreshScanInfoOutCenterStopEvent?.Invoke();
+ return true;
+ }
+
+ }
+}
diff --git a/SlnMesnac.TouchSocket/SlnMesnac.TouchSocket.csproj b/SlnMesnac.TouchSocket/SlnMesnac.TouchSocket.csproj
new file mode 100644
index 0000000..94f69ee
--- /dev/null
+++ b/SlnMesnac.TouchSocket/SlnMesnac.TouchSocket.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.TouchSocket/TcpServer.cs b/SlnMesnac.TouchSocket/TcpServer.cs
new file mode 100644
index 0000000..f62e138
--- /dev/null
+++ b/SlnMesnac.TouchSocket/TcpServer.cs
@@ -0,0 +1,115 @@
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TouchSocket.Core;
+using TouchSocket.Sockets;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.TouchSocket
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.TouchSocket
+{
+ public class TcpServer
+ {
+ private SerilogHelper _logger;
+ private readonly TcpService _service;
+ ///
+ /// 接收客户端指令委托
+ ///
+ public delegate void ReceivedClientBuffer(byte[] buffer);
+ public event ReceivedClientBuffer? ReceivedClientBufferEvent;
+
+ public delegate void RefreshClientInfo(TcpService tcpService);
+ public event RefreshClientInfo? RefreshClientInfoEvent;
+
+ public TcpServer(SerilogHelper logger, TcpService tcpService)
+ {
+ _logger = logger;
+ _service = tcpService;
+ }
+
+ public void Init(int serverPort)
+ {
+ try
+ {
+ _service.Connecting = (client, e) => {
+ _logger.Info($"客户端{client.IP}正在接入服务");
+ return EasyTask.CompletedTask;
+ };
+ _service.Connected = (client, e) => {
+ _logger.Info($"客户端{client.IP}接入服务成功");
+ RefreshClientInfoEvent?.Invoke(_service);
+ return EasyTask.CompletedTask;
+ };
+ _service.Disconnected = (client, e) => {
+ _logger.Info($"客户端{client.IP}断开连接");
+ RefreshClientInfoEvent?.Invoke(_service);
+ return EasyTask.CompletedTask;
+ };
+ _service.Received = (client, e) =>
+ {
+ //从客户端收到信息
+ var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意:数据长度是byteBlock.Len
+
+ byte[] receivedBuffer = new byte[e.ByteBlock.Len];
+ Array.Copy(e.ByteBlock.Buffer, 0, receivedBuffer, 0, e.ByteBlock.Len);
+ ReceivedClientBufferEvent?.Invoke(receivedBuffer);
+
+ return EasyTask.CompletedTask;
+ };
+
+ _service.Setup(new TouchSocketConfig()//载入配置
+ .SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })
+ .ConfigureContainer(a =>//容器的配置顺序应该在最前面
+ {
+ a.AddConsoleLogger();
+ })
+ .ConfigurePlugins(a =>
+ {
+ //自定义插件
+ }));
+ _service.Start();
+ _logger.Info($"TcpServer启动成功,监听端口:{serverPort}");
+ }
+ catch (Exception ex)
+ {
+ //throw new InvalidOperationException($"TcpServer启动异常:{ex.Message}");
+ _logger.Error($"TcpServer启动异常:{ex.Message}");
+ }
+
+ }
+
+ ///
+ /// 向所有客户端发送心跳
+ ///
+ public void SendHeartBeat()
+ {
+ var clients = _service.SocketClients.GetClients();
+ foreach (var item in clients)
+ {
+ _service.Send(item.Id,"heartbeat");
+ }
+ }
+ }
+}
diff --git a/SlnMesnac.TouchSocket/TouchSocketSetup.cs b/SlnMesnac.TouchSocket/TouchSocketSetup.cs
new file mode 100644
index 0000000..637d77f
--- /dev/null
+++ b/SlnMesnac.TouchSocket/TouchSocketSetup.cs
@@ -0,0 +1,48 @@
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.AspNetCore.Builder;
+using TouchSocket.Sockets;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.TouchSocket
+* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-03-27 21:58:35
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.TouchSocket
+{
+ ///
+ /// 注册服务
+ ///
+ public static class TouchSocketSetup
+ {
+
+ public static IApplicationBuilder UseTouchSocketExtensions(this IApplicationBuilder app)
+ {
+ var _server = app.ApplicationServices.GetService();
+ _server.Init(20108);
+
+ var _apiServer = app.ApplicationServices.GetService();
+ _apiServer.Init();
+ return app;
+ }
+ }
+}
\ No newline at end of file
diff --git a/SlnMesnac.TouchSocket/WebApiServer.cs b/SlnMesnac.TouchSocket/WebApiServer.cs
new file mode 100644
index 0000000..7c85740
--- /dev/null
+++ b/SlnMesnac.TouchSocket/WebApiServer.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using TouchSocket.Core;
+using TouchSocket.Http;
+using TouchSocket.Rpc;
+using TouchSocket.Sockets;
+using TouchSocket.WebApi.Swagger;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:T14-GEN3-7895
+* 命名空间:SlnMesnac.TouchSocket
+* 唯一标识:4e47989b-9d43-426e-b67a-529de3b1b0e8
+*
+* 创建者:WenJY
+* 电子邮箱:
+* 创建时间:2024-09-04 10:51:29
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.TouchSocket
+{
+ public class WebApiServer
+ {
+ private ApiServer _apiServer;
+
+ public WebApiServer(ApiServer apiServer)
+ {
+ _apiServer = apiServer;
+ }
+
+ public void Init()
+ {
+ try
+ {
+ var service = new HttpService();
+ service.Setup(new TouchSocketConfig()
+ .SetListenIPHosts(7789)
+ .ConfigureContainer(a =>
+ {
+ a.AddRpcStore(store =>
+ {
+
+ store.RegisterServer(_apiServer);//注册服务
+ });
+
+ a.AddCors(corsOption =>
+ {
+ corsOption.Add("cors", corsBuilder =>
+ {
+ corsBuilder.AllowAnyMethod()
+ .AllowAnyOrigin();
+ });
+ });
+
+ a.AddLogger(logger =>
+ {
+ logger.AddConsoleLogger();
+ logger.AddFileLogger();
+ });
+ })
+ .ConfigurePlugins(a =>
+ {
+ a.UseCheckClear();
+
+ a.Add();
+
+ a.UseWebApi()
+ .ConfigureConverter(converter =>
+ {
+ converter.AddJsonSerializerFormatter(new Newtonsoft.Json.JsonSerializerSettings() { Formatting = Newtonsoft.Json.Formatting.None });
+ });
+
+ a.UseSwagger();//使用Swagger页面
+ //.UseLaunchBrowser();
+
+ a.UseDefaultHttpServicePlugin();
+ }));
+ service.Start();
+
+ Console.WriteLine("以下连接用于测试webApi");
+ Console.WriteLine($"使用:http://127.0.0.1:7789/swagger/index.html");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.ToString());
+ }
+
+ //Console.ReadLine();
+ }
+ }
+
+ internal class AuthenticationPlugin : PluginBase, IHttpPlugin
+ {
+ public async Task OnHttpRequest(IHttpSocketClient client, HttpContextEventArgs e)
+ {
+ await e.InvokeNext();
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/App.xaml b/SlnMesnac.WPF/App.xaml
new file mode 100644
index 0000000..05764b6
--- /dev/null
+++ b/SlnMesnac.WPF/App.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.WPF/App.xaml.cs b/SlnMesnac.WPF/App.xaml.cs
new file mode 100644
index 0000000..72661c5
--- /dev/null
+++ b/SlnMesnac.WPF/App.xaml.cs
@@ -0,0 +1,155 @@
+using Lierda.WPFHelper;
+using Microsoft.Extensions.DependencyInjection;
+using Serilog;
+using SlnMesnac.Config;
+using System;
+using System.Windows;
+using Microsoft.Extensions.Configuration;
+using SlnMesnac.Extensions;
+using SlnMesnac.Serilog;
+using System.Reflection;
+using TouchSocket.Sockets;
+using SlnMesnac.WPF.Attribute;
+using SlnMesnac.WPF.Page.Login;
+
+namespace SlnMesnac.WPF
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ private System.Threading.Mutex? mutex = null;
+ private LierdaCracker cracker = new LierdaCracker();
+ public static IServiceProvider? ServiceProvider = null;
+
+ public new static App Current => (App)Application.Current;
+
+ // Startup事件
+ protected override async void OnStartup(StartupEventArgs e)
+ {
+
+ this.DispatcherUnhandledException += App_DispatcherUnhandledException; //全局异常处理
+
+ #region 进程判断,避免重复开启
+ bool ret;
+ mutex = new System.Threading.Mutex(true, System.Diagnostics.Process.GetCurrentProcess().ProcessName, out ret);
+ if (!ret)
+ {
+ MessageBox.Show("应用程序已开启,禁止重复运行");
+ Environment.Exit(0);
+ }
+ #endregion
+
+ cracker.Cracker(100); //设置GC回收间隔
+
+ base.OnStartup(e);
+
+ // 设置ServiceCollection
+ var services = new ServiceCollection();
+ ConfigureServices(services); // 配置服务
+
+ // 创建ServiceProvider
+ ServiceProvider = services.BuildServiceProvider();
+
+ // 配置Serilog和其他扩展
+ ServiceProvider.UseSerilogExtensions();
+
+ var appConfig = ServiceProvider.GetService();
+ Log.Information($"系统初始化完成,日志存放路径:{appConfig?.logPath}");
+
+ var loginWindow = ServiceProvider.GetRequiredService();
+ loginWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
+ loginWindow.Show();
+
+ }
+
+
+ ///
+ /// ConfigureServices
+ ///
+ ///
+ private void ConfigureServices(IServiceCollection services)
+ {
+ // 注册AppConfig
+ services.AddSingleton(provider =>
+ {
+ var configurationBuilder = new ConfigurationBuilder()
+ .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
+ .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
+ IConfiguration configuration = configurationBuilder.Build();
+ var ap = configuration.GetSection("AppConfig").Get();
+ return ap;
+ });
+
+ services.AddSingleton(typeof(SerilogHelper));
+
+ Assembly[] assemblies = {
+ Assembly.LoadFrom("SlnMesnac.Repository.dll"),
+ Assembly.LoadFrom("SlnMesnac.Plc.dll"),
+ Assembly.LoadFrom("SlnMesnac.Rfid.dll"),
+ Assembly.LoadFrom("SlnMesnac.Common.dll"),
+ Assembly.LoadFrom("SlnMesnac.TouchSocket.dll"),
+ Assembly.LoadFrom("SlnMesnac.Business.dll"),
+ Assembly.LoadFrom("SlnMesnac.Generate.dll")
+ };
+
+ services.Scan(scan => scan.FromAssemblies(assemblies)
+ .AddClasses()
+ .AsImplementedInterfaces()
+ .AsSelf()
+ .WithTransientLifetime());
+ services.AddSingleton(typeof(TcpService));
+ services.AddLogging(x => x.AddSerilog());
+
+ services.Scan(scan => scan
+ .FromAssemblyOf()
+ .AddClasses(classes => classes.WithAttribute()).AsSelf().WithSingletonLifetime());
+ services.Scan(scan => scan
+ .FromAssemblyOf()
+ .AddClasses(classes => classes.WithAttribute()).AsSelf().WithTransientLifetime());
+
+
+ // 注册ORM
+ services.AddSqlSugarSetup();
+
+ // 注册PLC工厂
+ //services.AddPlcFactorySetup();
+
+ //services.AddJob();
+
+ // 注册 EventBus 服务
+ //services.AddEventBus(builder =>
+ //{
+ // // 注册 ToDo 事件订阅者
+ // builder.AddSubscriber();
+ //});
+
+
+
+
+ }
+
+ // Exit事件
+ protected override void OnExit(ExitEventArgs e)
+ {
+ base.OnExit(e);
+
+ Log.Information($"系统退出,当前时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
+ // 释放资源
+ // ...
+ }
+
+ private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
+ {
+ // 处理异常
+ var info = e.Exception;
+ MessageBox.Show(e.Exception.Message);
+ Log.Error($"全局异常:{e.Exception.Message}", e.Exception);
+
+ // 防止默认的崩溃行为
+ e.Handled = true;
+ }
+
+ }
+}
diff --git a/SlnMesnac.WPF/AssemblyInfo.cs b/SlnMesnac.WPF/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/SlnMesnac.WPF/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/SlnMesnac.WPF/Attribute/RegisterAsSingletonAttribute.cs b/SlnMesnac.WPF/Attribute/RegisterAsSingletonAttribute.cs
new file mode 100644
index 0000000..86eadf3
--- /dev/null
+++ b/SlnMesnac.WPF/Attribute/RegisterAsSingletonAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SlnMesnac.WPF.Attribute
+{
+ public class RegisterAsSingletonAttribute:System.Attribute
+ {
+ }
+}
diff --git a/SlnMesnac.WPF/Attribute/RegisterAsTransientAttribute.cs b/SlnMesnac.WPF/Attribute/RegisterAsTransientAttribute.cs
new file mode 100644
index 0000000..037555d
--- /dev/null
+++ b/SlnMesnac.WPF/Attribute/RegisterAsTransientAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SlnMesnac.WPF.Attribute
+{
+ public class RegisterAsTransientAttribute:System.Attribute
+ {
+ }
+}
diff --git a/SlnMesnac.WPF/Attribute/RequirePermissionAttribute.cs b/SlnMesnac.WPF/Attribute/RequirePermissionAttribute.cs
new file mode 100644
index 0000000..aaefe90
--- /dev/null
+++ b/SlnMesnac.WPF/Attribute/RequirePermissionAttribute.cs
@@ -0,0 +1,109 @@
+using Microsoft.Extensions.DependencyInjection;
+using Rougamo;
+using Rougamo.Context;
+using SlnMesnac.WPF.Page.Loading;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Threading;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:T14-GEN3-7895
+* 命名空间:SlnMesnac.WPF.Attribute
+* 唯一标识:fff40cb6-18aa-47e0-917c-1fa653e6f978
+*
+* 创建者:WenJY
+* 电子邮箱:
+* 创建时间:2024-12-30 10:19:41
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.WPF.Attribute
+{
+ ///
+ /// 权限过滤
+ ///
+ public class RequirePermissionAttribute : MoAttribute
+ {
+ private LoadingWindow loadingWindow;
+ private string _permissionName;
+
+ public RequirePermissionAttribute(string permissionName)
+ {
+ _permissionName = permissionName;
+
+
+ }
+ public override void OnEntry(MethodContext context)
+ {
+ Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint));
+ newWindowThread.SetApartmentState(ApartmentState.STA); // 设置为 STA 模式
+ newWindowThread.IsBackground = true; // 设置为后台线程
+ newWindowThread.Start();
+
+ bool hasPermission = CheckPermission(_permissionName);
+
+ if (!hasPermission)
+ {
+ // 如果用户没有权限,抛出异常或采取其他措施
+ throw new UnauthorizedAccessException("User does not have the required permission.");
+ }
+
+ base.OnEntry(context);
+ }
+
+
+ public override void OnExit(MethodContext context)
+ {
+ Thread.Sleep(200);
+ if(loadingWindow != null)
+ {
+ loadingWindow.Dispatcher.Invoke(new Action(() =>
+ {
+ loadingWindow.Close(); // 关闭窗口
+ }));
+ }
+
+
+ base.OnExit(context);
+ }
+
+ ///
+ /// 判断权限
+ ///
+ ///
+ ///
+ private bool CheckPermission(string permissionName)
+ {
+ return true;
+ }
+
+ private void ThreadStartingPoint()
+ {
+ Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
+ {
+ loadingWindow = App.ServiceProvider.GetService();
+ loadingWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
+ loadingWindow.Topmost = true;
+ loadingWindow.Show();
+ }));
+
+ Dispatcher.Run();
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/Converter/Generate/RowToIndexConverter.cs b/SlnMesnac.WPF/Converter/Generate/RowToIndexConverter.cs
new file mode 100644
index 0000000..bfed787
--- /dev/null
+++ b/SlnMesnac.WPF/Converter/Generate/RowToIndexConverter.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.WPF.Converter.Generate
+* 唯一标识:38e34c93-1c10-4a1c-83b0-c545affdc224
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-11 10:27:10
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.WPF.Converter.Generate
+{
+ internal class RowToIndexConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ var item = values[0];
+ var dataGrid = values[1] as DataGrid;
+
+ if (item == null || dataGrid == null)
+ return null;
+
+ var index = dataGrid.Items.IndexOf(item) + 1;
+ return index;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/FodyWeavers.xml b/SlnMesnac.WPF/FodyWeavers.xml
new file mode 100644
index 0000000..a6a2edf
--- /dev/null
+++ b/SlnMesnac.WPF/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/SlnMesnac.WPF/MainWindow.xaml b/SlnMesnac.WPF/MainWindow.xaml
new file mode 100644
index 0000000..95bca2c
--- /dev/null
+++ b/SlnMesnac.WPF/MainWindow.xaml
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.WPF/MainWindow.xaml.cs b/SlnMesnac.WPF/MainWindow.xaml.cs
new file mode 100644
index 0000000..0e790b5
--- /dev/null
+++ b/SlnMesnac.WPF/MainWindow.xaml.cs
@@ -0,0 +1,33 @@
+using SlnMesnac.WPF.Attribute;
+using SlnMesnac.WPF.ViewModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SlnMesnac.WPF
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ [RegisterAsSingletonAttribute]
+ public partial class MainWindow : Window
+ {
+ public MainWindow(MainWindowViewModel mainWindowViewModel)
+ {
+ InitializeComponent();
+
+ this.DataContext = mainWindowViewModel;
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/Page/Generate/GenerateControl.xaml b/SlnMesnac.WPF/Page/Generate/GenerateControl.xaml
new file mode 100644
index 0000000..1c8cbe5
--- /dev/null
+++ b/SlnMesnac.WPF/Page/Generate/GenerateControl.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.WPF/Page/Generate/GenerateControl.xaml.cs b/SlnMesnac.WPF/Page/Generate/GenerateControl.xaml.cs
new file mode 100644
index 0000000..232564e
--- /dev/null
+++ b/SlnMesnac.WPF/Page/Generate/GenerateControl.xaml.cs
@@ -0,0 +1,32 @@
+using SlnMesnac.WPF.Attribute;
+using SlnMesnac.WPF.ViewModel.Generate;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace SlnMesnac.WPF.Page.Generate
+{
+ ///
+ /// GenerateControl.xaml 的交互逻辑
+ ///
+ [RegisterAsSingletonAttribute]
+ public partial class GenerateControl : UserControl
+ {
+ public GenerateControl(GenerateControlViewModel generateControlViewModel)
+ {
+ InitializeComponent();
+ this.DataContext = generateControlViewModel;
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml b/SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml
new file mode 100644
index 0000000..de2ef38
--- /dev/null
+++ b/SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml.cs b/SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml.cs
new file mode 100644
index 0000000..3b30af0
--- /dev/null
+++ b/SlnMesnac.WPF/Page/Loading/LoadingWindow.xaml.cs
@@ -0,0 +1,26 @@
+using SlnMesnac.WPF.Attribute;
+using System;
+using System.Windows;
+using System.Windows.Threading;
+
+namespace SlnMesnac.WPF.Page.Loading
+{
+ ///
+ /// LoadingWindow.xaml 的交互逻辑
+ ///
+ [RegisterAsTransientAttribute]
+ public partial class LoadingWindow : Window
+ {
+ public LoadingWindow()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnClosed(EventArgs e)
+ {
+ base.OnClosed(e);
+ // 停止 Dispatcher 消息循环
+ Dispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/Page/Login/LoginWindow.xaml b/SlnMesnac.WPF/Page/Login/LoginWindow.xaml
new file mode 100644
index 0000000..ad8efc4
--- /dev/null
+++ b/SlnMesnac.WPF/Page/Login/LoginWindow.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.WPF/Page/Login/LoginWindow.xaml.cs b/SlnMesnac.WPF/Page/Login/LoginWindow.xaml.cs
new file mode 100644
index 0000000..e1823c0
--- /dev/null
+++ b/SlnMesnac.WPF/Page/Login/LoginWindow.xaml.cs
@@ -0,0 +1,54 @@
+using SlnMesnac.WPF.Attribute;
+using SlnMesnac.WPF.ViewModel.Login;
+using System;
+using System.Windows;
+
+namespace SlnMesnac.WPF.Page.Login
+{
+ ///
+ /// LoginWindow.xaml 的交互逻辑
+ ///
+ [RegisterAsSingletonAttribute]
+ public partial class LoginWindow : Window
+ {
+ private readonly LoginViewModel _loginViewModel;
+ public LoginWindow(LoginViewModel loginViewModel)
+ {
+ _loginViewModel = loginViewModel;
+ InitializeComponent();
+ this.DataContext = _loginViewModel;
+ }
+
+ private async void LoginBtn_Click(object sender, RoutedEventArgs e)
+ {
+ string userName = UserNameStr.Text.ToString();
+ string password = PasswordStr.Password;
+
+ //if (string.IsNullOrEmpty(userName))
+ //{
+ // MessageBox.Show("用户名不允许为空");
+ // return;
+ //}
+
+ //if (string.IsNullOrEmpty(password))
+ //{
+ // MessageBox.Show("密码不允许为空");
+ // return;
+ //}
+
+ bool res = _loginViewModel.Login(userName,password);
+ if (res)
+ {
+ this.Closing += MainWindow_Closing;
+ this.Close();
+ }
+ }
+
+ private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ this.Closing -= MainWindow_Closing; // 防止多次绑定
+ e.Cancel = true;
+ this.Visibility = Visibility.Hidden; // 隐藏窗口
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/SlnMesnac.WPF.csproj b/SlnMesnac.WPF/SlnMesnac.WPF.csproj
new file mode 100644
index 0000000..071bb61
--- /dev/null
+++ b/SlnMesnac.WPF/SlnMesnac.WPF.csproj
@@ -0,0 +1,57 @@
+
+
+
+ Exe
+ net6.0-windows
+
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnMesnac.WPF/Templates/gif/loading.gif b/SlnMesnac.WPF/Templates/gif/loading.gif
new file mode 100644
index 0000000..ba81ff0
Binary files /dev/null and b/SlnMesnac.WPF/Templates/gif/loading.gif differ
diff --git a/SlnMesnac.WPF/Templates/icon/Icon.png b/SlnMesnac.WPF/Templates/icon/Icon.png
new file mode 100644
index 0000000..1560465
Binary files /dev/null and b/SlnMesnac.WPF/Templates/icon/Icon.png differ
diff --git a/SlnMesnac.WPF/Templates/image/background.jpg b/SlnMesnac.WPF/Templates/image/background.jpg
new file mode 100644
index 0000000..860c0b0
Binary files /dev/null and b/SlnMesnac.WPF/Templates/image/background.jpg differ
diff --git a/SlnMesnac.WPF/Templates/image/login-background.jpg b/SlnMesnac.WPF/Templates/image/login-background.jpg
new file mode 100644
index 0000000..96303ad
Binary files /dev/null and b/SlnMesnac.WPF/Templates/image/login-background.jpg differ
diff --git a/SlnMesnac.WPF/Templates/style/resourceStyle.xaml b/SlnMesnac.WPF/Templates/style/resourceStyle.xaml
new file mode 100644
index 0000000..e7155f2
--- /dev/null
+++ b/SlnMesnac.WPF/Templates/style/resourceStyle.xaml
@@ -0,0 +1,424 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SlnMesnac.WPF/ViewModel/Base/BaseViewModel.cs b/SlnMesnac.WPF/ViewModel/Base/BaseViewModel.cs
new file mode 100644
index 0000000..a850bd6
--- /dev/null
+++ b/SlnMesnac.WPF/ViewModel/Base/BaseViewModel.cs
@@ -0,0 +1,59 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace SlnMesnac.WPF.ViewModel.Base
+{
+ public class BaseViewModel : ObservableObject
+ {
+
+ public string EscapeUnicode(string input)
+ {
+ return Regex.Replace(input, "([0-9a-fA-F]+);", match =>
+ {
+ string hexValue = match.Groups[1].Value;
+ return $"\\u{hexValue}";
+ });
+ }
+
+ ///
+ /// 获取当前类中的方法
+ ///
+ ///
+ public Dictionary GetRelayCommandsAsDictionary()
+ {
+ var commandDict = new Dictionary();
+ var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
+ foreach (var property in properties)
+ {
+ if (property.PropertyType == typeof(IRelayCommand))
+ {
+ var command = property.GetValue(this) as IRelayCommand;
+ if (command != null)
+ {
+ commandDict[property.Name] = command;
+ }
+ }
+ }
+ var fields = this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
+ foreach (var field in fields)
+ {
+ if (field.FieldType == typeof(IRelayCommand))
+ {
+ var command = field.GetValue(this) as IRelayCommand;
+ if (command != null)
+ {
+ commandDict[field.Name] = command;
+ }
+ }
+ }
+ return commandDict;
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/ViewModel/Base/BaseViewModelAsPageQuery.cs b/SlnMesnac.WPF/ViewModel/Base/BaseViewModelAsPageQuery.cs
new file mode 100644
index 0000000..56d4b12
--- /dev/null
+++ b/SlnMesnac.WPF/ViewModel/Base/BaseViewModelAsPageQuery.cs
@@ -0,0 +1,75 @@
+
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TouchSocket.Core;
+
+namespace SlnMesnac.WPF.ViewModel.Base
+{
+ ///
+ /// ViewModel抽象类:分页
+ ///
+ public abstract partial class BaseViewModelAsPageQuery : ObservableObject
+ {
+ ///
+ /// 当前页码
+ ///
+ [ObservableProperty]
+ public int currentPage = 1;
+
+ ///
+ /// 每页显示的行数
+ ///
+ [ObservableProperty]
+ public int pageSize = 10;
+
+ ///
+ /// 总条数
+ ///
+ public int totalCount = 0;
+
+ ///
+ /// 总页数
+ ///
+ [ObservableProperty]
+ public int totalPages = 0;
+
+ ///
+ /// 首页
+ ///
+ [RelayCommand]
+ private void FirstPage() => ChangePage(1);
+
+ ///
+ /// 上一页
+ ///
+ [RelayCommand]
+ private void PreviousPage() => ChangePage(CurrentPage - 1);
+
+ ///
+ /// 下一页
+ ///
+ [RelayCommand]
+ private void NextPage() => ChangePage(CurrentPage + 1);
+
+ ///
+ /// 尾页
+ ///
+ [RelayCommand]
+ private void LastPage() => ChangePage(TotalPages);
+
+ private void ChangePage(int newPage)
+ {
+ if (newPage >= 1 && newPage <= TotalPages)
+ {
+ CurrentPage = newPage;
+ Query();
+ }
+ }
+ public abstract void Query();
+ }
+}
diff --git a/SlnMesnac.WPF/ViewModel/Generate/GenerateControlViewModel.cs b/SlnMesnac.WPF/ViewModel/Generate/GenerateControlViewModel.cs
new file mode 100644
index 0000000..83811b1
--- /dev/null
+++ b/SlnMesnac.WPF/ViewModel/Generate/GenerateControlViewModel.cs
@@ -0,0 +1,155 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.WindowsAPICodePack.Dialogs;
+using SlnMesnac.Config;
+using SlnMesnac.Generate;
+using SlnMesnac.WPF.Attribute;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.Linq;
+using System.Windows;
+
+#region << 版 本 注 释 >>
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2024 WenJY 保留所有权利。
+* CLR版本:4.0.30319.42000
+* 机器名称:LAPTOP-E0N2L34V
+* 命名空间:SlnMesnac.WPF.ViewModel.Generate
+* 唯一标识:7f1ddac5-3ff3-4974-ac90-d6eb684167c8
+*
+* 创建者:WenJY
+* 电子邮箱:wenjy@mesnac.com
+* 创建时间:2024-04-11 09:31:46
+* 版本:V1.0.0
+* 描述:
+*
+*--------------------------------------------------------------------
+* 修改人:
+* 时间:
+* 修改说明:
+*
+* 版本:V1.0.0
+*--------------------------------------------------------------------*/
+#endregion << 版 本 注 释 >>
+namespace SlnMesnac.WPF.ViewModel.Generate
+{
+ [RegisterAsSingleton]
+ public class GenerateControlViewModel : ObservableObject
+ {
+ private readonly AppConfig _appConfig;
+
+ private readonly GenerateCode _generateCode;
+
+ public GenerateControlViewModel(AppConfig appConfig, GenerateCode generateCode)
+ {
+ _appConfig = appConfig;
+ _generateCode = generateCode;
+
+ var configIds = _appConfig.sqlConfig.Select(x => x.configId).ToList();
+
+ // 初始化选项列表
+ Options = new ObservableCollection();
+
+ foreach (var configId in configIds)
+ {
+ Options.Add(configId);
+ }
+
+ QuerySearchCommand = new RelayCommand(Query);
+
+ CreateCodeCommand = new RelayCommand(CreateCode);
+ }
+
+ #region 参数定义
+ private ObservableCollection _options;
+ public ObservableCollection Options
+ {
+ get => _options;
+ set => SetProperty(ref _options, value);
+ }
+
+ private string _selectedOption;
+ public string SelectedOption
+ {
+ get => _selectedOption;
+ set => SetProperty(ref _selectedOption, value);
+ }
+
+ private ObservableCollection tablesDataGrid;
+
+ public ObservableCollection TablesDataGrid
+ {
+ get => tablesDataGrid;
+ set => SetProperty(ref tablesDataGrid, value);
+
+ }
+ #endregion
+
+ #region 事件定义
+ public RelayCommand QuerySearchCommand { get; set; }
+
+ public RelayCommand CreateCodeCommand { get; set; }
+ #endregion
+
+ ///
+ /// 查询事件
+ ///
+ ///
+ private void Query(string search)
+ {
+ var configId = _selectedOption;
+
+ if (!string.IsNullOrEmpty(configId))
+ {
+ var db = App.ServiceProvider.GetService();
+ var scope = db.AsTenant().GetConnectionScope(configId);
+
+ List tables = scope.DbMaintenance.GetTableInfoList(false);
+
+ if (tables != null)
+ {
+ TablesDataGrid = new ObservableCollection();
+ tables.ForEach(t => { TablesDataGrid.Add(t); });
+ }
+ }
+
+
+ }
+
+ private void CreateCode(string tableName)
+ {
+ var info = tableName;
+ var configId = _selectedOption;
+
+ string nameSpace = "SlnMesnac.Repository";
+
+ try
+ {
+ using (CommonOpenFileDialog dialog = new CommonOpenFileDialog())
+ {
+ dialog.IsFolderPicker = true; // 设置为选择文件夹
+ if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
+ {
+ string selectedPath = dialog.FileName;
+
+ var res = _generateCode.CreateCode(configId, tableName, selectedPath, nameSpace);
+
+ if (res)
+ {
+ MessageBox.Show($"{tableName}代码生成成功");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"{tableName}代码生成失败:{ex.Message}");
+ }
+ }
+
+ }
+}
diff --git a/SlnMesnac.WPF/ViewModel/Login/LoginViewModel.cs b/SlnMesnac.WPF/ViewModel/Login/LoginViewModel.cs
new file mode 100644
index 0000000..daf4805
--- /dev/null
+++ b/SlnMesnac.WPF/ViewModel/Login/LoginViewModel.cs
@@ -0,0 +1,52 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using Microsoft.Extensions.DependencyInjection;
+using SlnMesnac.Config;
+using SlnMesnac.WPF.Attribute;
+using System;
+using System.Windows;
+
+namespace SlnMesnac.WPF.ViewModel.Login
+{
+ [RegisterAsSingleton]
+ public partial class LoginViewModel: ObservableObject
+ {
+ private readonly AppConfig _appConfig;
+ [ObservableProperty]
+ public string systemTitle = string.Empty;
+
+ [ObservableProperty]
+ public string userName = string.Empty;
+
+ public LoginViewModel(AppConfig appConfig)
+ {
+ _appConfig = appConfig;
+ SystemTitle = "系统测试";
+ }
+
+
+ [RequirePermission("Login")]
+ public bool Login(string userName,string password)
+ {
+ bool res = true;
+ try
+ {
+ //res = _usersBusiness.Verify(userName, password);
+ if (res)
+ {
+ App.Current.Dispatcher.Invoke(() =>
+ {
+ MainWindow mainWindow = App.ServiceProvider.GetService();
+ App.Current.MainWindow = mainWindow;
+ mainWindow.Show();
+
+ });
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"登录失败:{ex.Message}");
+ }
+ return res;
+ }
+ }
+}
diff --git a/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs b/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs
new file mode 100644
index 0000000..d0be099
--- /dev/null
+++ b/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs
@@ -0,0 +1,132 @@
+
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Microsoft.Extensions.DependencyInjection;
+using SlnMesnac.Serilog;
+using SlnMesnac.WPF.Attribute;
+using SlnMesnac.WPF.Page.Generate;
+using SlnMesnac.WPF.ViewModel.Base;
+using System;
+using System.Windows;
+
+namespace SlnMesnac.WPF.ViewModel
+{
+ [RegisterAsSingletonAttribute]
+ public partial class MainWindowViewModel : BaseViewModel
+ {
+ public readonly SerilogHelper _logger;
+ private readonly GenerateControl _generateControl;
+
+ #region 参数定义
+ ///
+ /// PLC设备状态
+ ///
+ [ObservableProperty]
+ private int plcStatus = 0;
+
+ ///
+ /// 登录人员
+ ///
+ [ObservableProperty]
+ private string otherInfo;
+
+ ///
+ /// 系统标题
+ ///
+ [ObservableProperty]
+ private string systemTitle = string.Empty;
+
+ [ObservableProperty]
+ public System.Windows.Controls.UserControl userContent = new System.Windows.Controls.UserControl();
+
+ ///
+ /// 箱壳扫码器状态
+ ///
+ [ObservableProperty]
+ private int _shellScannerStatus = 0;
+
+ ///
+ /// 内胆扫码器状态
+ ///
+ [ObservableProperty]
+ private int _boldScannerStatus = 0;
+
+ #endregion
+
+
+ public MainWindowViewModel(SerilogHelper logger,GenerateControl generateControl)
+ {
+
+ _logger = logger;
+ _generateControl = generateControl;
+
+ }
+
+ ///
+ /// 窗体控制
+ ///
+ ///
+ [RelayCommand]
+ [RequirePermission("FormControl")]
+ private void FormControl(object obj)
+ {
+ try
+ {
+ string controlType = obj as string;
+ switch (controlType)
+ {
+ // 关闭当前窗口
+ case "Exit":
+ //Environment.Exit(0);
+ Application.Current.Shutdown();
+ break;
+ case "Generate":
+ UserContent = _generateControl;
+ break;
+ // 还原 或者 最大化当前窗口
+ case "Normal":
+ if (Application.Current.MainWindow.WindowState == WindowState.Normal)
+ {
+ Application.Current.MainWindow.WindowState = WindowState.Maximized;
+ break;
+ }
+ if (Application.Current.MainWindow.WindowState == WindowState.Maximized)
+ {
+ Application.Current.MainWindow.WindowState = WindowState.Normal;
+ break;
+ }
+ break;
+
+ // 最小化当前窗口
+ case "Minimized":
+ Application.Current.MainWindow.WindowState = WindowState.Minimized;
+ break;
+ default:
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("窗体控制逻辑异常", ex);
+ }
+ }
+
+ ///
+ /// 界面跳转
+ ///
+ [RelayCommand]
+ private void ControlOnClick(object obj)
+ {
+ try
+ {
+ string info = obj as string;
+ //UserContent = inStoreInfoControl;
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("界面跳转逻辑异常", ex);
+ }
+ }
+
+ }
+}
diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json
new file mode 100644
index 0000000..9346894
--- /dev/null
+++ b/SlnMesnac.WPF/appsettings.json
@@ -0,0 +1,60 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*",
+ "AppConfig": {
+ "logPath": "E:\\桌面\\SlnMesnac\\SlnMesnac.WPF\\bin\\Debug\\net6.0-windows",
+ "SqlConfig": [
+ {
+ "configId": "mes",
+ "dbType": 1,
+ "connStr": "server=.;uid=sa;pwd=123456;database=JiangYinMENS"
+ },
+ {
+ "configId": "mcs",
+ "dbType": 3,
+ "connStr": "Data Source=175.27.215.92/helowin;User ID=aucma_scada;Password=aucma"
+ }
+ ],
+ "PlcConfig": [
+ {
+ "configId": 1,
+ "plcType": "MelsecBinaryPlc",
+ "plcIp": "127.0.0.1",
+ "plcPort": 6000,
+ "plcKey": "mcs",
+ "isFlage": true
+ },
+ {
+ "configId": 2,
+ "plcType": "MelsecBinaryPlc",
+ "plcIp": "127.0.0.1",
+ "plcPort": 6001,
+ "plcKey": "cwss",
+ "isFlage": true
+ }
+ ],
+ "RfidConfig": [
+ {
+ "configId": 1,
+ "equipIp": "127.0.0.1",
+ "equipPort": 6003,
+ "equipKey": "test1",
+ "isFlage": true
+ },
+ {
+ "configId": 2,
+ "equipIp": "127.0.0.1",
+ "equipPort": 6004,
+ "equipKey": "test2",
+ "isFlage": true
+ }
+ ],
+ "redisConfig": "175.27.215.92:6379,password=redis@2023"
+ }
+}
diff --git a/SlnMesnac.sln b/SlnMesnac.sln
new file mode 100644
index 0000000..83da5e6
--- /dev/null
+++ b/SlnMesnac.sln
@@ -0,0 +1,109 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33502.453
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Common", "SlnMesnac.Common\SlnMesnac.Common.csproj", "{BB71F26A-7007-423E-83E9-7A3BAC25E934}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Config", "SlnMesnac.Config\SlnMesnac.Config.csproj", "{6EF7F087-7149-4689-885C-E0D05E1A9AA8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Model", "SlnMesnac.Model\SlnMesnac.Model.csproj", "{9EC081B6-971F-418C-A40C-5B8AD2E27417}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Repository", "SlnMesnac.Repository\SlnMesnac.Repository.csproj", "{C892C06A-496B-43B6-AEC7-AF9D70778C0C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Quartz", "SlnMesnac.Quartz\SlnMesnac.Quartz.csproj", "{12ED397C-951E-411C-9C43-CDABA79CA45B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Serilog", "SlnMesnac.Serilog\SlnMesnac.Serilog.csproj", "{DEE2F305-733C-47C8-891C-502121ABAD00}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Plc", "SlnMesnac.Plc\SlnMesnac.Plc.csproj", "{D17E9024-9D25-4CE4-8E98-8A6C859CE436}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.WPF", "SlnMesnac.WPF\SlnMesnac.WPF.csproj", "{B986555B-86D1-457A-95F5-B9135B9FBC55}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Business", "SlnMesnac.Business\SlnMesnac.Business.csproj", "{90296C1E-932E-4CD3-9B11-4376746C4C87}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.TouchSocket", "SlnMesnac.TouchSocket\SlnMesnac.TouchSocket.csproj", "{3700E2BB-09C4-43C0-A9DC-C18137B76591}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Mqtt", "SlnMesnac.Mqtt\SlnMesnac.Mqtt.csproj", "{7D908FF5-88AE-42AB-A193-F2896EF44AB1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Rfid", "SlnMesnac.Rfid\SlnMesnac.Rfid.csproj", "{40D23A4B-8372-4145-936C-08AE63C6D1F9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Generate", "SlnMesnac.Generate\SlnMesnac.Generate.csproj", "{00FC9358-2381-4C1B-BD45-6D31DD1DB7D3}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Extensions", "SlnMesnac.Extensions\SlnMesnac.Extensions.csproj", "{6D929802-24AA-42A7-92C5-303C3D59A990}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnMesnac.Redis", "SlnMesnac.Redis\SlnMesnac.Redis.csproj", "{0E041719-E755-43CD-8A0E-DF62E0B2E463}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {BB71F26A-7007-423E-83E9-7A3BAC25E934}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BB71F26A-7007-423E-83E9-7A3BAC25E934}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BB71F26A-7007-423E-83E9-7A3BAC25E934}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BB71F26A-7007-423E-83E9-7A3BAC25E934}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6EF7F087-7149-4689-885C-E0D05E1A9AA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6EF7F087-7149-4689-885C-E0D05E1A9AA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6EF7F087-7149-4689-885C-E0D05E1A9AA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6EF7F087-7149-4689-885C-E0D05E1A9AA8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9EC081B6-971F-418C-A40C-5B8AD2E27417}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9EC081B6-971F-418C-A40C-5B8AD2E27417}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9EC081B6-971F-418C-A40C-5B8AD2E27417}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9EC081B6-971F-418C-A40C-5B8AD2E27417}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C892C06A-496B-43B6-AEC7-AF9D70778C0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C892C06A-496B-43B6-AEC7-AF9D70778C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C892C06A-496B-43B6-AEC7-AF9D70778C0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C892C06A-496B-43B6-AEC7-AF9D70778C0C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {12ED397C-951E-411C-9C43-CDABA79CA45B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12ED397C-951E-411C-9C43-CDABA79CA45B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12ED397C-951E-411C-9C43-CDABA79CA45B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12ED397C-951E-411C-9C43-CDABA79CA45B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DEE2F305-733C-47C8-891C-502121ABAD00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DEE2F305-733C-47C8-891C-502121ABAD00}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DEE2F305-733C-47C8-891C-502121ABAD00}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DEE2F305-733C-47C8-891C-502121ABAD00}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D17E9024-9D25-4CE4-8E98-8A6C859CE436}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D17E9024-9D25-4CE4-8E98-8A6C859CE436}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D17E9024-9D25-4CE4-8E98-8A6C859CE436}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D17E9024-9D25-4CE4-8E98-8A6C859CE436}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B986555B-86D1-457A-95F5-B9135B9FBC55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B986555B-86D1-457A-95F5-B9135B9FBC55}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B986555B-86D1-457A-95F5-B9135B9FBC55}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B986555B-86D1-457A-95F5-B9135B9FBC55}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90296C1E-932E-4CD3-9B11-4376746C4C87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90296C1E-932E-4CD3-9B11-4376746C4C87}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90296C1E-932E-4CD3-9B11-4376746C4C87}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90296C1E-932E-4CD3-9B11-4376746C4C87}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3700E2BB-09C4-43C0-A9DC-C18137B76591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3700E2BB-09C4-43C0-A9DC-C18137B76591}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3700E2BB-09C4-43C0-A9DC-C18137B76591}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3700E2BB-09C4-43C0-A9DC-C18137B76591}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7D908FF5-88AE-42AB-A193-F2896EF44AB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7D908FF5-88AE-42AB-A193-F2896EF44AB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7D908FF5-88AE-42AB-A193-F2896EF44AB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7D908FF5-88AE-42AB-A193-F2896EF44AB1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {40D23A4B-8372-4145-936C-08AE63C6D1F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {40D23A4B-8372-4145-936C-08AE63C6D1F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {40D23A4B-8372-4145-936C-08AE63C6D1F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {40D23A4B-8372-4145-936C-08AE63C6D1F9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {00FC9358-2381-4C1B-BD45-6D31DD1DB7D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00FC9358-2381-4C1B-BD45-6D31DD1DB7D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00FC9358-2381-4C1B-BD45-6D31DD1DB7D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00FC9358-2381-4C1B-BD45-6D31DD1DB7D3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6D929802-24AA-42A7-92C5-303C3D59A990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6D929802-24AA-42A7-92C5-303C3D59A990}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D929802-24AA-42A7-92C5-303C3D59A990}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6D929802-24AA-42A7-92C5-303C3D59A990}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0E041719-E755-43CD-8A0E-DF62E0B2E463}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0E041719-E755-43CD-8A0E-DF62E0B2E463}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0E041719-E755-43CD-8A0E-DF62E0B2E463}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0E041719-E755-43CD-8A0E-DF62E0B2E463}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {D414D640-C2DE-44E2-930E-DD095881CDC1}
+ EndGlobalSection
+EndGlobal