commit 4ab21e29406a62a5180b20807fcf5f8d43d7bc84 Author: icewint Date: Tue May 14 16:30:56 2024 +0800 苏州卡特开始 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f3d037 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +Tools/*/bin +WcsMain/bin +Tools/*/obj +WcsMain/obj +bin +obj +.vs +.idea diff --git a/Tools/ApiTool/ApiTool.csproj b/Tools/ApiTool/ApiTool.csproj new file mode 100644 index 0000000..df21c88 --- /dev/null +++ b/Tools/ApiTool/ApiTool.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + + + + + + + diff --git a/Tools/ApiTool/Dto/ApiResponseInfo.cs b/Tools/ApiTool/Dto/ApiResponseInfo.cs new file mode 100644 index 0000000..674b1d8 --- /dev/null +++ b/Tools/ApiTool/Dto/ApiResponseInfo.cs @@ -0,0 +1,84 @@ +using System.Text; + +namespace ApiTool.Dto; + +public class ApiResponseInfo +{ + /// + /// 请求 URL + /// + public string? RequestUrl { get; set; } + + /// + /// 请求字符串 + /// + public string? RequestMsg { get; set; } + + /// + /// 响应字符串 + /// + public string? ResponseMsg { get; set; } + + /// + /// 请求时间 + /// + public DateTime? RequestTime { get; set; } + + /// + /// 响应时间 + /// + public DateTime? ResponseTime { get; set; } + + /// + /// 是否发送成功 + /// + /// + /// 注意:这里仅表示服务端有响应 + /// + public bool IsSend { get; set; } + + /// + /// 请求方式 + /// + public string? RequestMethod { get; set; } + + /// + /// 请求耗时 + /// + public double UseTime { get; set; } + + /// + /// 返回的异常,没有异常返回 null + /// + public Exception? RequestException { get; set; } + + /// + /// 重写toString + /// + /// + public override string ToString() + { + StringBuilder builder = new(); + builder.AppendLine($"[请求结果] {IsSend}"); + builder.AppendLine($"[请求方式] {RequestMethod}"); + builder.AppendLine($"[请求地址] {RequestUrl}"); + builder.AppendLine($"[请求信息] {RequestMsg}"); + builder.AppendLine($"[响应信息] {ResponseMsg}"); + builder.AppendLine($"[请求时间] {RequestTime}"); + builder.AppendLine($"[响应时间] {RequestTime}"); + builder.AppendLine($"[请求耗时] {UseTime} ms"); + if (RequestException != default) + { + builder.AppendLine($"[异常信息] {RequestException.Message}"); + } + return builder.ToString(); + } +} + +public class ApiResponseInfo : ApiResponseInfo where T : class, new() +{ + /// + /// 响应的实体类 + /// + public T? ResponseEntity { get; set; } +} \ No newline at end of file diff --git a/Tools/ApiTool/WebApiPost.cs b/Tools/ApiTool/WebApiPost.cs new file mode 100644 index 0000000..17c395a --- /dev/null +++ b/Tools/ApiTool/WebApiPost.cs @@ -0,0 +1,120 @@ +using System.Diagnostics; +using System.Net.Http.Headers; +using System.Text; +using ApiTool.Dto; +using Newtonsoft.Json; + + +namespace ApiTool; + +public class WebApiPost +{ + /* + * 作者:菻蔃 + * + * 版本时间:2024年5月10日 + * + */ + + public WebApiPost() { } + + private string? _baseUrl = string.Empty; + + private Action? _apiAction; + + public WebApiPost(Action apiAction) + { + _apiAction = apiAction; + } + + public WebApiPost(string url, Action action) + { + _baseUrl = url; + _apiAction = action; + } + + /// + /// 设置响应事件, + /// + /// + public void SetResponseAction(Action action) + { + _apiAction = action; + } + public void SetBaseUrl(string url) + { + _baseUrl = url; + } + + /// + /// 执行POST请求 + /// + /// + /// + /// + /// + /// + /// + public ApiResponseInfo HttpPost(TRequest requestEntity, string method = "", int time = 10000) where TRequest : class where TResponse : class, new() + { + ApiResponseInfo result = new() + { + RequestMethod = "POST" + }; + string address = _baseUrl + method; + Encoding encoding = Encoding.UTF8; + Stopwatch sw = new(); + string sendMes = JsonConvert.SerializeObject(requestEntity); + sw.Start(); + try + { + HttpContent content = new StringContent(sendMes, encoding, "application/json"); + HttpClient client = new(); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + client.Timeout = new TimeSpan(0, 0, 0, 0, time); + result.RequestTime = DateTime.Now; + var requestTask = client.PostAsync(address, content); + requestTask.Wait(); + var responseResult = requestTask.Result; + if (responseResult.IsSuccessStatusCode) + { + var responseRead = responseResult.Content.ReadAsStringAsync(); + responseRead.Wait(); + string responseString = responseRead.Result; + result.IsSend = true; + result.RequestMsg = sendMes; + result.RequestUrl = address; + result.ResponseMsg = responseString; + result.ResponseEntity = JsonConvert.DeserializeObject(responseString); + } + else + { + var responseCode = responseResult.StatusCode; + var responseRead = responseResult.Content.ReadAsStringAsync(); + responseRead.Wait(); + string responseString = responseRead.Result; + result.IsSend = false; + result.RequestMsg = sendMes; + result.RequestUrl = address; + result.RequestException = new Exception($"[{responseCode}]{responseString}"); + } + } + catch (Exception ex) + { + result.IsSend = false; + result.RequestMsg = sendMes; + result.RequestUrl = address; + result.RequestException = ex; + } + result.ResponseTime = DateTime.Now; + sw.Stop(); + result.ResponseTime = DateTime.Now; + TimeSpan ts = sw.Elapsed; + result.UseTime = ts.TotalMilliseconds; + _apiAction?.Invoke(result); + return result; + } + + +} \ No newline at end of file diff --git a/Tools/CirculateTool/CirculateTool.csproj b/Tools/CirculateTool/CirculateTool.csproj new file mode 100644 index 0000000..22e1b2e --- /dev/null +++ b/Tools/CirculateTool/CirculateTool.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + + + diff --git a/Tools/CirculateTool/CirculationAttribute.cs b/Tools/CirculateTool/CirculationAttribute.cs new file mode 100644 index 0000000..a821bc6 --- /dev/null +++ b/Tools/CirculateTool/CirculationAttribute.cs @@ -0,0 +1,30 @@ +namespace CirculateTool; + +/// +/// 一个类里面的方法加上这个特性就表示需要被循环执行 +/// +/// +/// 一个类里面的方法加上这个特性就表示需要被循环执行 +/// +/// 循环时间,默认500ms +/// 方法描述 +/// 方法描述 +[AttributeUsage(AttributeTargets.All)] +public class CirculationAttribute(string? methodDescription = null, int circulationTime = 500, string[]? tags = null) : Attribute +{ + + /// + /// 循环时间 + /// + public int CirculationTime { get; } = circulationTime; + + /// + /// 方法描述 + /// + public string? MethodDescription { get; } = methodDescription; + + /// + /// 方法或者类的标记 + /// + public string[]? Tags { get; } = tags; +} \ No newline at end of file diff --git a/Tools/CirculateTool/StartCirculation.cs b/Tools/CirculateTool/StartCirculation.cs new file mode 100644 index 0000000..d7babef --- /dev/null +++ b/Tools/CirculateTool/StartCirculation.cs @@ -0,0 +1,110 @@ +using System.Reflection; + +namespace CirculateTool; +/* + * 作者:菻蔃 + * 版本时间:2023年04月15日 + * + * 注意配合特性使用 + * + */ + +/// +/// 定时任务类 +/// +public class StartCirculation +{ + + /// + /// 触发的异常 + /// + public event ExceptionHandlerEvent? ExceptionHandler; + + public delegate void ExceptionHandlerEvent(string methodDescription, Exception ex); + + /// + /// 显示相关信息 + /// + public event MessageHandlerEvent? MessageHandler; + + public delegate void MessageHandlerEvent(string message); + + /// + /// 默认的循环时间 + /// + private readonly int _defaultCirculationTime = 500; + + /// + /// 启动一个程序集里面带有的类里面的定时方法 + /// + /// + /// + public virtual void StartAssemblyCirculation(Assembly assembly, object[]? instanceParams = null) + { + Type[] types = assembly.GetTypes(); + if (types.Length == 0) return; + foreach (Type type in types) + { + var attributes = type.GetCustomAttributes(false); + foreach (var attribute in attributes) + { + if (attribute is not CirculationAttribute) continue; + StartTask(type, instanceParams); + break; + } + } + } + + /// + /// 开启一个实例里面所有已经添加了特性的方法 + /// + /// + /// + public virtual void StartTask(Type type, object[]? instanceParams = null) + { + var methods = type.GetMethods(); + foreach (var method in methods) + { + var attributes = method.GetCustomAttributes(false); + foreach (var attribute in attributes) + { + if (attribute is not CirculationAttribute needDurable) continue; + string methodDescription = needDurable.MethodDescription ?? $"{type.Name}.{method.Name}"; + bool Action() => (bool)(method.Invoke(Activator.CreateInstance(type, instanceParams), []) ?? false); + StartTask(Action, methodDescription, needDurable.CirculationTime); + break; + } + } + } + + /// + /// 开启一个方法 + /// + /// + /// + /// + /// + public virtual async void StartTask(Func action, string? description = null, int? durableTime = null) + { + int durableTimeValue = durableTime ?? _defaultCirculationTime; + string methodDescription = description ?? action.Method.Name; + CancellationTokenSource cts = new(); + PeriodicTimer timer = new(new TimeSpan(0, 0, 0, 0, durableTimeValue)); + MessageHandler?.Invoke($"定时器:{methodDescription},已经启动,执行间隔为:{durableTimeValue} 毫秒。"); + while (await timer.WaitForNextTickAsync(cts.Token)) + { + try + { + var result = action(); + if (result) continue; + await cts.CancelAsync(); + MessageHandler?.Invoke($"定时器:{methodDescription},主动结束。"); + return; // 该return会结束这个线程 + } + catch (Exception ex) + { + ExceptionHandler?.Invoke(methodDescription, ex); + } + } + } +} \ No newline at end of file diff --git a/Tools/DataCheck/CheckData.cs b/Tools/DataCheck/CheckData.cs new file mode 100644 index 0000000..288345a --- /dev/null +++ b/Tools/DataCheck/CheckData.cs @@ -0,0 +1,55 @@ +using System.Text.RegularExpressions; + +namespace DataCheck; +/* + * 作者:icewint + * + */ + +/// +/// 数据校验类 +/// +public class CheckData +{ + /// + /// 校验是否满足设定的规则,需要添加 特性 + /// + /// + /// + /// + public static bool CheckDataRules(T data) where T : class + { + Type type = typeof(T); + var properties = type.GetProperties(); + foreach (var property in properties) + { + string? proValue = property.GetValue(data)?.ToString(); + var attributes = property.GetCustomAttributes(false); + foreach (var attribute in attributes) + { + if (attribute is DataRulesAttribute dataRules) + { + // 判断是否允许为 NULL + if (!dataRules.AllowNull && proValue == null) + { + // 如果不允许为 null 但是为 null 了就返回错误 + return false; + } + // 下面是允许为 null 的情况 + if (proValue == null) + { + // 允许 null 并且为 null 满足要求 + continue; + } + if (!Regex.IsMatch(proValue, dataRules.RegexRule)) + { + // 允许为 null 但不是 null 且不满足数据要求 + return false; + } + } + } + } + return true; + } + +} \ No newline at end of file diff --git a/Tools/DataCheck/DataCheck.csproj b/Tools/DataCheck/DataCheck.csproj new file mode 100644 index 0000000..0191b67 --- /dev/null +++ b/Tools/DataCheck/DataCheck.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + + + diff --git a/Tools/DataCheck/DataRulesAttribute.cs b/Tools/DataCheck/DataRulesAttribute.cs new file mode 100644 index 0000000..ee1c8d4 --- /dev/null +++ b/Tools/DataCheck/DataRulesAttribute.cs @@ -0,0 +1,18 @@ +namespace DataCheck; + +/// +/// 数据校验规则 +/// +[AttributeUsage(AttributeTargets.Property)] +public class DataRulesAttribute(bool allowNull = false, string regexRule = ".*") : Attribute +{ + /// + /// 是否允许空值 + /// + public readonly bool AllowNull = allowNull; + + /// + /// 正则表达式 + /// + public readonly string RegexRule = regexRule; +} \ No newline at end of file diff --git a/Tools/EncryptTool/EncryptTool.csproj b/Tools/EncryptTool/EncryptTool.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/Tools/EncryptTool/EncryptTool.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Tools/EncryptTool/Md5Encrypt.cs b/Tools/EncryptTool/Md5Encrypt.cs new file mode 100644 index 0000000..a30d361 --- /dev/null +++ b/Tools/EncryptTool/Md5Encrypt.cs @@ -0,0 +1,52 @@ +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; + +namespace EncryptTool; + + +/* + * 作者:菻蔃 + * 注意:MD5 加密会被机器容易的破解,请勿用于机密数据 + * 版本时间:2024年1月21日 + */ + + +/// +/// MD5 加密 +/// +public static class Md5Encrypt +{ + /// + /// 魔改版加密,用于加密密码,无法破解,本人也无法知道原密码 + /// + /// 需要加密的字符串 + /// 加密后返回的长度 + /// + public static string EncryptPassword(string? password, int length = 255) + { + if (string.IsNullOrEmpty(password)) { return string.Empty; } + var result = string.Empty; + var i = 0; + while (result.Length < length) + { + var bytes = MD5.HashData(Encoding.UTF8.GetBytes(password)); + var tempStr = Convert.ToBase64String(bytes); + tempStr = Regex.Replace(tempStr, "\\W", "").ToUpper(); + if (i % 2 == 0) + { + result += Regex.Replace(tempStr, "[0-9]", ""); + } + else + { + result += Regex.Replace(tempStr, "[A-Z]|[a-z]", ""); + } + password = tempStr; + i++; + } + return result[..length]; + } + + + +} diff --git a/Tools/HkCamera/Class1.cs b/Tools/HkCamera/Class1.cs new file mode 100644 index 0000000..3e64fba --- /dev/null +++ b/Tools/HkCamera/Class1.cs @@ -0,0 +1,6 @@ +namespace HkCamera; + +public class Class1 +{ + +} \ No newline at end of file diff --git a/Tools/HkCamera/HkCamera.csproj b/Tools/HkCamera/HkCamera.csproj new file mode 100644 index 0000000..0191b67 --- /dev/null +++ b/Tools/HkCamera/HkCamera.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + + + diff --git a/Tools/LedSimple/LEDColor.cs b/Tools/LedSimple/LEDColor.cs new file mode 100644 index 0000000..1d94a8c --- /dev/null +++ b/Tools/LedSimple/LEDColor.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LedSimple; + +public enum LEDColor +{ + Red = 0xff, + Green = 0xff00, + Yellow = 0xffff +} \ No newline at end of file diff --git a/Tools/LedSimple/LEDDLL.cs b/Tools/LedSimple/LEDDLL.cs new file mode 100644 index 0000000..c7c1810 --- /dev/null +++ b/Tools/LedSimple/LEDDLL.cs @@ -0,0 +1,844 @@ +using System.Runtime.InteropServices; + +namespace LedSimple; + +public class Leddll +{ + //颜色值 R 0x0000ff G 0x00ff00 B 0xff0000 + public const int COLOR_RED = 0xff; //红色 + public const int COLOR_GREEN = 0xff00; //绿色 + public const int COLOR_YELLOW = 0xffff; //黄色 + + public const int ADDTYPE_STRING = 0; //添加类型为字符串 + public const int ADDTYPE_FILE = 1; //添加类型为文件 + + public const int OK = 0;//函数返回成功 + + //******节目定时启用日期时间星期的标志宏*************************************************************************** + public const int ENABLE_DATE = 0x01; + public const int ENABLE_TIME = 0x02; + public const int ENABLE_WEEK = 0x04; + //***************************************************************************************************************** + + //******节目定时星期里某天启用宏*********************************************************** + public const int WEEK_MON = 0x01; + public const int WEEK_TUES = 0x02; + public const int WEEK_WEN = 0x04; + public const int WEEK_THUR = 0x08; + public const int WEEK_FRI = 0x10; + public const int WEEK_SAT = 0x20; + public const int WEEK_SUN = 0x40; + //***************************************************************************** + + //[StructLayout(LayoutKind.Sequential, Size = 8, CharSet = CharSet.Unicode, Pack = 1)] + + //**通讯设置结构体********************************************************* + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct COMMUNICATIONINFO + { + public int LEDType; ////LED类型 0.6代T系A系XC系 1.6代E系 2.X1X2 3.7代C系 + public int SendType; //通讯方式 0.为Tcp发送(又称固定IP通讯), 1.广播发送(又称单机直连) 2.串口通讯 3.磁盘保存 4.广域网通讯 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string IpStr; //LED屏的IP地址,只有通讯方式为0时才需赋值,其它通讯方式无需赋值 + public int Commport; //串口号,只有通讯方式为2时才需赋值,其它通讯方式无需赋值 + public int Baud; //波特率,只有通讯方式为2时才需赋值,其它通讯方式无需赋值, 0.9600 1.57600 2.115200 直接赋值 9600,19200,38400,57600,115200亦可 + public int LedNumber; //LED的屏号,只有通讯方式为2时,且用485通讯时才需赋值,其它通讯方式无需赋值 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string OutputDir; //磁盘保存的目录,只有通讯方式为3时才需赋值,其它通讯方式无需赋值 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)] + public string networkIdStr; //网络ID,只有通讯方式为4时才需赋值,其它通讯方式无需赋值 + }; + //*********************************************************************** + + //**区域坐标结构体********************************************************* + public struct AREARECT + { + public int left; //区域左上角横坐标 + public int top; //区域左上角纵坐标 + public int width; //区域的宽度 + public int height; //区域的高度 + }; + //**************************************************************************** + //***字体属性结构对********************************************************** + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct FONTPROP + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string FontName; //字体名 + public int FontSize; //字号(单位磅) + public int FontColor; //字体颜色 + public int FontBold; //是否加粗 + public int FontItalic; //是否斜体 + public int FontUnderLine; //时否下划线 + }; + //**************************************************************************** + + //**页面显示的属性结构体**************************************************** + public struct PLAYPROP + { + public int InStyle; //入场特技值(取值范围 0-38) + public int OutStyle; //退场特技值(现无效,预留,置0) + public int Speed; //特技显示速度(取值范围1-255) 值越大,速度越慢 + public int DelayTime; //页面留停时间(1-65535) 注:当入场特技为连续左移、连续右移、连续上移、连续下移时,此参数无效 + }; + /* 特技值对应 + 0=立即显示 + 1=随机 + 2=左移 + 3=右移 + 4=上移 + 5=下移 + 6=连续左移 + 7=连续右移 + 8=连续上移 + 9=连续下移 + 10=闪烁 + 11=激光字(向上) + 12=激光字(向下) + 13=激光字(向左) + 14=激光字(向右) + 15=水平交叉拉幕 + 16=上下交叉拉幕 + 17=左右切入 + 18=上下切入 + 19=左覆盖 + 20=右覆盖 + 21=上覆盖 + 22=下覆盖 + 23=水平百叶(左右) + 24=水平百叶(右左) + 25=垂直百叶(上下) + 26=垂直百叶(下上) + 27=左右对开 + 28=上下对开 + 29=左右闭合 + 30=上下闭合 + 31=向左拉伸 + 32=向右拉伸 + 33=向上拉伸 + 34=向下拉伸 + 35=分散向左拉伸 + 36=分散向右拉伸 + 37=冒泡 + 38=下雪 + */ + //******************************************************************************* + //**设置节目定时属性结构体**************************************************** + public struct PROGRAMTIME + { + public int EnableFlag; //启用定时的标记,ENABLE_DATE为启用日期,ENABLE_TIME为启用时间,ENABLE_WEEK为启用星期,可用或运算进行组合,如 ENABLE_DATE | ENABLE_TIME | ENABLE_WEEK + public int WeekValue; //启用星期后,选择要定时的星期里的某些天,用宏 WEEK_MON,WEEK_TUES,WEEK_WEN,WEEK_THUR,WEEK_FRI,WEEK_SAT,WEEK_SUN 通过或运算进行组合 + public int StartYear; //起始年 + public int StartMonth; //起始月 + public int StartDay; //起始日 + public int StartHour; //起姐时 + public int StartMinute; //起始分 + public int StartSecond; //起始秒 + public int EndYear; //结束年 + public int EndMonth; //结束月 + public int EndDay; //结束日 + public int EndHour; //结束时 + public int EndMinute; //结束分 + public int EndSecond; //结束秒 + }; + //********************************************************************************** + //数字时钟属性结构体********************************************************************************* + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct DIGITALCLOCKAREAINFO + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string ShowStr; //自定义显示字符串 + //[MarshalAs(UnmanagedType.Struct)] + public FONTPROP ShowStrFont; //自定义显示字符串以及日期星期时间的字体属性,注意此字体属性里的FontColor只对自定义显示字体有效,其它项的颜色有单独的颜色属性,属性的赋值见FONTPROP结构体说明 + public int TimeLagType; //时差类型 0为超前,1为滞后 + public int HourNum; //时差小时数 + public int MiniteNum; //时差分钟数 + public int DateFormat; //日期格式 0.YYYY年MM月DD日 1.YY年MM月DD日 2.MM/DD/YYYY 3.YYYY/MM/DD 4.YYYY-MM-DD 5.YYYY.MM.DD 6.MM.DD.YYYY 7.DD.MM.YYYY + public int DateColor; //日期字体颜色 格式是16进制 BBGGRR(如:红色0xff 绿色0xff00 黄色0xffff) + public int WeekFormat; //星期格式 0.星期X 1.Monday 2.Mon. + public int WeekColor; //星期字体颜色 + public int TimeFormat; //时间格式 0.HH时mm分ss秒 1.HH時mm分ss秒 2.HH:mm:ss 3.上午 HH:mm:ss 4.AM HH:mm:ss 5.HH:mm:ss 上午 6.HH:mm:ss AM + public int TimeColor; //时间字体颜色 + public int IsShowYear; //是否显示年 TRUE为显示 FALSE不显示 下同 + public int IsShowWeek; //是否显示星期 + public int IsShowMonth; //是否显示月 + public int IsShowDay; //是否显示日 + public int IsShowHour; //是否显示时 + public int IsShowMinute; //是否显示分 + public int IsShowSecond; //是否显示秒 + public int IsMutleLineShow; //是否多行显示 + }; + //****************************************************************************** + //**模拟时钟属性结构体********************************************************* + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct CLOCKAREAINFO + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] + public string ShowStr; //自定义显示字符串 + public FONTPROP ShowStrFont; //自定义显示字符串字体属性 + public int TimeLagType; //时差类型 0为超前,1为滞后 + public int HourNum; //时差小时数 + public int MiniteNum; //时差分钟数 + public int ClockType; //表盘类型 0.圆形 1.正方形 + public int HourMarkColor; //时标颜色 格式是16进制 BBGGRR(如:红色0xff 绿色0xff00 黄色0xffff) + public int HourMarkType; //时标类型 0.圆形 1.正方形 + public int HourMarkWidth; //时标宽度 1~16 + public int MiniteMarkColor; //分标颜色 + public int MiniteMarkType; //分标类型 0.圆形 1.正方形 + public int MiniteMarkWidth; //分标宽度 1~16 + public int HourPointerColor; //时针颜色 + public int MinutePointerColor; //分针颜色 + public int SecondPointerColor; //秒针颜色 + public int HourPointerWidth; //时针的宽度 1~5 + public int MinutePointerWidth; //分针的宽度 1~5 + public int SecondPointerWidth; //秒针的宽度 1~5 + public int IsShowDate; //是否显示日期 + public int DateFormat; //日期格式 0.YYYY年MM月DD日 1.YY年MM月DD日 2.MM/DD/YYYY 3.YYYY/MM/DD 4.YYYY-MM-DD 5.YYYY.MM.DD 6.MM.DD.YYYY 7.DD.MM.YYYY + public FONTPROP DateFont; //日期字体属性 + public int IsShowWeek; //是否显示星期 + public int WeekFormat; //星期格式 0.星期X 1.Monday 2.Mon. + public FONTPROP WeekFont; //星期字体属性 + }; + //************************************************************************************** + + //**计时属性结构体********************************************************************** + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct TIMEAREAINFO + { + public int ShowFormat; //显示格式 0.xx天xx时xx分xx秒 1.xx天xx時xx分xx秒 2.xxDayxxHourxxMinxxSec 3.XXdXXhXXmXXs 4.xx:xx:xx:xx + public int nYear; //结束年 + public int nMonth; //结束月 + public int nDay; //结束日 + public int nHour; //结束时 + public int nMinute; //结束分 + public int nSecond; //结束秒 + public int IsShowDay; //是否显示天 + public int IsShowHour; //是否显示时 + public int IsShowMinute; //是否显示分 + public int IsShowSecond; //是否显示秒 + public int IsMutleLineShow; //是否多行显示,指的是自定义文字与计时文字是否分行显示 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string ShowStr; //自定义文字字符串 + public int TimeStrColor; //计时文字的颜色 + public FONTPROP ShowFont; //自定义文字及计时文字颜色,其中FontColor只对文定义文字有效,计时文字颜色为TimeStrColor + }; + //**************************************************************************************** + + + //**LED通讯参数修改结构体***************************************************************** + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct LEDCOMMUNICATIONPARAMETER + { + public int dwMask; //要修改项的标记 0.修改网络通讯参数 1.修改串口通讯参数 2.修改网口和串口通讯参数 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string IpStr; //新的IP地址,只有dwMask为0或2时才需赋值,其它值无需赋值,格式例如 192.168.1.100 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string NetMaskStr; //新的子网掩码,只有dwMask为0或2时才需赋值,其它值无需赋值,格式例如 255.255.255.0 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string GatewayStr; //新的网关,只有dwMask为0或2时才需赋值,其它值无需赋值,格式例如 192.168.1.1 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)] + public string MacStr; //新的MAC地址,只有dwMask为0或2时才需赋值,其它值无需赋值,格式例如 12-34-56-78-9a-bc,如无需修改请设为 ff-ff-ff-ff-ff-ff + public int Baud; //波特率,只有dwMask为1或2时才需赋值,其它值无需赋值,0.9600 1.57600 2.115200 + public int LedNumber; //LED屏号 1~255,网络通讯和232通讯赋值 1 即可,485必需和控制卡显示的屏号相同才可通讯 + }; + //***************************************************************************************** + + + //**流水边框属性结构体************************************************************************ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct WATERBORDERINFO + { + public int Flag; //流水边框加载类型标志,0.为动态库预置的边框 1.为从文件加载的边框 + public int BorderType; //边框的类型,Flag为0是有效,0.单色边框 1.双基色边框 2.全彩边框 + public int BorderValue; //边框的值,Flag为0是有效,单色边框取值范围是0~39,双基色边框取值范围是0~34,全彩边框取值范围是0~21 + public int BorderColor; //边框线颜色,Flag为0并且BorderType为0是才有效 + public int BorderStyle; //边框显示的样式 0.固定 1.顺时针 2.逆时针 3.闪烁 + public int BorderSpeed;//边框流动的速度 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string WaterBorderBmpPath; //边框图片文件的路径,注意只能是bmp图片,图片大小必需是宽度为32点,取高度小于等于8 + }; + //********************************************************************************************* + + + + //**定时开关屏设置属性************************************************************************ + public struct ONOFFTIMEINFO + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] TimeFlag; //支持3个定时,1代表打开 0关闭 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] StartHour; //开始时钟 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] StartMinute; //开始分钟 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] EndHour; //结束时钟 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] EndMinute; //结束分钟 + }; + //******************************************************************************************** + + //**定时亮度设置属性************************************************************************** + public struct BRIGHTNESSTIMEINFO + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] TimeFlag; //支持3个定时,1代表打开 0关闭 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] StartHour; //开始时钟 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] StartMinute; //开始分钟 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] EndHour; //结束时钟 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] EndMinute; //结束分钟 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[] BrightnessValue; //亮度值0~15 + }; + //******************************************************************************************* + + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public delegate int SERVERINFOCALLBACK(int Msg, int wParam, nint ptr); + + public enum LV_MSG + { + LV_MSG_NONE, + LV_MSG_CARD_ONLINE,//上线通知,通过CARD_INFO结构体指针获取详细上线信息 + LV_MSG_CARD_OFFLINE,//下线通知,通过CARD_INFO结构体指针获取详细下线信息 + }; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct CARD_INFO + { + public int port; //控制卡端口 + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string ipStr; //控制卡IP + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)] + public string networkIdStr; //控制卡唯一网络ID(每张卡都贴有唯一网络ID) + }; + /******************************************************************************************** +* LV_InitLed 初始化屏的类型和颜色顺序(C卡) +* 当Led上显示的文字区域的颜色与下发的不一致, 请的确认Led 屏的RGB顺序,并调用此接口 +* 参数说明 +* nLedType 屏类型 0.6代T系A系XC系 1.6代E系 2.X1X2 3.7代C系 4: E5,E6 +* nRgb 模组的RGB顺序,仅C卡有效,其他卡固定为0. C卡时, 0: R->G->B 1: G->R->B 2:R->B->G 3:B->R->G 4:B->G->R 5:G->B->R +* 返回值 无 +* +********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_InitLed", CharSet = CharSet.Unicode)] + public static extern void LV_InitLed(int nLedType, int nRgb); + + + /******************************************************************************************** + * LV_CreateProgramEx 创建节目对象,返回类型为 HPROGRAM + * + * 参数说明 + * LedWidth 屏的宽度 + * LedHeight 屏的高度 + * ColorType 屏的颜色 1.单色 2.双基色 3.三基色 注:C卡全彩参数为3 X系列卡参数固定为 4 + * GrayLevel 灰度等级 赋值 1-5对应的灰度等级分别为 无,4,8,16,32 注:目前C系列的卡才支持,其它型号(T,A,U,XC,W,E,X)参数必须为0 + * SaveType 节目保存位置,默认为0保存存为flash节目,3保存为ram节目 + * 注:flash节目掉电不清除,ram节目掉电清除。应用场景需要实时刷新的,建议保存为ram节目, 目前仅C卡程序才支持切换, + * 其他卡默认出货为flash程序,如果需要RAM程序请联系业务或者在官网下载,然后使用Led Player对卡进行升级 + * 返回值 + * 0 创建节目对象失败 + * 非0 创建节目对象成功 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_CreateProgramEx", CharSet = CharSet.Unicode)] + public static extern nint LV_CreateProgramEx(int LedWidth, int LedHeight, int ColorType, int GrayLevel, int SaveType); + + /********************************************************************************************* + * LV_AddProgram 添加一个节目 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * ProgramTime 节目播放时长 0.节目播放时长 非0.指定播放时长 + * LoopCount 循环播放次数 1-255 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddProgram", CharSet = CharSet.Unicode)] + public static extern int LV_AddProgram(nint hProgram, int ProgramNo, int ProgramTime, int LoopCount); + + /********************************************************************************************* + * LV_SetProgramTime 设置节目定时 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * pProgramTime 节目定时属性,设置方式见PROGRAMTIME结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_SetProgramTime", CharSet = CharSet.Unicode)] + public static extern int LV_SetProgramTime(nint hProgram, int ProgramNo, ref PROGRAMTIME pProgramTime); + + /********************************************************************************************* + * LV_AddImageTextArea 添加一个图文区域 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * pAreaRect 区域坐标属性,设置方式见AREARECT结构体注示 + * nLayout 区域层号,1.前景区(默认) 0.背景区 注:除C系列,其它默认为1 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddImageTextArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddImageTextArea(nint hProgram, int ProgramNo, int AreaNo, ref AREARECT pAreaRect, int nLayout); + + /********************************************************************************************* + * LV_AddFileToImageTextArea 添加一个文件到图文区 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * FilePath 文件路径,支持的文件类型有 txt rtf bmp gif png jpg jpeg tiff + * pPlayProp 显示的属性,设置方式见PLAYPROP结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddFileToImageTextArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddFileToImageTextArea(nint hProgram, int ProgramNo, int AreaNo, string FilePath, ref PLAYPROP pPlayProp); + + /********************************************************************************************* + * LV_AddSingleLineTextToImageTextArea 添加一个单行文本到图文区 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * AddType 添加的类型 0.为字符串 1.文件(只支持txt和rtf文件) + * AddStr AddType为0则为字符串数据,AddType为1则为文件路径 + * pFontProp 如果AddType为字符串类型或AddType为文件类型且文件为txt则可传入以赋值的该结构体,其它可赋NULL + * pPlayProp 显示的属性,设置方式见PLAYPROP结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddSingleLineTextToImageTextArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddSingleLineTextToImageTextArea(nint hProgram, int ProgramNo, int AreaNo, int AddType, string AddStr, ref FONTPROP pFontProp, ref PLAYPROP pPlayProp); + + /********************************************************************************************* + * LV_AddMultiLineTextToImageTextArea 添加一个多行文本到图文区 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * AddType 添加的类型 0.为字符串 1.文件(只支持txt和rtf文件) + * AddStr AddType为0则为字符串数据,AddType为1则为文件路径 换行符(\n) + * pFontProp 如果AddType为字符串类型或AddType为文件类型且文件为txt则可传入以赋值的该结构体,其它可赋NULL + * pPlayProp 显示的属性,设置方式见PLAYPROP结构体注示 + * nAlignment 水平对齐样式,0.左对齐 1.右对齐 2.水平居中 (注意:只对字符串和txt文件有效) + * IsVCenter 是否垂直居中 0.置顶(默认) 1.垂直居中 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddMultiLineTextToImageTextArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddMultiLineTextToImageTextArea(nint hProgram, int ProgramNo, int AreaNo, int AddType, string AddStr, ref FONTPROP pFontProp, ref PLAYPROP pPlayProp, int nAlignment, int IsVCenter); + + /********************************************************************************************* + * LV_AddStaticTextToImageTextArea 添加一个静止文本到图文区 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * AddType 添加的类型 0.为字符串 1.文件(只支持txt和rtf文件) + * AddStr AddType为0则为字符串数据,AddType为1则为文件路径 + * pFontProp 如果AddType为字符串类型或AddType为文件类型且文件为txt则可传入以赋值的该结构体,其它可赋NULL + * DelayTime 显示的时长 1~65535 + * nAlignment 水平对齐样式,0.左对齐 1.右对齐 2.水平居中 (注意:只对字符串和txt文件有效) + * IsVCenter 是否垂直居中 0.置顶(默认) 1.垂直居中 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddStaticTextToImageTextArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddStaticTextToImageTextArea(nint hProgram, int ProgramNo, int AreaNo, int AddType, string AddStr, ref FONTPROP pFontProp, int DelayTime, int nAlignment, int IsVCenter); + + /********************************************************************************************* + * LV_QuickAddSingleLineTextArea 快速添加一个向左移的单行文本区域 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * pAreaRect 区域坐标属性,设置方式见AREARECT结构体注示 + * AddType 添加的类型 0.为字符串 1.文件(只支持txt和rtf文件) + * AddStr AddType为0则为字符串数据,AddType为1则为文件路径 + * pFontProp 如果AddType为字符串类型或AddType为文件类型且文件为txt则可传入以赋值的该结构体,其它可赋NULL + * nSpeed 滚动速度 1~255 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_QuickAddSingleLineTextArea", CharSet = CharSet.Unicode)] + public static extern int LV_QuickAddSingleLineTextArea(nint hProgram, int ProgramNo, int AreaNo, ref AREARECT pAreaRect, int AddType, string AddStr, ref FONTPROP pFontProp, int nSpeed); + + /********************************************************************************************* + * LV_AddDigitalClockArea 添加一个数字时钟区域 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * pAreaRect 区域坐标属性,设置方式见AREARECT结构体注示 + * pDigitalClockAreaInfo 数字时钟属性,见DIGITALCLOCKAREAINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddDigitalClockArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddDigitalClockArea(nint hProgram, int ProgramNo, int AreaNo, ref AREARECT pAreaRect, ref DIGITALCLOCKAREAINFO pDigitalClockAreaInfo); + + /********************************************************************************************* + * LV_AddTimeArea 添加一个计时区域 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号(取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * pAreaRect 区域坐标属性,设置方式见AREARECT结构体注示 + * pTimeAreaInfo 计时属性,见TIMEAREAINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddTimeArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddTimeArea(nint hProgram, int ProgramNo, int AreaNo, ref AREARECT pAreaRect, ref TIMEAREAINFO pTimeAreaInfo); + + /********************************************************************************************* + * LV_AddClockArea 添加一个模拟时钟区域 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * pAreaRect 区域坐标属性,设置方式见AREARECT结构体注示 + * pClockAreaInfo 模拟时钟属性,见CLOCKAREAINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddClockArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddClockArea(nint hProgram, int ProgramNo, int AreaNo, ref AREARECT pAreaRect, ref CLOCKAREAINFO pClockAreaInfo); + + /********************************************************************************************* + * LV_AddNeiMaArea 添加一个内码区域 + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 从0开始(0-255) + * AreaNo 区域号 (1-255) + * pAreaRect 区域坐标属性,设置方式见AREARECT结构体注示 + * 除C卡外的其他卡,内码区域的起点X和Y坐标必须为8的整数倍,如0,8,16等, 宽高必须大于所用字体大小 + * NeiMaStr 文本字符串 注:字符串编码是GB2312 + * FontSize 字体大小 16 24 32 + * FontColor 文字颜色 格式BBGGRR 0xff 红色 0xff00 绿色 0xffff黄色 + * pPlayProp 显示的属性,设置方式见PLAYPROP结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddNeiMaArea", CharSet = CharSet.Unicode)] + public static extern int LV_AddNeiMaArea(nint hProgram, int ProgramNo, int AreaNo, ref AREARECT pAreaRect, string NeiMaStr, int FontSize, int FontColor, ref PLAYPROP pPlayProp); + + + /********************************************************************************************* + * LV_RefreshNeiMaArea 刷新内码区域 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * NeiMaStr 刷新的数据字符串,格式可以查看<<内码区域局部更新协议>>文档 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_RefreshNeiMaArea", CharSet = CharSet.Unicode)] + public static extern int LV_RefreshNeiMaArea(ref COMMUNICATIONINFO pCommunicationInfo, string NeiMaStr); + + /********************************************************************************************* + * LV_AddWaterBorder 添加一个流水边框区域 + * + * 参数说明 + * hProgram 节目对象句柄 + * ProgramNo 节目号 (取值范围0-255)(从0开始) + * AreaNo 区域号 (取值范围1-255) + * pAreaRect 区域坐标属性,设置方式见AREARECT结构体注示 + * pWaterBorderInfo 流水边框属性,见WATERBORDERINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AddWaterBorder", CharSet = CharSet.Unicode)] + public static extern int LV_AddWaterBorder(nint hProgram, int ProgramNo, int AreaNo, ref AREARECT pAreaRect, ref WATERBORDERINFO pWaterBorderInfo); + + /********************************************************************************************* + * LV_DeleteProgram 销毁节目对象(注意:如果此节目对象不再使用,请调用此函数销毁,否则会造成内存泄露) + * + * 参数说明 + * hProgram 节目对象句柄 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_DeleteProgram", CharSet = CharSet.Unicode)] + public static extern void LV_DeleteProgram(nint hProgram); + + /********************************************************************************************* + * LV_Send 发送节目,此发送为一对一发送 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * hProgram 节目对象句柄 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_Send", CharSet = CharSet.Unicode)] + public static extern int LV_Send(ref COMMUNICATIONINFO pCommunicationInfo, nint hProgram); + + /********************************************************************************************* + * LV_TestOnline 测试LED屏是否可连接上 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_TestOnline", CharSet = CharSet.Unicode)] + public static extern int LV_TestOnline(ref COMMUNICATIONINFO pCommunicationInfo); + + /********************************************************************************************* + * LV_SetBasicInfoEx 设置基本屏参 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * ColorType 屏的颜色 1.单色 2.双基色 3.三基色 注:C卡全彩参数为3 X系列卡参数固定为 4 + * GrayLevel 灰度等级 赋值 1-5对应的灰度等级分别为 无,4,8,16,32 注:目前C系列的卡才支持,其它型号(T,A,U,XC,W,E,X)参数必须为0 + * LedWidth 屏的宽度点数 + * LedHeight 屏的高度点数 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_SetBasicInfoEx", CharSet = CharSet.Unicode)] + public static extern int LV_SetBasicInfoEx(ref COMMUNICATIONINFO pCommunicationInfo, int ColorType, int GrayLevel, int LedWidth, int LedHeight); + + /********************************************************************************************* + * LV_SetOEDA 设置OE DA + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * Oe OE 0.低有效 1.高有效 + * Da DA 0.负极性 1.正极性 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_SetOEDA", CharSet = CharSet.Unicode)] + public static extern int LV_SetOEDA(ref COMMUNICATIONINFO pCommunicationInfo, int Oe, int Da); + + /********************************************************************************************* + * LV_AdjustTime 校时 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_AdjustTime", CharSet = CharSet.Unicode)] + public static extern int LV_AdjustTime(ref COMMUNICATIONINFO pCommunicationInfo); + + /********************************************************************************************* + * LV_PowerOnOff 开关屏 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * OnOff 开关值 0.开屏 1.关屏 2.重启(仅支持C卡) + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_PowerOnOff", CharSet = CharSet.Unicode)] + public static extern int LV_PowerOnOff(ref COMMUNICATIONINFO pCommunicationInfo, int OnOff); + + /********************************************************************************************* + * LV_TimePowerOnOff 定时开关屏 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * pTimeInfo 定时开关屏属性,详见ONOFFTIMEINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_TimePowerOnOff", CharSet = CharSet.Unicode)] + public static extern int LV_TimePowerOnOff(ref COMMUNICATIONINFO pCommunicationInfo, ref ONOFFTIMEINFO pTimeInfo); + + /********************************************************************************************* + * LV_SetBrightness 设置亮度 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * BrightnessValue 亮度值 0~15 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_SetBrightness", CharSet = CharSet.Unicode)] + public static extern int LV_SetBrightness(ref COMMUNICATIONINFO pCommunicationInfo, int BrightnessValue); + + /********************************************************************************************* + * LV_TimeBrightness 定时亮度 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * pBrightnessTimeInfo 定时亮度属性,详见BRIGHTNESSTIMEINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_TimeBrightness", CharSet = CharSet.Unicode)] + public static extern int LV_TimeBrightness(ref COMMUNICATIONINFO pCommunicationInfo, ref BRIGHTNESSTIMEINFO pBrightnessTimeInfo); + + /********************************************************************************************* + * LV_LedTest LED测试 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * TestValue 测试值 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_LedTest", CharSet = CharSet.Unicode)] + public static extern int LV_LedTest(ref COMMUNICATIONINFO pCommunicationInfo, int TestValue); + + /********************************************************************************************* + * LV_TimeLocker LED定时锁屏 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * LockerYear 锁屏年 + * LockerMonth 锁屏月 + * LockerDay 锁屏日 + * LockerHour 锁屏时 + * LockerMinute 锁屏分 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_TimeLocker", CharSet = CharSet.Unicode)] + public static extern int LV_TimeLocker(ref COMMUNICATIONINFO pCommunicationInfo, int LockerYear, int LockerMonth, int LockerDay, int LockerHour, int LockerMinute); + + /********************************************************************************************* + * LV_CancelLocker 取消定时锁屏 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_CancelLocker", CharSet = CharSet.Unicode)] + public static extern int LV_CancelLocker(ref COMMUNICATIONINFO pCommunicationInfo); + + /********************************************************************************************* + * LV_SetLedCommunicationParameter 设置LED通讯参数 + * + * 参数说明 + * pCommunicationInfo 通讯参数,赋值方式见COMMUNICATIONINFO结构体注示 + * pLedCommunicationParameter 详见LEDCOMMUNICATIONPARAMETER结构体注示 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_SetLedCommunicationParameter", CharSet = CharSet.Unicode)] + public static extern int LV_SetLedCommunicationParameter(ref COMMUNICATIONINFO pCommunicationInfo, ref LEDCOMMUNICATIONPARAMETER pLedCommunicationParameter); + /********************************************************************************************* + * LV_LedInitServer 启动控制卡心跳包服务 注:C2M、C4M才支持 + * + * 参数说明 + * port 监听的端口 + * 返回值 + * 0 成功 + * 非0 失败,调用LV_GetError来获取错误信息 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_LedInitServer", CharSet = CharSet.Unicode)] + public static extern int LV_LedInitServer(int port); + /********************************************************************************************* + * LV_LedShudownServer 断开控制卡心跳包服务 注:C2M、C4M才支持 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_LedShudownServer", CharSet = CharSet.Unicode)] + public static extern int LV_LedShudownServer(); + /********************************************************************************************* + * LV_RegisterLedServerCallback 注册回调函数 注:C2M、C4M才支持 + * + * 参数说明 + * serverCallback 回调函数 + ********************************************************************************************/ + [DllImport("lv_led_64.dll", EntryPoint = "LV_RegisterLedServerCallback", CharSet = CharSet.Unicode)] + public static extern int LV_RegisterLedServerCallback(SERVERINFOCALLBACK serverCallback); + + /********************************************************************************************* + * LV_GetError 获取错误信息(只支持中文) + * + * 参数说明 + * nErrCode 函数执行返回的错误代码 + * 返回值 + * 错误信息字符串 + ********************************************************************************************/ + public static string LS_GetError(int nErrCode) + { + string ErrStr = nErrCode switch + { + -1 => "无效的节目句柄。", + -2 => "节目已经存在。", + -3 => "指定的节目不存在。", + -4 => "定的区域不存在。", + -5 => "创建socket失败。", + -6 => "错误的回复包。", + -7 => "不支持的文件类型。", + -8 => "IP网关掩码或MAC字符串格式错误。", + -9 => "错误的波特率。", + -10 => "文件路径不存在。", + -11 => "区域重叠。", + -12 => "打开文件失败。", + -14 => "区域已存在。", + -15 => "无效的发送类型。", + -16 => "绘图失败。", + -17 => "创建文件夹失败。", + -30 => "打开串口失败。", + -31 => "设置串口超时失败。", + -32 => "设置串口缓冲区失败。", + -33 => "串口发送数据失败。", + -34 => "串口接收数据失败。", + -35 => "串口设置失败。", + -36 => "串口接收数据超时。", + -37 => "USB不支持群发。", + -38 => "发送取消。", + -100 => "网络连接失败。", + -101 => "网络发送失败。", + -102 => "网络接收数据失败。", + -103 => "bind失败。", + -104 => "无可用网卡。", + 0xc140 => "Logo与参屏大小不适应。", + 0xdaa3 => "控制器繁忙。", + 0xd5b0 => "固件程序型号不匹配。", + 0xd5b4 => "不是有效的固件程序。", + 0xdab8 => "节目颜色或屏宽高与控制卡屏参设定值不一致。", + 0xc1ba => "超出控制卡带载。", + 0xdab5 => "节目数据大小超过允许的最大值。", + _ => "未定义错误。", + }; + return ErrStr; + } + +} \ No newline at end of file diff --git a/Tools/LedSimple/LedSimple.csproj b/Tools/LedSimple/LedSimple.csproj new file mode 100644 index 0000000..e49f24c --- /dev/null +++ b/Tools/LedSimple/LedSimple.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + true + + + + + Always + + + Always + + + + diff --git a/Tools/LedSimple/lv_led_64.dll b/Tools/LedSimple/lv_led_64.dll new file mode 100644 index 0000000..fabcd78 Binary files /dev/null and b/Tools/LedSimple/lv_led_64.dll differ diff --git a/Tools/LogTool/LogTool.csproj b/Tools/LogTool/LogTool.csproj new file mode 100644 index 0000000..0191b67 --- /dev/null +++ b/Tools/LogTool/LogTool.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + + + diff --git a/Tools/LogTool/WcsLog.cs b/Tools/LogTool/WcsLog.cs new file mode 100644 index 0000000..ba5cd73 --- /dev/null +++ b/Tools/LogTool/WcsLog.cs @@ -0,0 +1,104 @@ +using System.Text; + +namespace LogTool; + +public class WcsLog +{ + private static WcsLog? instance; + + public static WcsLog Instance() + { + instance ??= new WcsLog(); + return instance; + } + + + private static readonly object writeLog = new(); + /// + /// 通用写日志类 + /// + /// 文件夹名称 + /// 日志内容 + /// 是否在日志中自动添加时间 + public void WriteLog(string LogName, string strLog, bool addTime = true) + { + Task.Factory.StartNew(() => + { + lock (writeLog) + { + string LogAddress = AppDomain.CurrentDomain.BaseDirectory + "Log\\" + LogName; + StringBuilder logBuilder = new(); + if (addTime) + { + logBuilder.AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss:fff}]"); + } + logBuilder.AppendLine($"{strLog}"); + DirectoryInfo di = new(LogAddress); + if (di.Exists == false) { di.Create(); } + string logFileName = LogAddress + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".log"; + using FileStream fs = new(logFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + using StreamWriter sw = new(fs); + try + { + sw.WriteLine(logBuilder); + } + catch (Exception ex) + { + _ = ex; + } + } + }); + } + + /// + /// 写系统日志 + /// + /// + public void WriteSystemLog(string strLog) => WriteLog("系统日志", strLog); + + /// + /// 写事件日志 + /// + /// + public void WriteEventLog(string strLog) => WriteLog("事件日志", strLog); + /// + /// 写事件日志 + /// + /// + public void WriteEventLog(StringBuilder strLog) => WriteLog("事件日志", strLog.ToString(), false); + + /// + /// 写入Tcp日志 + /// + /// + public void WriteTcpLog(StringBuilder strLog) => WriteLog("Tcp日志", strLog.ToString(), false); + + /// + /// 写接口日志 + /// + /// + public void WriteApiRequestLog(string strLog) => WriteLog("接口请求日志", strLog); + + /// + /// 写异常日志 + /// + /// + public void WriteExceptionLog(string strLog) => WriteLog("异常日志", strLog); + /// + /// 写异常日志 + /// + /// + public void WriteExceptionLog(StringBuilder strLog) => WriteLog("异常日志", strLog.ToString(), false); + + /// + /// 写数据库日志 + /// + /// + public void WriteSQLLog(string strLog) => WriteLog("数据库日志", strLog); + + /// + /// 写接口接收日志 + /// + /// + public void WriteApiAcceptLog(string strLog) => WriteLog("接口接收日志", strLog); +} \ No newline at end of file diff --git a/Tools/PlcTool/PlcTool.csproj b/Tools/PlcTool/PlcTool.csproj new file mode 100644 index 0000000..dc01f7f --- /dev/null +++ b/Tools/PlcTool/PlcTool.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + + + + + + + + diff --git a/Tools/PlcTool/Siemens/DataConvert.cs b/Tools/PlcTool/Siemens/DataConvert.cs new file mode 100644 index 0000000..ba3d8e6 --- /dev/null +++ b/Tools/PlcTool/Siemens/DataConvert.cs @@ -0,0 +1,72 @@ +using HslCommunication; +using HslCommunication.Profinet.Siemens; +using PlcTool.Siemens.Entity; + +namespace PlcTool.Siemens; + +/// +/// 数据转换类 +/// +public static class DataConvert +{ + + /// + /// 将string转化为西门子PLC类型 + /// 不满足条件的转化为1200 + /// 支持的string: + /// 1500 + /// 1200 + /// 300 + /// 400 + /// 200 + /// 200s + /// + /// + /// + public static SiemensPLCS ToPlcKind(this string? plcKandStr) + { + return plcKandStr switch + { + "1500" => SiemensPLCS.S1500, + "1200" => SiemensPLCS.S1200, + "400" => SiemensPLCS.S400, + "300" => SiemensPLCS.S300, + "200s" => SiemensPLCS.S200Smart, + "200" => SiemensPLCS.S200, + _ => SiemensPLCS.S1200, + }; + } + + /// + /// PLC读写固定返回类 + /// 返回一个新的类, + /// + /// + /// + public static SemS7Result ToSemS7Result(this OperateResult operateResult) + { + return new SemS7Result() + { + Success = operateResult.IsSuccess, + ErrCode = operateResult.ErrorCode, + Message = operateResult.Message + }; + } + /// + /// PLC读写固定返回类 + /// 返回一个新的类, + /// + /// + /// + /// + public static SemS7Result ToSemS7Result(this OperateResult operateResult) + { + return new SemS7Result() + { + Success = operateResult.IsSuccess, + ErrCode = operateResult.ErrorCode, + Message = operateResult.Message, + Value = operateResult.Content + }; + } +} \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/Entity/PlcDBName.cs b/Tools/PlcTool/Siemens/Entity/PlcDBName.cs new file mode 100644 index 0000000..defbf4f --- /dev/null +++ b/Tools/PlcTool/Siemens/Entity/PlcDBName.cs @@ -0,0 +1,13 @@ +namespace PlcTool.Siemens.Entity; + +/// +/// DB 信息 +/// +public class PlcDBName +{ + public uint? PlcId { get; set; } + + public string? DBName { get; set; } + + public string? DBAddress { get; set; } +} \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/Entity/SemS7Result.cs b/Tools/PlcTool/Siemens/Entity/SemS7Result.cs new file mode 100644 index 0000000..65cd207 --- /dev/null +++ b/Tools/PlcTool/Siemens/Entity/SemS7Result.cs @@ -0,0 +1,32 @@ +using Newtonsoft.Json; +using System.Text; + +namespace PlcTool.Siemens.Entity; + +public class SemS7Result +{ + + public bool Success { get; set; } = false; + + public int? ErrCode { get; set; } + + public string? Message { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } +} + +/// +/// PLC操作的返回泛型类 +/// +/// +public class SemS7Result : SemS7Result +{ + public T? Value { get; set; } + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } +} \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/Entity/SiemensS7Connection.cs b/Tools/PlcTool/Siemens/Entity/SiemensS7Connection.cs new file mode 100644 index 0000000..59eb467 --- /dev/null +++ b/Tools/PlcTool/Siemens/Entity/SiemensS7Connection.cs @@ -0,0 +1,19 @@ +using HslCommunication.Profinet.Siemens; + +namespace PlcTool.Siemens.Entity; + +/// +/// PLC 连接信息类 +/// +public class SiemensS7Connection +{ + /// + /// PLC 的编号 + /// + public int? PlcId { get; set; } + + /// + /// 连接信息 + /// + public SiemensS7Net? SiemensS7 { get; set; } +} \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/PLCAttribute/PlcDBAddressAttribute.cs b/Tools/PlcTool/Siemens/PLCAttribute/PlcDBAddressAttribute.cs new file mode 100644 index 0000000..2b0233e --- /dev/null +++ b/Tools/PlcTool/Siemens/PLCAttribute/PlcDBAddressAttribute.cs @@ -0,0 +1,7 @@ +namespace PlcTool.Siemens.PLCAttribute; + +/// +/// 用于标记 PLC 通讯地址 +/// +[AttributeUsage(AttributeTargets.Property)] +public class PlcDBAddressAttribute : Attribute { } \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/PLCAttribute/PlcDBNameAttribute.cs b/Tools/PlcTool/Siemens/PLCAttribute/PlcDBNameAttribute.cs new file mode 100644 index 0000000..6489a52 --- /dev/null +++ b/Tools/PlcTool/Siemens/PLCAttribute/PlcDBNameAttribute.cs @@ -0,0 +1,7 @@ +namespace PlcTool.Siemens.PLCAttribute; + +/// +/// 用于标记 PLC 通讯地址的名称 +/// +[AttributeUsage(AttributeTargets.Property)] +public class PlcDBNameAttribute : Attribute { } \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/PLCAttribute/PlcIPAttribute.cs b/Tools/PlcTool/Siemens/PLCAttribute/PlcIPAttribute.cs new file mode 100644 index 0000000..33db43b --- /dev/null +++ b/Tools/PlcTool/Siemens/PLCAttribute/PlcIPAttribute.cs @@ -0,0 +1,7 @@ +namespace PlcTool.Siemens.PLCAttribute; + +/// +/// 用于标记 PLC 的IP +/// +[AttributeUsage(AttributeTargets.Property)] +public class PlcIPAttribute : Attribute { } \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/PLCAttribute/PlcIdAttribute.cs b/Tools/PlcTool/Siemens/PLCAttribute/PlcIdAttribute.cs new file mode 100644 index 0000000..9ca844b --- /dev/null +++ b/Tools/PlcTool/Siemens/PLCAttribute/PlcIdAttribute.cs @@ -0,0 +1,7 @@ +namespace PlcTool.Siemens.PLCAttribute; + +/// +/// 用于标记 PLC 的编号 +/// +[AttributeUsage(AttributeTargets.Property)] +public class PlcIdAttribute : Attribute { } \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/PLCAttribute/PlcKindAttribute.cs b/Tools/PlcTool/Siemens/PLCAttribute/PlcKindAttribute.cs new file mode 100644 index 0000000..2f6b7ec --- /dev/null +++ b/Tools/PlcTool/Siemens/PLCAttribute/PlcKindAttribute.cs @@ -0,0 +1,16 @@ +namespace PlcTool.Siemens.PLCAttribute; + +/// +/// 用于标记PLC的系列 +/// +/// +/// 支持的string: +/// 1500 +/// 1200 +/// 300 +/// 400 +/// 200 +/// 200s +/// +[AttributeUsage(AttributeTargets.Property)] +public class PlcKindAttribute : Attribute { } \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/PLCAttribute/RackAttribute.cs b/Tools/PlcTool/Siemens/PLCAttribute/RackAttribute.cs new file mode 100644 index 0000000..a2fa896 --- /dev/null +++ b/Tools/PlcTool/Siemens/PLCAttribute/RackAttribute.cs @@ -0,0 +1,7 @@ +namespace PlcTool.Siemens.PLCAttribute; + +/// +/// plc 机架 +/// +[AttributeUsage(AttributeTargets.Property)] +public class RackAttribute : Attribute { } \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/PLCAttribute/SlotAttribute.cs b/Tools/PlcTool/Siemens/PLCAttribute/SlotAttribute.cs new file mode 100644 index 0000000..4d33bb4 --- /dev/null +++ b/Tools/PlcTool/Siemens/PLCAttribute/SlotAttribute.cs @@ -0,0 +1,7 @@ +namespace PlcTool.Siemens.PLCAttribute; + +/// +/// plc 插槽 +/// +[AttributeUsage(AttributeTargets.Property)] +public class SlotAttribute : Attribute { } \ No newline at end of file diff --git a/Tools/PlcTool/Siemens/SiemensS7.cs b/Tools/PlcTool/Siemens/SiemensS7.cs new file mode 100644 index 0000000..ca1aca4 --- /dev/null +++ b/Tools/PlcTool/Siemens/SiemensS7.cs @@ -0,0 +1,827 @@ +using System.Reflection; +using System.Text; +using HslCommunication; +using HslCommunication.Profinet.Siemens; +using PlcTool.Siemens.Entity; +using PlcTool.Siemens.PLCAttribute; + +namespace PlcTool.Siemens; + +public class SiemensS7 +{ + + /* + * 作者:菻蔃 + * + * 版本时间:2023年4月15日 + * + */ + + private const string tip = "致其他开发者,此组件为收费组件,若您有意使用,请自行联系作者购买授权,擅自使用本公司激活码将承担责任"; + + /// + /// 存储PLC连接 + /// + readonly List siemensS7Connections = []; + + /// + /// 存储DB块具体在哪个PLC中 + /// + readonly List plcDBNames = []; + + + + /// + /// 操作PLC的类,传入PLC类型,地址,和组件激活码。 + /// + /// + /// + public SiemensS7(string? authorizationCode = null) + { + if (string.IsNullOrEmpty(authorizationCode)) + { + /*致本公司开发者,此为 10.6.1 版本激活码,若激活失败,尝试使用此版本*/ + /*致其他开发者,此组件为收费组件,若您有意使用,请自行联系作者购买授权,擅自使用本公司激活码将承担责任*/ + authorizationCode = "f562cc4c-4772-4b32-bdcd-f3e122c534e3"; + } + bool isAuthorization = Authorization.SetAuthorizationCode(authorizationCode); + if (!isAuthorization) + { + /*这里抛出异常,一定记得提醒开发者注册*/ + throw new Exception("组件未激活,上述激活码可能会因为版本更新而失效,请联系公司获取最新激活码,测试时可注释此行,未激活将只能使用24小时,切记上线前一定记得激活!!!"); + } + } + + /// + /// 添加PLC信息 + /// + /// + /// + /// + public SiemensS7 SetPlcs(List plcs) where T : class + { + if (plcs == null || plcs.Count == 0) + { + throw new Exception("传入数据为空。"); + } + Type type = typeof(T); + var properties = type.GetProperties(); + /*定义两个存储属性的变量*/ + PropertyInfo? plcIdProperty = null; + PropertyInfo? plcIPProperty = null; + PropertyInfo? plcKindProperty = null; + PropertyInfo? rackProperty = null; + PropertyInfo? soltindProperty = null; + /*轮询查找到的属性给变量赋值*/ + foreach (var property in properties) + { + var plcIdattributes = property.GetCustomAttributes(typeof(PlcIdAttribute), false); + if (plcIdattributes.Length != 0) + { + plcIdProperty = property; + } + var plcIPattributes = property.GetCustomAttributes(typeof(PlcIPAttribute), false); + if (plcIPattributes.Length != 0) + { + plcIPProperty = property; + } + var plcKindattributes = property.GetCustomAttributes(typeof(PlcKindAttribute), false); + if (plcKindattributes.Length != 0) + { + plcKindProperty = property; + } + var rackattributes = property.GetCustomAttributes(typeof(RackAttribute), false); + if (rackattributes.Length != 0) + { + rackProperty = property; + } + var soltattributes = property.GetCustomAttributes(typeof(SlotAttribute), false); + if (soltattributes.Length != 0) + { + soltindProperty = property; + } + } + /*判断是否有对应的特性*/ + if (plcIdProperty == null || plcIPProperty == null || plcKindProperty == null) + { + throw new Exception("未正确识别类中的属性特性,需要同时添加 PlcIdAttribution、PlcIPAttribute 和 PlcKindAttribute 三个特性。"); + } + /*添加对应的值*/ + foreach (T plc in plcs) + { + var plckind = plcKindProperty.GetValue(plc)!.ToString().ToPlcKind(); + var plcip = plcIPProperty.GetValue(plc)!.ToString(); + + SiemensS7Connection siemensS7Connection = new() + { + PlcId = Convert.ToInt32(plcIdProperty.GetValue(plc)), + SiemensS7 = new SiemensS7Net(plckind, plcip) + }; + siemensS7Connection.SiemensS7.Rack = Convert.ToByte(rackProperty!.GetValue(plc)); + siemensS7Connection.SiemensS7.Slot = Convert.ToByte(soltindProperty!.GetValue(plc)); + siemensS7Connections.Add(siemensS7Connection); + } + return this; + } + + /// + /// 添加PLC的Db地址信息 + /// + /// + /// + /// + public SiemensS7 SetPlcDB(List? dbNames) where T : class + { + if (dbNames == default || dbNames.Count == 0) + { + throw new Exception("传入的数据为空"); + } + Type type = typeof(T); + var properties = type.GetProperties(); + /*定义两个存储属性的变量*/ + PropertyInfo? plcIdProperty = null; + PropertyInfo? dbNameProperty = null; + PropertyInfo? dbAddressProperty = null; + /*轮询查找到的属性给变量赋值*/ + foreach (var property in properties) + { + var plcIdattributes = property.GetCustomAttributes(typeof(PlcIdAttribute), false); + if (plcIdattributes.Length != 0) + { + plcIdProperty = property; + } + var dbNameattributes = property.GetCustomAttributes(typeof(PlcDBNameAttribute), false); + if (dbNameattributes.Length != 0) + { + dbNameProperty = property; + } + var dbAddressattributes = property.GetCustomAttributes(typeof(PlcDBAddressAttribute), false); + if (dbAddressattributes.Length != 0) + { + dbAddressProperty = property; + } + } + /*判断是否有对应的特性*/ + if (plcIdProperty == null || dbNameProperty == null || dbAddressProperty == null) + { + throw new Exception("未正确识别类中的属性特性,需要同时添加 PlcIdAttribute、PlcDBNameAttribute、PlcDBAddressAttribute 三个特性。"); + } + /*添加对应的值*/ + foreach (T dbName in dbNames) + { + PlcDBName plcDBName = new() + { + PlcId = Convert.ToUInt32(plcIdProperty.GetValue(dbName)), + DBName = dbNameProperty.GetValue(dbName)!.ToString(), + }; + var dbaddress = dbAddressProperty.GetValue(dbName); + plcDBName.DBAddress = dbaddress == null ? "" : dbaddress.ToString(); + plcDBNames.Add(plcDBName); + } + return this; + } + + + /// + /// 连接PLC + /// + /// + /// 请使用异步重载方法 + /// + public SemS7Result ConnectPlcs() + { + if (siemensS7Connections.Count == 0) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = "没有设置PLC连接,请先调用 SetPlcs 方法。" + }; + } + /*连接PLC*/ + foreach (SiemensS7Connection siemensS7Connection in siemensS7Connections) + { + if (siemensS7Connection.SiemensS7 == default) + { + continue; + } + siemensS7Connection.SiemensS7.ConnectTimeOut = 2000; + var connectResult = siemensS7Connection.SiemensS7.ConnectServer(); + if (!connectResult.IsSuccess) + { + // 只要有一个连接失败,直接返回错误信息 + connectResult.Message = + $"PLC:{siemensS7Connection.SiemensS7.IpAddress} 连接失败,异常信息:{connectResult.Message}"; + return connectResult.ToSemS7Result(); + } + } + return new SemS7Result() + { + Success = true, + ErrCode = 0, + Message = "所有PLC连接成功" + }; + } + + #region 根据名称读写PLC数据 + + + /// + /// 根据名称写入PLC值,目前不支持 string + /// 写入前请提前转换好对应的数据格式 + /// + /// + /// + /// + public (SemS7Result result, byte[]? bytes) WritePlcWhithName(string plcDBName, params object[] values) + { + if (values.Length == 0) + { + return (new SemS7Result() + { + Success = false, + ErrCode = 997, + Message = $"写入失败,传入的值为空。" + }, default); + } + /*根据名称获取地址*/ + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return (new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }, default); + } + (Exception? Ex, byte[]? bytes) getByte = GetPlcBytes(values); + if (getByte.Ex != null) + { + return (new SemS7Result() + { + Success = false, + ErrCode = 996, + Message = $"{getByte.Ex.Message}" + }, default); + } + byte[]? bytes = getByte.bytes;//获取转化成功的数组 + OperateResult operateResult = siemensS7.Write(dbAddress, bytes); + return (operateResult.ToSemS7Result(), bytes); + } + + /// + /// 写入bool值 + /// + /// + /// + /// + public SemS7Result WriteBoolWhithName(string plcDBName, params bool[] values) + { + if (values.Length == 0) + { + return new SemS7Result() + { + Success = false, + ErrCode = 997, + Message = $"写入失败,传入的值为空。" + }; + } + /*根据名称获取地址*/ + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + OperateResult operateResult = siemensS7.Write(dbAddress, values); + return operateResult.ToSemS7Result(); + } + + /// + /// 根据地址写入值 + /// + /// /// + /// + /// + /// + public SemS7Result WritePlcWhithAddress(int plcNo, string plcDBAddress, params object[] values) + { + if (values.Length == 0) + { + return new SemS7Result() + { + Success = false, + ErrCode = 997, + Message = $"写入失败,传入的值为空。" + }; + } + /*根据名称获取地址*/ + SiemensS7Net? siemensS7 = GetSiemensS7(plcNo); + if (siemensS7 == default) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = "找不到该PLC连接" + }; + } + (Exception? Ex, byte[]? bytes) getByte = GetPlcBytes(values); + if (getByte.Ex != null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 996, + Message = $"{getByte.Ex.Message}" + }; + } + byte[]? bytes = getByte.bytes;//获取转化成功的数组 + OperateResult operateResult = siemensS7.Write(plcDBAddress, bytes); + return operateResult.ToSemS7Result(); + } + + + + /// + /// 根据名称写入PLC值,写入string + /// 写入前请提前转换好对应的数据格式 + /// + /// + /// + /// 自定的编码信息,一般System.Text.Encoding.ASCII即可,中文需要 Encoding.GetEncoding("gb2312") + /// + public SemS7Result WriteStringWhithName(string plcDBName, string value, Encoding encoding) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.Write(dbAddress, value, encoding).ToSemS7Result(); + } + + /// + /// 读取一个Byte数组 + /// + /// + /// + /// + public SemS7Result ReadByteWithName(string plcDBName, ushort length) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.Read(dbAddress, length).ToSemS7Result(); + } + + /// + /// 读取一个Byte + /// + /// + /// + public SemS7Result ReadByteWithName(string plcDBName) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + SemS7Result actionResult = ReadByteWithName(dbAddress!, 1); + if (!actionResult.Success) + { + return new SemS7Result() + { + Success = false, + ErrCode = actionResult.ErrCode, + Message = actionResult.Message + }; + } + + var values = actionResult.Value; + if (values == default || values.Length == 0) + { + return new SemS7Result() + { + Success = false, + ErrCode = actionResult.ErrCode, + Message = actionResult.Message + }; + } + return new SemS7Result() + { + Success = true, + ErrCode = actionResult.ErrCode, + Message = actionResult.Message, + Value = values[0] + }; + } + + + /// + /// 根据名称读取一定数量的Int16值 + /// 对应PLC数据类型为 W,int, + /// + /// + /// + /// + public SemS7Result ReadInt16WithName(string plcDBName, ushort length) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.ReadInt16(dbAddress, length).ToSemS7Result(); + } + + + + /// + /// 根据名称读取一个Int16值 + /// 对应PLC数据类型为 W,int, + /// + /// + /// + public SemS7Result ReadInt16WithName(string plcDBName) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.ReadInt16(dbAddress).ToSemS7Result(); + } + + /// + /// 根据名称读取一定数量的Int32值 + /// 对应PLC数据类型为 DW,Dint, + /// + /// + /// + /// + public SemS7Result ReadInt32WithName(string plcDBName, ushort length) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.ReadInt32(dbAddress, length).ToSemS7Result(); + } + + /// + /// 根据名称读取一个Int32值 + /// 对应PLC数据类型为 DW,Dint, + /// + /// + /// + public SemS7Result ReadInt32WithName(string plcDBName) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.ReadInt32(dbAddress).ToSemS7Result(); + } + + /// + /// 根据名称读取一定数量的bool值 + /// 对应PLC数据类型为 X + /// + /// + /// /// + /// + public SemS7Result ReadBoolWithName(string plcDBName, ushort length) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.ReadBool(dbAddress, length).ToSemS7Result(); + } + + /// + /// 根据名称读取一个Int32值 + /// 对应PLC数据类型为 X + /// + /// + /// + public SemS7Result ReadBoolWithName(string plcDBName) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.ReadBool(dbAddress).ToSemS7Result(); + } + + /// + /// 根据名称读取string值 + /// 对应PLC数据类型为 string + /// + /// + /// + /// 自定的编码信息,一般System.Text.Encoding.ASCII即可,中文需要 Encoding.GetEncoding("gb2312") + /// + public SemS7Result ReadStringWithName(string plcDBName, ushort length, Encoding encoding) + { + (SiemensS7Net? siemensS7, string? dbAddress, string? errText) = GetSiemensS7(plcDBName); + if (siemensS7 == null) + { + return new SemS7Result() + { + Success = false, + ErrCode = 999, + Message = errText + }; + } + return siemensS7.ReadString(dbAddress, length, encoding).ToSemS7Result(); + } + + + /// + /// 根据DB名称查找其对应的连接 + /// + /// + /// + private (SiemensS7Net? siemensS7, string? dbAddress, string? errText) GetSiemensS7(string dbName) + { + if (plcDBNames.Count == 0 || siemensS7Connections.Count == 0) + { + return (null, null, "未设置 plc 或者 未设置 DB地址,请调用 SetPlcs 方法设置 plc 或者 调用 SetPlcDB 方法设置 DB地址"); + } + /*找出该地址对应的ID*/ + PlcDBName? plcDBName = plcDBNames.Find(f => f.DBName == dbName); + if (plcDBName == default) + { + return (null, null, "该DB地址不存在,请核实wcs数据录入是否正确"); + } + /*找出该ID对应的连接*/ + SiemensS7Connection? siemensS7Connection = siemensS7Connections.Find(f => f.PlcId == plcDBName.PlcId); + if (siemensS7Connection == default) + { + return (null, null, "该PLC连接不存在,请核实wcs数据录入是否正确"); + } + return (siemensS7Connection.SiemensS7, plcDBName.DBAddress, null); + } + + + /// + /// 根据plcNo 返回连接信息 + /// + /// + /// + private SiemensS7Net? GetSiemensS7(int plcNo) + { + /*找出该ID对应的连接*/ + SiemensS7Connection? siemensS7Connection = siemensS7Connections.Find(f => f.PlcId == plcNo); + if (siemensS7Connection == default) + { + return default; + } + return siemensS7Connection.SiemensS7; + } + + #endregion + + + //NetworkDoubleBase dataTransfrom = new NetworkDoubleBase(); + private readonly SiemensS7Net dataTransfrom = new(SiemensPLCS.S1500); + + #region 将 byte 数组转化为值 + + + /// + /// 将数组转化为值 + /// + /// + /// + /// + /// + public object? Trans(byte[] bytes, int index) where T : struct + { + Type type = typeof(T); + if (type == typeof(short)) + { + return dataTransfrom.ByteTransform.TransInt16(bytes, index); + } + else if (type == typeof(int)) + { + return dataTransfrom.ByteTransform.TransInt32(bytes, index); + } + else if (type == typeof(bool)) + { + return dataTransfrom.ByteTransform.TransBool(bytes, index); + } + else if (type == typeof(double)) + { + return dataTransfrom.ByteTransform.TransDouble(bytes, index); + } + else if (type == typeof(float)) + { + return dataTransfrom.ByteTransform.TransSingle(bytes, index); + } + else if (type == typeof(uint)) + { + return dataTransfrom.ByteTransform.TransUInt32(bytes, index); + } + else if (type == typeof(ushort)) + { + return dataTransfrom.ByteTransform.TransUInt16(bytes, index); + } + else + { + return null; // 不支持的数据类型 + } + + } + + #endregion + + + #region 将传入的值转化成 byte 数组 + /// + /// 将传入的值转化成byte数组 + /// + /// + /// + public (Exception? Ex, byte[]? bytes) GetPlcBytes(object[] values) + { + List bytes = []; + foreach (object value in values) + { + Type type = value.GetType(); + if (type == typeof(short)) + { + short va = Convert.ToInt16(value); + byte[] data = dataTransfrom.ByteTransform.TransByte(va); + bytes.AddRange(data); + } + else if (type == typeof(int)) + { + int va = Convert.ToInt32(value); + byte[] data = dataTransfrom.ByteTransform.TransByte(va); + bytes.AddRange(data); + } + else if (type == typeof(bool)) + { + bool va = Convert.ToBoolean(value); + byte[] data = dataTransfrom.ByteTransform.TransByte(va); + bytes.AddRange(data); + } + else if (type == typeof(double)) + { + double va = Convert.ToDouble(value); + byte[] data = dataTransfrom.ByteTransform.TransByte(va); + bytes.AddRange(data); + } + else if (type == typeof(float)) + { + float va = Convert.ToSingle(value); + byte[] data = dataTransfrom.ByteTransform.TransByte(va); + bytes.AddRange(data); + } + else if (type == typeof(uint)) + { + uint va = Convert.ToUInt32(value); + byte[] data = dataTransfrom.ByteTransform.TransByte(va); + bytes.AddRange(data); + } + else if (type == typeof(ushort)) + { + ushort va = Convert.ToUInt16(value); + byte[] data = dataTransfrom.ByteTransform.TransByte(va); + bytes.AddRange(data); + } + else + { + return (new Exception($"传入的数据中有不支持的数据类型 {type.Name} "), null); + } + } + return (null, [.. bytes]); + } + + #endregion + + + #region 根据名称和偏移量返回地址 + + /// + /// 根据名称和偏移量返回地址 + /// + /// + /// + /// + public string GetAddressWithNameAndBit(string dbName, int moveBit) + { + /* + * 1、判断有几个点 + * 有一个点的不是bool值 + * 有两个点的是bool值 + * 必须写全,如DB100等价于DB100.0,但不允许写DB100,因为容易识别错误 + */ + if (plcDBNames.Count == 0) + { + return string.Empty; // 没有注册DB地址, + } + /*找出该地址对应的ID*/ + PlcDBName? plcDBName = plcDBNames.Find(f => f.DBName == dbName); + if (plcDBName == default) + { + return string.Empty; // 找不到DB地址 + } + + string startDBAddress = plcDBName.DBAddress ?? string.Empty; + string[] dbInfos = startDBAddress.Split('.'); + if (dbInfos.Length == 2) + { + // 只有一个点,判断为非Bool值 + int startPoint = Convert.ToInt32(dbInfos[1]); + string newDBAddress = $"{dbInfos[0]}.{startPoint + moveBit}"; + return newDBAddress; + } + else if (dbInfos.Length == 3) + { + // 有两个点,判断为bool值 + int bigAddress = Convert.ToInt32(dbInfos[1]); + int smallAddress = Convert.ToInt32(dbInfos[2]); + while (moveBit > 0) + { + smallAddress++; + if (smallAddress >= 8) + { + bigAddress++; + smallAddress = 0; + } + moveBit--; + } + + return $"{dbInfos[0]}.{bigAddress}.{smallAddress}"; + } + + return string.Empty; + } + + + #endregion + + + +} \ No newline at end of file diff --git a/Tools/SocketTool/Entity/ExecuteResult.cs b/Tools/SocketTool/Entity/ExecuteResult.cs new file mode 100644 index 0000000..bbcd00a --- /dev/null +++ b/Tools/SocketTool/Entity/ExecuteResult.cs @@ -0,0 +1,68 @@ +namespace SocketTool.Entity; + +public class ExecuteResult +{ + public ExecuteResult() { } + + public ExecuteResult(bool? isSuccess, string? errMeg) + { + IsSuccess = isSuccess; + ErrorMessage = errMeg; + } + /// + /// 是否成功 + /// + public bool? IsSuccess + { + get; + set; + } + /// + /// 错误信息 + /// + public string? ErrorMessage + { + get; + set; + } + /// + /// 返回信息 + /// + public object? ReturnInfo + { + get; + set; + } +} + +/// +/// 信息的返回类 +/// +/// 返回的结果泛型 +public class ExecuteResult where T : class +{ + /// + /// 是否成功 + /// + public bool? IsSuccess + { + get; + set; + } + /// + /// 错误信息 + /// + public string? ErrorMessage + { + get; + set; + } + /// + /// 返回信息 + /// + public T? ReturnInfo + { + get; + set; + } +} \ No newline at end of file diff --git a/Tools/SocketTool/Entity/ScanCodeClass.cs b/Tools/SocketTool/Entity/ScanCodeClass.cs new file mode 100644 index 0000000..2883314 --- /dev/null +++ b/Tools/SocketTool/Entity/ScanCodeClass.cs @@ -0,0 +1,44 @@ +namespace SocketTool.Entity; + +public class ScanCodeClass +{ + /// + /// 传入数据的IP地址 + /// + public string? IpAddress + { + get; + set; + } + /// + /// 整数性扫码编号,请勿混淆 + /// + public int ScanID + { + get; + set; + } + + /// + /// 条码 + /// + public string? Code + { + get; + set; + } + + /// + /// 字符串格式的扫码编号,请勿混淆 + /// + public string? StrScanID + { + get; + set; + } + + public override string ToString() + { + return $"({StrScanID}){Code}"; + } +} \ No newline at end of file diff --git a/Tools/SocketTool/Entity/SocketModel.cs b/Tools/SocketTool/Entity/SocketModel.cs new file mode 100644 index 0000000..a4d3473 --- /dev/null +++ b/Tools/SocketTool/Entity/SocketModel.cs @@ -0,0 +1,41 @@ +using System.Net; +using System.Net.Sockets; + +namespace SocketTool.Entity; + +public class SocketModel +{ + + /// + /// socket信息 + /// + public Socket? Socket + { + get; + set; + } + + /// + /// 连接的远端IP + /// + public IPEndPoint? HostEP { get; set; } + + /// + /// 这个socket所在的线程 + /// + public Thread? Thread + { + get; + set; + } + + /// + /// 连接的socket地址 + /// + public string? SocketIp { get; set; } + + /// + /// 是否连接 + /// + public bool IsConnected { get; set; } +} \ No newline at end of file diff --git a/Tools/SocketTool/SocketClient.cs b/Tools/SocketTool/SocketClient.cs new file mode 100644 index 0000000..b8ddb55 --- /dev/null +++ b/Tools/SocketTool/SocketClient.cs @@ -0,0 +1,361 @@ +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Text.RegularExpressions; +using SocketTool.Entity; + +namespace SocketTool; + +/// +/// socket 客户端 .net6 版 +/// +public class SocketClient +{ + #region 全局变量 + + private List NeedConnectSockets = []; // 需要连接的socket + + int IPCount;//传入的连接数 + + #endregion + + #region 全局属性 + /// + /// 字符串解析格式 + /// + private Encoding? Encod { get; set; } + #endregion + + /// + /// socket连接类,自带自动重连功能 + /// 传入参数示例:127.0.0.1:8090 + /// + /// + /// + /// + public SocketClient(Encoding? encoding, params string?[] IPPorts) + { + Encod = encoding; + IPCount = IPPorts.Length;//数量赋值 + foreach (string? IPPort in IPPorts) + { + if (string.IsNullOrEmpty(IPPort)) + { + continue; + } + string ipAndPort = IPPort.Replace(":", ":");//将中文冒号替换成英文冒号 + if (!ipAndPort.Contains(':')) + { + // 不含有端口号的直接抛异常,必须处理 + throw new Exception($"地址:{IPPort} 格式不正确,必须处理以后才能正常运行。"); + } + string[] ipp = ipAndPort.Split(':'); + if (ipp.Length != 2 || string.IsNullOrEmpty(ipp[0]) || string.IsNullOrEmpty(ipp[1])) + { + // 拆分后没有地址或者端口号的直接抛异常,必须处理 + throw new Exception($"地址:{IPPort} 格式不正确,必须处理以后才能正常运行。"); + } + string IP = ipp[0]; + int Port = CheckIP(IP, ipp[1]); + if (Port != 0) + { + Socket socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + NeedConnectSockets.Add(new SocketModel() + { + Socket = socket, + SocketIp = IPPort, + IsConnected = false, + HostEP = new IPEndPoint(IPAddress.Parse(IP), Port) + }); + } + } + } + /// + /// 检查IP地址和端口号是否满足格式 + /// 如果格式错误返回0,否则返回Int格式的端口号 + /// + /// + /// + /// + private static int CheckIP(string? IP, string? Portstr) + { + if (string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Portstr)) + { + throw new Exception("传入的IP或者端口存在异常"); + } + int Port;//int格式的端口号 + try + { + Port = Convert.ToInt32(Portstr); + } + catch + { + return 0; + } + string CheckString = "^((1[0-9][0-9]\\.)|(2[0-4][0-9]\\.)|(25[0-5]\\.)|([1-9][0-9]\\.)|([0-9]\\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]))$"; + bool IsIPOK = Regex.IsMatch(IP, CheckString); + if (!IsIPOK || Port < 1 || Port > 65535) + { + throw new Exception($"地址:{IP} 的端口号:{Portstr} 格式不正确,必须处理以后才能正常运行。"); + } + return Port; + } + + /// + /// 连接事件,需要调用 + /// + public void Connect() + { + if (NeedConnectSockets.Count < 1) + { + return; + } + // 连接 socket + foreach (SocketModel needConnectSocket in NeedConnectSockets) + { + Thread connectSocket = new(() => + { + ConnectSocket(needConnectSocket); + }) + { + IsBackground = true + }; + connectSocket.Start(); + //Task.Factory.StartNew(()=>ConnectSocket(needConnectSocket)); + } + // 启用重连 + Thread reConnectSocket = new(ReConnectSocket) + { + IsBackground = true + }; + reConnectSocket.Start(); + //Task.Factory.StartNew(ReConnectSocket); + } + + + /// + /// 连接 socket + /// + /// + private void ConnectSocket(SocketModel socketInfo) + { + while (true)//此循环经本人考虑再三后加上,去掉此循环将导致=>在服务端未开启的情况下开启客户端,后面服务端开启,虽然可以通过下方重连连上服务端,但无法接受数据 + { + try + { + SocketConnecting?.Invoke(socketInfo.SocketIp ?? "");//触发连接中事件 + socketInfo.Socket!.Connect(socketInfo.HostEP!);//尝试连接 + SocketOnline?.Invoke(socketInfo.SocketIp ?? "");//触发连接成功事件 + socketInfo.Thread = Thread.CurrentThread; + socketInfo.IsConnected = true; + break; + } + catch (Exception ex) + { + SocketConnectFail?.Invoke(socketInfo.SocketIp ?? "", ex);//出发连接中事件 + Thread.Sleep(2000); + } + } + Socket socket = socketInfo.Socket; // 拉取地址 + while (true) + { + byte[] recvBytes = new byte[1024 * 1024]; + try + { + int bytes = socket.Receive(recvBytes, recvBytes.Length, SocketFlags.None); + if (bytes <= 0) + { + continue; + } + string? recvStr = Encod?.GetString(recvBytes, 0, bytes); //此处编码方式请根据服务端发送的编码方式修改对应,否则可能造成部分字符乱码 + if (string.IsNullOrEmpty(recvStr)) + { + continue; + } + if (recvStr.Trim().Length > 0) + { + GetSocketMessage?.Invoke(recvStr, socketInfo.SocketIp ?? ""); + if (HandleCodeInfo != null) + { + ManCode(recvStr, socketInfo.SocketIp ?? ""); //处理条码并触发其他事件 + } + } + } + catch (Exception ex) + { + _ = ex; + RecevErrEvent?.Invoke(socketInfo.SocketIp ?? "", ex); + socketInfo.IsConnected = false; + return; + } + } + } + + + /// + /// 重新连接 Socket + /// + private void ReConnectSocket() + { + Thread.Sleep(5000); + while (true) + { + foreach (SocketModel needConnectSocket in NeedConnectSockets) + { + Socket socket = needConnectSocket.Socket!; + Thread.Sleep(300); + try + { + try + { + socket.SendTimeout = 1000; + socket.Send(Encoding.ASCII.GetBytes(" ")); + if (!socket.Connected) + { + needConnectSocket.IsConnected = false; + } + } + catch (Exception ex) + { + _ = ex.ToString(); + SocketOffline?.Invoke(needConnectSocket.SocketIp ?? ""); //触发掉线事件 + try + { + socket.Close(); //关闭已经断开的socket + } + catch (Exception exception) + { + _ = exception; + } + + Thread connectSocket = new(() => + { + ConnectSocket(needConnectSocket); + }) + { + IsBackground = true + }; + connectSocket.Start(); + //Task.Factory.StartNew(() => ConnectSocket(needConnectSocket)); + } + } + catch (Exception ex) + { + _ = ex.ToString(); + } + } + } + + } + + + + + + /// + /// 处理收到的条码,并引发事件 + /// + /// + /// + private void ManCode(string? code, string? IPAddress) + { + //多线程处理,增加程序运行速度 + ThreadPool.QueueUserWorkItem((useless) => + { + List? scanCodeClasses = SplitCode(code, IPAddress); + if (scanCodeClasses != default) + { + foreach (ScanCodeClass scc in scanCodeClasses) + { + HandleCodeInfo?.Invoke(scc); + } + } + }); + } + /// + /// 拆条码,将前缀和条码拆下来 + /// + /// + /// + /// + private List? SplitCode(string? GetCode, string? Ipaddress) + { + if (string.IsNullOrEmpty(GetCode) || string.IsNullOrEmpty(Ipaddress)) + { + return default; + } + if (!GetCode.Contains('(')) + { + return default; + } + List sccs = []; + string[] GetCodeCuts = GetCode.Split('('); + foreach (string GetCodeCut in GetCodeCuts) + { + if (GetCodeCut == "" || GetCodeCut.Trim().Length == 0 || !GetCodeCut.Contains(')')) { continue; } + string[] ScanCode = GetCodeCut.Split(')'); + if (ScanCode.Length < 2) { continue; } + ScanCodeClass scc = new() + { + IpAddress = Ipaddress, + ScanID = Convert.ToInt32(ScanCode[0]), + StrScanID = ScanCode[0], + Code = ScanCode[1] + }; + sccs.Add(scc); + } + return sccs; + } + + #region 事件 + + public delegate void HandleInfo(ScanCodeClass scc); + /// + /// 条码处理事件, + /// ScanID或者ScanIDStr为null的是没有前缀的条码 + /// + public event HandleInfo? HandleCodeInfo; + + + + public delegate void GetMessage(string Message, string IPAddress); + /// + /// 条码处理事件, + /// + public event GetMessage? GetSocketMessage; + + + public delegate void OffLine(string IPAddress); + /// + /// 当有地址掉线时触发 + /// + public event OffLine? SocketOffline; + + public delegate void OnLine(string IPAddress); + /// + /// 当地址连接成功时触发 + /// + public event OnLine? SocketOnline; + + public delegate void Connecting(string IPAddress); + /// + /// 当地址连接正在连接时触发 + /// + public event Connecting? SocketConnecting; + + public delegate void ConnectFail(string IPAddress, Exception ex); + /// + /// 当地址连接正在连接时触发 + /// + public event ConnectFail? SocketConnectFail; + + public delegate void RecevErr(string IPAddress, Exception ex); + /// + /// 当地址连接接收数据异常时触发 + /// + public event RecevErr? RecevErrEvent; + #endregion + + + +} \ No newline at end of file diff --git a/Tools/SocketTool/SocketTool.csproj b/Tools/SocketTool/SocketTool.csproj new file mode 100644 index 0000000..22e1b2e --- /dev/null +++ b/Tools/SocketTool/SocketTool.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + AnyCPU;x64;x86 + + + diff --git a/WcsMain/.config/dotnet-tools.json b/WcsMain/.config/dotnet-tools.json new file mode 100644 index 0000000..6b93cca --- /dev/null +++ b/WcsMain/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "7.0.3", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file diff --git a/WcsMain/ApiClient/DataEntity/WmsEntity/ApplyInRequest.cs b/WcsMain/ApiClient/DataEntity/WmsEntity/ApplyInRequest.cs new file mode 100644 index 0000000..a96c3da --- /dev/null +++ b/WcsMain/ApiClient/DataEntity/WmsEntity/ApplyInRequest.cs @@ -0,0 +1,28 @@ +namespace WcsMain.ApiClient.DataEntity.WmsEntity; + +/// +/// 申请入库 +/// +public class ApplyInRequest +{ + /// + /// 申请点位 + /// + public string? Point { get; set; } + + /// + /// 载具号 + /// + public string? VehicleNo { get; set; } + + /// + /// 条码信息 + /// + public string? CodeMessage { get; set; } + + /// + /// 备注 + /// + public string? Remark { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiClient/DataEntity/WmsEntity/SendWmsTaskStatusRequest.cs b/WcsMain/ApiClient/DataEntity/WmsEntity/SendWmsTaskStatusRequest.cs new file mode 100644 index 0000000..16600c6 --- /dev/null +++ b/WcsMain/ApiClient/DataEntity/WmsEntity/SendWmsTaskStatusRequest.cs @@ -0,0 +1,40 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiClient.DataEntity.WmsEntity; + +/// +/// 发送WMS任务状态请求实体 +/// +public class SendWmsTaskStatusRequest +{ + /// + /// 任务号 + /// + [JsonPropertyName("taskId")] + public string? TaskId { get; set; } + + /// + /// 任务状态 + /// + [JsonPropertyName("taskStatus")] + public int? TaskStatus { get; set; } + + /// + /// 任务类型 + /// + [JsonPropertyName("destination")] + public string? Destination { get; set; } + + /// + /// 载具号 + /// + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 信息 + /// + [JsonPropertyName("message")] + public string? Message { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiClient/DataEntity/WmsEntity/UploadPickStandRequest.cs b/WcsMain/ApiClient/DataEntity/WmsEntity/UploadPickStandRequest.cs new file mode 100644 index 0000000..07be159 --- /dev/null +++ b/WcsMain/ApiClient/DataEntity/WmsEntity/UploadPickStandRequest.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiClient.DataEntity.WmsEntity; + +/// +/// 上传箱子到达拣选口的请求类 +/// +public class UploadPickStandRequest +{ + /// + /// 载具号 + /// + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 拣选站台 + /// + [JsonPropertyName("pickStand")] + public string? PickStand { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiClient/DataEntity/WmsEntity/WmsResponse.cs b/WcsMain/ApiClient/DataEntity/WmsEntity/WmsResponse.cs new file mode 100644 index 0000000..ba6fec1 --- /dev/null +++ b/WcsMain/ApiClient/DataEntity/WmsEntity/WmsResponse.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiClient.DataEntity.WmsEntity; + +public class WmsResponse +{ + /// + /// 代码 + /// + [JsonPropertyName("code")] + public int? Code { get; set; } + + /// + /// 信息 + /// + [JsonPropertyName("message")] + public string? Message { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/ControllerFilter/ExceptionFilter/WcsExceptionFilterAttribute.cs b/WcsMain/ApiServe/ControllerFilter/ExceptionFilter/WcsExceptionFilterAttribute.cs new file mode 100644 index 0000000..bed7e56 --- /dev/null +++ b/WcsMain/ApiServe/ControllerFilter/ExceptionFilter/WcsExceptionFilterAttribute.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using WcsMain.ApiServe.Factory; + +namespace WcsMain.ApiServe.ControllerFilter.ExceptionFilter; + +/// +/// Wcs 接口异常处理 +/// +public class WcsExceptionFilterAttribute : ExceptionFilterAttribute +{ + public override void OnException(ExceptionContext context) + { + base.OnException(context); + if (context.ExceptionHandled == false) + { + var response = WcsApiResponseFactory.ServiceErr($"服务器异常,参考信息:{context.Exception}"); + context.Result = new ObjectResult(response) + { + // 返回状态码设置为200,表示成功 + StatusCode = StatusCodes.Status200OK, + }; + } + context.ExceptionHandled = true; + } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/ControllerFilter/ResponseFilterAttribute.cs b/WcsMain/ApiServe/ControllerFilter/ResponseFilterAttribute.cs new file mode 100644 index 0000000..d9819c8 --- /dev/null +++ b/WcsMain/ApiServe/ControllerFilter/ResponseFilterAttribute.cs @@ -0,0 +1,118 @@ +using LogTool; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Newtonsoft.Json; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.DataService; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.ControllerFilter; + +/// +/// 过滤器,记录日志数据 +/// +[Component] +public class ResponseFilterAttribute(AppApiAcceptDao acceptDao, DataBaseData dataBaseData) : ActionFilterAttribute +{ + private readonly DataBaseData _dataBaseData = dataBaseData; + private readonly AppApiAcceptDao _acceptDao = acceptDao; + + public override void OnActionExecuting(ActionExecutingContext context) + { + base.OnActionExecuting(context); + //请求的方法,GET,POST + string requestMethod = context.HttpContext.Request.Method.ToUpper(); + //记录进入请求的时间 + context.RouteData.Values.Add("StartTime", DateTime.Now); + string requestStr = string.Empty; // 记录请求值 + switch (requestMethod) + { + case "GET": + requestStr = JsonConvert.SerializeObject(context.ActionArguments); + break; + case "POST": + bool isHaveRequestObj = context.ActionArguments.TryGetValue("request", out object? requestObj); + if (isHaveRequestObj) + { + requestStr = JsonConvert.SerializeObject(requestObj); + } + break; + case "PUT": + goto case "GET"; + case "PUSH": + goto case "GET"; + case "DELETE": + goto case "GET"; + } + context.RouteData.Values.Add("requestData", requestStr); + } + + + public override void OnActionExecuted(ActionExecutedContext context) + { + base.OnActionExecuted(context); + + /* 获取返回值,封装成JSON返回 */ + ObjectResult? response = (ObjectResult?)context.Result; + var responseValue = response?.Value; + string responseStr = JsonConvert.SerializeObject(responseValue); // 返回的JSON字符串 + + /* 获取请求值,记下请求日志 */ + HttpRequest request = context.HttpContext.Request; + AppApiAccept accept = new() + { + AcceptId = _dataBaseData.GetNewUUID(), + Path = request.Path.ToString(), + Method = request.Method, + MediaType = request.ContentType, + ClientAddress = + $"{context.HttpContext.Connection.RemoteIpAddress}:{context.HttpContext.Connection.RemotePort}", + }; + + RouteValueDictionary keyValues = request.RouteValues; + // 获取请求时间,和当前时间比较,计算接口执行时间 + bool isHaveStartTime = keyValues.TryGetValue("StartTime", out object? startTimeObj); + DateTime endTime = DateTime.Now; + if (isHaveStartTime) + { + DateTime startTime = (DateTime)(startTimeObj ?? new DateTime(1900, 1, 1)); + accept.RequestTime = startTime; + accept.ResponseTime = endTime; + TimeSpan span = endTime - startTime; + double useTime = span.TotalMilliseconds; //接口用时 + accept.UseTime = useTime; + } + else + { + accept.RequestTime = new DateTime(1900, 1, 1); + accept.ResponseTime = endTime; + accept.UseTime = 0; + } + // 获取请求数据,和返回数据 + var isHaveRequestObject = keyValues.TryGetValue("requestData", out object? requestObj); + if (isHaveRequestObject) + { + string reqMsg = $"{requestObj}"; + accept.RequestMsg = reqMsg; + } + else + { + accept.RequestMsg = "未抓取到请求数据。"; + } + string respMsg = $"{responseStr}"; + accept.ResponseMsg = respMsg; + + if (context.Exception != null) + { + accept.ErrMsg = context.Exception.Message; + } + Task.Factory.StartNew(() => + { + WcsLog.Instance().WriteApiAcceptLog(accept.ToString()); + _acceptDao.Insert(accept); // 插入数据库 + }); + } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/ControllerFilter/WmsApiExceptionFilterAttribute.cs b/WcsMain/ApiServe/ControllerFilter/WmsApiExceptionFilterAttribute.cs new file mode 100644 index 0000000..38fafbc --- /dev/null +++ b/WcsMain/ApiServe/ControllerFilter/WmsApiExceptionFilterAttribute.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity; + +namespace WcsMain.ApiServe.ControllerFilter; + +/// +/// 全局异常处理 +/// +public class WmsApiExceptionFilterAttribute : ExceptionFilterAttribute +{ + + public override void OnException(ExceptionContext context) + { + base.OnException(context); + if (context.ExceptionHandled == false) + { + WmsApiResponse exceptionResponse = new() + { + Code = 9999, + Message = $"您的请求发生异常,请检查数据格式或联系我们,将参考信息提供给我们,参考信息:{context.Exception}" + }; + context.Result = new ObjectResult(exceptionResponse) + { + // 返回状态码设置为200,表示成功 + StatusCode = StatusCodes.Status200OK, + }; + } + context.ExceptionHandled = true; + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/Equipment/ConveyStatusResponse.cs b/WcsMain/ApiServe/Controllers/Dto/Equipment/ConveyStatusResponse.cs new file mode 100644 index 0000000..b598241 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/Equipment/ConveyStatusResponse.cs @@ -0,0 +1,28 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.Equipment; + +/// +/// 输送设备信息 ---- 卡特专用 +/// +public class ConveyStatusResponse +{ + /// + /// 输送机编号,名称 + /// + [JsonPropertyName("conveyNo")] + public string? ConveyNo { get; set; } + + /// + /// 是否含有货物 + /// + [JsonPropertyName("existGoods")] + public bool? ExistGoods { get; set; } + + /// + /// 是否含有AGV + /// + [JsonPropertyName("existAGV")] + public bool? ExistAGV { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/Equipment/PickStandInfoResponse.cs b/WcsMain/ApiServe/Controllers/Dto/Equipment/PickStandInfoResponse.cs new file mode 100644 index 0000000..8ef8c8e --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/Equipment/PickStandInfoResponse.cs @@ -0,0 +1,22 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.Equipment; + +/// +/// 拣选站台信息 +/// +public class PickStandInfoResponse +{ + /// + /// 站台号 + /// + [JsonPropertyName("standId")] + public string? StandId { get; set; } + + /// + /// 箱子号 + /// + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/Equipment/StackerStatusResponse.cs b/WcsMain/ApiServe/Controllers/Dto/Equipment/StackerStatusResponse.cs new file mode 100644 index 0000000..d0b6316 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/Equipment/StackerStatusResponse.cs @@ -0,0 +1,40 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.Equipment; + +/// +/// 堆垛机状态返回实体类 +/// +public class StackerStatusResponse +{ + /// + /// 堆垛机编号 + /// + [JsonPropertyName("stackerNo")] + public string? StackerNo { get; set; } + + /// + /// 堆垛机控制方式 + /// + [JsonPropertyName("controlModel")] + public string? ControlModel { get; set; } + + /// + /// 堆垛机状态 + /// + [JsonPropertyName("onlineStatus")] + public string? OnlineStatus { get; set; } + + /// + /// 堆垛机任务号 + /// + [JsonPropertyName("plcId")] + public string? PlcId { get; set; } + + /// + /// 堆垛机报警编号 + /// + [JsonPropertyName("errCode")] + public string? ErrCode { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WMSEntity/Equipment/QueryStandStatusRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/Equipment/QueryStandStatusRequest.cs new file mode 100644 index 0000000..7f2ed7e --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/Equipment/QueryStandStatusRequest.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WMSEntity.Equipment +{ + public class QueryStandStatusRequest + { + /// + /// 站台类型 + /// + [JsonPropertyName("standType")] + public int? StandType { get; set; } + } +} diff --git a/WcsMain/ApiServe/Controllers/Dto/WMSEntity/Equipment/QueryStandStatusResponse.cs b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/Equipment/QueryStandStatusResponse.cs new file mode 100644 index 0000000..a26ceaa --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/Equipment/QueryStandStatusResponse.cs @@ -0,0 +1,25 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WMSEntity.Equipment +{ + public class QueryStandStatusResponse + { + /// + /// 响应时间 + /// + [JsonPropertyName("responseTime")] + public string? ResponseTime { get; set; } + + /// + /// 动作允许 + /// + [JsonPropertyName("allowAction")] + public bool? AllowAction { get; set; } + + /// + /// 信息 + /// + [JsonPropertyName("msg")] + public string? Msg { get; set; } + } +} diff --git a/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsApiResponse.cs b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsApiResponse.cs new file mode 100644 index 0000000..b566169 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsApiResponse.cs @@ -0,0 +1,35 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WMSEntity; + +/// +/// WMS的固定返回类 +/// +public class WmsApiResponse +{ + /// + /// 请求ID + /// + [JsonPropertyName("code")] + public int? Code { get; set; } + + /// + /// 信息 + /// + [JsonPropertyName("message")] + public string? Message { get; set; } + + +} +/// +/// Api统一回复类 +/// +/// +public class WmsApiResponse : WmsApiResponse where T : class +{ + /// + /// 返回数据 + /// + [JsonPropertyName("returnData")] + public T? ReturnData { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/DisposeStandRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/DisposeStandRequest.cs new file mode 100644 index 0000000..afb56cd --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/DisposeStandRequest.cs @@ -0,0 +1,36 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; + +/// +/// wms 推送站台拣选完成 +/// +public class DisposeStandRequest +{ + + /// + /// 拣选站台 + /// + [DataRules] + [JsonPropertyName("pickStand")] + public string? PickStand { get; set; } + + + /// + /// 拣选料箱 + /// + [DataRules] + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 状态 + /// + [DataRules] + [JsonPropertyName("status")] + public int? Status { get; set; } + + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/GetStackerRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/GetStackerRequest.cs new file mode 100644 index 0000000..b4b191f --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/GetStackerRequest.cs @@ -0,0 +1,70 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; + +/// +/// SetStackerTask 接口的请求类 +/// 对应方法名称为 GetStackerTask ---- WMS向WCS发送堆垛机任务 +/// +public class GetStackerRequest +{ + /// + /// 任务ID + /// + [DataRules] + [JsonPropertyName("taskId")] + public string? TaskId { get; set; } + + /// + /// 任务类型 + /// + [DataRules] + [JsonPropertyName("taskType")] + public int? TaskType { get; set; } + + /// + /// 任务起点 + /// + [JsonPropertyName("origin")] + public string? Origin { get; set; } + + /// + /// 优先级 + /// + [JsonPropertyName("priority")] + public int? Priority { get; set; } + + /// + /// 中间点 + /// + [JsonPropertyName("midpoint")] + public string? Midpoint { get; set; } + + /// + /// 任务终点 + /// + [JsonPropertyName("destination")] + public string? Destination { get; set; } + + /// + /// 载具号 + /// + [DataRules] + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 载具尺寸 + /// + [JsonPropertyName("vehicleSize")] + public int? VehicleSize { get; set; } + + /// + /// 载具重量 + /// + [JsonPropertyName("weight")] + public decimal? Weight { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/SetPickTaskRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/SetPickTaskRequest.cs new file mode 100644 index 0000000..dcd7502 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/SetPickTaskRequest.cs @@ -0,0 +1,30 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; + +/// +/// SetPickTask 接口的请求实体类 +/// +public class SetPickTaskRequest +{ + /// + /// 载具号 + /// + [DataRules(false, "^.+$")] + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 拣选站台 + /// + [DataRules] + [JsonPropertyName("pickStand")] + public List? PickStand { get; set; } + + /// + /// 备注信息 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/UpdateStackerTaskStatusRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/UpdateStackerTaskStatusRequest.cs new file mode 100644 index 0000000..4b7d8d1 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WMSEntity/WmsTask/UpdateStackerTaskStatusRequest.cs @@ -0,0 +1,35 @@ +using System.Text.Json.Serialization; +using DataCheck; + +namespace WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; + +/// +/// UpdateStackerTaskStatus 接口的请求类 +/// +public class UpdateStackerTaskStatusRequest +{ + /// + /// 任务编号 + /// + [DataRules] + [JsonPropertyName("taskId")] + public string? TaskId { get; set; } + + /// + /// 状态类型 + /// + /// + /// 0 —— 重置任务状态 + /// 3 —— 完成任务 + /// 999 —— 删除任务 + /// + [DataRules] + [JsonPropertyName("taskStatus")] + public int? TaskStatus { get; set; } + + /// + /// 目的地,WMS 重置任务时候会要求更改目的地 + /// + [JsonPropertyName("destination")] + public string? Destination { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsApiResponse.cs b/WcsMain/ApiServe/Controllers/Dto/WcsApiResponse.cs new file mode 100644 index 0000000..c1c77da --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsApiResponse.cs @@ -0,0 +1,57 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto; + +/// +/// Api统一回复类 +/// +public class WcsApiResponse +{ + /// + /// 响应代码 + /// + [JsonPropertyName("code")] + public int Code { get; set; } + + /// + /// 响应信息 + /// + [JsonPropertyName("msg")] + public string Msg { get; set; } = string.Empty; + + +} + +/// +/// Api统一回复类 +/// +/// +public class WcsApiResponse : WcsApiResponse where T : class +{ + /// + /// 返回数据 + /// + [JsonPropertyName("returnData")] + public T? ReturnData { get; set; } +} + + + +/// +/// Api统一回复类 +/// +/// +public class WcsApiResponse : WcsApiResponse where T1 : new() where T2 : class +{ + /// + /// 备用 + /// + [JsonPropertyName("tag")] + public T1? Tag { get; set; } + + /// + /// 返回数据 + /// + [JsonPropertyName("returnData")] + public T2? ReturnData { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/ApiAccept/GetApiAcceptWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/ApiAccept/GetApiAcceptWithPageRequest.cs new file mode 100644 index 0000000..ac0f62f --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/ApiAccept/GetApiAcceptWithPageRequest.cs @@ -0,0 +1,41 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiAccept; + +public class GetApiAcceptWithPageRequest +{ + + /// + /// 模糊查询字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchStr { get; set; } + + /// + /// 查询时间范围 + /// + [JsonPropertyName("timeRange")] + public List? TimeRange { get; set; } + + /// + /// 分页信息 + /// + [JsonPropertyName("page")] + public ApiAcceptPage? Page { get; set; } +} + +public class ApiAcceptPage +{ + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/ApiRequest/GetApiRequestWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/ApiRequest/GetApiRequestWithPageRequest.cs new file mode 100644 index 0000000..37b8f8c --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/ApiRequest/GetApiRequestWithPageRequest.cs @@ -0,0 +1,40 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiRequest; + +public class GetApiRequestWithPageRequest +{ + /// + /// 模糊查询字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchStr { get; set; } + + /// + /// 查询时间范围 + /// + [JsonPropertyName("timeRange")] + public List? TimeRange { get; set; } + + /// + /// 分页信息 + /// + [JsonPropertyName("page")] + public ApiRequestPage? Page { get; set; } +} + +public class ApiRequestPage +{ + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Config/EditeConfigRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Config/EditeConfigRequest.cs new file mode 100644 index 0000000..2fb2347 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Config/EditeConfigRequest.cs @@ -0,0 +1,48 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Config; + +public class EditeConfigRequest +{ + /// + /// 配置键 + /// + [DataRules] + [JsonPropertyName("configKey")] + public string? ConfigKey { get; set; } + + /// + /// 配置名称 + /// + [JsonPropertyName("configName")] + public string? ConfigName { get; set; } + + /// + /// 配置值 + /// + [JsonPropertyName("configValue")] + public string? ConfigValue { get; set; } + + /// + /// 配置类型 + /// + [JsonPropertyName("configType")] + public string? ConfigType { get; set; } + + /// + /// 备注信息 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + /// + /// 是否是编辑模式,、 + /// + /// + /// 编辑模式表示更新数据, + /// + [JsonPropertyName("isEdite")] + public bool IsEdite { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Config/GetConfigWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Config/GetConfigWithPageRequest.cs new file mode 100644 index 0000000..2e92006 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Config/GetConfigWithPageRequest.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Config; + + +/// +/// 分页请求获取配置项的请求参数 +/// +public class GetConfigWithPageRequest +{ + /// + /// 查询字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchString { get; set; } + + /// + /// 页面大小 + /// + [JsonPropertyName("pageSize")] + public int? PageSize { get; set; } + + /// + /// 页面页码 + /// + [JsonPropertyName("pageIndex")] + public int? PageIndex { get; set; } + + + +} diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/CusPickTask/UpdatePickTaskRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/CusPickTask/UpdatePickTaskRequest.cs new file mode 100644 index 0000000..61d18ab --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/CusPickTask/UpdatePickTaskRequest.cs @@ -0,0 +1,34 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.CusPickTask; + +public class UpdatePickTaskRequest +{ + /// + /// 记录号 + /// + [DataRules] + [JsonPropertyName("recordId")] + public string? RecordId { get; set; } + + /// + /// 载具号 + /// + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 拣选站台 + /// + [JsonPropertyName("pickStand")] + public string? PickStand { get; set; } + + /// + /// 是否拣选完成 + /// + [DataRules] + [JsonPropertyName("pickStatus")] + public bool? PickStatus { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/DB/EditeDBRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/DB/EditeDBRequest.cs new file mode 100644 index 0000000..f24e436 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/DB/EditeDBRequest.cs @@ -0,0 +1,42 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.DB; + +public class EditeDBRequest +{ + /// + /// PLCID + /// + [JsonPropertyName("plcId")] + public int? PlcId { get; set; } + + /// + /// DB名称 + /// + [JsonPropertyName("dbName")] + public string? DbName { get; set; } + + /// + /// DB地址 + /// + [JsonPropertyName("dbAddress")] + public string? DbAddress { get; set; } + + /// + /// 是否系统级别 + /// + [JsonPropertyName("isSystem")] + public int? IsSystem { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + /// + /// 是否是编辑状态 + /// + [JsonPropertyName("isEdite")] + public bool IsEdite { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Equipment/ResetStackerRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Equipment/ResetStackerRequest.cs new file mode 100644 index 0000000..20623b9 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Equipment/ResetStackerRequest.cs @@ -0,0 +1,14 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Equipment; + +public class ResetStackerRequest +{ + /// + /// 堆垛机编号 + /// + [DataRules] + [JsonPropertyName("stackerId")] + public string? StackerId { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Equipment/StackerContinueRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Equipment/StackerContinueRequest.cs new file mode 100644 index 0000000..702d7e7 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Equipment/StackerContinueRequest.cs @@ -0,0 +1,14 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Equipment; + +public class StackerContinueRequest +{ + /// + /// 堆垛机编号 + /// + [DataRules] + [JsonPropertyName("stackerId")] + public string? StackerId { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Location/GetLocationWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Location/GetLocationWithPageRequest.cs new file mode 100644 index 0000000..4b40dd0 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Location/GetLocationWithPageRequest.cs @@ -0,0 +1,48 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Location; + +/// +/// GetLocationWithPage 接口请求类 +/// +public class GetLocationWithPageRequest +{ + + /// + /// 查询的字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchStr { get; set; } + + /// + /// 任务类型 + /// + [JsonPropertyName("locationStatus")] + public List? LocationStatus { get; set; } + + /// + /// 分页信息 + /// + [JsonPropertyName("page")] + public LocationPage? Page { get; set; } + + + +} + + +public class LocationPage +{ + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Location/UpdateLocationRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Location/UpdateLocationRequest.cs new file mode 100644 index 0000000..7570b83 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Location/UpdateLocationRequest.cs @@ -0,0 +1,90 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Location; + +public class UpdateLocationRequest +{ + /// + /// Wcs点位 + /// + [JsonPropertyName("wcsLocation")] + public string? WcsLocation { get; set; } + + /// + /// Wms点位,该列主要用于映射 + /// + [JsonPropertyName("wmsLocation")] + public string? WmsLocation { get; set; } + + /// + /// 巷道编号 + /// + [JsonPropertyName("tunnelNo")] + public int? TunnelNo { get; set; } + + /// + /// 设备编号 + /// + [JsonPropertyName("equipmentId")] + public int? EquipmentId { get; set; } + + /// + /// 点位状态 + /// + [JsonPropertyName("locationStatus")] + public int? LocationStatus { get; set; } + + /// + /// 排 + /// + [JsonPropertyName("queue")] + public int? Queue { get; set; } + + /// + /// 列 + /// + [JsonPropertyName("line")] + public int? Line { get; set; } + + /// + /// 层 + /// + [JsonPropertyName("layer")] + public int? Layer { get; set; } + + /// + /// 深 + /// + [JsonPropertyName("depth")] + public int? Depth { get; set; } + + /// + /// 点位类型 + /// + [JsonPropertyName("locationType")] + public int? LocationType { get; set; } + + /// + /// 载具编号 + /// + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 修改时间 + /// + [JsonPropertyName("modifyTime")] + public DateTime? ModifyTime { get; set; } + + /// + /// 说明信息 + /// + [JsonPropertyName("explain")] + public string? Explain { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/AddMenuRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/AddMenuRequest.cs new file mode 100644 index 0000000..52e48f1 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/AddMenuRequest.cs @@ -0,0 +1,60 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Menu; + +public class AddMenuRequest +{ + /// + /// 主菜单序号 + /// + [JsonPropertyName("mainMenuIndex")] + public string? MainMenuIndex { get; set; } + + /// + /// 主菜单名称 + /// + [JsonPropertyName("mainMenuName")] + public string? MainMenuName { get; set; } + + /// + /// 主菜单图标 + /// + [JsonPropertyName("mainMenuIco")] + public string? MainMenuIco { get; set; } + + /// + /// 次菜单序号 + /// + [JsonPropertyName("minorMenuIndex")] + public string? MinorMenuIndex { get; set; } + + /// + /// 次菜单名称 + /// + [JsonPropertyName("minorMenuName")] + public string? MinorMenuName { get; set; } + + /// + /// 次菜单图标 + /// + [JsonPropertyName("minorMenuIco")] + public string? MinorMenuIco { get; set; } + + /// + /// 次菜单路由 + /// + [JsonPropertyName("minorMenuRouter")] + public string? MinorMenuRouter { get; set; } + + /// + /// 菜单状态 ---- 1 表示可以使用 + /// + [JsonPropertyName("menuStatus")] + public int? MenuStatus { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/GetMenuWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/GetMenuWithPageRequest.cs new file mode 100644 index 0000000..1b070bb --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/GetMenuWithPageRequest.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Menu; + +public class GetMenuWithPageRequest +{ + /// + /// 分页信息 + /// + [JsonPropertyName("page")] + public MenuPage? Page { get; set; } + +} + +public class MenuPage +{ + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } + + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/UpdateMenuRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/UpdateMenuRequest.cs new file mode 100644 index 0000000..2bc0c62 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Menu/UpdateMenuRequest.cs @@ -0,0 +1,61 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Menu; + +public class UpdateMenuRequest +{ + /// + /// 主菜单序号 + /// + [JsonPropertyName("mainMenuIndex")] + public string? MainMenuIndex { get; set; } + + /// + /// 主菜单名称 + /// + [JsonPropertyName("mainMenuName")] + public string? MainMenuName { get; set; } + + /// + /// 主菜单图标 + /// + [JsonPropertyName("mainMenuIco")] + public string? MainMenuIco { get; set; } + + /// + /// 次菜单序号 + /// + [JsonPropertyName("minorMenuIndex")] + public string? MinorMenuIndex { get; set; } + + /// + /// 次菜单名称 + /// + [JsonPropertyName("minorMenuName")] + public string? MinorMenuName { get; set; } + + /// + /// 次菜单图标 + /// + [JsonPropertyName("minorMenuIco")] + public string? MinorMenuIco { get; set; } + + /// + /// 次菜单路由 + /// + [JsonPropertyName("minorMenuRouter")] + public string? MinorMenuRouter { get; set; } + + /// + /// 菜单状态 ---- 1 表示可以使用 + /// + [JsonPropertyName("menuStatus")] + public int? MenuStatus { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/PLC/EditePLCRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/PLC/EditePLCRequest.cs new file mode 100644 index 0000000..4b73d89 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/PLC/EditePLCRequest.cs @@ -0,0 +1,57 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.PLC; + +/// +/// 修改 PLC 请求实体类 +/// +public class EditePLCRequest +{ + /// + /// 是否处于编辑模式 + /// + [JsonPropertyName("isEdite")] + public bool IsEdite { get; set; } + + /// + /// PLC的编号 + /// + [JsonPropertyName("plcId")] + public int? PlcId { get; set; } + + /// + /// PLC 的IP + /// + [JsonPropertyName("plcIp")] + public string? PlcIp { get; set; } + + /// + /// 机架 + /// + [JsonPropertyName("rack")] + public int? Rack { get; set; } + + /// + /// 插槽 + /// + [JsonPropertyName("slot")] + public int? Slot { get; set; } + + /// + /// PLC的类型 + /// + [JsonPropertyName("plcKind")] + public string? PlcKind { get; set; } + + /// + /// PLC的状态 + /// + [JsonPropertyName("plcStatus")] + public int? PlcStatus { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Settings/EditSettingsRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Settings/EditSettingsRequest.cs new file mode 100644 index 0000000..328148a --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Settings/EditSettingsRequest.cs @@ -0,0 +1,40 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Settings; + +/// +/// 编辑设置项的请求类 +/// +public class EditSettingsRequest +{ + /// + /// 设置键 + /// + [JsonPropertyName("settingKey")] + public string? SettingKey { get; set; } + + /// + /// 设置名称 + /// + [JsonPropertyName("settingName")] + public string? SettingName { get; set; } + + /// + /// 设置值 + /// + [JsonPropertyName("settingValue")] + public string? SettingValue { get; set; } + + /// + /// 设置类型 + /// + [JsonPropertyName("settingType")] + public string? SettingType { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/Socket/EditSocketRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Socket/EditSocketRequest.cs new file mode 100644 index 0000000..e93fc04 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/Socket/EditSocketRequest.cs @@ -0,0 +1,44 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.Socket; + +/// +/// 编辑 socket 的请求类 +/// +public class EditSocketRequest +{ + /// + /// socket编号,唯一 + /// + [DataRules] + [JsonPropertyName("socketNo")] + public string? SocketNo { get; set; } + + /// + /// socket的IP端口 + /// + [DataRules] + [JsonPropertyName("socketIpPort")] + public string? SocketIpPort { get; set; } + + /// + /// socket的状态 + /// + [DataRules] + [JsonPropertyName("socketStatus")] + public string? SocketStatus { get; set; } + + /// + /// 备注 + /// + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + /// + /// 是否处于编辑模式 + /// + [DataRules] + [JsonPropertyName("isEdite")] + public bool? IsEdite { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/SystemController/GetSysMsgWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/SystemController/GetSysMsgWithPageRequest.cs new file mode 100644 index 0000000..1335e27 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/SystemController/GetSysMsgWithPageRequest.cs @@ -0,0 +1,25 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.SystemController; + +public class GetSysMsgWithPageRequest +{ + + /// + /// 查询字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchStr { get; set; } + + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/SystemController/LogRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/SystemController/LogRequest.cs new file mode 100644 index 0000000..7891830 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/SystemController/LogRequest.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; +using DataCheck; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.SystemController; + +public class LogRequest +{ + /// + /// log类型 + /// + [JsonPropertyName("logType")] + [DataRules] + public string? LogType { get; set; } + + /// + /// log文件名 + /// + [JsonPropertyName("logFileName")] + [DataRules] + public string? LogFileName { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/GetUserWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/GetUserWithPageRequest.cs new file mode 100644 index 0000000..9c960e2 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/GetUserWithPageRequest.cs @@ -0,0 +1,45 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.User; + +public class GetUserWithPageRequest +{ + /// + /// 查询的字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchStr { get; set; } + + /// + /// 用户状态 + /// + [JsonPropertyName("userStatus")] + public List? UserStatus { get; set; } + + /// + /// 查询时间范围 + /// + [JsonPropertyName("timeRange")] + public List? TimeRange { get; set; } + + /// + /// 分页信息 + /// + [JsonPropertyName("page")] + public UserPage? Page { get; set; } +} + +public class UserPage +{ + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/LoginRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/LoginRequest.cs new file mode 100644 index 0000000..759b850 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/LoginRequest.cs @@ -0,0 +1,24 @@ +using DataCheck; +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.User; + +/// +/// 登录请求类 +/// +public class LoginRequest +{ + /// + /// 用户ID + /// + [DataRules] + [JsonPropertyName("userId")] + public string? UserId { get; set; } + + /// + /// 用户密码 + /// + [DataRules] + [JsonPropertyName("userPassword")] + public string? UserPassword { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/LoginResponse.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/LoginResponse.cs new file mode 100644 index 0000000..b800b1a --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/User/LoginResponse.cs @@ -0,0 +1,87 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.User; + +/// +/// d登录接口响应类 +/// +public class LoginResponse +{ + /// + /// 用户名称 + /// + [JsonPropertyName("userName")] + public string? UserName { get; set; } + + /// + /// 菜单 + /// + [JsonPropertyName("menu")] + public List? Menu { get; set; } + +} + +/// +/// 菜单 +/// +public class MainMenuData +{ + /// + /// 主菜单序号 + /// + [JsonPropertyName("index")] + public string? Index { get; set; } + + /// + /// 主菜单名称 + /// + [JsonPropertyName("mainMenu")] + public string? MainMenu { get; set; } + + /// + /// 主菜单图标 + /// + [JsonPropertyName("ico")] + public string? Ico { get; set; } + + /// + /// 次级菜单 + /// + [JsonPropertyName("minor")] + public List? Minor { get; set; } + + +} + +/// +/// 次级菜单 +/// +public class MinorMenuData +{ + /// + /// 次菜单序号 + /// + [JsonPropertyName("index")] + public string? Index { get; set; } + + /// + /// 次菜单名称 + /// + [JsonPropertyName("minorMenu")] + public string? MinorMenu { get; set; } + + /// + /// 次菜单图标 + /// + [JsonPropertyName("ico")] + public string? Ico { get; set; } + + /// + /// 次菜单路由 + /// + [JsonPropertyName("router")] + public string? Router { get; set; } + + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/UserGroup/AddUserGroupRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/UserGroup/AddUserGroupRequest.cs new file mode 100644 index 0000000..30286c0 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/UserGroup/AddUserGroupRequest.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.UserGroup; + +public class AddUserGroupRequest +{ + /// + /// 用户组ID + /// + [JsonPropertyName("groupId")] + public string? GroupId { get; set; } + + /// + /// 用户组名称 + /// + [JsonPropertyName("groupName")] + public string? GroupName { get; set; } + + /// + /// 用户组状态 + /// + [JsonPropertyName("groupStatus")] + public int? GroupStatus { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/UserRule/UpdateUserRuleRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/UserRule/UpdateUserRuleRequest.cs new file mode 100644 index 0000000..8fa7313 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/UserRule/UpdateUserRuleRequest.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; +using DataCheck; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.UserRule; + +public class UpdateUserRuleRequest +{ + /// + /// 用户组名称 + /// + [DataRules] + [JsonPropertyName("userGroupId")] + public string? UserGroupId { get; set; } + + /// + /// 用户权限 + /// + [JsonPropertyName("userRules")] + public List? UserRules { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/WcsTask/GetWcsTaskWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WcsTask/GetWcsTaskWithPageRequest.cs new file mode 100644 index 0000000..2d0c7f1 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WcsTask/GetWcsTaskWithPageRequest.cs @@ -0,0 +1,53 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.WcsTask; + +public class GetWcsTaskWithPageRequest +{ + /// + /// 查询的字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchStr { get; set; } + + /// + /// 任务类型 + /// + [JsonPropertyName("taskType")] + public List? TaskType { get; set; } + + /// + /// 任务状态 + /// + [JsonPropertyName("taskStatus")] + public List? TaskStatus { get; set; } + + /// + /// 查询时间范围 + /// + [JsonPropertyName("timeRange")] + public List? TimeRange { get; set; } + + /// + /// 分页信息 + /// + [JsonPropertyName("page")] + public WcsPage? Page { get; set; } +} + + +public class WcsPage +{ + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/WcsTask/UpdateWcsTaskStatusRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WcsTask/UpdateWcsTaskStatusRequest.cs new file mode 100644 index 0000000..4abd914 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WcsTask/UpdateWcsTaskStatusRequest.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; +using DataCheck; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.WcsTask; + +/// +/// 更新 wcs 任务状态请求类 +/// +public class UpdateWcsTaskStatusRequest +{ + /// + /// plc任务号 + /// + [DataRules] + [JsonPropertyName("plcId")] + public int? PlcId { get; set; } + + /// + /// 状态 + /// + [DataRules] + [JsonPropertyName("taskStatus")] + public int? TaskStatus { get; set; } + + /// + /// 优先级 + /// + [DataRules] + [JsonPropertyName("priority")] + public int? Priority { get; set; } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/WmsTask/GetWmsTaskWithPageRequest.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WmsTask/GetWmsTaskWithPageRequest.cs new file mode 100644 index 0000000..e0ace1f --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WmsTask/GetWmsTaskWithPageRequest.cs @@ -0,0 +1,56 @@ +using System.Text.Json.Serialization; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.WmsTask; + +/// +/// 分页查询 WMS 任务的实体 +/// +public class GetWmsTaskWithPageRequest +{ + /// + /// 查询的字符串 + /// + [JsonPropertyName("searchStr")] + public string? SearchStr { get; set; } + + /// + /// 任务类型 + /// + [JsonPropertyName("taskType")] + public List? TaskType { get; set; } + + /// + /// 任务状态 + /// + [JsonPropertyName("taskStatus")] + public List? TaskStatus { get; set; } + + /// + /// 查询时间范围 + /// + [JsonPropertyName("timeRange")] + public List? TimeRange { get; set; } + + /// + /// 分页信息 + /// + [JsonPropertyName("page")] + public WmsPage? Page { get; set; } + +} + +public class WmsPage +{ + /// + /// 每页大小 + /// + [JsonPropertyName("pageSize")] + public int PageSize { get; set; } + + /// + /// 当前页数 + /// + [JsonPropertyName("pageIndex")] + public int PageIndex { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/Dto/WcsDto/WmsTask/SetWmsTask.cs b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WmsTask/SetWmsTask.cs new file mode 100644 index 0000000..d32c597 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/Dto/WcsDto/WmsTask/SetWmsTask.cs @@ -0,0 +1,71 @@ +using System.Text.Json.Serialization; +using DataCheck; + +namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.WmsTask; + +/// +/// 创建任务的统一类 +/// +public class SetWmsTask +{ + /// + /// 任务ID + /// + [DataRules] + [JsonPropertyName("taskId")] + public string? TaskId { get; set; } + + /// + /// 任务类型 + /// + [DataRules] + [JsonPropertyName("taskType")] + public int? TaskType { get; set; } + + /// + /// 优先级 + /// + [JsonPropertyName("priority")] + public int? Priority { get; set; } + + /// + /// 任务起点 + /// + [JsonPropertyName("origin")] + public string? Origin { get; set; } + + /// + /// 中间点 + /// + [JsonPropertyName("midpoint")] + public string? Midpoint { get; set; } + + /// + /// 任务终点 + /// + [JsonPropertyName("destination")] + public string? Destination { get; set; } + + /// + /// 载具号 + /// + [DataRules] + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 载具尺寸 + /// + [DataRules] + [JsonPropertyName("vehicleSize")] + public int? VehicleSize { get; set; } + + /// + /// 载具重量 + /// + [DataRules] + [JsonPropertyName("weight")] + public decimal? Weight { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/TestController.cs b/WcsMain/ApiServe/Controllers/TestController.cs new file mode 100644 index 0000000..ccd2a78 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/TestController.cs @@ -0,0 +1,72 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter; + +namespace WcsMain.ApiServe.Controllers; + +/// +/// 测试接口,用于测试接口是否通断 +/// +/// +/// 构造函数,注入显示类 +/// +/// +[ApiController] +[Route("api/Test")] +[ServiceFilter] +public class TestController(ILogger logger) : ControllerBase +{ + + private readonly ILogger _logger = logger; + + + /// + /// Get测试 + /// + /// + [HttpGet("GetTest")] + public string GetTest() + { + _logger.LogInformation("正常"); + return "正常"; + } + + /// + /// Get测试 + /// + /// + [HttpGet("RestartTest")] + public string RestartTest() + { + string? path = Process.GetCurrentProcess().MainModule?.FileName; + Process process = new(); + process.StartInfo.FileName = path; + process.Start(); + Process.GetCurrentProcess().Kill(); + + return "正常"; + } + + /// + /// Post测试 + /// + /// + /// + [HttpPost("PostTest")] + public string PostTest([FromBody] string body) + { + return $"正常,收到的信息为:{body}"; + } + + + /// + /// Post异常测试 + /// + /// + /// + [HttpPost("PostErrorTest")] + public string PostErrorTest([FromBody] string body) + { + throw new Exception($"异常异常:{body}"); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/ThreeDController/TaskController.cs b/WcsMain/ApiServe/Controllers/ThreeDController/TaskController.cs new file mode 100644 index 0000000..7b0fd62 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/ThreeDController/TaskController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Service.TreeDService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.ThreeDController; + +[Route("api/threeD")] +[ApiController] +public class TaskController(TaskService taskService) : ControllerBase +{ + private readonly TaskService _taskService = taskService; + + /// + /// 查询WMS任务 + /// + /// + [HttpGet("getWmsTask")] + public WcsApiResponse> GetWmsTask() => _taskService.GetWmsTask(); + + /// + /// 查询WMS任务 + /// + /// + [HttpGet("getWmsTaskNotEnd")] + public WcsApiResponse> GetWmsTaskNoEnd() => _taskService.GetWmsTaskNoEnd(); + + /// + /// 根据 plcId 查询任务 + /// + /// + /// + [HttpGet("queryRunningTask")] + public WcsApiResponse GetWcsTask([FromQuery(Name = "plcId")] int? plcId) => _taskService.GetWcsTask(plcId); +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/ApiAcceptController.cs b/WcsMain/ApiServe/Controllers/WcsController/ApiAcceptController.cs new file mode 100644 index 0000000..9e139fd --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/ApiAcceptController.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiAccept; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/apiAccept")] +[ApiController] +[WcsExceptionFilter] +public class ApiAcceptController(ApiAcceptService apiAcceptService) : ControllerBase +{ + + private readonly ApiAcceptService _apiAcceptService = apiAcceptService; + + /// + /// 查询所有的WCS任务 + /// + /// + [HttpPost("getApiAcceptWithPage")] + public WcsApiResponse> GetApiAcceptWithPage([FromBody] GetApiAcceptWithPageRequest request) => _apiAcceptService.GetApiAcceptWithPage(request); +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/ApiRequestController.cs b/WcsMain/ApiServe/Controllers/WcsController/ApiRequestController.cs new file mode 100644 index 0000000..aae2360 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/ApiRequestController.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiRequest; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/apiRequest")] +[ApiController] +[WcsExceptionFilter] +public class ApiRequestController(ApiRequestService apiRequestService) : ControllerBase +{ + + private readonly ApiRequestService _apiRequestService = apiRequestService; + + /// + /// 查询所有的WCS请求其他系统的记录 + /// + /// + [HttpGet("getApiRequest")] + public WcsApiResponse> GetApiRequest() => _apiRequestService.GetApiRequest(); + + /// + /// 查询所有的WCS任务 + /// + /// + [HttpPost("getApiRequestWithPage")] + public WcsApiResponse> GetApiRequestWithPage([FromBody] GetApiRequestWithPageRequest request) => _apiRequestService.GetApiRequestWithPage(request); + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/ConfigController.cs b/WcsMain/ApiServe/Controllers/WcsController/ConfigController.cs new file mode 100644 index 0000000..58733ec --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/ConfigController.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Config; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/config")] +[ApiController] +[WcsExceptionFilter] +public class ConfigController(ConfigService configService) : ControllerBase +{ + + private readonly ConfigService _configService = configService; + + /// + /// 查询配置项 + /// + /// + /// + [HttpGet("getConfig")] + public WcsApiResponse> GetConfig([FromQuery(Name = "configKey")] string? configKey) => _configService.GetConfig(configKey); + + /// + /// 分页请求,获取配置项 + /// + /// + /// + [HttpPost("getConfigWithPage")] + public WcsApiResponse> GetConfigWithPage([FromBody] GetConfigWithPageRequest request) => _configService.GetConfigWithPage(request); + + /// + /// 添加或者修改配置项 + /// + /// + /// + [HttpPost("editeConfig")] + public WcsApiResponse EditeConfig([FromBody] EditeConfigRequest request) => _configService.EditeConfig(request); +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/EquipmentController.cs b/WcsMain/ApiServe/Controllers/WcsController/EquipmentController.cs new file mode 100644 index 0000000..570225b --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/EquipmentController.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.Equipment; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Equipment; +using WcsMain.ApiServe.Service.WcsService; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +/// +/// 查询设备状态信息 +/// +[Route("api/wcs/equipment")] +[ApiController] +[WcsExceptionFilter] +public class EquipmentController(EquipmentService equipmentService) : ControllerBase +{ + + private readonly EquipmentService _equipmentService = equipmentService; + + + [HttpGet("queryStackerInfo")] + public WcsApiResponse> GetStackerInfo() => _equipmentService.GetStackerInfo(); + + /// + /// 查询库前输送机信息 + /// + /// + [HttpGet("queryStackerConveyInfo")] + public WcsApiResponse> GetConveyInfo() => _equipmentService.GetConveyInfo(); + + + /// + /// 复位堆垛机 + /// + /// + /// + [HttpPost("resetStacker")] + public WcsApiResponse ResetStacker([FromBody] ResetStackerRequest request) => _equipmentService.ResetStacker(request); + + /// + /// 堆垛机继续运行 + /// + /// + /// + [HttpPost("stackerContinue")] + public WcsApiResponse StackerContinue([FromBody] StackerContinueRequest request) => _equipmentService.StackerContinue(request); +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/LocationController.cs b/WcsMain/ApiServe/Controllers/WcsController/LocationController.cs new file mode 100644 index 0000000..beb8915 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/LocationController.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Location; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/location")] +[ApiController] +[WcsExceptionFilter] +public class LocationController(LocationService locationService) : ControllerBase +{ + + private readonly LocationService _locationService = locationService; + + /// + /// 查询所有的点位状态 + /// + /// + [HttpGet("getLocation")] + public WcsApiResponse> GetLocation() + { + return _locationService.GetLocation(); + } + + /// + /// 分页查询所有的点位状态 + /// + /// + [HttpPost("getLocationWithPage")] + public WcsApiResponse> GetLocationWithPage([FromBody] GetLocationWithPageRequest request) + { + return _locationService.GetLocationWithPage(request); + } + + /// + /// 更新点位信息 + /// + /// + /// + [HttpPost("updateLocation")] + public WcsApiResponse UpdateLocation([FromBody] UpdateLocationRequest request) + { + return _locationService.UpdateLocation(request); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/MenuController.cs b/WcsMain/ApiServe/Controllers/WcsController/MenuController.cs new file mode 100644 index 0000000..8610a4a --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/MenuController.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Menu; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/menu")] +[ApiController] +[WcsExceptionFilter] +public class MenuController(MenuService menuService) : ControllerBase +{ + + private readonly MenuService _menuService = menuService; + + /// + /// ҳѯ˵ + /// + /// + /// + [HttpPost("getMenuWithPage")] + public WcsApiResponse> GetMenuWithPage([FromBody] GetMenuWithPageRequest request) + { + return _menuService.GetMenuWithPage(request); + } + + /// + /// ²˵Ϣ + /// + /// + /// + [HttpPost("updateMenu")] + public WcsApiResponse UpdateMenu([FromBody] UpdateMenuRequest request) + { + return _menuService.UpdateMenu(request); + } + + /// + /// Ӳ˵Ϣ + /// + /// + /// + [HttpPost("addMenu")] + public WcsApiResponse AddMenu([FromBody] AddMenuRequest request) + { + return _menuService.AddMenu(request); + } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/PlcController.cs b/WcsMain/ApiServe/Controllers/WcsController/PlcController.cs new file mode 100644 index 0000000..c6b6b6c --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/PlcController.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.PLC; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/plc")] +[ApiController] +[WcsExceptionFilter] +public class PlcController(PlcService plcService) : ControllerBase +{ + + private readonly PlcService _plcService = plcService; + + /// + /// 查询plc + /// + /// + [HttpGet("getPlc")] + public WcsApiResponse> GetPlc() + { + return _plcService.GetPlc(); + } + + /// + /// 添加或者修改配置项 + /// + /// + /// + [HttpPost("editePlc")] + public WcsApiResponse EditePlc([FromBody] EditePLCRequest request) + { + return _plcService.EditePlc(request); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/PlcDbController.cs b/WcsMain/ApiServe/Controllers/WcsController/PlcDbController.cs new file mode 100644 index 0000000..7b0aafb --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/PlcDbController.cs @@ -0,0 +1,51 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.DB; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/db")] +[ApiController] +[WcsExceptionFilter] +public class PlcDbController(PlcDbService plcDbService) : ControllerBase +{ + + private readonly PlcDbService _plcDbService = plcDbService; + + /// + /// 查询 db + /// + /// + [HttpGet("getDB")] + public WcsApiResponse> GetDB() + { + return _plcDbService.GetDB(); + } + + + /// + /// 添加或者修改db项 + /// + /// + /// + [HttpPost("editeDB")] + public WcsApiResponse EditeDB([FromBody] EditeDBRequest request) + { + return _plcDbService.EditePlc(request); + } + + /// + /// 删除一个DB信息 + /// + /// + /// + [HttpDelete("deleteDB")] + public WcsApiResponse DeleteDb([FromQuery(Name = "dbName")] string? dbName) + { + return _plcDbService.DeleteDB(dbName); + } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/RunningInfoController.cs b/WcsMain/ApiServe/Controllers/WcsController/RunningInfoController.cs new file mode 100644 index 0000000..838ec90 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/RunningInfoController.cs @@ -0,0 +1,55 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.SystemController; +using WcsMain.ApiServe.Service.WcsService; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/runningInfo")] +[ApiController] +[WcsExceptionFilter] +public class RunningInfoController(RunningInfoService runningInfoService) : ControllerBase +{ + + + private readonly RunningInfoService _runningInfoService = runningInfoService; + + + /// + /// 获取日志的文件名称 + /// + /// + /// + [HttpGet("getLogFileName")] + public WcsApiResponse> GetLogFileName([FromQuery(Name = "logType")] string? logType) + { + return _runningInfoService.GetLogFileName(logType); + } + + + /// + /// 验证下载文件是否存在 + /// + /// + /// + [HttpPost("checkDownLoadLog")] + public WcsApiResponse CheckDownLoadLog([FromBody] LogRequest request) + { + return _runningInfoService.CheckDownLoadLog(request); + } + + + /// + /// 下载文件 + /// + /// + /// + [HttpPost("downLoadLog")] + public FileContentResult DownLoadLog([FromBody] LogRequest request) + { + return _runningInfoService.DownLoadLog(request, this); + } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/SettingController.cs b/WcsMain/ApiServe/Controllers/WcsController/SettingController.cs new file mode 100644 index 0000000..1ddffbc --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/SettingController.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Settings; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("/api/wcs/setting")] +[ApiController] +public class SettingController(SettingService settingService) : ControllerBase +{ + + private readonly SettingService _settingService = settingService; + + /// + /// 查询设置项 + /// + /// + /// + [HttpGet("getSettings")] + public WcsApiResponse> GetConfig([FromQuery(Name = "settingKey")] string? settingKey) + { + return _settingService.GetConfig(settingKey); + } + + + + /// + /// 添加或者修改配置项 + /// + /// + /// + [HttpPost("editSettings")] + public WcsApiResponse EditeConfig([FromBody] EditSettingsRequest request) + { + return _settingService.EditeConfig(request); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/SocketController.cs b/WcsMain/ApiServe/Controllers/WcsController/SocketController.cs new file mode 100644 index 0000000..81c45c5 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/SocketController.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Socket; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/socket")] +[ApiController] +public class SocketController(SocketService socketService) : ControllerBase +{ + + private readonly SocketService _socketService = socketService; + + /// + /// 查询 socket 连接信息 + /// + /// + [HttpGet("getSocket")] + public WcsApiResponse> GetDB() + { + return _socketService.GetDB(); + } + + + /// + /// 编辑 socket + /// + /// + /// + [HttpPost("editSocket")] + public WcsApiResponse EditSocket([FromBody] EditSocketRequest request) + { + return _socketService.EditSocket(request); + } + + /// + /// 删除一条信息 + /// + /// + /// + [HttpDelete("deleteSocket")] + public WcsApiResponse DeleteSocket([FromQuery(Name = "socketNo")] string? socketNoStr) + { + return _socketService.DeleteSocket(socketNoStr); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/StackerController.cs b/WcsMain/ApiServe/Controllers/WcsController/StackerController.cs new file mode 100644 index 0000000..afe644f --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/StackerController.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/stacker")] +[ApiController] +[WcsExceptionFilter] +public class StackerController(StackerService stackerService) : ControllerBase +{ + + private readonly StackerService _stackerService = stackerService; + + + /// + /// 查询所有的 堆垛机信息 + /// + /// + [HttpGet("getStacker")] + public WcsApiResponse> GetStacker() + { + return _stackerService.GetStacker(); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/UserController.cs b/WcsMain/ApiServe/Controllers/WcsController/UserController.cs new file mode 100644 index 0000000..b2a3a13 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/UserController.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.User; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/user")] +[ApiController] +[WcsExceptionFilter] +public class UserController(UserService userService) : ControllerBase +{ + private readonly UserService _userService = userService; + + + /// + /// 用户登录 + /// + /// + /// + /// + /// 若登录成功则返回用户名和用户菜单 + /// + [HttpPost("login")] + public WcsApiResponse Login([FromBody] LoginRequest request) + { + return _userService.Login(request); + } + + /// + /// 分页查询所有用户信息 + /// + /// + /// + [HttpPost("getUserWithPage")] + public WcsApiResponse> GetUserWithPage([FromBody] GetUserWithPageRequest request) + { + return _userService.GetUserWithPage(request); + } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/UserGroupController.cs b/WcsMain/ApiServe/Controllers/WcsController/UserGroupController.cs new file mode 100644 index 0000000..fa9fd8c --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/UserGroupController.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.UserGroup; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/userGroup")] +[ApiController] +public class UserGroupController(UserGroupService userGroupService) : ControllerBase +{ + + + private readonly UserGroupService _userGroupService = userGroupService; + + /// + /// ѯû + /// + /// + [HttpGet("getUserGroup")] + public WcsApiResponse> GetUserGroup() + { + return _userGroupService.GetUserGroup(); + } + + /// + /// û + /// + /// + /// + [HttpPost("addUserGroup")] + public WcsApiResponse AddUserGroup([FromBody] AddUserGroupRequest request) + { + return _userGroupService.AddUserGroup(request); + } + + /// + /// ɾû + /// + /// + /// + [HttpDelete("deleteUserGroup")] + public WcsApiResponse DeleteUserGroup([FromQuery] string? groupId) + { + return _userGroupService.DeleteUserGroup(groupId); + } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/UserRuleController.cs b/WcsMain/ApiServe/Controllers/WcsController/UserRuleController.cs new file mode 100644 index 0000000..f1259a0 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/UserRuleController.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.UserRule; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/userRule")] +[ApiController] +[WcsExceptionFilter] +public class UserRuleController(UserRuleService userRuleService) : ControllerBase +{ + + + private readonly UserRuleService _userRuleService = userRuleService; + + /// + /// ȡûȨ + /// + /// + [HttpGet("getUserRule")] + public WcsApiResponse> GetUserRule([FromQuery] string? groupId) + { + return _userRuleService.GetUserRule(groupId); + } + + /// + /// ûȨ + /// + /// + /// + [HttpPost("updateUserRule")] + public WcsApiResponse UpdateUserRule([FromBody] UpdateUserRuleRequest request) + { + return _userRuleService.UpdateUserRule(request); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/WcsTaskController.cs b/WcsMain/ApiServe/Controllers/WcsController/WcsTaskController.cs new file mode 100644 index 0000000..25a4262 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/WcsTaskController.cs @@ -0,0 +1,61 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.WcsTask; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/wcsTask")] +[ApiController] +[WcsExceptionFilter] +public class WcsTaskController(WcsTaskService wcsTaskService) : ControllerBase +{ + + private readonly WcsTaskService _wcsTaskService = wcsTaskService; + + + /// + /// 查询所有的正在运行的WCS任务 + /// + /// + [HttpGet("getWcsTask")] + public WcsApiResponse> GetWcsTask() + { + return _wcsTaskService.GetWcsTask(); + } + + /// + /// 根据任务号获取任务信息,包括运行表和备份表 + /// + /// + /// + [HttpGet("getWcsTaskWithTaskId")] + public WcsApiResponse> GetWcsTaskWithTaskId([FromQuery(Name = "taskId")] string taskId) + { + return _wcsTaskService.GetWcsTaskWithTaskId(taskId); + } + + /// + /// 分页查询正在运行的任务 + /// + /// + /// + [HttpPost("getWcsTaskWithPage")] + public WcsApiResponse> GetWcsTaskWithPage([FromBody] GetWcsTaskWithPageRequest request) + { + return _wcsTaskService.GetWcsTaskWithPage(request); + } + + /// + /// 更新任务信息 + /// + /// + /// + [HttpPost("updateStatus")] + public WcsApiResponse UpdateWcsTaskStatus([FromBody] UpdateWcsTaskStatusRequest request) + { + return _wcsTaskService.UpdateWcsTaskStatus(request); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WcsController/WmsTaskController.cs b/WcsMain/ApiServe/Controllers/WcsController/WmsTaskController.cs new file mode 100644 index 0000000..a2ef376 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WcsController/WmsTaskController.cs @@ -0,0 +1,60 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter.ExceptionFilter; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.WmsTask; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; +using WcsMain.ApiServe.Service.WcsService; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ApiServe.Controllers.WcsController; + +[Route("api/wcs/wmsTask")] +[ApiController] +[WcsExceptionFilter] +public class WmsTaskController(WmsTaskService wmsTaskService) : ControllerBase +{ + private readonly WmsTaskService _wmsTaskService = wmsTaskService; + + /// + /// 查询WMS任务 + /// + /// + [HttpGet("getWmsTask")] + public WcsApiResponse> GetWmsTask() + { + return _wmsTaskService.GetWmsTask(); + } + + /// + /// 分页查询所有的Wms任务 + /// + /// + [HttpPost("getWmsTaskWithPage")] + public WcsApiResponse> GetWmsTaskWithPage([FromBody] GetWmsTaskWithPageRequest request) + { + return _wmsTaskService.GetWmsTaskWithPage(request); + } + + /// + /// wcs前端向Wcs发送任务 + /// + /// + /// + [HttpPost("setStackerTask")] + public WcsApiResponse GetStackerTask([FromBody] SetWmsTask request) + { + return _wmsTaskService.GetStackerTask(request); + } + + /// + /// Wms向Wcs请求修改任务状态 + /// + /// + /// + [HttpPost("updateWmsTaskStatus")] + public WcsApiResponse UpdateStackerTaskStatus([FromBody] UpdateStackerTaskStatusRequest request) + { + return _wmsTaskService.UpdateStackerTaskStatus(request); + } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Controllers/WmsController/EquipmentController.cs b/WcsMain/ApiServe/Controllers/WmsController/EquipmentController.cs new file mode 100644 index 0000000..87f5b25 --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WmsController/EquipmentController.cs @@ -0,0 +1,43 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity.Equipment; +using WcsMain.ApiServe.Service.WmsService; +using WcsMain.ApiServe.ControllerFilter; + +namespace WcsMain.ApiServe.Controllers.WmsController +{ + /// + /// 设备控制接口 ---- 供Wms调用 + /// + [Route("api/wms/equipment")] + [ApiController] + [ServiceFilter(typeof(ResponseFilterAttribute))] + [WmsApiExceptionFilter] + public class EquipmentController(EquipmentService equipmentService) : ControllerBase + { + + private readonly EquipmentService _equipmentService = equipmentService; + + /// + /// 查询站台是否允许动作 + /// + /// + /// + [HttpPost("queryStandStatus")] + public WmsApiResponse QueryStandStatus([FromBody] QueryStandStatusRequest request) + { + return _equipmentService.QueryStandStatus(request); + } + + /// + /// 通知输送机卸货完成 + /// + /// + [HttpPost("unloadSuccess")] + public WmsApiResponse UnloadSuccess() + { + return _equipmentService.UnloadSuccess(); + } + + } +} diff --git a/WcsMain/ApiServe/Controllers/WmsController/WmsTaskController.cs b/WcsMain/ApiServe/Controllers/WmsController/WmsTaskController.cs new file mode 100644 index 0000000..db5884a --- /dev/null +++ b/WcsMain/ApiServe/Controllers/WmsController/WmsTaskController.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.ControllerFilter; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; +using WcsMain.ApiServe.Service.WmsService; + +namespace WcsMain.ApiServe.Controllers.WmsController; + +/// +/// Wms任务接口 +/// +[Route("api/wms/wmsTask")] +[ApiController] +[ServiceFilter] +[WmsApiExceptionFilter] +public class WmsTaskController(WmsTaskService wmsTaskService) : ControllerBase +{ + + private readonly WmsTaskService _wmsTaskService = wmsTaskService; + + /// + /// Wms向Wcs发送任务 + /// + /// + /// + [HttpPost("setStackerTask")] + public WmsApiResponse GetStackerTask([FromBody] List request) + { + return _wmsTaskService.GetStackerTask(request); + } + + + /// + /// Wms向Wcs请求修改任务状态 + /// + /// + /// + [HttpPost("changeTaskStatus")] + public WmsApiResponse UpdateStackerTaskStatus([FromBody] UpdateStackerTaskStatusRequest request) + { + return _wmsTaskService.UpdateStackerTaskStatus(request); + } + + + + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Factory/WcsApiResponseFactory.cs b/WcsMain/ApiServe/Factory/WcsApiResponseFactory.cs new file mode 100644 index 0000000..e6f6fb8 --- /dev/null +++ b/WcsMain/ApiServe/Factory/WcsApiResponseFactory.cs @@ -0,0 +1,170 @@ +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.Enum.ApiServer; + +namespace WcsMain.ApiServe.Factory; + +public static class WcsApiResponseFactory +{ + /// + /// 表示一个操作成功的响应 + /// + /// + public static WcsApiResponse Success(string msg = "操作成功") + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg + }; + public static WcsApiResponse Success(T? data = default, string msg = "操作成功") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg, + ReturnData = data + }; + public static WcsApiResponse Success(T1? tag = default, T2? data = default, string msg = "操作成功") where T1 : new() where T2 : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg, + Tag = tag, + ReturnData = data + }; + + /// + /// 表示一个操作失败的响应 + /// + /// + /// + public static WcsApiResponse Fail(string msg = "操作失败") + => new() + { + Code = (int)ApiResponseCodeEnum.fail, + Msg = msg + }; + public static WcsApiResponse Fail(T? data = default, string msg = "操作失败") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.fail, + Msg = msg, + ReturnData = data + }; + public static WcsApiResponse Fail(T1? tag = default, T2? data = default, string msg = "操作失败") where T1 : new() where T2 : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg, + Tag = tag, + ReturnData = data +}; + + + /// + /// 表示一个请求参数错误的响应 + /// + /// + /// + public static WcsApiResponse RequestErr(string msg = "请求参数错误") + => new() + { + Code = (int)ApiResponseCodeEnum.requestDataErr, + Msg = msg + }; + public static WcsApiResponse RequestErr(T? data = default, string msg = "请求参数错误") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.requestDataErr, + Msg = msg, + ReturnData = data + }; + public static WcsApiResponse RequestErr(T1? tag = default, T2? data = default, string msg = "请求参数错误") where T1 : new() where T2 : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg, + Tag = tag, + ReturnData = data +}; + + /// + /// 表示一个数据重复的响应 + /// + /// + /// + public static WcsApiResponse DataRepetition(string msg = "数据重复") + => new() + { + Code = (int)ApiResponseCodeEnum.dataRepetition, + Msg = msg + }; + public static WcsApiResponse DataRepetition(T? data = default, string msg = "数据重复") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.dataRepetition, + Msg = msg, + ReturnData = data + }; + public static WcsApiResponse DataRepetition(T1? tag = default, T2? data = default, string msg = "数据重复") where T1 : new() where T2 : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg, + Tag = tag, + ReturnData = data +}; + + /// + /// 表示一个服务器异常的响应 + /// + /// + /// + public static WcsApiResponse ServiceErr(string msg = "服务器异常") + => new() + { + Code = (int)ApiResponseCodeEnum.serviceErr, + Msg = msg + }; + public static WcsApiResponse ServiceErr(T? data = default, string msg = "服务器异常") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.serviceErr, + Msg = msg, + ReturnData = data + }; + public static WcsApiResponse ServiceErr(T1? tag = default, T2? data = default, string msg = "服务器异常") where T1 : new() where T2 : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg, + Tag = tag, + ReturnData = data +}; + + /// + /// 表示一个数据库异常的响应 + /// + /// + /// + public static WcsApiResponse DataBaseErr(string msg = "后台数据库异常,请重试") + => new() + { + Code = (int)ApiResponseCodeEnum.dataBaseErr, + Msg = msg + }; + public static WcsApiResponse DataBaseErr(T? data = default, string msg = "后台数据库异常,请重试") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.dataBaseErr, + Msg = msg, + ReturnData = data + }; + public static WcsApiResponse DataBaseErr(T1? tag = default, T2? data = default, string msg = "后台数据库异常,请重试") where T1 : new() where T2 : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Msg = msg, + Tag = tag, + ReturnData = data + }; + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Factory/WmsApiResponseFactory.cs b/WcsMain/ApiServe/Factory/WmsApiResponseFactory.cs new file mode 100644 index 0000000..84329ad --- /dev/null +++ b/WcsMain/ApiServe/Factory/WmsApiResponseFactory.cs @@ -0,0 +1,123 @@ +using WcsMain.ApiServe.Controllers.Dto.WMSEntity; +using WcsMain.Enum.ApiServer; + +namespace WcsMain.ApiServe.Factory; + +public class WmsApiResponseFactory +{ + /// + /// 表示一个操作成功的响应 + /// + /// + public static WmsApiResponse Success(string msg = "操作成功") + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Message = msg + }; + public static WmsApiResponse Success(T? data = default, string msg = "操作成功") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.success, + Message = msg, + ReturnData = data + }; + + /// + /// 表示一个操作失败的响应 + /// + /// + /// + public static WmsApiResponse Fail(string msg = "操作失败") + => new() + { + Code = (int)ApiResponseCodeEnum.fail, + Message = msg + }; + public static WmsApiResponse Fail(T? data = default, string msg = "操作失败") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.fail, + Message = msg, + ReturnData = data + }; + + + /// + /// 表示一个请求参数错误的响应 + /// + /// + /// + public static WmsApiResponse RequestErr(string msg = "请求参数错误") + => new() + { + Code = (int)ApiResponseCodeEnum.requestDataErr, + Message = msg, + }; + public static WmsApiResponse RequestErr(T? data = default, string msg = "请求参数错误") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.requestDataErr, + Message = msg, + ReturnData = data + }; + + + /// + /// 表示一个数据重复的响应 + /// + /// + /// + public static WmsApiResponse DataRepetition(string msg = "数据重复") + => new() + { + Code = (int)ApiResponseCodeEnum.dataRepetition, + Message = msg, + }; + public static WmsApiResponse DataRepetition(T? data = default, string msg = "数据重复") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.dataRepetition, + Message = msg, + ReturnData = data + }; + + /// + /// 表示一个服务器异常的响应 + /// + /// + /// + public static WmsApiResponse ServiceErr(string msg = "服务器异常") + => new() + { + Code = (int)ApiResponseCodeEnum.serviceErr, + Message = msg, + }; + public static WmsApiResponse ServiceErr(T? data = default, string msg = "服务器异常") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.serviceErr, + Message = msg, + ReturnData = data + }; + + /// + /// 表示一个数据库异常的响应 + /// + /// + /// + public static WmsApiResponse DataBaseErr(string msg = "后台数据库异常,请重试") + => new() + { + Code = (int)ApiResponseCodeEnum.dataBaseErr, + Message = msg, + }; + public static WmsApiResponse DataBaseErr(T? data = default, string msg = "后台数据库异常,请重试") where T : class + => new() + { + Code = (int)ApiResponseCodeEnum.dataBaseErr, + Message = msg, + ReturnData = data + }; + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/TreeDService/TaskService.cs b/WcsMain/ApiServe/Service/TreeDService/TaskService.cs new file mode 100644 index 0000000..d9f1d34 --- /dev/null +++ b/WcsMain/ApiServe/Service/TreeDService/TaskService.cs @@ -0,0 +1,53 @@ +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.TreeDService; + +[Service] +public class TaskService(AppWmsTaskDao wmsTaskDao, AppWcsTaskDao wcsTaskDao) +{ + private readonly AppWcsTaskDao _wcsTaskDao = wcsTaskDao; + private readonly AppWmsTaskDao _wmsTaskDao = wmsTaskDao; + + /// + /// 查询WMS任务 + /// + /// + public WcsApiResponse> GetWmsTask() + { + List? wmsTasks = _wmsTaskDao.SelectToWeb(); + return WcsApiResponseFactory.Success(wmsTasks); + } + + /// + /// 查询WMS任务 + /// + /// + public WcsApiResponse> GetWmsTaskNoEnd() + { + List? wmsTasks = _wmsTaskDao.SelectWmsTaskNotEnd(); + return WcsApiResponseFactory.Success(wmsTasks); + } + + /// + /// 根据 plcId 查询任务 + /// + /// + /// + public WcsApiResponse GetWcsTask(int? plcId) + { + if (plcId == default || plcId == 0) + { + return WcsApiResponseFactory.RequestErr(default, $"无法识别查询的 plcId ,值为:{plcId}"); + } + List? queryResult = _wcsTaskDao.Select(new AppWcsTask() { PlcId = plcId }); + if (queryResult == default || queryResult.Count < 1) + { + return WcsApiResponseFactory.Fail(default, $"未找到该 plcId 对应的任务,值为:{plcId}"); + } + return WcsApiResponseFactory.Success(queryResult[0]); + } +} diff --git a/WcsMain/ApiServe/Service/WcsService/ApiAcceptService.cs b/WcsMain/ApiServe/Service/WcsService/ApiAcceptService.cs new file mode 100644 index 0000000..d989832 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/ApiAcceptService.cs @@ -0,0 +1,29 @@ +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiAccept; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class ApiAcceptService(AppApiAcceptDao apiAcceptDao) +{ + private readonly AppApiAcceptDao _apiAcceptDao = apiAcceptDao; + + /// + /// 分页查询API接收记录 + /// + /// + /// + public WcsApiResponse> GetApiAcceptWithPage(GetApiAcceptWithPageRequest request) + { + var (apiRequests, totalRows) = _apiAcceptDao.SelectPage(request); + if(apiRequests == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(apiRequests, totalRows.ToString()); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/ApiRequestService.cs b/WcsMain/ApiServe/Service/WcsService/ApiRequestService.cs new file mode 100644 index 0000000..adcf590 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/ApiRequestService.cs @@ -0,0 +1,43 @@ +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiRequest; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class ApiRequestService(AppApiRequestDao apiRequestDao) +{ + private readonly AppApiRequestDao _apiRequestDao = apiRequestDao; + + /// + /// 获取所有API请求记录 + /// + /// + public WcsApiResponse> GetApiRequest() + { + List? apiRequests = _apiRequestDao.Select(); + if(apiRequests == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(apiRequests); + } + + /// + /// 分页获取API请求记录 + /// + /// + /// + public WcsApiResponse> GetApiRequestWithPage(GetApiRequestWithPageRequest request) + { + var (apiRequests, totalRows) = _apiRequestDao.SelectPage(request); + if(apiRequests == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(apiRequests, totalRows.ToString()); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/ConfigService.cs b/WcsMain/ApiServe/Service/WcsService/ConfigService.cs new file mode 100644 index 0000000..5ada07a --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/ConfigService.cs @@ -0,0 +1,79 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Config; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class ConfigService(AppConfigDao configDao) +{ + private readonly AppConfigDao _configDao = configDao; + + /// + /// 查询配置项,若查询参数为空则返回所有信息 + /// + /// + /// + public WcsApiResponse> GetConfig(string? configKey) + { + var configs = _configDao.GetAllConfig(configKey); + if(configs == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(configs); + } + + /// + /// 分页查询系统配置项 + /// + /// + /// + public WcsApiResponse> GetConfigWithPage(GetConfigWithPageRequest request) + { + var (configs, totalNumber) = _configDao.GetAllConfigWithPage(request); + if (configs == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(configs, totalNumber.ToString()); + } + + /// + /// 添加修改配置项 + /// + /// + /// + public WcsApiResponse EditeConfig(EditeConfigRequest request) + { + // 检查必填的数据 + var checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + AppConfig config = new() + { + ConfigKey = request.ConfigKey, + ConfigName = request.ConfigName, + ConfigType = request.ConfigType, + ConfigValue = request.ConfigValue, + Remark = request.Remark + }; + if (request.IsEdite) // 修改信息 + { + var result = _configDao.Update(config); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + else // 添加信息 + { + var result = _configDao.Insert(config); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/EquipmentService.cs b/WcsMain/ApiServe/Service/WcsService/EquipmentService.cs new file mode 100644 index 0000000..973bb75 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/EquipmentService.cs @@ -0,0 +1,60 @@ +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.WcsAttribute.AutoFacAttribute; +using WcsMain.ApiServe.Controllers.Dto.Equipment; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Equipment; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class EquipmentService(AppStackerDao stackerDao) +{ + + private readonly AppStackerDao _stackerDao = stackerDao; + + /// + /// 查询所有堆垛机状态 + /// + /// + public WcsApiResponse> GetStackerInfo() + { + return WcsApiResponseFactory.Fail>(msg: "暂不支持"); + } + + + /// + /// 查询库前输送机信息 + /// + /// + public WcsApiResponse> GetConveyInfo() + { + // [TODO] + return WcsApiResponseFactory.Fail>(msg: "该功能暂不支持"); + } + + + + /// + /// 复位堆垛机 + /// + /// + /// + public WcsApiResponse ResetStacker(ResetStackerRequest request) + { + return WcsApiResponseFactory.Fail($"暂不支持"); + + } + + + /// + /// 堆垛机继续运行 + /// + /// + /// + public WcsApiResponse StackerContinue(StackerContinueRequest request) + { + return WcsApiResponseFactory.Fail($"暂不支持"); + } + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/LocationService.cs b/WcsMain/ApiServe/Service/WcsService/LocationService.cs new file mode 100644 index 0000000..81df705 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/LocationService.cs @@ -0,0 +1,72 @@ +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Location; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class LocationService(AppLocationDao locationDao) +{ + + private readonly AppLocationDao _locationDao = locationDao; + + /// + /// 查询所有的点位状态 + /// + /// + public WcsApiResponse> GetLocation() + { + List? locations = _locationDao.Select(); + if (locations == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(locations, "查询成功"); + } + + /// + /// 分页查询点位的状态 + /// + /// + /// + public WcsApiResponse> GetLocationWithPage(GetLocationWithPageRequest request) + { + (List? locations, int totalRows) = _locationDao.SelectPage(request); + if(locations == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(locations, totalRows.ToString()); + } + + /// + /// 更新点位状态 + /// + /// + /// + public WcsApiResponse UpdateLocation(UpdateLocationRequest request) + { + AppLocation updateEntity = new() + { + WcsLocation = request.WcsLocation, + WmsLocation = request.WmsLocation, + TunnelNo = request.TunnelNo, + EquipmentId = request.EquipmentId, + LocationStatus = request.LocationStatus, + Queue = request.Queue, + Line = request.Line, + Layer = request.Layer, + Depth = request.Depth, + LocationType = request.LocationType, + VehicleNo = request.VehicleNo, + ModifyTime = DateTime.Now, + Explain = request.Explain, + Remark = request.Remark + }; + var result = _locationDao.Update(updateEntity); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } +} diff --git a/WcsMain/ApiServe/Service/WcsService/MenuService.cs b/WcsMain/ApiServe/Service/WcsService/MenuService.cs new file mode 100644 index 0000000..0e716d6 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/MenuService.cs @@ -0,0 +1,77 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Menu; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; +using WcsMain.ApiServe.Factory; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class MenuService(AppMenuDao menuDao) +{ + private readonly AppMenuDao _menuDao = menuDao; + + /// + /// 分页查询菜单信息 + /// + /// + /// + public WcsApiResponse> GetMenuWithPage(GetMenuWithPageRequest request) + { + var (menus, totalRows) = _menuDao.SelectPage(request); + if (menus == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(menus, totalRows.ToString()); + } + + /// + /// 更新菜单信息 + /// + /// + /// + public WcsApiResponse UpdateMenu(UpdateMenuRequest request) + { + var menuData = new AppMenu() + { + MainMenuIndex = request.MainMenuIndex, + MainMenuName = request.MainMenuName, + MainMenuIco = request.MainMenuIco, + MinorMenuIndex = request.MinorMenuIndex, + MinorMenuName = request.MinorMenuName, + MinorMenuIco = request.MinorMenuIco, + MinorMenuRouter = request.MinorMenuRouter, + MenuStatus = request.MenuStatus, + Remark = request.Remark + }; + var result = _menuDao.Update(menuData); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + + + /// + /// 添加一个菜单信息 + /// + /// + /// + public WcsApiResponse AddMenu(AddMenuRequest request) + { + var menuData = new AppMenu() + { + MainMenuIndex = request.MainMenuIndex, + MainMenuName = request.MainMenuName, + MainMenuIco = request.MainMenuIco, + MinorMenuIndex = request.MinorMenuIndex, + MinorMenuName = request.MinorMenuName, + MinorMenuIco = request.MinorMenuIco, + MinorMenuRouter = request.MinorMenuRouter, + MenuStatus = request.MenuStatus, + Remark = request.Remark + }; + var result = _menuDao.Insert(menuData); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + +} diff --git a/WcsMain/ApiServe/Service/WcsService/PlcDbService.cs b/WcsMain/ApiServe/Service/WcsService/PlcDbService.cs new file mode 100644 index 0000000..b883eee --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/PlcDbService.cs @@ -0,0 +1,81 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.DB; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class PlcDbService(AppDBDao dBDao) +{ + private readonly AppDBDao _dBDao = dBDao; + + /// + /// 查询所有的Db地址信息 + /// + /// + public WcsApiResponse> GetDB() + { + List? dbs = _dBDao.Select(); + if(dbs == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(dbs, "查询成功"); + } + + + + /// + /// 添加修改db + /// + /// + /// + public WcsApiResponse EditePlc(EditeDBRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + AppDB db = new() + { + PlcId = Convert.ToInt32(request.PlcId), + DBName = request.DbName, + DBAddress = request.DbAddress, + IsSystem = request.IsSystem, + Remark = request.Remark + }; + if (request.IsEdite) + { + // 修改信息 + var result = _dBDao.Update(db); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + else + { + // 添加信息 + var result = _dBDao.Insert(db); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + + } + + /// + /// 删除DB信息 + /// + /// + /// + public WcsApiResponse DeleteDB(string? dbName) + { + if (string.IsNullOrEmpty(dbName)) + { + return WcsApiResponseFactory.RequestErr(); + } + var result = _dBDao.Delete(new AppDB() { DBName = dbName }); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/PlcService.cs b/WcsMain/ApiServe/Service/WcsService/PlcService.cs new file mode 100644 index 0000000..d3b5737 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/PlcService.cs @@ -0,0 +1,65 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.PLC; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class PlcService(AppPLCDao pLCDao) +{ + + private readonly AppPLCDao _plcDao = pLCDao; + + + public WcsApiResponse> GetPlc() + { + List? plcs = _plcDao.Query(); + if (plcs == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(plcs, "查询成功"); + } + + + /// + /// 添加修改plc + /// + /// + /// + public WcsApiResponse EditePlc(EditePLCRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr>(); + } + AppPLC plc = new() + { + PLCId = Convert.ToInt32(request.PlcId), + PLCIp = request.PlcIp, + PLCKind = request.PlcKind, + PLCRack = request.Rack, + PLCSlot = request.Slot, + PLCStatus = request.PlcStatus, + Remark = request.Remark + }; + if (request.IsEdite) + { + // 修改信息 + var result = _plcDao.Update(plc); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + else + { + // 添加信息 + var result = _plcDao.Insert(plc); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/RunningInfoService.cs b/WcsMain/ApiServe/Service/WcsService/RunningInfoService.cs new file mode 100644 index 0000000..33a578d --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/RunningInfoService.cs @@ -0,0 +1,67 @@ +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.SystemController; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.WcsAttribute.AutoFacAttribute; +using WcsMain.ApiServe.Factory; +using DataCheck; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class RunningInfoService +{ + + /// + /// 获取日志名称 + /// + /// + /// + public WcsApiResponse> GetLogFileName(string? logType) + { + string logAddress = AppDomain.CurrentDomain.BaseDirectory + $"Log\\{logType}\\"; + DirectoryInfo directoryInfo = new(logAddress); + bool isExist = directoryInfo.Exists; + if (!isExist) + { + return WcsApiResponseFactory.Fail>(msg: "没有相关的日志"); + } + var fileInfos = directoryInfo.GetFiles(); + List fileNames = []; + foreach (FileInfo fileInfo in fileInfos) + { + fileNames.Add(fileInfo.Name); + } + return WcsApiResponseFactory.Success(fileNames, "查询成功"); + } + + /// + /// 验证下载文件是否存在 + /// + /// + /// + public WcsApiResponse CheckDownLoadLog([FromBody] LogRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + string logAddress = AppDomain.CurrentDomain.BaseDirectory + $"Log\\{request.LogType}\\{request.LogFileName}"; + bool isHave = System.IO.File.Exists(logAddress); + return isHave ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.Fail("文件不存在"); + } + + /// + /// 下载文件 + /// + /// + /// + public FileContentResult DownLoadLog(LogRequest request, ControllerBase controllerBase) + { + string logAddress = AppDomain.CurrentDomain.BaseDirectory + $"Log\\{request.LogType}\\{request.LogFileName}"; + byte[] fileBytes = System.IO.File.ReadAllBytes(logAddress); + return controllerBase.File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, "log.txt"); + } + + +} diff --git a/WcsMain/ApiServe/Service/WcsService/SettingService.cs b/WcsMain/ApiServe/Service/WcsService/SettingService.cs new file mode 100644 index 0000000..de5db29 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/SettingService.cs @@ -0,0 +1,56 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Settings; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class SettingService(AppSettingsDao settingsDao) +{ + + private readonly AppSettingsDao _settingsDao = settingsDao; + + /// + /// 根据键名查询设置项 + /// + /// + /// + public WcsApiResponse> GetConfig(string? settingKey) + { + List? configs = _settingsDao.Select(new AppSettings() { SettingKey = settingKey }); + if(configs == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(configs, "查询成功"); + } + + /// + /// 更新配置名称 + /// + /// + /// + public WcsApiResponse EditeConfig(EditSettingsRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + int updateRows = _settingsDao.Update(new AppSettings() + { + SettingKey = request.SettingKey, + SettingName = request.SettingName, + SettingValue = request.SettingValue, + SettingType = request.SettingType, + Remark = request.Remark + }); + return updateRows > 0? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + + +} diff --git a/WcsMain/ApiServe/Service/WcsService/SocketService.cs b/WcsMain/ApiServe/Service/WcsService/SocketService.cs new file mode 100644 index 0000000..45ff99c --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/SocketService.cs @@ -0,0 +1,107 @@ +using WcsMain.ExtendMethod; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Socket; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; +using WcsMain.ApiServe.Factory; +using DataCheck; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class SocketService(AppTcpDao socketDao) +{ + + private readonly AppTcpDao _socketDao = socketDao; + + /// + /// 查询 socket 连接信息 + /// + /// + public WcsApiResponse> GetDB() + { + List? sockets = _socketDao.Query(); + if (sockets == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(sockets, "查询成功"); + } + + /// + /// 编辑 或者 新增一条记录 + /// + /// + /// + public WcsApiResponse EditSocket(EditSocketRequest request) + { + bool checkRequest = CheckData.CheckDataRules(request); + if (!checkRequest || request.IsEdite == default) + { + return WcsApiResponseFactory.RequestErr(); + } + if (!request.SocketNo.IsNumber() || request.IsEdite == default) + { + return WcsApiResponseFactory.RequestErr(); + } + int socketNo = Convert.ToInt32(request.SocketNo); + if ((bool)request.IsEdite!) + { + // 更新现有记录 + int socketStatus = request.SocketStatus.IsNumber() ? Convert.ToInt32(request.SocketStatus) : 0; + /* 插入新记录 */ + AppTcp socket = new() + { + TcpId = socketNo, + TcpIp = request.SocketIpPort, + TcpStatus = socketStatus, + Remark = request.Remark, + }; + int updateRows = _socketDao.Update(socket); + return updateRows > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + else + { + // 新增一条记录 + /* 校验这个编号是否已经存在 */ + List? checks = _socketDao.Query(new AppTcp() { TcpId = socketNo }); + if (checks == default) + { + return WcsApiResponseFactory.DataBaseErr(); + } + if (checks.Count > 0) + { + return WcsApiResponseFactory.DataRepetition("SocketNo重复,已经存在一个相同的编号"); + } + int socketStatus = request.SocketStatus.IsNumber() ? Convert.ToInt32(request.SocketStatus) : 0; + /* 插入新记录 */ + AppTcp socket = new() + { + TcpId = socketNo, + TcpIp = request.SocketIpPort, + TcpStatus = socketStatus, + Remark = request.Remark, + }; + int insertRows = _socketDao.Insert(socket); + return insertRows > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + } + + + /// + /// 删除一条记录 + /// + /// + /// + public WcsApiResponse DeleteSocket(string? socketNoStr) + { + if (!socketNoStr.IsNumber()) + { + return WcsApiResponseFactory.RequestErr(); + } + int socketNo = Convert.ToInt32(socketNoStr); + int deleteRows = _socketDao.Delete(new AppTcp() { TcpId = socketNo }); + return deleteRows > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/StackerService.cs b/WcsMain/ApiServe/Service/WcsService/StackerService.cs new file mode 100644 index 0000000..618b90c --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/StackerService.cs @@ -0,0 +1,29 @@ +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class StackerService(AppStackerDao stackerDao) +{ + + private readonly AppStackerDao _stackerDao = stackerDao; + + /// + /// 查询所有的 堆垛机信息 + /// + /// + public WcsApiResponse> GetStacker() + { + List? stackers = _stackerDao.Select(new AppStacker()); + if(stackers == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(stackers, "查询成功"); + } + +} diff --git a/WcsMain/ApiServe/Service/WcsService/UserGroupService.cs b/WcsMain/ApiServe/Service/WcsService/UserGroupService.cs new file mode 100644 index 0000000..025ba47 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/UserGroupService.cs @@ -0,0 +1,95 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.UserGroup; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class UserGroupService(AppUserGroupDao userGroupDao) +{ + private readonly AppUserGroupDao _userGroupDao = userGroupDao; + + /// + /// 查询用户组 + /// + /// + public WcsApiResponse> GetUserGroup() + { + var userGroup = _userGroupDao.Query(); + if(userGroup == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(userGroup); + } + + + /// + /// 添加用户组的请求 + /// + /// + /// + public WcsApiResponse AddUserGroup(AddUserGroupRequest request) + { + // 校验请求参数 + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + // 检查该用户组是否存在 + List? checkUserGroup = _userGroupDao.Query(new AppUserGroup { GroupId = request.GroupId }); + if (checkUserGroup == default) + { + return WcsApiResponseFactory.DataBaseErr(); + } + if (checkUserGroup.Count > 0) // 用户组已经存在 + { + return WcsApiResponseFactory.DataRepetition("该用户组已经存在"); + } + // 插入用户 + var userGroup = new AppUserGroup() + { + GroupId = request.GroupId, + GroupName = request.GroupName, + GroupStatus = request.GroupStatus + }; + var result = _userGroupDao.Insert(userGroup); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + + + /// + /// 删除指定的用户组 + /// + /// + /// + public WcsApiResponse DeleteUserGroup(string? groupId) + { + // 校验请求参数 + if (string.IsNullOrEmpty(groupId)) + { + return WcsApiResponseFactory.RequestErr(); + } + // 检查该用户组是否存在 + List? checkUserGroup = _userGroupDao.Query(new AppUserGroup { GroupId = groupId }); + if (checkUserGroup == default) + { + return WcsApiResponseFactory.DataBaseErr(); + } + if (checkUserGroup.Count < 0) // 用户组不存在 + { + return WcsApiResponseFactory.DataRepetition("该用户组不存在"); + } + // 删除用户组 + var result = _userGroupDao.Delete(new AppUserGroup { GroupId = groupId }); + return result > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + + + + } +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/UserRuleService.cs b/WcsMain/ApiServe/Service/WcsService/UserRuleService.cs new file mode 100644 index 0000000..3d52dc4 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/UserRuleService.cs @@ -0,0 +1,46 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.UserRule; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class UserRuleService(AppUserRuleDao userRuleDao) +{ + private readonly AppUserRuleDao _userRuleDao = userRuleDao; + + /// + /// 获取用户组权限 + /// + /// + public WcsApiResponse> GetUserRule(string? groupId) + { + var userRule = _userRuleDao.Query(new AppUserRule() { GroupId = groupId }); + if(userRule == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(userRule, "查询成功"); + } + + /// + /// 更新用户组权限 + /// + /// + /// + public WcsApiResponse UpdateUserRule(UpdateUserRuleRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + bool result = _userRuleDao.UpdateUserRule(request); + return result ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.Fail(); + } + +} diff --git a/WcsMain/ApiServe/Service/WcsService/UserService.cs b/WcsMain/ApiServe/Service/WcsService/UserService.cs new file mode 100644 index 0000000..80f9043 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/UserService.cs @@ -0,0 +1,107 @@ +using DataCheck; +using EncryptTool; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.User; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class UserService(AppUserDao appUserDao, AppMenuDao menuDao) +{ + private readonly AppUserDao _userDao = appUserDao; + private readonly AppMenuDao _menuDao = menuDao; + + /// + /// 登录请求的具体实现 + /// + /// + /// + public WcsApiResponse Login(LoginRequest request) + { + // 数据校验 + var checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + string encryptPwd = Md5Encrypt.EncryptPassword(request.UserPassword); + /* 判断用户账户ID和密码是否正确 */ + List? loginUser = _userDao.Query(new AppUser { UserId = request.UserId, UserPassword = encryptPwd }); + if (loginUser == default) + { + return WcsApiResponseFactory.DataBaseErr(); + } + if (loginUser.Count < 1) + { + return WcsApiResponseFactory.RequestErr(msg: "用户不存在或者密码不正确"); + } + /* 查找该用户的菜单 */ // ---- 目前无权限控制,默认返回所有菜单 + var loginResponse = GetUserMenu(loginUser[0]); + return WcsApiResponseFactory.Success(loginResponse, "登录成功"); + } + + /// + /// 查找用户的菜单 + /// + /// + /// + private LoginResponse? GetUserMenu(AppUser user) + { + var menus = _menuDao.GetMenuWithGroupId(user.UserGroup!); + if (menus == default || menus.Count < 1) + { + return default; + } + LoginResponse loginResponse = new() { UserName = user.UserName, Menu = [] }; + // ---- 找出主菜单 + List<(string Index, string MainMenuName, string ico)> mainMenuInfo = []; + foreach (var menu in menus) + { + if (mainMenuInfo.Exists(e => e.MainMenuName == menu.MainMenuName)) continue; + (string Index, string MainMenuName, string ico) newMenu = (menu.MainMenuIndex!, menu.MainMenuName!, menu.MainMenuIco!); + mainMenuInfo.Add(newMenu); + loginResponse.Menu.Add(new MainMenuData + { + Index = menu.MainMenuIndex, + MainMenu = menu.MainMenuName, + Ico = menu.MainMenuIco, + }); + } + loginResponse.Menu = [.. loginResponse.Menu.OrderBy(o => o.Index)]; + // ---- 找出次级菜单 + foreach (var mainMenu in loginResponse.Menu) + { + var findResult = menus.FindAll(f => f.MainMenuName == mainMenu.MainMenu); + mainMenu.Minor = []; + foreach (var minorMenu in findResult) + { + mainMenu.Minor.Add(new MinorMenuData + { + Index = minorMenu.MinorMenuIndex, + MinorMenu = minorMenu.MinorMenuName, + Router = minorMenu.MinorMenuRouter, + Ico = minorMenu.MinorMenuIco, + }); + } + mainMenu.Minor = [.. mainMenu.Minor.OrderBy(o => o.Index)]; + } + return loginResponse; + } + + /// + /// 分页查询所有用户 + /// + /// + /// + public WcsApiResponse> GetUserWithPage(GetUserWithPageRequest request) + { + var (users, total) = _userDao.QueryWithPage(request); + return WcsApiResponseFactory.Success(users, total.ToString()); + } + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WcsService/WcsTaskService.cs b/WcsMain/ApiServe/Service/WcsService/WcsTaskService.cs new file mode 100644 index 0000000..7ba2505 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/WcsTaskService.cs @@ -0,0 +1,94 @@ +using DataCheck; +using Microsoft.AspNetCore.Mvc; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.WcsTask; +using WcsMain.ApiServe.Factory; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + + +[Service] +public class WcsTaskService(AppWcsTaskDao wcsTaskDao) +{ + private readonly AppWcsTaskDao _wcsTaskDao = wcsTaskDao; + + /// + /// 查询所有的Wcs任务列表 + /// + /// + public WcsApiResponse> GetWcsTask() + { + List? wcsTasks = _wcsTaskDao.Select(); + if(wcsTasks == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(wcsTasks, "查询成功"); + } + + + /// + /// 根据任务号获取任务信息,包括运行表和备份表 + /// + /// + /// + public WcsApiResponse> GetWcsTaskWithTaskId(string taskId) + { + List? wcsTasks = _wcsTaskDao.GetAllTasksWithBakData(taskId); + if (wcsTasks == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(wcsTasks, "查询成功"); + } + + /// + /// 分页查询正在运行的任务 + /// + /// + /// + public WcsApiResponse> GetWcsTaskWithPage([FromBody] GetWcsTaskWithPageRequest request) + { + (List? wcsTasks, int totalRows) = _wcsTaskDao.SelectPage(request); + if (wcsTasks == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(wcsTasks, totalRows.ToString()); + } + + /// + /// 更新任务信息 + /// + /// + /// + public WcsApiResponse UpdateWcsTaskStatus(UpdateWcsTaskStatusRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + var taskData = _wcsTaskDao.Select(new AppWcsTask() { PlcId = request.PlcId }); + if (taskData == default) + { + return WcsApiResponseFactory.DataBaseErr(); + } + if (taskData.Count < 1) + { + return WcsApiResponseFactory.Fail("找不到该任务,可能该任务不存在或者已经完结"); + } + int updateRows = _wcsTaskDao.Update(new AppWcsTask() + { + PlcId = request.PlcId, + TaskStatus = request.TaskStatus, + Priority = request.Priority, + Remark = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss},手动修改信息" + }); + return updateRows > 0 ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.DataBaseErr(); + } + +} diff --git a/WcsMain/ApiServe/Service/WcsService/WmsTaskService.cs b/WcsMain/ApiServe/Service/WcsService/WmsTaskService.cs new file mode 100644 index 0000000..7536880 --- /dev/null +++ b/WcsMain/ApiServe/Service/WcsService/WmsTaskService.cs @@ -0,0 +1,137 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.WmsTask; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; +using WcsMain.ApiServe.Factory; +using WcsMain.Business.CommonAction; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.DataService; +using WcsMain.Enum.TaskEnum; +using WcsMain.StaticData; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WcsService; + +[Service] +public class WmsTaskService(WmsTaskAction wmsTaskAction, AppWmsTaskDao wmsTaskDao, DataBaseData dataBaseData) +{ + private readonly DataBaseData _dataBaseData = dataBaseData; + private readonly WmsTaskAction _wmsTaskAction = wmsTaskAction; + private readonly AppWmsTaskDao _wmsTaskDao = wmsTaskDao; + + + /// + /// 查询Wms 任务表 + /// + /// + public WcsApiResponse> GetWmsTask() + { + List? wmsTasks = _wmsTaskDao.SelectToWeb(); + if(wmsTasks == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(wmsTasks, "查询成功"); + } + + + /// + /// 分页查询 Wms 任务表 + /// + /// + /// + public WcsApiResponse> GetWmsTaskWithPage(GetWmsTaskWithPageRequest request) + { + (List? wmsTasks, int totalRows) = _wmsTaskDao.SelectPage(request); + if(wmsTasks == default) + { + return WcsApiResponseFactory.DataBaseErr>(); + } + return WcsApiResponseFactory.Success(totalRows, wmsTasks); + } + + /// + /// Wcs 前端发来的任务 + /// + /// + /// + public WcsApiResponse GetStackerTask(SetWmsTask request) + { + request.TaskId = _dataBaseData.GetNewUUID(); + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + /* 插入库存信息 */ // ---- 库存由WMS管理,数据库表也无需操作 + AppWmsTask wmsTask = new() + { + TaskId = request.TaskId, + TaskType = request.TaskType, + TaskStatus = (int)WmsTaskStatusEnum.create, + Priority = request.Priority ?? 0, + Origin = request.Origin, + MidPoint = request.Midpoint, + Destination = request.Destination, + VehicleNo = request.VehicleNo, + VehicleSize = request.VehicleSize ?? -1, + Weight = request.Weight ?? -1, + CreateTime = DateTime.Now, + ModifyTime = DateTime.Now, + CreatePerson = StaticString.WCS, + }; + /* 插入任务数据 */ + //int insertRows = _wmsTaskDao.Insert(wmsTasks.ToArray()); // ---- 直接插入任务数据 + int insertRows = _wmsTaskDao.InsertTaskAndMarkErr(wmsTask); // ---- 先清除这个料箱之前未作的任务,然后插入新数据 + if (insertRows > 0) + { + return WcsApiResponseFactory.Success($"任务创建成功,任务号:{request.TaskId}"); + } + return WcsApiResponseFactory.Fail("数据插入失败,请稍后重试或者联系我们"); + } + + /// + /// 变更任务状态 + /// + /// + /// + public WcsApiResponse UpdateStackerTaskStatus(UpdateStackerTaskStatusRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) + { + return WcsApiResponseFactory.RequestErr(); + } + /* 校验任务是否存在 */ + var tasks = _wmsTaskDao.Select(new AppWmsTask { TaskId = request.TaskId }); + if (tasks == default) + { + // 查询失败 + return WcsApiResponseFactory.DataBaseErr(); + } + if (tasks.Count == 0) + { + // 任务不存在 + return WcsApiResponseFactory.Fail($"任务不存在,任务号:{request.TaskId}"); + } + int? status = request.TaskStatus; + switch (status) + { + case 0: + string resetErrText = _wmsTaskAction.ResetWmsTaskStatus(request.TaskId, request.Destination, StaticString.WCS); // 重置任务 + return string.IsNullOrEmpty(resetErrText) ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.Fail(resetErrText); + case 3: + string completeErrText = _wmsTaskAction.CompleteWmsTaskStatus(request.TaskId, StaticString.WCS); // 完成任务 + return string.IsNullOrEmpty(completeErrText) ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.Fail(completeErrText); + case 999: + string deleteErrText = _wmsTaskAction.DeleteWmsTaskStatus(request.TaskId, StaticString.WCS); // 删除任务 + return string.IsNullOrEmpty(deleteErrText) ? WcsApiResponseFactory.Success() : WcsApiResponseFactory.Fail(deleteErrText); + default: + return WcsApiResponseFactory.Fail($"任务状态不支持:任务状态:{request.TaskStatus}"); + } + } + + + +} \ No newline at end of file diff --git a/WcsMain/ApiServe/Service/WmsService/EquipmentService.cs b/WcsMain/ApiServe/Service/WmsService/EquipmentService.cs new file mode 100644 index 0000000..e7055c4 --- /dev/null +++ b/WcsMain/ApiServe/Service/WmsService/EquipmentService.cs @@ -0,0 +1,37 @@ +using WcsMain.ApiServe.Controllers.Dto.WMSEntity.Equipment; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity; +using WcsMain.ApiServe.Factory; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WmsService; + + +[Service] +public class EquipmentService +{ + + /// + /// 查询站台是否允许动作 + /// + /// + /// + public WmsApiResponse QueryStandStatus(QueryStandStatusRequest request) + { + if (request == null) + { + return WmsApiResponseFactory.RequestErr(msg: "无法解析请求值"); + } + return WmsApiResponseFactory.RequestErr(msg: "暂不支持"); + + } + + /// + /// 通知输送机卸货完成 + /// + /// + public WmsApiResponse UnloadSuccess() + { + return WmsApiResponseFactory.Fail("暂不支持"); + } + +} diff --git a/WcsMain/ApiServe/Service/WmsService/WmsTaskService.cs b/WcsMain/ApiServe/Service/WmsService/WmsTaskService.cs new file mode 100644 index 0000000..e8afdcc --- /dev/null +++ b/WcsMain/ApiServe/Service/WmsService/WmsTaskService.cs @@ -0,0 +1,116 @@ +using DataCheck; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity; +using WcsMain.ApiServe.Controllers.Dto.WMSEntity.WmsTask; +using WcsMain.ApiServe.Factory; +using WcsMain.Business.CommonAction; +using WcsMain.Common; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.TaskEnum; +using WcsMain.ExtendMethod; +using WcsMain.StaticData; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.ApiServe.Service.WmsService; + +/// +/// Wms任务接口逻辑 +/// +[Service] +public class WmsTaskService(WmsTaskAction wmsTaskAction, AppWmsTaskDao wmsTaskDao) +{ + private readonly AppWmsTaskDao _wmsTaskDao = wmsTaskDao; + private readonly WmsTaskAction _wmsTaskAction = wmsTaskAction; + + /// + /// 接收WMS任务数据处理 + /// + /// + /// + /// + public WmsApiResponse GetStackerTask(List request) + { + if (request.Count < 1) return WmsApiResponseFactory.RequestErr("请求的任务数量为 0"); + /* 插入库存信息 */ // ---- 库存由WMS管理,数据库表也无需操作 + List wmsTasks = []; + foreach (var taskData in request) + { + /* 检验传入的数据格式 */ + bool checkData = CheckData.CheckDataRules(taskData); + if (!checkData) return WmsApiResponseFactory.RequestErr("请求的任务数据部分存在格式问题,请检查数据格式"); + /* 检验起点和终点是否正常 */ + var existOringin = CommonData.AppLocations.ExistWmsLocation(taskData.Origin); + var existDestination = CommonData.AppLocations.ExistWmsLocation(taskData.Destination); + if(!existOringin || !existDestination) return WmsApiResponseFactory.RequestErr($"任务号:{taskData.TaskId} 的起点或者终点不正确"); + /* 构造任务 */ + wmsTasks.Add(new AppWmsTask() + { + TaskId = taskData.TaskId, + TaskType = taskData.TaskType, + TaskStatus = (int)WmsTaskStatusEnum.create, + Priority = taskData.Priority ?? -1, + Origin = taskData.Origin, + MidPoint = taskData.Midpoint, + Destination = taskData.Destination, + VehicleNo = taskData.VehicleNo, + VehicleSize = taskData.VehicleSize ?? -1, + Weight = taskData.Weight ?? -1, + CreateTime = DateTime.Now, + ModifyTime = DateTime.Now, + CreatePerson = StaticString.WMS, + }); + } + List taskIds = []; // 存放任务号 + foreach (var checkEntity in wmsTasks) + { + /* 检查任务号是否重复 */ + List? checkSame = _wmsTaskDao.Select(new AppWmsTask() { TaskId = checkEntity.TaskId }); + if (checkSame == default) return WmsApiResponseFactory.DataBaseErr(); + if (checkSame.Count > 0 || taskIds.Exists(e => e == checkEntity.TaskId)) + { + return WmsApiResponseFactory.RequestErr($"任务:{checkEntity.TaskId} 已存在,请勿重复"); + } + taskIds.Add(checkEntity.TaskId); + } + /* 插入任务数据 */ + //int insertRows = _wmsTaskDao.Insert(wmsTasks.ToArray()); // ---- 直接插入任务数据 + int insertRows = _wmsTaskDao.InsertTaskAndMarkErr([.. wmsTasks]); // ---- 先清除这个料箱之前未作的任务,然后插入新数据 + if (insertRows > 0) return WmsApiResponseFactory.Success($"任务创建成功,任务号:{string.Join(',', taskIds)}"); + return WmsApiResponseFactory.Fail("数据插入失败,请稍后重试或者联系我们"); + } + + + + /// + /// 更新任务状态 + /// + /// + /// + public WmsApiResponse UpdateStackerTaskStatus(UpdateStackerTaskStatusRequest request) + { + bool checkData = CheckData.CheckDataRules(request); + if (!checkData) return WmsApiResponseFactory.RequestErr(); + /* 校验任务是否存在 */ + var tasks = _wmsTaskDao.Select(new AppWmsTask { TaskId = request.TaskId }); + if (tasks == default) return WmsApiResponseFactory.DataBaseErr(); // 数据库连接失败 + if (tasks.Count == 0) return WmsApiResponseFactory.RequestErr($"任务:{request.TaskId} 不存在"); + int? status = request.TaskStatus; + switch(status) + { + case 0: + string resetErrText = _wmsTaskAction.ResetWmsTaskStatus(request.TaskId, request.Destination, StaticString.WMS); // 重置任务 + return string.IsNullOrEmpty(resetErrText) ? WmsApiResponseFactory.Success() : WmsApiResponseFactory.Fail(resetErrText); + case 3: + string completeErrText = _wmsTaskAction.CompleteWmsTaskStatus(request.TaskId, StaticString.WMS); // 完成任务 + return string.IsNullOrEmpty(completeErrText) ? WmsApiResponseFactory.Success() : WmsApiResponseFactory.Fail(completeErrText); + case 999: + string deleteErrText = _wmsTaskAction.DeleteWmsTaskStatus(request.TaskId, StaticString.WMS); // 删除任务 + return string.IsNullOrEmpty(deleteErrText) ? WmsApiResponseFactory.Success() : WmsApiResponseFactory.Fail(deleteErrText); + default: + return WmsApiResponseFactory.RequestErr($"不支持的任务状态:{request.TaskStatus}"); + } + } + + + +} \ No newline at end of file diff --git a/WcsMain/AppEntity/LED/LEDData.cs b/WcsMain/AppEntity/LED/LEDData.cs new file mode 100644 index 0000000..596af51 --- /dev/null +++ b/WcsMain/AppEntity/LED/LEDData.cs @@ -0,0 +1,86 @@ +namespace WcsMain.AppEntity.LED; + +/// +/// 需要展示在LED显示器上的内容 +/// +public class LEDData +{ + /// + /// 展示的模式,用于区分各种样式 + /// + public LEDShowModel? ShowModel { get; set; } + + + + /// + /// 出入库模式 + /// + public string? TaskModel { get; set; } + + /// + /// 载具号 + /// + public string? VehicleNo { get; set; } + + /// + /// plc任务号 + /// + public int? PlcId { get; set; } + + /// + /// 任务起点 + /// + public string? Origin { get; set; } + + /// + /// 任务终点 + /// + public string? Destination { get; set; } + + + + public static bool operator ==(LEDData? left, LEDData? right) + { + if (left == default && right == default) { return true; }; + if (left == default && right != default) { return false; }; + if (left != default && right == default) { return false; }; + return left!.Equals(right); + } + + public static bool operator !=(LEDData? left, LEDData? right) + { + if (left == default && right == default) { return false; }; + if (left == default && right != default) { return true; }; + if (left != default && right == default) { return true; }; + return !left!.Equals(right); + } + + public override bool Equals(object? obj) + { + if (obj == default) { return false; } + if (obj is LEDData ledData) + { + if (ShowModel == LEDShowModel.stackerTask) + { + if (TaskModel == ledData.TaskModel + && VehicleNo == ledData.VehicleNo + && PlcId == ledData.PlcId + && Origin == ledData.Origin + && Destination == ledData.Destination) + { return true; } // 上面这些值都相等旧返回 true + } + } + return false; + } + + public override int GetHashCode() + { + return GetType().GetHashCode(); + } +} + + +public enum LEDShowModel +{ + stackerTask = 1, // 显示堆垛机任务 +} \ No newline at end of file diff --git a/WcsMain/AppEntity/SystemData/AppConfigEntity.cs b/WcsMain/AppEntity/SystemData/AppConfigEntity.cs new file mode 100644 index 0000000..0b38d76 --- /dev/null +++ b/WcsMain/AppEntity/SystemData/AppConfigEntity.cs @@ -0,0 +1,107 @@ +using WcsMain.WcsAttribute.AppConfig; + +namespace WcsMain.AppEntity.SystemData; + +/* + * ConfigKey 对应表内的 config_key + * 若此处填写没有的 ConfigKey,则该变量会保持默认值;若不填写 ConfigKey 则会读取该属性的名称 + */ + +/// +/// 数据库配置表的映射 +/// +public class AppConfigEntity +{ + /******************************* 系统基本信息 *******************************/ + + /// + /// Wcs 系统在系统中的编号 + /// + [ConfigKey("WcsId")] + public string? WcsId { get; set; } + + + /***************************** API信息 *************************************/ + + /// + /// Wms 的根地址 + /// + [ConfigKey("WmsBaseApiAddress")] + public string? WmsBaseAddressApiAddress { get; set; } + + /// + /// 请求入库的地址 + /// + [ConfigKey("ApplyEnterApiAddress")] + public string? ApplyEnterApiAddress { get; set;} + + /// + /// 发送 Wms 任务状态 + /// + [ConfigKey("SendWmsTaskStatusApiAddress")] + public string? SendWmsTaskStatusApiAddress { get; set; } + + /// + /// 上报载具到达 + /// + [ConfigKey("VehicleArriveApiAddress")] + public string? VehicleArriveApiAddress { get; set; } + + + + + /****************************** 功能配置 ******************************/ + + /// + /// 表示是否开启定时器 + /// + /// + /// 0 - 关闭 + /// 1 - 开启 + /// + [ConfigKey("UseCirculation")] + public string? UseCirculation { get; set; } + + /// + /// 表示是否开启连接PLC + /// + /// + /// 0 - 关闭 + /// 1 - 开启 + /// + [ConfigKey("UseConnectPlc")] + public string? UseConnectPlc { get; set; } + + + /// + /// 表示是否开启 Socket 连接 + /// + /// + /// 0 - 关闭 + /// 1 - 开启 + /// + [ConfigKey("UseSocket")] + public string? UseSocket { get; set; } + + + /// + /// 表示过账确认的方法 + /// + /// + /// 0 - 直接写过账区 + /// 1 - 写过账反馈区 + /// + [ConfigKey("CheckAccountMethod")] + public string? CheckAccountMethod { get; set; } + + + /// + /// 是否是扫码入库 + /// + /// + /// 0 - 不是扫码入库 + /// 1 - 扫码入库 + /// + [ConfigKey("ExcuteStackerInTaskWithScan")] + public string? ExcuteStackerInTaskWithScan { get; set; } +} diff --git a/WcsMain/AppEntity/SystemData/AppSettingJsonEntity.cs b/WcsMain/AppEntity/SystemData/AppSettingJsonEntity.cs new file mode 100644 index 0000000..70b6e5a --- /dev/null +++ b/WcsMain/AppEntity/SystemData/AppSettingJsonEntity.cs @@ -0,0 +1,49 @@ +using System.Diagnostics.CodeAnalysis; + +namespace WcsMain.AppEntity.SystemData; + +/// +/// 应用程序内的设置 JSON 的设置映射 +/// +public class AppSettingJsonEntity +{ + /// + /// Mysql 数据库连接字符串 + /// + public string? DBMysql { get; set; } + + /// + /// Mssql 数据库连接字符串 + /// + public string? DBMssql { get; set; } + + /// + /// mssql 本地测试 + /// + public string? DBMssqlLocal { get; set; } + + /// + /// mysql 本地数据库 + /// + public string? DBMysqlLocal { get; set; } + + /// + /// 系统配置项 + /// + [NotNull] + public ApplicationConfig? ApplicationConfig { get; set; } + + /// + /// 系统启动的发布地址 + /// + public string[]? UseUrls { get; set; } +} + + +public class ApplicationConfig +{ + /// + /// 是否仅以 api 形式运行,此状态下不会运行 Wcs 相关内容 + /// + public bool? ApiOnly { get; set; } +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/CommonCirculation/ConnectPlcWithCirculation.cs b/WcsMain/Business/CirculationTask/CommonCirculation/ConnectPlcWithCirculation.cs new file mode 100644 index 0000000..75b0daf --- /dev/null +++ b/WcsMain/Business/CirculationTask/CommonCirculation/ConnectPlcWithCirculation.cs @@ -0,0 +1,35 @@ +using CirculateTool; +using WcsMain.Common; +using WcsMain.PlcOperation; + +namespace WcsMain.Business.CirculationTask; + +/// +/// 定时器检测 PLC 是否连接,若没有连接则重新连接 +/// +[Circulation] +public class ConnectPlcWithCirculation(ConnectPLCs connectPLCs) +{ + private readonly ConnectPLCs _connectPLCs = connectPLCs; + + /// + /// 当plc断开时重新连接 PLC + /// + /// + [Circulation("连接PLC", 5000)] + public bool ReconnectPlc() + { + if (CommonData.IsConnectPlc == false) + { + // 如果处于未连接的状态则需要连接 + /* 连接 PLC */ + bool isContinue = _connectPLCs.ConnectPlc(); + if (!isContinue) + { + return false; // 没有需要连接PLC可能,不需要接着继续检测了 + } + } + return true; + } + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/CommonCirculation/DataClear.cs b/WcsMain/Business/CirculationTask/CommonCirculation/DataClear.cs new file mode 100644 index 0000000..00de5d1 --- /dev/null +++ b/WcsMain/Business/CirculationTask/CommonCirculation/DataClear.cs @@ -0,0 +1,53 @@ +using CirculateTool; +using WcsMain.Business.CommonAction; + +namespace WcsMain.Business.CirculationTask.CommonCirculation; + +/// +/// 数据清理 +/// +[Circulation("数据清理")] +public class DataClear(ClearData clearData) +{ + private readonly ClearData _clearData = clearData; + + /// + /// 定时清理无用数据, ---- 每隔10分钟清理一次 + /// + /// + [Circulation("数据清理", 1000 * 60 * 30)] + public bool ClearDataCirculate() + { + try + { + // 清理接口接收记录表 -- 保留多少天 + int apiAcceptCount = _clearData.ClearApiAcceptData(30); + ConsoleLog.Tip(apiAcceptCount > 0, $"[数据清理]接口接收记录:{apiAcceptCount}"); + + // 清理日志文件 -- 清理多少天之前 + int logCount = _clearData.ClearLogFile(60); + ConsoleLog.Tip(logCount > 0, $"[数据清理]日志文件:{logCount}"); + + // 清理接口请求记录表 -- 保留多少天 + int apiRequestCount = _clearData.ClearApiRequestData(30); + ConsoleLog.Tip(apiRequestCount > 0, $"[数据清理]接口请求记录:{apiRequestCount}"); + + // 清理WCS任务备份表 -- 保留多少天 + int apiWcsTaskCount = _clearData.ClearWcsTaskData(30); + ConsoleLog.Tip(apiWcsTaskCount > 0, $"[数据清理]WCS任务备份记录:{apiWcsTaskCount}"); + + // 清理WMS任务表 -- 保留多少天 + int apiWmsTaskCount = _clearData.ClearWmsTaskData(30); + ConsoleLog.Tip(apiWmsTaskCount > 0, $"[数据清理]WMS任务记录:{apiWmsTaskCount}"); + } + catch (Exception ex) + { + ConsoleLog.Error($"[数据清理]线程发生异常,异常信息:{ex}"); + } + + + + return true; + } + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/CommonCirculation/HeartBeat.cs b/WcsMain/Business/CirculationTask/CommonCirculation/HeartBeat.cs new file mode 100644 index 0000000..af0b03d --- /dev/null +++ b/WcsMain/Business/CirculationTask/CommonCirculation/HeartBeat.cs @@ -0,0 +1,17 @@ +using CirculateTool; +using WcsMain.PlcOperation; + +namespace WcsMain.Business.CirculationTask.CommonCirculation; + +[Circulation] +public class HeartBeat +{ + + //[Circulation("输送机心跳", 1000)] + public bool ConveyHeartBeat() + { + ConveyOperation.Instance().WriteHeartBeat(); + return true; + } + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/CommonCirculation/LedShow.cs b/WcsMain/Business/CirculationTask/CommonCirculation/LedShow.cs new file mode 100644 index 0000000..eea80eb --- /dev/null +++ b/WcsMain/Business/CirculationTask/CommonCirculation/LedShow.cs @@ -0,0 +1,38 @@ +using WcsMain.Common; + +namespace WcsMain.Business.CirculationTask.CommonCirculation; + +public class LedShow +{ + private static LedShow? _instance; + public static LedShow Instance() => _instance ??= new LedShow(); + + + /// + /// 显示默认值 + /// + public void ShowDefault() + { + CommonTool.LedUsing.ShowDefaultMsg("192.168.103.16", "入库站台"); + CommonTool.LedUsing.ShowDefaultMsg("192.168.103.17", "出库站台"); + } + + + /// + /// 显示入库显示屏 + /// + /// + public DateTime ShowTaskInMessage(string message) + { + CommonTool.LedUsing.ShowDefaultMsg("192.168.103.16", message); + return DateTime.Now; + } + + public DateTime ShowTaskOutMessage(string message) + { + CommonTool.LedUsing.ShowDefaultMsg("192.168.103.17", message); + return DateTime.Now; + } + + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/ScanMethod.cs b/WcsMain/Business/CirculationTask/ScanMethod.cs new file mode 100644 index 0000000..44f9999 --- /dev/null +++ b/WcsMain/Business/CirculationTask/ScanMethod.cs @@ -0,0 +1,75 @@ +using WcsMain.DataService; + +namespace WcsMain.Business.CirculationTask; + +/// +/// 读取 PLC 的扫码 +/// +//[Circulation] +public class ScanMethod(DataBaseData dataBaseData) +{ + private readonly DataBaseData _dataBaseData = dataBaseData; + + + //private static string[]? _scanId; + //private static ScanCodeAction? scanCodeAction; + + ///// + ///// + ///// + ///// + ////[Circulation("读取扫码信息", 100)] + //public bool ReadScanCode() + //{ + // if (_scanId == default) + // { + // GetScanNo(); + // return true; + // } + // foreach (string scanId in _scanId) + // { + // Thread.Sleep(10); + // (string? errText, short scanOk, string code) = ConveyOperation.Instance().ReadScanInfo(scanId); + // if (!string.IsNullOrEmpty(errText)) + // { + // ConsoleLog.Error($"在扫码:{scanId} 处读取信息失败,信息:{errText}"); + // Thread.Sleep(10000); + // continue; + // } + // if (scanOk != 1) { continue; } + // ConveyOperation.Instance().ClearScanStatus(scanId); + // Task.Factory.StartNew(() => + // { + // ConsoleLog.Info($"扫码器:{scanId} 收到数据:{code}"); + // if (string.IsNullOrEmpty(code)) { return; }// 没有条码,不处理 + // scanCodeAction ??= new ScanCodeAction(); + // Type type = scanCodeAction.GetType(); + // var methods = type.GetMethods(); + // if (methods.Length < 1) { return; } // 类里面没有方法 + // foreach (var method in methods) + // { + // string? methodName = DataBaseData.Instance().GetConfig($"ScanMethod{scanId}"); + // if (string.IsNullOrEmpty(methodName)) { return; } + // if (method.Name == methodName) + // { + // method.Invoke(scanCodeAction, [new ScanCodeClass() { Code = code, StrScanID = scanId }]); + // return; + // } + // } + // ConsoleLog.Error($"扫码器编号:{scanId} 未找到方法,请配置 config 参数。"); + // }); + // } + // return true; + //} + + + + //private void GetScanNo() + //{ + // string? scans = DataBaseData.Instance().GetConfig("scanNo"); + // if (string.IsNullOrEmpty(scans)) { return; } + // _scanId = scans.Split(','); + //} + + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/Stacker/CheckAccount.cs b/WcsMain/Business/CirculationTask/Stacker/CheckAccount.cs new file mode 100644 index 0000000..9916cf9 --- /dev/null +++ b/WcsMain/Business/CirculationTask/Stacker/CheckAccount.cs @@ -0,0 +1,159 @@ +using CirculateTool; +using WcsMain.Business.CommonAction; +using WcsMain.Common; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum; +using WcsMain.ExtendMethod; +using WcsMain.PlcOperation.Entity; +using WcsMain.PlcOperation.Stacker; + +namespace WcsMain.Business.CirculationTask.Stacker; + +/// +/// 过账,PLC任务回告 +/// +[Circulation()] +public class CheckAccount(StackerOperation stackerOperation, AppWcsTaskDao wcsTaskDao, WCSTaskExecuteEvent wcsTaskEvent) +{ + private readonly WCSTaskExecuteEvent _wcsTaskEvent = wcsTaskEvent; + private readonly AppWcsTaskDao _wcsTaskDao = wcsTaskDao; + private readonly StackerOperation _stackerOperation = stackerOperation; + + /// + /// PLC过账 + /// + /// + [Circulation("监控PLC地址,过账", 1000)] + public bool CheckAccountTask() + { + var openStackers = CommonData.AppStackers.Open(); + List? taskFeedBackEntities = _stackerOperation.GetTaskFeedBackData(1, openStackers); + if (taskFeedBackEntities == default || taskFeedBackEntities.Count < 1) + { + return true; + } + foreach (TaskFeedBackEntity taskFeedBackEntity in taskFeedBackEntities) + { + if (taskFeedBackEntity.PlcId == 0) { continue; } + List? wcsTasks = _wcsTaskDao.Select(new AppWcsTask() { PlcId = taskFeedBackEntity.PlcId }); + if (wcsTasks == default) + { + ConsoleLog.Error($"【异常】堆垛机过账查询任务数据失败,和数据库服务器连接中断"); + Thread.Sleep(2000); + continue; // 网络连接中断 + } + if (wcsTasks.Count < 1) + { + ConsoleLog.Warning($"【提示】堆垛机过账区获取任务ID:{taskFeedBackEntity.PlcId},无关联任务"); + _stackerOperation.ClearFeedBackData(taskFeedBackEntity); // 清除过账 + continue; // 任务无数据 + } + var wcsTask = wcsTasks[0]; + switch (taskFeedBackEntity.FeedBackType) + { + case (int)TaskFeedBackTypeEnum.cancel: // 任务取消 + CancelTask(taskFeedBackEntity, wcsTask); + break; + case (int)TaskFeedBackTypeEnum.complete: // 任务完成 + CompleteTask(taskFeedBackEntity, wcsTask); + break; + case (int)TaskFeedBackTypeEnum.doubleIn: // 重复入库 + DoubleInFeedBackType(taskFeedBackEntity, wcsTask); + break; + case (int)TaskFeedBackTypeEnum.emptyOut: // 空出库 + EmptyOutFeedBackType(taskFeedBackEntity, wcsTask); + break; + default: + OtherTaskFeedBackType(taskFeedBackEntity); // 其他任务类型 + break; + } + } + return true; + } + + /// + /// 过账任务取消 + /// + /// + /// + private void CancelTask(TaskFeedBackEntity taskFeedBackEntity, AppWcsTask wcsTask) + { + ConsoleLog.Warning($"【提示】过账区反馈:PlcId:{taskFeedBackEntity.PlcId} 已经被取消,后续任务也一并取消,任务号:{wcsTask.TaskId}"); + string? cleanAccountErr = _stackerOperation.ClearFeedBackData(taskFeedBackEntity); // 清除过账 + if (!string.IsNullOrEmpty(cleanAccountErr)) + { + ConsoleLog.Warning($"【警告】取消任务清除过账区发生异常,信息:{cleanAccountErr}"); + } + /* 执行 WMS 任务异常动作 */ + _wcsTaskEvent.ErrTaskEvent(wcsTask, "任务被PLC取消"); + + } + + /// + /// 过账任务完成 + /// + /// + /// + private void CompleteTask(TaskFeedBackEntity taskFeedBackEntity, AppWcsTask wcsTask) + { + ConsoleLog.Tip($"【提示】过账区获取任务ID:{taskFeedBackEntity.PlcId},任务已经完成,任务号:{wcsTask.TaskId}"); + var cleanAccountErr = _stackerOperation.ClearFeedBackData(taskFeedBackEntity); // 清除过账 + if (!string.IsNullOrEmpty(cleanAccountErr)) + { + ConsoleLog.Warning($"【警告】完成任务清除过账区发生异常,信息:{cleanAccountErr}"); + } + /* 执行 WMS 任务完成动作 */ + _wcsTaskEvent.CompleteTaskEvent(wcsTask, "PLC上报完成"); + } + + + + /// + /// 过账卸货位置有货 + /// + /// + /// + private void DoubleInFeedBackType(TaskFeedBackEntity taskFeedBackEntity, AppWcsTask wcsTask) + { + ConsoleLog.Warning($"[提示]过账区获取任务ID:{taskFeedBackEntity.PlcId},卸货位置有货,任务号:{wcsTask.TaskId}"); + string? cleanAccountErr = _stackerOperation.ResetFeedBackData(taskFeedBackEntity); // 清除过账 + if (!string.IsNullOrEmpty(cleanAccountErr)) + { + ConsoleLog.Warning($"[警告]取消任务清除过账区发生异常,信息:{cleanAccountErr}"); + } + /* 执行 WMS 任务异常动作 */ + _wcsTaskEvent.DoubleInTaskEvent(wcsTask, "卸货位置有货"); + } + + /// + /// 过账取货位置无货 + /// + /// + /// + private void EmptyOutFeedBackType(TaskFeedBackEntity taskFeedBackEntity, AppWcsTask wcsTask) + { + ConsoleLog.Warning($"[警告]过账区获取任务ID:{taskFeedBackEntity.PlcId},取货位置无货,任务号:{wcsTask.TaskId}"); + string? cleanAccountErr = _stackerOperation.ResetFeedBackData(taskFeedBackEntity); // 清除过账 + if (!string.IsNullOrEmpty(cleanAccountErr)) + { + ConsoleLog.Warning($"[警告]取消任务清除过账区发生异常,信息:{cleanAccountErr}"); + } + /* 执行 WMS 任务异常动作 */ + _wcsTaskEvent.EmptyOutTaskEvent(wcsTask, "取货位置无货"); + } + + + + /// + /// 其他过账类型 + /// + /// + private void OtherTaskFeedBackType(TaskFeedBackEntity taskFeedBackEntity) + { + ConsoleLog.Warning($"[警告]过账区获取任务ID:{taskFeedBackEntity.PlcId},无法识别的过账类型:{taskFeedBackEntity.FeedBackType}"); + _stackerOperation.ClearFeedBackData(taskFeedBackEntity); // 清除过账 + } + + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/Stacker/ExecuteWcsTask.cs b/WcsMain/Business/CirculationTask/Stacker/ExecuteWcsTask.cs new file mode 100644 index 0000000..3883954 --- /dev/null +++ b/WcsMain/Business/CirculationTask/Stacker/ExecuteWcsTask.cs @@ -0,0 +1,398 @@ +using CirculateTool; +using WcsMain.Business.CommonAction; +using WcsMain.Common; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.Stacker; +using WcsMain.Enum.TaskEnum; +using WcsMain.ExtendMethod; +using WcsMain.PlcOperation.Entity.Stacker; +using WcsMain.PlcOperation.Stacker; + +namespace WcsMain.Business.CirculationTask.Stacker; + +/// +/// 执行堆垛机任务类 +/// +[Circulation(tags: ["stacker"])] +public class ExecuteWcsTask(StackerOperation stackerOperation, AppWcsTaskDao wcsTaskDao, WCSTaskExecuteEvent wcsTaskEvent) +{ + private readonly WCSTaskExecuteEvent _wcsTaskEvent = wcsTaskEvent; + private readonly AppWcsTaskDao _wcsTaskDao = wcsTaskDao; + private readonly StackerOperation _stackerOperation = stackerOperation; + + /// + /// 执行堆垛机任务 + /// + /// + [Circulation("执行堆垛机任务")] + public bool ExecuteStackerTask() + { + foreach (var stacker in CommonData.AppStackers.Open()) + { + var stackerUseStatus = _stackerOperation.StackerCanUse(stacker.StackerId, out int plcId); + if (stackerUseStatus == StackerUseStatusEnum.Free) + { + /* 空闲时正常执行任务 */ + // 入库 + if (!CommonData.AppConfig.ExcuteStackerInTaskWithScan.ToBool()) // 不是扫码入库 + { + bool exeInTask = ExecuteInTask(stacker.StackerId); + if (exeInTask) continue; + } + // 出库 + bool exeOutTask = ExecuteOutTask(stacker.StackerId); + if (exeOutTask) continue; + // 拣选 + bool exePickTask = ExecutePickTask(stacker.StackerId); + if (exePickTask) continue; + // 移库 + bool exeMoveTask = ExecuteMoveTask(stacker.StackerId); + if (exeMoveTask) continue; + } + if (stackerUseStatus == StackerUseStatusEnum.waitTask) + { + /* 重复入库时执行任务 */ + bool exeDoubleInTask = ExecuteDoubleInTask(stacker.StackerId, plcId); + if (exeDoubleInTask) continue; + } + } + return true; + } + + + /// + /// 执行堆垛机入库任务,若执行了任务则返回 true + /// + /// + /// + private bool ExecuteInTask(int? stackerId) + { + if (stackerId == default) return false; + var wcsTasks = _wcsTaskDao.SelectInTaskWithStacker((int)stackerId!); // 此处方法内已经判断状态 + if (wcsTasks == default) + { + ConsoleLog.Error($"【异常】{stackerId} 号堆垛机入库任务查询失败,与数据库连接异常"); + Thread.Sleep(5000); + return false; + } + if (wcsTasks.Count == 0) return false; + var wcsTask = wcsTasks[0]; // 取第一条任务 + /* 校验入库站台是否可以取货 */ + // TODO + /* 检验并返回起点终点信息 */ + var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); + var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); + if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 + { + // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 + ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); + return false; + } + StackerPlcTask stackerTask = new() + { + StackerId = stackerId, + PlcId = wcsTask.PlcId, + TaskType = Convert.ToInt16(wcsTask.TaskType), + GetStand = 0, + InTunnelId = Convert.ToInt16(stackerId), + OutTunnelId = Convert.ToInt16(stackerId), + SetStand = 0, + GetQueue = Convert.ToInt16(originLocationInfo.Queue), + GetLine = Convert.ToInt16(originLocationInfo.Line), + GetLayer = Convert.ToInt16(originLocationInfo.Layer), + GetDeep = Convert.ToInt16(originLocationInfo.Depth), + SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), + SetLine = Convert.ToInt16(destinationLocationInfo.Line), + SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), + SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), + Size = Convert.ToInt16(wcsTask.VehicleSize), + Weight = Convert.ToInt16(wcsTask.Weight), + Code = wcsTask.PlcVehicleNo ?? 0, + }; + var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); + if (string.IsNullOrEmpty(writeStackerTaskErrText)) + { + ConsoleLog.Success($"堆垛机:{stackerId} 写入入库任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); + _wcsTaskEvent.StartTaskEvent(wcsTask); + return true; + } + else + { + ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入入库任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); + } + return false; + } + + /// + /// 执行堆垛机出库任务,若执行了任务则返回 true + /// + /// + /// + public bool ExecuteOutTask(int? stackerId) + { + if (stackerId == default) return false; + var wcsTasks = _wcsTaskDao.SelectOutTaskWithStacker((int)stackerId!); + if (wcsTasks == default) + { + ConsoleLog.Error($"【异常】{stackerId} 号堆垛机出库任务查询失败,与数据库连接异常"); + Thread.Sleep(5000); + return false; + } + if (wcsTasks.Count == 0) return false; + var wcsTask = wcsTasks[0]; // 取第一条任务 + /* 校验出库站台是否可以卸货 */ + // TODO + /* 检验并返回起点终点信息 */ + var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); + var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); + if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 + { + // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 + ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); + return false; + } + StackerPlcTask stackerTask = new() + { + StackerId = stackerId, + PlcId = wcsTask.PlcId, + TaskType = Convert.ToInt16(wcsTask.TaskType), + GetStand = 0, + InTunnelId = Convert.ToInt16(stackerId), + OutTunnelId = Convert.ToInt16(stackerId), + SetStand = 0, + GetQueue = Convert.ToInt16(originLocationInfo.Queue), + GetLine = Convert.ToInt16(originLocationInfo.Line), + GetLayer = Convert.ToInt16(originLocationInfo.Layer), + GetDeep = Convert.ToInt16(originLocationInfo.Depth), + SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), + SetLine = Convert.ToInt16(destinationLocationInfo.Line), + SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), + SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), + Size = Convert.ToInt16(wcsTask.VehicleSize), + Weight = Convert.ToInt16(wcsTask.Weight), + Code = wcsTask.PlcVehicleNo ?? 0, + }; + var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); + if (string.IsNullOrEmpty(writeStackerTaskErrText)) + { + ConsoleLog.Success($"堆垛机:{stackerId} 写入出库任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); + _wcsTaskEvent.StartTaskEvent(wcsTask); + return true; + } + else + { + ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入出库任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); + } + return false; + + } + + /// + /// 执行堆垛机拣选任务,若执行了任务则返回 true + /// + /// + /// + public bool ExecutePickTask(int? stackerId) + { + if (stackerId == default) return false; + var wcsTasks = _wcsTaskDao.SelectPickOutTaskWithStacker((int)stackerId!); + if (wcsTasks == default) + { + ConsoleLog.Error($"【异常】{stackerId} 号堆垛机拣选任务查询失败,与数据库连接异常"); + Thread.Sleep(5000); + return false; + } + if (wcsTasks.Count == 0) return false; + var wcsTask = wcsTasks[0]; // 取第一条任务 + /* 校验出库站台是否可以卸货 */ + // TODO + /* 检验并返回起点终点信息 */ + var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); + var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); + if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 + { + // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 + ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); + return false; + } + StackerPlcTask stackerTask = new() + { + StackerId = stackerId, + PlcId = wcsTask.PlcId, + TaskType = Convert.ToInt16(wcsTask.TaskType), + GetStand = 0, + InTunnelId = Convert.ToInt16(stackerId), + OutTunnelId = Convert.ToInt16(stackerId), + SetStand = 0, + GetQueue = Convert.ToInt16(originLocationInfo.Queue), + GetLine = Convert.ToInt16(originLocationInfo.Line), + GetLayer = Convert.ToInt16(originLocationInfo.Layer), + GetDeep = Convert.ToInt16(originLocationInfo.Depth), + SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), + SetLine = Convert.ToInt16(destinationLocationInfo.Line), + SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), + SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), + Size = Convert.ToInt16(wcsTask.VehicleSize), + Weight = Convert.ToInt16(wcsTask.Weight), + Code = wcsTask.PlcVehicleNo ?? 0, + }; + var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); + if (string.IsNullOrEmpty(writeStackerTaskErrText)) + { + ConsoleLog.Success($"堆垛机:{stackerId} 写入拣选任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); + _wcsTaskEvent.StartTaskEvent(wcsTask); + return true; + } + else + { + ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入拣选任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); + } + return false; + + } + + /// + /// 执行堆垛机移库任务,若执行了任务则返回 true + /// + /// + /// + public bool ExecuteMoveTask(int? stackerId) + { + if (stackerId == default) return false; + var wcsTasks = _wcsTaskDao.SelectMoveTaskWithStacker((int)stackerId!); + if (wcsTasks == default) + { + ConsoleLog.Error($"【异常】{stackerId} 号堆垛机移库任务查询失败,与数据库连接异常"); + Thread.Sleep(5000); + return false; + } + if (wcsTasks.Count == 0) return false; + var wcsTask = wcsTasks[0]; // 取第一条任务 + /* 检验并返回起点终点信息 */ + var originLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Origin); + var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(wcsTask.Destination); + if (destinationLocationInfo == default || originLocationInfo == default) // 起点终点错误,直接标记错误 + { + // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 + ConsoleLog.Warning($"【警告】任务号:{wcsTask.TaskId},Plc任务号:{wcsTask.PlcId} 无法执行,起点或者终点存在异常"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"起点或者终点存在异常"); + return false; + } + StackerPlcTask stackerTask = new() + { + StackerId = stackerId, + PlcId = wcsTask.PlcId, + TaskType = Convert.ToInt16(wcsTask.TaskType), + GetStand = 0, + InTunnelId = Convert.ToInt16(stackerId), + OutTunnelId = Convert.ToInt16(stackerId), + SetStand = 0, + GetQueue = Convert.ToInt16(originLocationInfo.Queue), + GetLine = Convert.ToInt16(originLocationInfo.Line), + GetLayer = Convert.ToInt16(originLocationInfo.Layer), + GetDeep = Convert.ToInt16(originLocationInfo.Depth), + SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), + SetLine = Convert.ToInt16(destinationLocationInfo.Line), + SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), + SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), + Size = Convert.ToInt16(wcsTask.VehicleSize), + Weight = Convert.ToInt16(wcsTask.Weight), + Code = wcsTask.PlcVehicleNo ?? 0, + }; + var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); + if (string.IsNullOrEmpty(writeStackerTaskErrText)) + { + ConsoleLog.Success($"堆垛机:{stackerId} 写入移库任务成功,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination}"); + _wcsTaskEvent.StartTaskEvent(wcsTask); + return true; + } + else + { + ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入移库任务失败,箱号:{wcsTask.VehicleNo},PlcId:{wcsTask.PlcId};{wcsTask.Origin} => {wcsTask.Destination},异常信息:{writeStackerTaskErrText}"); + _wcsTaskEvent.ErrTaskEvent(wcsTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); + } + return false; + + } + + /// + /// 执行重复入库新任务,若执行了返回true + /// + /// + /// + /// + public bool ExecuteDoubleInTask(int? stackerId, int plcId) + { + if (stackerId == default || plcId == 0) return false; + /* 查找这个PlcId对应的wms任务 */ + List? doubleInTasks = _wcsTaskDao.Select(new AppWcsTask { PlcId = plcId }); + if (doubleInTasks == default) + { + ConsoleLog.Error($"【异常】{stackerId} 号堆垛机重复入库任务检验失败,与数据库连接异常"); + Thread.Sleep(5000); + return false; + } + if (doubleInTasks.Count == 0) return false; // 找不到对应的PlcId的任务 + var doubleTask = doubleInTasks[0]; + /* 查找这个任务的新任务 */ + List? newTasks = _wcsTaskDao.Select(new AppWcsTask { TaskId = doubleTask.TaskId, TaskType = (int)TaskTypeEnum.newTaskForDoubleIn, TaskStatus = (int)WmsTaskStatusEnum.create }); + if (newTasks == default) + { + ConsoleLog.Error($"【异常】{stackerId} 号堆垛机重复入库任务新任务查询失败,与数据库连接异常"); + Thread.Sleep(5000); + return false; + } + if (newTasks.Count == 0) return false; + var newTask = newTasks[0]; + var destinationLocationInfo = CommonData.AppLocations.DetailWithWcsLocation(newTask.Destination); + if (destinationLocationInfo == default) // 终点错误,直接标记错误 + { + // 已经在接口内做了检查,按道理此处不会出错。直接返回异常,任务直接取消 + ConsoleLog.Warning($"【警告】任务号:{newTask.TaskId},Plc任务号:{newTask.PlcId} 无法执行,新终点存在异常"); + _wcsTaskEvent.ErrTaskEvent(newTask, $"新终点存在异常"); + return false; + } + StackerPlcTask stackerTask = new() + { + StackerId = stackerId, + PlcId = newTask.PlcId, + TaskType = Convert.ToInt16(TaskTypeEnum.inTask), + GetStand = 0, + InTunnelId = Convert.ToInt16(stackerId), + OutTunnelId = Convert.ToInt16(stackerId), + SetStand = 0, + GetQueue = 0, + GetLine = 0, + GetLayer = 0, + GetDeep = 0, + SetQueue = Convert.ToInt16(destinationLocationInfo.Queue), + SetLine = Convert.ToInt16(destinationLocationInfo.Line), + SetLayer = Convert.ToInt16(destinationLocationInfo.Layer), + SetDeep = Convert.ToInt16(destinationLocationInfo.Depth), + Size = Convert.ToInt16(newTask.VehicleSize), + Weight = Convert.ToInt16(newTask.Weight), + Code = newTask.PlcVehicleNo ?? 0, + }; + var writeStackerTaskErrText = _stackerOperation.WriteTask(stackerTask); + if (string.IsNullOrEmpty(writeStackerTaskErrText)) + { + ConsoleLog.Success($"堆垛机:{stackerId} 写入重复入库新任务成功,箱号:{newTask.VehicleNo},PlcId:{newTask.PlcId};新目的地:{newTask.Destination}"); + _wcsTaskEvent.StartTaskEvent(newTask); + return true; + } + else + { + ConsoleLog.Warning($"【警告】堆垛机:{stackerId} 写入重复入库新任务失败,箱号:{newTask.VehicleNo},PlcId:{newTask.PlcId};新目的地:{newTask.Destination},异常信息:{writeStackerTaskErrText}"); + _wcsTaskEvent.ErrTaskEvent(newTask, $"写入任务失败,异常信息:{writeStackerTaskErrText}"); + } + return false; + } + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/StackerConvey/CheckAccount.cs b/WcsMain/Business/CirculationTask/StackerConvey/CheckAccount.cs new file mode 100644 index 0000000..d961ba9 --- /dev/null +++ b/WcsMain/Business/CirculationTask/StackerConvey/CheckAccount.cs @@ -0,0 +1,108 @@ +using CirculateTool; +using WcsMain.Business.CommonAction; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum; +using WcsMain.PlcOperation.Entity; +using WcsMain.PlcOperation.StackerConvey; + +namespace WcsMain.Business.CirculationTask.StackerConvey; + +/// +/// 过账,PLC任务回告 ---- 库前输送线 +/// +[Circulation] +public class CheckAccount(AppWcsTaskDao wcsTaskDao, StackerConveyOperation stackerConveyOperation, WCSTaskExecuteEvent wcsTaskEvent) +{ + private readonly WCSTaskExecuteEvent _wcsTaskEvent = wcsTaskEvent; + private readonly StackerConveyOperation _stackerConveyOperation = stackerConveyOperation; + private readonly AppWcsTaskDao _wcsTaskDao = wcsTaskDao; + + /// + /// PLC过账 + /// + /// + [Circulation("监控PLC地址,过账", 1000)] + public bool CheckAccountTask() + { + List? taskFeedBackEntities = _stackerConveyOperation.GetConveyTaskFeedBackData(20); + if (taskFeedBackEntities == default || taskFeedBackEntities.Count < 1) {return true; } + foreach (TaskFeedBackEntity taskFeedBackEntity in taskFeedBackEntities) + { + if (taskFeedBackEntity.PlcId == 0) { continue; } + List? wcsTasks = _wcsTaskDao.Select(new AppWcsTask() { PlcId = taskFeedBackEntity.PlcId }); + if (wcsTasks == default) + { + ConsoleLog.Error($"【异常】库前输送过账查询任务数据失败,和数据库服务器连接中断"); + Thread.Sleep(2000); + continue; // 网络连接中断 + } + if (wcsTasks.Count < 1) + { + ConsoleLog.Warning($"【提示】库前输送过账区获取任务ID:{taskFeedBackEntity.PlcId},无关联任务"); + _stackerConveyOperation.ClearFeedBackData(taskFeedBackEntity); // 清除过账 + continue; // 任务无数据 + } + var wcsTask = wcsTasks[0]; + switch (taskFeedBackEntity.FeedBackType) + { + case (int)TaskFeedBackTypeEnum.cancel: // 任务取消 + CancelTask(taskFeedBackEntity, wcsTask); + break; + case (int)TaskFeedBackTypeEnum.complete: // 任务完成 + CompleteTask(taskFeedBackEntity, wcsTask); + break; + default: + OtherTaskFeedBackType(taskFeedBackEntity); // 其他任务类型, + break; + } + } + return true; + } + + /// + /// 过账任务取消 + /// + /// + private void CancelTask(TaskFeedBackEntity taskFeedBackEntity, AppWcsTask wcsTask) + { + ConsoleLog.Warning($"【提示】库前输送过账区获取任务ID:{taskFeedBackEntity.PlcId},任务已经被取消,后续任务也一并取消,任务号:{wcsTask.TaskId}"); + string? cleanAccountErr = _stackerConveyOperation.ResetFeedBackData(taskFeedBackEntity); // 清除过账 + if (!string.IsNullOrEmpty(cleanAccountErr)) + { + ConsoleLog.Warning($"[警告]取消任务清除过账区发生异常,信息:{cleanAccountErr}"); + } + /* 执行 WMS 任务异常动作 */ + _wcsTaskEvent.ErrTaskEvent(wcsTask, "任务被PLC取消"); + + } + + /// + /// 过账任务完成 + /// + /// + private void CompleteTask(TaskFeedBackEntity taskFeedBackEntity, AppWcsTask wcsTask) + { + ConsoleLog.Tip($"[提示]过账区获取任务ID:{taskFeedBackEntity.PlcId},任务已经完成,任务号:{wcsTask.TaskId}"); + string? cleanAccountErr = _stackerConveyOperation.ResetFeedBackData(taskFeedBackEntity); // 清除过账 + if (!string.IsNullOrEmpty(cleanAccountErr)) + { + ConsoleLog.Warning($"[警告]完成任务清除过账区发生异常,信息:{cleanAccountErr}"); + } + /* 执行 WMS 任务完成动作 */ + _wcsTaskEvent.CompleteTaskEvent(wcsTask, "PLC上报完成"); + } + + + + /// + /// 其他过账类型 + /// + /// + private void OtherTaskFeedBackType(TaskFeedBackEntity taskFeedBackEntity) + { + ConsoleLog.Warning($"[警告]过账区获取任务ID:{taskFeedBackEntity.PlcId},无法识别的过账类型:{taskFeedBackEntity.FeedBackType}"); + _stackerConveyOperation.ResetFeedBackData(taskFeedBackEntity); // 清除过账 + } + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/StackerConvey/ExecuteScanMethod.cs b/WcsMain/Business/CirculationTask/StackerConvey/ExecuteScanMethod.cs new file mode 100644 index 0000000..a6b78ea --- /dev/null +++ b/WcsMain/Business/CirculationTask/StackerConvey/ExecuteScanMethod.cs @@ -0,0 +1,32 @@ +using CirculateTool; + +namespace WcsMain.Business.CirculationTask.StackerConvey; + +//[Circulation("执行输送机扫码方法")] +public class ExecuteScanMethod +{ + + #region 扫码入库 + + + /// + /// 扫码入库 + /// + /// + [Circulation("扫码入库", 1000)] + public bool ScanTaskIn() + { + //var code = StackerConveyOperation.Instance().ReadConveyCode("R1"); + + return true; + } + + + + #endregion + + + + + +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/TaskData/ResolveWmsTask.cs b/WcsMain/Business/CirculationTask/TaskData/ResolveWmsTask.cs new file mode 100644 index 0000000..7f40d71 --- /dev/null +++ b/WcsMain/Business/CirculationTask/TaskData/ResolveWmsTask.cs @@ -0,0 +1,237 @@ +using CirculateTool; +using WcsMain.ExtendMethod; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.DataService; +using WcsMain.Enum.TaskEnum; +using WcsMain.Business.CommonAction; +using WcsMain.Common; +using WcsMain.StaticData; + +namespace WcsMain.Business.CirculationTask.TaskData; + +/// +/// WMS任务解析类 +/// +[Circulation()] +public class ResolveWmsTask(AppWmsTaskDao wmsTaskDao, SendWmsTaskStatus sendWmsTaskStatus, DataBaseData dataBaseData) +{ + private readonly DataBaseData _dataBaseData = dataBaseData; + private readonly SendWmsTaskStatus _sendWmsTaskStatus = sendWmsTaskStatus; + private readonly AppWmsTaskDao _wmsTaskDao = wmsTaskDao; + + /// + /// 解析WMS任务 + /// + /// + [Circulation("解析WMS任务,转换为WCS任务")] + public bool ResolveTask() + { + List? needResolveTask = _wmsTaskDao.Select(new AppWmsTask() { TaskStatus = (int)WmsTaskStatusEnum.create }); + if (needResolveTask == default) + { + ConsoleLog.Error("【异常】解析Wms任务时拉取任务列表失败,与数据库连接中断"); + Thread.Sleep(5000); + return true; + } + needResolveTask.ForEach(ResolveTask); + return true; + } + + + /// + /// 解析任务 + /// + /// + private void ResolveTask(AppWmsTask wmsTask) + { + /* 校验起点终点是否在点位表 */ + bool checkResult = CommonData.AppLocations.ExistWmsLocation(wmsTask.Origin, wmsTask.Destination); + if(!checkResult) + { + _wmsTaskDao.Update(new() + { + TaskId = wmsTask.TaskId, + TaskStatus = (int)WmsTaskStatusEnum.err, + TaskMsg = "不受支持的起点或终点", + EndTime = DateTime.Now + }); + if(wmsTask.CreatePerson == StaticString.WMS) + { + _sendWmsTaskStatus.SendTaskErr(wmsTask.TaskId, "不受支持的起点或终点"); + } + return; + } + /* 解析任务转换为WCS任务,一般根据项目,此处自定义规则 */ + List? wcsTasks = TransToWcsTask(wmsTask); + if(wcsTasks == default || wcsTasks.Count < 1) + { + + } + + } + + + + /// + /// 处理WMS任务,插入WCS任务 + /// + /// + /// + private List? TransToWcsTask(AppWmsTask task) + { + return task.TaskType switch + { + // 入库 + (int)WmsTaskTypeEnum.inTask => TransInTaskToWcsTask(task)?.ToList(), + // 出库 + (int)WmsTaskTypeEnum.outTask => TransOutTaskToWcsTask(task)?.ToList(), + // 移库 + (int)WmsTaskTypeEnum.moveTask => TransMoveTaskToWcsTask(task)?.ToList(), + // 拣选 + (int)WmsTaskTypeEnum.pick => TransPickTaskToWcsTask(task)?.ToList(), + // 其他任务,未识别的任务类型,直接报错 + _ => TransOtherTaskToWcsTask(task)?.ToList(), + }; + } + + /// + /// 转换入库任务 + /// + /// + /// + private IEnumerable? TransInTaskToWcsTask(AppWmsTask wmsTask) + { + AppLocation? wcsOrigin = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Origin); + AppLocation? wcsDestination = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Destination); + if (wcsOrigin == default || wcsDestination == default) { yield break; } + int? plcId = _dataBaseData.GetNewPlcTaskId(); + if(plcId == default) { yield break; } + AppWcsTask wcsTask = new() + { + PlcId = plcId, + TaskId = wmsTask.TaskId, + TaskType = (int)WcsTaskTypeEnum.inTask, + TaskStatus = (int)WcsTaskStatusEnum.create, + Origin = wcsOrigin!.WcsLocation, + + Destination = wcsDestination.WcsLocation, + VehicleNo = wmsTask.VehicleNo, + PlcVehicleNo = wmsTask.VehicleNo.ToPlcVehicleNo(), + Priority = wmsTask.Priority, + VehicleSize = wmsTask.VehicleSize, + Weight = wmsTask.Weight, + WmsTime = wmsTask.CreateTime, + CreatePerson = wmsTask.CreatePerson, + CreateTime = DateTime.Now, + }; + yield return wcsTask; + } + + /// + /// 转换出库任务 + /// + /// + /// + private IEnumerable? TransOutTaskToWcsTask(AppWmsTask wmsTask) + { + AppLocation? wcsOrigin = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Origin); + AppLocation? wcsDestination = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Destination); + if (wcsOrigin == default || wcsDestination == default) { yield break; } + int? plcId = _dataBaseData.GetNewPlcTaskId(); + if (plcId == default) { yield break; } + AppWcsTask wcsTask = new() + { + PlcId = plcId, + TaskId = wmsTask.TaskId, + TaskType = (int)WcsTaskTypeEnum.outTask, + TaskStatus = (int)WcsTaskStatusEnum.create, + Origin = wcsOrigin.WcsLocation, + Destination = wcsDestination.WcsLocation, + VehicleNo = wmsTask.VehicleNo, + PlcVehicleNo = wmsTask.VehicleNo.ToPlcVehicleNo(), + Priority = wmsTask.Priority, + VehicleSize = wmsTask.VehicleSize, + Weight = wmsTask.Weight, + WmsTime = wmsTask.CreateTime, + CreatePerson = wmsTask.CreatePerson, + CreateTime = DateTime.Now, + }; + yield return wcsTask; + } + + /// + /// 转换拣选任务 + /// + /// + /// + private IEnumerable? TransPickTaskToWcsTask(AppWmsTask wmsTask) + { + AppLocation? wcsOrigin = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Origin); + AppLocation? wcsDestination = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Destination); + if (wcsOrigin == default || wcsDestination == default) { yield break; } + int? plcId = _dataBaseData.GetNewPlcTaskId(); + if (plcId == default) { yield break; } + AppWcsTask wcsTask = new() + { + PlcId = plcId, + TaskId = wmsTask.TaskId, + TaskType = (int)WcsTaskTypeEnum.pick, + TaskStatus = (int)WcsTaskStatusEnum.create, + Origin = wcsOrigin.WcsLocation, + Destination = wcsDestination.WcsLocation, + VehicleNo = wmsTask.VehicleNo, + PlcVehicleNo = wmsTask.VehicleNo.ToPlcVehicleNo(), + Priority = wmsTask.Priority, + VehicleSize = wmsTask.VehicleSize, + Weight = wmsTask.Weight, + WmsTime = wmsTask.CreateTime, + CreatePerson = wmsTask.CreatePerson, + CreateTime = DateTime.Now, + }; + yield return wcsTask; + } + + /// + /// 转换移库任务 + /// + /// + /// + private IEnumerable? TransMoveTaskToWcsTask(AppWmsTask wmsTask) + { + AppLocation? wcsOrigin = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Origin); + AppLocation? wcsDestination = CommonData.AppLocations.DetailWithWmsLocation(wmsTask.Destination); + if (wcsOrigin == default || wcsDestination == default) { yield break; } + int? plcId = _dataBaseData.GetNewPlcTaskId(); + if (plcId == default) { yield break; } + AppWcsTask wcsTask = new() + { + PlcId = plcId, + TaskId = wmsTask.TaskId, + TaskType = (int)WcsTaskTypeEnum.moveTask, + TaskSort = 1, + TaskStatus = (int)WcsTaskStatusEnum.create, + Origin = wcsOrigin.WcsLocation, + Destination = wcsDestination.WcsLocation, + VehicleNo = wmsTask.VehicleNo, + PlcVehicleNo = wmsTask.VehicleNo.ToPlcVehicleNo(), + Priority = wmsTask.Priority, + VehicleSize = wmsTask.VehicleSize, + Weight = wmsTask.Weight, + WmsTime = wmsTask.CreateTime, + CreatePerson = wmsTask.CreatePerson, + CreateTime = DateTime.Now, + }; + yield return wcsTask; + } + + /// + /// 转换其他任务 + /// + /// + /// + private IEnumerable? TransOtherTaskToWcsTask(AppWmsTask wmsTask) + { + yield break; + } +} \ No newline at end of file diff --git a/WcsMain/Business/CirculationTask/TestCirculation.cs b/WcsMain/Business/CirculationTask/TestCirculation.cs new file mode 100644 index 0000000..9f08ce4 --- /dev/null +++ b/WcsMain/Business/CirculationTask/TestCirculation.cs @@ -0,0 +1,17 @@ +namespace WcsMain.Business.CirculationTask; + +/// +/// 测试类 +/// +//[Circulation] +public class TestCirculation +{ + + //[Circulation("测试websocket发送", 1000)] + public bool SendWebSocket() + { + //WebSocketOperation.Instance().Send(DateTime.Now.ToString("F")); + return true; + } + +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/ClearData.cs b/WcsMain/Business/CommonAction/ClearData.cs new file mode 100644 index 0000000..3728b9e --- /dev/null +++ b/WcsMain/Business/CommonAction/ClearData.cs @@ -0,0 +1,104 @@ +using WcsMain.ExtendMethod; +using WcsMain.DataBase.Dao; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Business.CommonAction; + +/// +/// 清理数据类 +/// +[Component] +public class ClearData(AppWmsTaskDao wmsTaskDao, AppWcsTaskDao wcsTaskDao, AppApiRequestDao apiRequestDao, AppApiAcceptDao apiAcceptDao) +{ + + private readonly AppWmsTaskDao _wmsTaskDao = wmsTaskDao; + private readonly AppWcsTaskDao _wcsTaskDao = wcsTaskDao; + private readonly AppApiRequestDao _apiRequestDao = apiRequestDao; + private readonly AppApiAcceptDao _apiAcceptDao = apiAcceptDao; + + + + /* 定时清除 WMS 任务表 */ + /// + /// 清理超过一定时间的 WMS 任务表数据 + /// + /// + public int ClearWmsTaskData(int days) + { + return _wmsTaskDao.ClearData(days); + + } + + + /* 定时清除 WCS 任务备份表 */ + /// + /// 清理超过一定天数的 WCS 任务备份表数据 + /// + /// + public int ClearWcsTaskData(int days) + { + return _wcsTaskDao.ClearData(days); + } + + /* 定时清除 日志文件 */ + /// + /// 清理日志文件 + /// + /// + public int ClearLogFile(int days) + { + int clearCount = 0; + string LogAddress = AppDomain.CurrentDomain.BaseDirectory + "\\Log"; + DirectoryInfo di = new(LogAddress); + if (!di.Exists) return clearCount; + var directories = di.GetDirectories(); + if (directories.Length <= 0) return clearCount; + foreach (DirectoryInfo directory in directories) + { + var files = directory.GetFiles(); + if (files.Length <= 0) continue; + foreach (FileInfo fileInfo in files) + { + try + { + string fileName = fileInfo.Name; + DateTime? time = fileName.ToDateTime(); + if (time == default) continue; + TimeSpan? ts = (DateTime.Now - time!); + if (ts?.Days > days) // --------------------------------- 日志保存的天数 + { + fileInfo.Delete(); + clearCount++; + } + } + catch { } // 无论任何情况都放弃执行 + } + } + return clearCount; + } + + /* 定时清除接口请求表 */ + /// + /// 清理接口发送信息表 + /// + /// + public int ClearApiRequestData(int days) + { + return _apiRequestDao.ClearData(days); + } + + + + /* 定时清除接口接收表 */ + /// + /// 清理接口接收信息表 + /// + /// + public int ClearApiAcceptData(int days) + { + return _apiAcceptDao.ClearData(days); + } + + + +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/CusBindingVehicle.cs b/WcsMain/Business/CommonAction/CusBindingVehicle.cs new file mode 100644 index 0000000..f68d299 --- /dev/null +++ b/WcsMain/Business/CommonAction/CusBindingVehicle.cs @@ -0,0 +1,34 @@ +namespace WcsMain.Business.CommonAction; + +/// +/// 绑定任务号和箱子 +/// +//[Component] +public class CusBindingVehicle +{ + + ///// + ///// 绑定任务号和载具号 + ///// + ///// + ///// + //public void VehicleBinding(string? vehicleNo, int plcId) + //{ + // if (string.IsNullOrEmpty(vehicleNo)) + // { + // return; + // } + // // 清理旧数据 + // AppVehicleBindingDao.Instance().DeleteWithVehicleNo(vehicleNo); + // // 绑定新数据 + // AppVehicleBindingDao.Instance().Insert(new AppVehicleBinding() + // { + // vehicleNo = vehicleNo, + // PlcId = plcId, + // BindingTime = DateTime.Now + // }); + + //} + + +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/LEDUsing.cs b/WcsMain/Business/CommonAction/LEDUsing.cs new file mode 100644 index 0000000..3f13d8c --- /dev/null +++ b/WcsMain/Business/CommonAction/LEDUsing.cs @@ -0,0 +1,152 @@ +using LedSimple; + +namespace WcsMain.Business.CommonAction; + +public class LedUsing(int ledWidth, int ledHeight, int colorType, int nAlignment = 2, int isVCenter = 1) +{ + private readonly int _ledWidth = ledWidth;//屏的宽度 + private readonly int _ledHeight = ledHeight;//屏的高度 + private readonly int _colorType = colorType;//屏的色彩——1.单色 2.双基色 3.七彩 4.全彩 + private readonly int _nAlignment = nAlignment;//水平对齐样式,0.左对齐 1.右对齐 2.水平居中 (注意:只对字符串和txt文件有效) + private readonly int _isVCenter = isVCenter; //是否垂直居中 0.置顶(默认) 1.垂直居中 + + /// + /// 红色宋体字 + /// + private Leddll.FONTPROP _fontRed = new() { FontName = "宋体", FontSize = 9, FontColor = (int)LEDColor.Red, FontBold = 0 }; + + /// + /// 红色宋体字 + /// + private Leddll.FONTPROP _fontRedBig = new() { FontName = "宋体", FontSize = 12, FontColor = (int)LEDColor.Red, FontBold = 0 }; + /// + /// 红色宋体字 + /// + private Leddll.FONTPROP _fontGreen = new() { FontName = "宋体", FontSize = 9, FontColor = (int)LEDColor.Green, FontBold = 0 }; + /// + /// 立即显示的节目效果 + /// + private Leddll.PLAYPROP _playProp = new() { InStyle = 0 }; + + + /// + /// 发送锁 + /// + private static readonly object SendLock = new(); + + + + /// + /// 展示默认的显示内容 ---- 江西隆成立库 256*96 + /// + /// + /// + public void ShowDefaultMsg(string ip, string msg) + { + try + { + Leddll.COMMUNICATIONINFO communicationInfo = GetCommunicationInfo(ip); + Leddll.DIGITALCLOCKAREAINFO date = new() + { + DateFormat = 0, + TimeFormat = 0, + IsShowDay = 1, + IsShowHour = 1, + IsShowMonth = 1, + IsShowSecond = 1, + IsShowYear = 1, + IsShowMinute = 1, + }; + lock (SendLock) + { + Leddll.LV_AdjustTime(ref communicationInfo); // 校时 + + int nResult; + //LedDll.LV_InitLed(3, 0); 当Led上显示的文字区域的颜色与下发的不一致, 请的确认Led 屏的RGB顺序,并调用此接口 + nint hProgram;//节目句柄 + hProgram = Leddll.LV_CreateProgramEx(_ledWidth, _ledHeight, _colorType, 0, 0);//注意此处屏宽高及颜色参数必需与设置屏参的屏宽高及颜色一致,否则发送时会提示错误 + //此处可自行判断有未创建成功,hProgram返回NULL失败,非NULL成功,一般不会失败 + //int nProgramId = 0; + nResult = Leddll.LV_AddProgram(hProgram, 1, 0, 1);//添加一个节目,参数说明见函数声明注示 + + /* 添加内容 */ + // ---- 公司名称 + Leddll.AREARECT areaHeader = new() // 添加区域 + { + left = 0, + top = 10, + width = 256, + height = 20 + }; //区域坐标属性结构体变量 + int addAreaHeaderResult = Leddll.LV_AddImageTextArea(hProgram, 1, 1, ref areaHeader, 0); + if (addAreaHeaderResult == 0) + { + // 添加到显示 + nResult = Leddll.LV_AddMultiLineTextToImageTextArea(hProgram, 1, 1, Leddll.ADDTYPE_STRING, "江西隆成医药", + ref _fontRedBig, ref _playProp, 2, 1); + } + // ---- 控制方式,联机状态 + Leddll.AREARECT areaMain = new() // 添加区域 + { + left = 0, + top = 35, + width = 256, + height = 20 + }; //区域坐标属性结构体变量 + if (msg.Length > 25) + { + nResult = Leddll.LV_QuickAddSingleLineTextArea(hProgram, 1, 2, ref areaMain, 0, msg + " ", + ref _fontRed, 10); + } + else + { + int addAreaMain = Leddll.LV_AddImageTextArea(hProgram, 1, 2, ref areaMain, 1); + if (addAreaMain == 0) + { + // 添加到显示 + nResult = Leddll.LV_AddMultiLineTextToImageTextArea(hProgram, 1, 2, Leddll.ADDTYPE_STRING, msg, + ref _fontRed, ref _playProp, 2, 1); + } + } + // ---- 时间 + Leddll.AREARECT areaTime = new() // 添加区域 + { + left = 0, + top = 60, + width = 256, + height = 20 + }; //区域坐标属性结构体变量 + int addAreaTime = Leddll.LV_AddDigitalClockArea(hProgram, 1, 3, ref areaTime, ref date); + /* 发送 LED */ + nResult = Leddll.LV_Send(ref communicationInfo, hProgram); //发送,见函数声明注示 + Thread.Sleep(100); + Leddll.LV_DeleteProgram(hProgram); //删除节目内存对象,详见函数声明注示 + } + } + catch (Exception ex) + { + _ = ex; + } + } + + private Leddll.COMMUNICATIONINFO GetCommunicationInfo(string ip) + { + Leddll.COMMUNICATIONINFO CommunicationInfo = new() + { + //TCP通讯******************************************************************************** + SendType = 0,//设为固定IP通讯模式,即TCP通讯 + IpStr = ip,//给IpStr赋值LED控制卡的IP + LedNumber = 1,//LED屏号为1,注意socket通讯和232通讯不识别屏号,默认赋1就行了,485必需根据屏的实际屏号进行赋值 + //广播通讯******************************************************************************** + //CommunicationInfo.SendType=1;//设为单机直连,即广播通讯无需设LED控制器的IP地址 + //串口通讯******************************************************************************** + //CommunicationInfo.SendType=2;//串口通讯 + //CommunicationInfo.Commport=1;//串口的编号,如设备管理器里显示为 COM3 则此处赋值 3 + //CommunicationInfo.Baud=9600;//波特率 + //CommunicationInfo.LedNumber=1; + };//定义一通讯参数结构体变量用于对设定的LED通讯,具体对此结构体元素赋值说明见COMMUNICATIONINFO结构体定义部份注示 + return CommunicationInfo; + } + + +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/ScanCodeAction.cs b/WcsMain/Business/CommonAction/ScanCodeAction.cs new file mode 100644 index 0000000..845b4b6 --- /dev/null +++ b/WcsMain/Business/CommonAction/ScanCodeAction.cs @@ -0,0 +1,29 @@ +using SocketTool.Entity; + +namespace WcsMain.Business.CommonAction; +/* + * 扫码器方法类: + * 使用方法:系统自动调用,需要在 config 表内配置参数 + * 配置的参数名称为:ScanMethod{ScanID},ScanID 为 string 格式,参数对应的值为方法名称, + * 方法必须为 public 格式,参数为 ScanCodeClass + */ + +/// +/// 扫码器处理事件 +/// +public class ScanCodeAction +{ + + /// + /// 测试 + /// + /// + public void PickScanTest(ScanCodeClass codeEntity) + { + + } + + + + +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/SendWmsTaskStatus.cs b/WcsMain/Business/CommonAction/SendWmsTaskStatus.cs new file mode 100644 index 0000000..a2fe8ac --- /dev/null +++ b/WcsMain/Business/CommonAction/SendWmsTaskStatus.cs @@ -0,0 +1,311 @@ +using WcsMain.ApiClient.DataEntity.WmsEntity; +using WcsMain.Common; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum; +using WcsMain.Plugins; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Business.CommonAction; + +/// +/// 用于发送WMS任务状态的类 +/// +[Component] +public class SendWmsTaskStatus(AppWmsTaskDao wmsTaskDao, WmsWebApiPost wmsWebApiPost) +{ + private readonly WmsWebApiPost _wmsWebApiPost = wmsWebApiPost; + private readonly AppWmsTaskDao _wmsTaskDao = wmsTaskDao; + + /// + /// 发送 WMS 任务异常 + /// + /// + /// + /// + public void SendTaskErr(string? taskId, string? errMsg, ushort count = 5) + { + Task.Factory.StartNew(() => { + AppWmsTask? wmsTask = default; + for (int i = 0; i < count; i++) + { + List? tasks = _wmsTaskDao.Select(new AppWmsTask { TaskId = taskId }); + if (tasks == default) + { + ConsoleLog.Error($"【异常】发送WMS任务状态时查询数据库失败,和数据库连接中断,任务号:{taskId}"); + Thread.Sleep(100); + continue; + } + if (tasks.Count == 0) + { + ConsoleLog.Warning($"【警告】发送WMS任务状态时查询数据库异常,找不到任务,任务号:{taskId}"); + return; + } + wmsTask = tasks[0]; + } + if (wmsTask == default) { return; } + SendWmsTaskStatusRequest request = new() + { + TaskId = wmsTask.TaskId, + TaskStatus = (int)SendWmsTaskStatusEnum.err, + Destination = wmsTask.Destination, + VehicleNo = wmsTask.VehicleNo, + Message = errMsg + }; + for (int i = 1; i <= count; i++) + { + var response = _wmsWebApiPost.HttpPost(request, CommonData.AppConfig.SendWmsTaskStatusApiAddress ?? ""); + if (!response.IsSend) + { + ConsoleLog.Error($"【异常】发送WMS[任务异常]失败,发送次数:{i},任务号:{wmsTask.TaskId},参考信息:{response.RequestException?.Message}"); + continue; + } + var responseObj = response.ResponseEntity; + if (responseObj == default) + { + ConsoleLog.Error($"【异常】发送WMS[任务异常]失败,解析WMS返回数据失败,发送次数:{i},任务号:{wmsTask.TaskId}"); + return; + } + if (responseObj.Code == 0) + { + ConsoleLog.Tip($"发送WMS[任务异常]成功任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},{wmsTask.Origin} => {wmsTask.Destination}"); + return; + } + ConsoleLog.Error($"【异常】发送WMS[任务异常]失败,WMS返回异常,任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},参考信息:{responseObj.Message}"); + } + }); + } + + /// + /// 发送 WMS 取货位置无货 + /// + /// + /// + public void SendTaskEmptyOut(string? taskId, ushort count = 5) + { + Task.Factory.StartNew(() => { + AppWmsTask? wmsTask = default; + for (int i = 0; i < count; i++) + { + List? tasks = _wmsTaskDao.Select(new AppWmsTask { TaskId = taskId }); + if (tasks == default) + { + ConsoleLog.Error($"【异常】发送WMS任务状态时查询数据库失败,和数据库连接中断,任务号:{taskId}"); + Thread.Sleep(100); + continue; + } + if (tasks.Count == 0) + { + ConsoleLog.Warning($"【警告】发送WMS任务状态时查询数据库异常,找不到任务,任务号:{taskId}"); + return; + } + wmsTask = tasks[0]; + } + if (wmsTask == default) { return; } + SendWmsTaskStatusRequest request = new() + { + TaskId = wmsTask.TaskId, + TaskStatus = (int)SendWmsTaskStatusEnum.emptyOut, + Destination = wmsTask.Destination, + VehicleNo = wmsTask.VehicleNo, + Message = "取货位置无货" + }; + for (int i = 1; i <= count; i++) + { + var response = _wmsWebApiPost.HttpPost(request, CommonData.AppConfig.SendWmsTaskStatusApiAddress ?? ""); + if (!response.IsSend) + { + ConsoleLog.Error($"【异常】发送WMS[取货位置无货]失败,发送次数:{i},任务号:{wmsTask.TaskId},参考信息:{response.RequestException?.Message}"); + continue; + } + var responseObj = response.ResponseEntity; + if (responseObj == default) + { + ConsoleLog.Error($"【异常】发送WMS[取货位置无货]失败,解析WMS返回数据失败,发送次数:{i},任务号:{wmsTask.TaskId}"); + return; + } + if (responseObj.Code == 0) + { + ConsoleLog.Tip($"发送WMS[取货位置无货]成功任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},{wmsTask.Origin} => {wmsTask.Destination}"); + return; + } + ConsoleLog.Error($"【异常】发送WMS[取货位置无货]失败,WMS返回异常,任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},参考信息:{responseObj.Message}"); + } + }); + } + + /// + /// 发送 WMS 卸货位置有货 + /// + /// + /// + public void SendTaskDoubleIn(string? taskId, ushort count = 5) + { + Task.Factory.StartNew(() => { + AppWmsTask? wmsTask = default; + for (int i = 0; i < count; i++) + { + List? tasks = _wmsTaskDao.Select(new AppWmsTask { TaskId = taskId }); + if (tasks == default) + { + ConsoleLog.Error($"【异常】发送WMS任务状态时查询数据库失败,和数据库连接中断,任务号:{taskId}"); + Thread.Sleep(100); + continue; + } + if (tasks.Count == 0) + { + ConsoleLog.Warning($"【警告】发送WMS任务状态时查询数据库异常,找不到任务,任务号:{taskId}"); + return; + } + wmsTask = tasks[0]; + } + if (wmsTask == default) { return; } + SendWmsTaskStatusRequest request = new() + { + TaskId = wmsTask.TaskId, + TaskStatus = (int)SendWmsTaskStatusEnum.doubleIn, + Destination = wmsTask.Destination, + VehicleNo = wmsTask.VehicleNo, + Message = "卸货位置有货" + }; + for (int i = 1; i <= count; i++) + { + var response = _wmsWebApiPost.HttpPost(request, CommonData.AppConfig.SendWmsTaskStatusApiAddress ?? ""); + if (!response.IsSend) + { + ConsoleLog.Error($"【异常】发送WMS[卸货位置有货]失败,发送次数:{i},任务号:{wmsTask.TaskId},参考信息:{response.RequestException?.Message}"); + continue; + } + var responseObj = response.ResponseEntity; + if (responseObj == default) + { + ConsoleLog.Error($"【异常】发送WMS[卸货位置有货]失败,解析WMS返回数据失败,发送次数:{i},任务号:{wmsTask.TaskId}"); + return; + } + if (responseObj.Code == 0) + { + ConsoleLog.Tip($"发送WMS[卸货位置有货]成功任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},{wmsTask.Origin} => {wmsTask.Destination}"); + return; + } + ConsoleLog.Error($"【异常】发送WMS[卸货位置有货]失败,WMS返回异常,任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},参考信息:{responseObj.Message}"); + } + }); + } + + + /// + /// 向WMS发送任务开始执行 + /// + /// + /// + public void SendTaskStart(string? taskId, ushort count = 5) + { + Task.Factory.StartNew(() => { + AppWmsTask? wmsTask = default; + for (int i = 0; i < count; i++) + { + List? tasks = _wmsTaskDao.Select(new AppWmsTask { TaskId = taskId }); + if (tasks == default) + { + ConsoleLog.Error($"【异常】发送WMS任务状态时查询数据库失败,和数据库连接中断,任务号:{taskId}"); + Thread.Sleep(100); + continue; + } + if (tasks.Count == 0) + { + ConsoleLog.Warning($"【警告】发送WMS任务状态时查询数据库异常,找不到任务,任务号:{taskId}"); + return; + } + wmsTask = tasks[0]; + } + if (wmsTask == default) { return; } + SendWmsTaskStatusRequest request = new() + { + TaskId = wmsTask.TaskId, + TaskStatus = (int)SendWmsTaskStatusEnum.start, + Destination = wmsTask.Destination, + VehicleNo = wmsTask.VehicleNo, + Message = "开始执行" + }; + for (int i = 1; i <= count; i++) + { + var response = _wmsWebApiPost.HttpPost(request, CommonData.AppConfig.SendWmsTaskStatusApiAddress ?? ""); + if (!response.IsSend) + { + ConsoleLog.Error($"【异常】发送WMS[开始执行]失败,发送次数:{i},任务号:{wmsTask.TaskId},参考信息:{response.RequestException?.Message}"); + continue; + } + var responseObj = response.ResponseEntity; + if (responseObj == default) + { + ConsoleLog.Error($"【异常】发送WMS[开始执行]失败,解析WMS返回数据失败,发送次数:{i},任务号:{wmsTask.TaskId}"); + return; + } + if (responseObj.Code == 0) + { + ConsoleLog.Tip($"发送WMS[开始执行]成功任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},{wmsTask.Origin} => {wmsTask.Destination}"); + return; + } + ConsoleLog.Error($"【异常】发送WMS[开始执行]失败,WMS返回异常,任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},参考信息:{responseObj.Message}"); + } + }); + } + + /// + /// 向WMS发送任务完成 + /// + /// + /// + public void SendTaskComplete(string? taskId, ushort count = 5) + { + Task.Factory.StartNew(() => { + AppWmsTask? wmsTask = default; + for (int i = 0; i < count; i++) + { + List? tasks = _wmsTaskDao.Select(new AppWmsTask { TaskId = taskId }); + if (tasks == default) + { + ConsoleLog.Error($"【异常】发送WMS任务状态时查询数据库失败,和数据库连接中断,任务号:{taskId}"); + Thread.Sleep(100); + continue; + } + if (tasks.Count == 0) + { + ConsoleLog.Warning($"【警告】发送WMS任务状态时查询数据库异常,找不到任务,任务号:{taskId}"); + return; + } + wmsTask = tasks[0]; + } + if (wmsTask == default) { return; } + SendWmsTaskStatusRequest request = new() + { + TaskId = wmsTask.TaskId, + TaskStatus = (int)SendWmsTaskStatusEnum.complete, + Destination = wmsTask.Destination, + VehicleNo = wmsTask.VehicleNo, + Message = "任务完成" + }; + for (int i = 1; i <= count; i++) + { + var response = _wmsWebApiPost.HttpPost(request, CommonData.AppConfig.SendWmsTaskStatusApiAddress ?? ""); + if (!response.IsSend) + { + ConsoleLog.Error($"【异常】发送WMS[任务完成]失败,发送次数:{i},任务号:{wmsTask.TaskId},参考信息:{response.RequestException?.Message}"); + continue; + } + var responseObj = response.ResponseEntity; + if (responseObj == default) + { + ConsoleLog.Error($"【异常】发送WMS[任务完成]失败,解析WMS返回数据失败,发送次数:{i},任务号:{wmsTask.TaskId}"); + return; + } + if (responseObj.Code == 0) + { + ConsoleLog.Tip($"发送WMS[任务完成]成功任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},{wmsTask.Origin} => {wmsTask.Destination}"); + return; + } + ConsoleLog.Error($"【异常】发送WMS[任务完成]失败,WMS返回异常,任务号:{wmsTask.TaskId},载具号:{wmsTask.VehicleNo},参考信息:{responseObj.Message}"); + } + }); + } +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/WCSTaskExecuteEvent.cs b/WcsMain/Business/CommonAction/WCSTaskExecuteEvent.cs new file mode 100644 index 0000000..c7d5f8d --- /dev/null +++ b/WcsMain/Business/CommonAction/WCSTaskExecuteEvent.cs @@ -0,0 +1,147 @@ +using WcsMain.ExtendMethod; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.DataBase.MixDao; +using WcsMain.Enum.TaskEnum; +using WcsMain.WcsAttribute.AutoFacAttribute; +using WcsMain.StaticData; + +namespace WcsMain.Business.CommonAction; + +/// +/// WCS 任务 触发的事件 +/// +[Component] +public class WCSTaskExecuteEvent(TaskDao taskDao, SendWmsTaskStatus sendWmsTaskStatus, AppLocationDao locationDao) +{ + private readonly AppLocationDao _locationDao = locationDao; + private readonly SendWmsTaskStatus _sendWmsTaskStatus = sendWmsTaskStatus; + private readonly TaskDao _taskDao = taskDao; + + /// + /// 任务执行异常触发事件 + /// + /// + /// + public void ErrTaskEvent(AppWcsTask task, string errText) + { + string errMsg = _taskDao.TaskErrAndCancelOtherTask(task, errText); + if (!string.IsNullOrEmpty(errMsg)) + { + ConsoleLog.Error($"【异常】任务异常更新数据库失败,任务信息:{task},参考信息:{errMsg}"); + } + if (task.CreatePerson == StaticString.WMS) + { + _sendWmsTaskStatus.SendTaskErr(task.TaskId, errText); + } + } + + + /// + /// 任务执行异常触发事件 --- 取货位置无货 + /// + /// + /// + public void EmptyOutTaskEvent(AppWcsTask task, string errText) + { + string errMsg = _taskDao.TaskErr(task, errText); + if (!string.IsNullOrEmpty(errMsg)) + { + ConsoleLog.Error($"【异常】任务异常更新数据库失败,任务信息:{task},参考信息:{errMsg}"); + } + if (task.CreatePerson == StaticString.WMS) + { + _sendWmsTaskStatus.SendTaskEmptyOut(task.TaskId); + } + } + + /// + /// 任务执行异常触发事件 --- 卸货位置有货 + /// + /// + /// + public void DoubleInTaskEvent(AppWcsTask task, string errText) + { + string errMsg = _taskDao.TaskErr(task, errText); + if (!string.IsNullOrEmpty(errMsg)) + { + ConsoleLog.Error($"【异常】卸货位置有货更新数据库失败,任务信息:{task},参考信息:{errMsg}"); + } + if (task.CreatePerson == StaticString.WMS) + { + _sendWmsTaskStatus.SendTaskDoubleIn(task.TaskId); + } + } + + + + + /// + /// WCS任务开始时触发 + /// + /// + public void StartTaskEvent(AppWcsTask task) + { + string errMsg = _taskDao.StartTask(task); + if (!string.IsNullOrEmpty(errMsg)) + { + ConsoleLog.Error($"【异常】任务开始更新数据库失败,任务信息:{task},参考信息:{errMsg}"); + } + if (task.IsFirstTask() && task.CreatePerson == StaticString.WMS) + { + _sendWmsTaskStatus.SendTaskStart(task.TaskId); + } + } + + + + #region WCS 任务完成时触发 + + /// + /// WCS任务完成时触发 + /// + /// + /// + public void CompleteTaskEvent(AppWcsTask task, string msg) + { + UpdateLocationInfo(task); // 更新库位的相关信息 + HandleTaskData(task, msg); // 处理任务数据 + } + + private void HandleTaskData(AppWcsTask task, string msg) + { + string errMsg = _taskDao.ComlpeteTask(task, msg); + if(!string.IsNullOrEmpty(errMsg)) + { + ConsoleLog.Error($"【异常】PlcId:{task.PlcId} 任务完成失败,异常信息:{errMsg}"); + } + } + + + /// + /// 更新库位的相关信息, + /// + /// + /// + /// 特别注意:随缘更新,具体占用情况必须以WMS为准 + /// + private void UpdateLocationInfo(AppWcsTask task) + { + switch (task.TaskType) + { + case (int)TaskTypeEnum.inTask: // 入库任务 + _locationDao.Update(AppLocation.CreateUsedInstance(task.Destination, task.VehicleNo)); + break; + case (int)TaskTypeEnum.outTask: // 出库任务 + _locationDao.Update(AppLocation.CreateEmptyInstance(task.Origin)); + break; + case (int)TaskTypeEnum.moveTask: // 移库任务 + _locationDao.Update(AppLocation.CreateUsedInstance(task.Destination, task.VehicleNo), AppLocation.CreateEmptyInstance(task.Origin)); + break; + } + } + #endregion + + + +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/WMSApiResponseAction.cs b/WcsMain/Business/CommonAction/WMSApiResponseAction.cs new file mode 100644 index 0000000..bb823f6 --- /dev/null +++ b/WcsMain/Business/CommonAction/WMSApiResponseAction.cs @@ -0,0 +1,52 @@ +using ApiTool.Dto; +using LogTool; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.DataService; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Business.CommonAction; + +/// +/// WMS 接口响应触发事件 +/// +[Component] +public class WMSApiResponseAction(DataBaseData dataBaseData, AppApiRequestDao apiRequestDao) +{ + + private readonly DataBaseData _dataBaseData = dataBaseData; + private readonly AppApiRequestDao _apiRequestDao = apiRequestDao; + + /// + /// 当请求其他系统时触发本方法 + /// + /// + public void WMSApiResponse(ApiResponseInfo responseInfo) + { + try + { + // 写日志 + WcsLog.Instance().WriteApiRequestLog(responseInfo.ToString()); + // 存库 + AppApiRequest insertData = new() + { + RequestId = _dataBaseData.GetNewUUID(), + RequestUrl = responseInfo.RequestUrl, + RequestMethod = responseInfo.RequestMethod, + IsSuccess = responseInfo.IsSend ? 1 : 0, + RequestMsg = responseInfo.RequestMsg, + ResponseMsg = responseInfo.ResponseMsg, + RequestTime = responseInfo.RequestTime, + ResponseTime = responseInfo.ResponseTime, + UseTime = responseInfo.UseTime, + ErrMsg = responseInfo.RequestException?.Message, + }; + _apiRequestDao.Insert(insertData); + } + catch (Exception ex) + { + ConsoleLog.Error($"【异常】写接口日志发生异常,信息:{ex}"); + } + } + +} \ No newline at end of file diff --git a/WcsMain/Business/CommonAction/WmsTaskAction.cs b/WcsMain/Business/CommonAction/WmsTaskAction.cs new file mode 100644 index 0000000..72b7e39 --- /dev/null +++ b/WcsMain/Business/CommonAction/WmsTaskAction.cs @@ -0,0 +1,73 @@ +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.StaticData; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Business.CommonAction; + +[Component] +public class WmsTaskAction(AppWmsTaskDao wmsTaskDao, SendWmsTaskStatus sendWmsTaskStatus) +{ + private readonly SendWmsTaskStatus _sendWmsTaskStatus = sendWmsTaskStatus; + private readonly AppWmsTaskDao _wmsTaskDao = wmsTaskDao; + + /// + /// 重置WMS任务 + /// + /// + /// + /// + /// + public string ResetWmsTaskStatus(string? taskId, string? newDestination, string systemName) + { + string resetErrMessage = _wmsTaskDao.ResetTaskWithTaskId(taskId, newDestination, $"任务被{systemName}重置"); + if (string.IsNullOrEmpty(resetErrMessage)) return string.Empty; // 重置成功 + // 重置失败,返回错误信息 + return $"重置状态失败:任务号:{taskId},参考异常信息:{resetErrMessage}"; + } + + /// + /// 完成WMS任务 + /// + /// + /// + /// + public string CompleteWmsTaskStatus(string? taskId, string sysName) + { + List? wmsTasks = _wmsTaskDao.Select(new AppWmsTask() { TaskId = taskId }); + if (wmsTasks != default && wmsTasks.Count > 0) + { + AppWmsTask wmsTask = wmsTasks[0]; + if (sysName != StaticString.WMS && wmsTask.CreatePerson == StaticString.WMS) + { + _sendWmsTaskStatus.SendTaskComplete(taskId); + } + } + string resetErrMessage = _wmsTaskDao.CompleteTaskWithTaskId(taskId, $"【{sysName}】完成"); + if (string.IsNullOrEmpty(resetErrMessage)) return string.Empty; // 完成成功 + return $"完成任务失败。任务号:{taskId},参考异常信息:{resetErrMessage}"; + } + + /// + /// 删除WMS任务 + /// + /// + /// + /// + public string DeleteWmsTaskStatus(string? taskId, string sysName) + { + List? wmsTasks = _wmsTaskDao.Select(new AppWmsTask() { TaskId = taskId }); + if (wmsTasks != default && wmsTasks.Count > 0) + { + AppWmsTask wmsTask = wmsTasks[0]; + if (sysName != StaticString.WMS && wmsTask.CreatePerson == StaticString.WMS) + { + _sendWmsTaskStatus.SendTaskErr(taskId, $"{sysName} 删除/取消"); + } + } + string resetErrMessage = _wmsTaskDao.DeleteTaskWithTaskId(taskId, $"【{sysName}】删除/取消"); + if (string.IsNullOrEmpty(resetErrMessage)) return string.Empty; // 删除成功 + return $"删除/取消任务失败。任务号:{taskId},参考异常信息:{resetErrMessage}"; + } + +} diff --git a/WcsMain/Business/Convey/ConnectPlcServe.cs b/WcsMain/Business/Convey/ConnectPlcServe.cs new file mode 100644 index 0000000..dcb270a --- /dev/null +++ b/WcsMain/Business/Convey/ConnectPlcServe.cs @@ -0,0 +1,109 @@ +using WcsMain.Business.Convey.DataHandler; +using WcsMain.Common; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.General; +using WcsMain.Enum.Tcp; +using WcsMain.Tcp.Client; +using WcsMain.Tcp.Entity; +using WcsMain.Tcp.Entity.Message; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Business.Convey; + +/// +/// 连接并接收 PLC 的信息 +/// +[Component] +public class ConnectPlcServe(AppTcpDao tcpDao, BaseConveyDataHandler conveyDataHandler) +{ + private readonly AppTcpDao _tcpDao = tcpDao; + private readonly BaseConveyDataHandler _conveyDataHandler = conveyDataHandler; + + + public void SetBaseAction() + { + CommonTool.PlcTcpClient = new PlcTcpClient(); + CommonTool.PlcTcpClient.SetConnecting((tcpData) => ConsoleLog.Info($"{tcpData} 正在连接")); + CommonTool.PlcTcpClient.SetConnectFailAction((tcpData, ex) => ConsoleLog.Warning($"{tcpData} 连接失败,参考信息:{ex.Message}")); + CommonTool.PlcTcpClient.SetConnectSuccess((tcpData) => ConsoleLog.Success($"{tcpData} 连接成功")); + CommonTool.PlcTcpClient.SetConnectOffline((tcpData) => ConsoleLog.Warning($"{tcpData} 失去连接")); + CommonTool.PlcTcpClient.GetMessage(GetMessage); + } + + /// + /// 连接PLC服务 + /// + public void ConnectPlc() + { + Task.Factory.StartNew(() => + { + List? tcps = default; + while (true) + { + tcps = _tcpDao.Query(new AppTcp { TcpStatus = (int)TrueFalseEnum.TRUE, TcpType = (int)TcpType.PLC }); + if (tcps != default) break; + Thread.Sleep(5000); + continue; + } + if (tcps.Count == 0) return; + CommonTool.PlcTcpClient.SetBaseTcpServe(tcps); + CommonTool.PlcTcpClient.Connect(); + }, TaskCreationOptions.LongRunning); + } + + /// + /// 收到信息时的处理 + /// + /// + /// + private void GetMessage(TcpServeConnectionData tcpServe, string msg) + { + ConsoleLog.Tcp($"{tcpServe} 收到信息:{msg}"); + MsgHeader? header = CommonTool.PlcTcpClient.GetMsgHeader(msg); + if(header == default) { return; } + switch(header.MsgType) + { + case "SEND": + GetRequest(tcpServe, header, msg); + return; + case "RESP": + GetResponse(); + return; + default: + return; + } + } + + /***************************** 请求和响应事件 *****************************/ + + + private void GetResponse() + { + + } + + + private void GetRequest(TcpServeConnectionData tcpServe, MsgHeader header, string msg) + { + switch(header.MsgTag) + { + case "GTROUTER": // plc向WCS请求路向 ---- 箱式线 + _conveyDataHandler.GetRouter(tcpServe.DisplayName, msg); + return; + + + } + + + } + + + /****************************** 请求事件 ******************************/ + + + + + + +} diff --git a/WcsMain/Business/Convey/DataHandler/BaseConveyDataHandler.cs b/WcsMain/Business/Convey/DataHandler/BaseConveyDataHandler.cs new file mode 100644 index 0000000..e4af11a --- /dev/null +++ b/WcsMain/Business/Convey/DataHandler/BaseConveyDataHandler.cs @@ -0,0 +1,136 @@ +using System.Reflection; +using WcsMain.Business.Convey.DataHandler.GetRouter; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Tcp.Entity.Convey; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Business.Convey.DataHandler; + +/// +/// 输送线收到的数据处理基础类 +/// +[Component] +public class BaseConveyDataHandler(AppRouterMethodDao routerMethodDao) +{ + private readonly AppRouterMethodDao _routerMethodDao = routerMethodDao; + + private Dictionary? methodConfig; + + /// + /// 处理 PLC 请求分拣路向逻辑 + /// + /// + /// + public void GetRouter(string? displayName, string msg) + { + LoadingMethodConfig(); // 加载配置信息,仅第一次加载 + if(methodConfig == default) + { + ConsoleLog.Warning("路由处理参数尚未加载,可能是和数据库服务连接存在异常"); + return; + } + GetRouterData? routerData = FormatGetRouterData(msg); + if(routerData == default ) + { + ConsoleLog.Warning($"数据不能正常识别,数据:{msg}"); + return; + } + var getInstance = methodConfig.TryGetValue(routerData.Area ?? "", out var instance); + if(!getInstance || instance == default) + { + ConsoleLog.Warning($"点位:{routerData.Area} 未配置处理逻辑或者处理逻辑不可用"); + return; + } + if(routerData.Code == "NoRead") + { + instance.NoRead(routerData, displayName, msg); + } + else + { + instance.ReadSuccess(routerData, displayName, msg); + } + } + + /*************************/ + + /// + /// 加载获取路由的参数 + /// + private void LoadingMethodConfig() + { + if (methodConfig != default) return; + List? appRouters = _routerMethodDao.Query(); + if (appRouters == default) return; + methodConfig = []; + // 扫描创建继承 BaseGetRouter 的类的实例 + Dictionary classInstances = []; + var assembly = Assembly.GetExecutingAssembly(); + var assTypes = assembly.GetTypes(); + foreach (var assType in assTypes) + { + var interfaces = assType.GetInterfaces(); + foreach (var inteface in interfaces) + { + if (inteface.GetType() != typeof(BaseGetRouter)) continue; + var instance = Activator.CreateInstance(inteface.GetType()); + if (instance == default) continue; + classInstances.Add(assType.Name, (BaseGetRouter)instance); + } + } + // 将实例和请求点位绑定 + foreach (var appRouter in appRouters) + { + if(string.IsNullOrEmpty(appRouter.ClassName)) continue; + bool isGetInstance = classInstances.TryGetValue(appRouter.ClassName, out var inst); + if (!isGetInstance) continue; + methodConfig.TryAdd(appRouter.Area ?? "", inst); + } + } + + + + /****************************** 格式化数据 ***************************/ + + /// + /// PLC请求WCS路向的请求体格式化 + /// + /// + /// + private GetRouterData? FormatGetRouterData(string msg) + { + if (string.IsNullOrEmpty(msg)) return default; + msg = msg.Trim().TrimStart('<').TrimEnd('>'); + string[] datas = msg.Split(';'); + if (datas.Length != 14) return default; + try + { + return new GetRouterData + { + MsgType = datas[0], + ClientId = datas[1], + MsgId = datas[2], + MsgTag = datas[3], + Area = datas[4], + SortStatus = datas[5], + Code = datas[6], + Size = datas[7], + Weight = Convert.ToDecimal(string.IsNullOrEmpty(datas[8]) ? 0 : datas[8]), + Length = Convert.ToDecimal(string.IsNullOrEmpty(datas[9]) ? 0 : datas[9]), + Width = Convert.ToDecimal(string.IsNullOrEmpty(datas[10]) ? 0 : datas[10]), + Hight = Convert.ToDecimal(string.IsNullOrEmpty(datas[11]) ? 0 : datas[11]), + Spare1 = datas[12], + Spare2 = datas[13], + }; + } + catch (Exception ex) // 防止转换decimal失败 + { + _ = ex; + return default; + } + + + } + + +} diff --git a/WcsMain/Business/Convey/DataHandler/GetRouter/BaseGetRouter.cs b/WcsMain/Business/Convey/DataHandler/GetRouter/BaseGetRouter.cs new file mode 100644 index 0000000..0604022 --- /dev/null +++ b/WcsMain/Business/Convey/DataHandler/GetRouter/BaseGetRouter.cs @@ -0,0 +1,30 @@ +using WcsMain.Tcp.Entity.Convey; + +namespace WcsMain.Business.Convey.DataHandler.GetRouter; + +public class BaseGetRouter +{ + /// + /// 读码失败 + /// + /// + /// + /// + /// + public virtual void NoRead(GetRouterData routerData, string? disPlayName, string msg) + { + throw new NotImplementedException(); + } + + /// + /// 不是读码失败 + /// + /// + /// + /// + /// + public virtual void ReadSuccess(GetRouterData routerData, string? disPlayName, string msg) + { + throw new NotImplementedException(); + } +} diff --git a/WcsMain/Business/Convey/DataHandler/GetRouter/DeliverGetRouter.cs b/WcsMain/Business/Convey/DataHandler/GetRouter/DeliverGetRouter.cs new file mode 100644 index 0000000..6c63f84 --- /dev/null +++ b/WcsMain/Business/Convey/DataHandler/GetRouter/DeliverGetRouter.cs @@ -0,0 +1,8 @@ +namespace WcsMain.Business.Convey.DataHandler.GetRouter; + +/// +/// 发货获取路向 +/// +public class DeliverGetRouter : BaseGetRouter +{ +} diff --git a/WcsMain/Business/Convey/DataHandler/GetRouter/LoginGetRouter.cs b/WcsMain/Business/Convey/DataHandler/GetRouter/LoginGetRouter.cs new file mode 100644 index 0000000..c6e24a5 --- /dev/null +++ b/WcsMain/Business/Convey/DataHandler/GetRouter/LoginGetRouter.cs @@ -0,0 +1,9 @@ +namespace WcsMain.Business.Convey.DataHandler.GetRouter; + +/// +/// 注册口获取路向 +/// +public class LoginGetRouter : BaseGetRouter +{ + +} diff --git a/WcsMain/Business/Convey/DataHandler/GetRouter/PickGetRouter.cs b/WcsMain/Business/Convey/DataHandler/GetRouter/PickGetRouter.cs new file mode 100644 index 0000000..f3bc597 --- /dev/null +++ b/WcsMain/Business/Convey/DataHandler/GetRouter/PickGetRouter.cs @@ -0,0 +1,8 @@ +namespace WcsMain.Business.Convey.DataHandler.GetRouter; + +/// +/// 拣选请求获取路向 +/// +public class PickGetRouter : BaseGetRouter +{ +} diff --git a/WcsMain/Business/Convey/DataHandler/GetRouter/RecheckGetRouter.cs b/WcsMain/Business/Convey/DataHandler/GetRouter/RecheckGetRouter.cs new file mode 100644 index 0000000..ab00e82 --- /dev/null +++ b/WcsMain/Business/Convey/DataHandler/GetRouter/RecheckGetRouter.cs @@ -0,0 +1,8 @@ +namespace WcsMain.Business.Convey.DataHandler.GetRouter; + +/// +/// 复核获取路向 +/// +public class RecheckGetRouter : BaseGetRouter +{ +} diff --git a/WcsMain/Business/Convey/DataHandler/GetRouter/ReplenishGetRouter.cs b/WcsMain/Business/Convey/DataHandler/GetRouter/ReplenishGetRouter.cs new file mode 100644 index 0000000..0588de3 --- /dev/null +++ b/WcsMain/Business/Convey/DataHandler/GetRouter/ReplenishGetRouter.cs @@ -0,0 +1,8 @@ +namespace WcsMain.Business.Convey.DataHandler.GetRouter; + +/// +/// 补货获取路向 +/// +public class ReplenishGetRouter : BaseGetRouter +{ +} diff --git a/WcsMain/Common/CommonData.cs b/WcsMain/Common/CommonData.cs new file mode 100644 index 0000000..e970ce4 --- /dev/null +++ b/WcsMain/Common/CommonData.cs @@ -0,0 +1,49 @@ +using Autofac; +using System.Diagnostics.CodeAnalysis; +using WcsMain.AppEntity.SystemData; +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.Common; + +/// +/// 共享数据 +/// +public static class CommonData +{ + /// + /// IOC + /// + [NotNull] + public static IContainer? Container { get; set; } + + /// + /// 系统设置项,加载于 appsettings.json + /// + [NotNull] + public static AppSettingJsonEntity? Settings { get; set; } + + /// + /// 数据库的 Config 配置 + /// + [NotNull] + public static AppConfigEntity? AppConfig { get; set; } + + /// + /// 堆垛机数据 + /// + [NotNull] + public static List? AppStackers { get; set; } + + /// + /// 点位信息 + /// + [NotNull] + public static List? AppLocations { get; set; } + + + + /// + /// 指示是否连接PLC + /// + public static bool IsConnectPlc { get; set; } = false; +} \ No newline at end of file diff --git a/WcsMain/Common/CommonTool.cs b/WcsMain/Common/CommonTool.cs new file mode 100644 index 0000000..3fa1e78 --- /dev/null +++ b/WcsMain/Common/CommonTool.cs @@ -0,0 +1,62 @@ +using Fleck; +using PlcTool.Siemens; +using SqlSugar; +using System.Diagnostics.CodeAnalysis; +using WcsMain.Business.CommonAction; +using WcsMain.Tcp.Client; + +namespace WcsMain.Common; + +/// +/// 公用工具类 +/// +public class CommonTool +{ + + #region 数据库连接 + + + /// + /// 数据库连接 + /// + [NotNull] + public static ISqlSugarClient? DbServe { get; set; } + + #endregion + + #region PLC 连接 + + /// + /// PLC连接 + /// + public static SiemensS7? Siemens { get; set; } + + + #endregion + + + #region PLC 的 TCP 连接 + + /// + /// TCP 连接的PLC通讯 + /// + [NotNull] + public static PlcTcpClient? PlcTcpClient { get; set; } + + + #endregion + + #region WMS 接口 + + // 请查看 Plugins 文件夹 WmsWebApiPost + + #endregion + + + + public static WebSocketServer? Websocket; + + public static readonly LedUsing LedUsing = new(256, 96, 1); + + +} \ No newline at end of file diff --git a/WcsMain/ConsoleLog.cs b/WcsMain/ConsoleLog.cs new file mode 100644 index 0000000..01da51c --- /dev/null +++ b/WcsMain/ConsoleLog.cs @@ -0,0 +1,252 @@ +using System.Runtime.InteropServices; +using LogTool; +using System.Text; + +namespace WcsMain; + +/// +/// 输出信息 +/// +public class ConsoleLog +{ + + private static readonly object _locker = new(); + + /// + /// 输出提示信息 + /// + /// + public static void Info(params string[] messages) => Info(true, messages); + + /// + /// 输出提示信息 + /// + /// + /// + public static void Info(bool isShow, params string[] messages) + { + if (!isShow) return; + if (messages == default || messages.Length == 0) return; + DateTime now = DateTime.Now; + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine(now.ToString("yyyy-MM-dd HH:mm:ss:fff")); + foreach (string message in messages) + { + stringBuilder.AppendLine($" -- {message}"); + } + lock (_locker) + { + Console.ForegroundColor = ConsoleColor.Magenta; + Console.Write(stringBuilder.ToString()); + WcsLog.Instance().WriteEventLog(stringBuilder); + } + } + + + /// + /// 输出错误信息 + /// + /// + public static void Error(params string[] messages) => Error(true, messages); + + /// + /// 输出错误信息 + /// + /// + /// + public static void Error(bool isShow, params string[] messages) + { + if (!isShow) return; + if (messages == default || messages.Length == 0) return; + DateTime now = DateTime.Now; + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine(now.ToString("yyyy-MM-dd HH:mm:ss:fff")); + foreach (string message in messages) + { + stringBuilder.AppendLine($" -- {message}"); + } + lock (_locker) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.Write(stringBuilder.ToString()); + WcsLog.Instance().WriteEventLog(stringBuilder); + } + } + + + /// + /// 输出异常信息 + /// + /// + public static void Exception(params string[] messages) => Exception(true, messages); + + /// + /// 输出异常信息 + /// + /// + /// + public static void Exception(bool isShow, params string[] messages) + { + if (!isShow) return; + if (messages == default || messages.Length == 0) return; + DateTime now = DateTime.Now; + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine(now.ToString("yyyy-MM-dd HH:mm:ss:fff")); + foreach (string message in messages) + { + stringBuilder.AppendLine($" -- {message}"); + } + lock (_locker) + { + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.Write(stringBuilder.ToString()); + WcsLog.Instance().WriteExceptionLog(stringBuilder); + } + } + + + /// + /// 输出成功信息 + /// + /// + public static void Success(params string[] messages) => Success(true, messages); + + /// + /// 输出成功信息 + /// + /// + /// + public static void Success(bool isShow, params string[] messages) + { + if (!isShow) return; + if (messages == default || messages.Length == 0) return; + DateTime now = DateTime.Now; + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine(now.ToString("yyyy-MM-dd HH:mm:ss:fff")); + foreach (string message in messages) + { + stringBuilder.AppendLine($" -- {message}"); + } + lock (_locker) + { + Console.ForegroundColor = ConsoleColor.DarkGreen; + Console.Write(stringBuilder.ToString()); + WcsLog.Instance().WriteEventLog(stringBuilder); + } + } + + + /// + /// 输出警告信息 + /// + /// + public static void Warning(params string[] messages) => Warning(true, messages); + + /// + /// 输出警告信息 + /// + /// + /// + public static void Warning(bool isShow, params string[] messages) + { + if (!isShow) return; + if (messages == default || messages.Length == 0) return; + DateTime now = DateTime.Now; + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine(now.ToString("yyyy-MM-dd HH:mm:ss:fff")); + foreach (string message in messages) + { + stringBuilder.AppendLine($" -- {message}"); + } + lock (_locker) + { + Console.ForegroundColor = ConsoleColor.DarkYellow; + Console.Write(stringBuilder.ToString()); + WcsLog.Instance().WriteEventLog(stringBuilder); + } + } + + + /// + /// 输出蓝色提示信息 + /// + /// + public static void Tip(params string[] messages) => Tip(true, messages); + + /// + /// 输出蓝色提示信息 + /// + /// + /// + public static void Tip(bool isShow, params string[] messages) + { + if (!isShow) return; + if (messages == default || messages.Length == 0) return; + DateTime now = DateTime.Now; + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine(now.ToString("yyyy-MM-dd HH:mm:ss:fff")); + foreach (string message in messages) + { + stringBuilder.AppendLine($" -- {message}"); + } + lock (_locker) + { + Console.ForegroundColor = ConsoleColor.Blue; + Console.Write(stringBuilder.ToString()); + WcsLog.Instance().WriteEventLog(stringBuilder); + } + } + + /// + /// Tcp 通讯专用 + /// + /// + public static void Tcp(params string[] messages) => Tcp(true, messages); + + /// + /// Tcp 通讯专用 + /// + /// + /// + public static void Tcp(bool isShow, params string[] messages) + { + if (!isShow) return; + if (messages == default || messages.Length == 0) return; + DateTime now = DateTime.Now; + StringBuilder stringBuilder = new(); + stringBuilder.AppendLine(now.ToString("yyyy-MM-dd HH:mm:ss:fff")); + foreach (string message in messages) + { + stringBuilder.AppendLine($" -- {message}"); + } + lock (_locker) + { + Console.ForegroundColor = ConsoleColor.White; + Console.Write(stringBuilder.ToString()); + WcsLog.Instance().WriteTcpLog(stringBuilder); + } + } + + + const int STD_INPUT_HANDLE = -10; + const uint ENABLE_QUICK_EDIT_MODE = 0x0040; + [DllImport("kernel32.dll", SetLastError = true)] + internal static extern nint GetStdHandle(int hConsoleHandle); + [DllImport("kernel32.dll", SetLastError = true)] + internal static extern bool GetConsoleMode(nint hConsoleHandle, out uint mode); + [DllImport("kernel32.dll", SetLastError = true)] + internal static extern bool SetConsoleMode(nint hConsoleHandle, uint mode); + + /// + /// 禁用快速编辑 ---- 此项会屏蔽控制台输入 + /// + public static void DisbleQuickEditMode() + { + nint hStdin = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hStdin, out uint mode); + mode &= ~ENABLE_QUICK_EDIT_MODE; + SetConsoleMode(hStdin, mode); + } + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppApiAcceptDao.cs b/WcsMain/DataBase/Dao/AppApiAcceptDao.cs new file mode 100644 index 0000000..2c38a82 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppApiAcceptDao.cs @@ -0,0 +1,105 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiAccept; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppApiAcceptDao +{ + + /// + /// 插入一条数据 + /// + /// + /// + public int Insert(AppApiAccept data) + { + try + { + return CommonTool.DbServe.Insertable(data).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 查询所有数据 + /// + /// + public List? Select() + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .OrderByDescending(o => o.RequestTime).ToList(); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + + + /*----------------------业务方法--------------------------------- */ + + /// + /// 分页查询数据 + /// + /// + /// + public (List? apiRequests, int totalRows) SelectPage(GetApiAcceptWithPageRequest request) + { + try + { + int totalRows = 0; + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(request.SearchStr), + w => w.RequestMsg!.Contains(request.SearchStr!) + || w.ResponseMsg!.Contains(request.SearchStr!) + || w.Path!.Contains(request.SearchStr!) + || w.ClientAddress!.Contains(request.SearchStr!)); + if (request.TimeRange is { Count: 2 }) // 时间范围 + { + sqlFuc.Where(w => w.RequestTime > request.TimeRange[0] && w.RequestTime < request.TimeRange[1]); + } + sqlFuc = sqlFuc.OrderByDescending(o => new { o.RequestTime }); + var queryResult = sqlFuc.ToPageList(request.Page!.PageIndex, request.Page!.PageSize, ref totalRows); + return (queryResult, totalRows); + } + catch (Exception ex) + { + _ = ex; + return default; + } + + } + + /// + /// 保留多少天数据 + /// + /// + /// + public int ClearData(int days) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable().Where(w => w.RequestTime < DateTime.Now.AddDays(-days)); + return sqlFuc.ExecuteCommand(); + + } + catch (Exception ex) + { + _ = ex; + return default; + } + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppApiRequestDao.cs b/WcsMain/DataBase/Dao/AppApiRequestDao.cs new file mode 100644 index 0000000..f7495e1 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppApiRequestDao.cs @@ -0,0 +1,111 @@ +using System.ComponentModel; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.ApiRequest; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_app_api_request 的操作类 +/// +[Component] +public class AppApiRequestDao +{ + + /// + /// 插入一条数据 + /// + /// + /// + public int Insert(AppApiRequest data) + { + try + { + return CommonTool.DbServe.Insertable(data).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 查询所有数据 + /// + /// + public List? Select() + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .OrderByDescending(o => o.RequestTime).ToList(); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + + + /*----------------------业务方法--------------------------------- */ + + /// + /// 分页查询数据 + /// + /// + /// + public (List? apiRequests, int totalRows) SelectPage(GetApiRequestWithPageRequest request) + { + try + { + int totalRows = 0; + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(request.SearchStr), + w => w.RequestMsg!.Contains(request.SearchStr!) + || w.ResponseMsg!.Contains(request.SearchStr!) + || w.RequestUrl!.Contains(request.SearchStr!) + || w.RequestMethod!.Contains(request.SearchStr!)); + if (request.TimeRange is { Count: 2 }) // 时间范围 + { + sqlFuc.Where(w => w.RequestTime > request.TimeRange[0] && w.RequestTime < request.TimeRange[1]); + } + sqlFuc = sqlFuc.OrderByDescending(o => new { o.RequestTime }); + var queryResult = sqlFuc.ToPageList(request.Page!.PageIndex, request.Page!.PageSize, ref totalRows); + return (queryResult, totalRows); + } + catch (Exception ex) + { + _ = ex; + return default; + } + + } + + + /// + /// 保留多少条数据 + /// + /// + /// + public int ClearData(int days) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable().Where(w => w.RequestTime < DateTime.Now.AddDays(-days)); + return sqlFuc.ExecuteCommand(); + + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppConfigDao.cs b/WcsMain/DataBase/Dao/AppConfigDao.cs new file mode 100644 index 0000000..2f4331f --- /dev/null +++ b/WcsMain/DataBase/Dao/AppConfigDao.cs @@ -0,0 +1,114 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Config; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppConfigDao +{ + /// + /// 返回所有的配置信息 + /// + /// + public List? Query() + { + try + { + List configs = CommonTool.DbServe.Queryable().OrderBy(o => o.ConfigType).ToList(); + return configs; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 根据主键更新信息 + /// + /// + /// + public int Update(AppConfig config) + { + try + { + return CommonTool.DbServe.Updateable(config).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 插入一条信息 + /// + /// + /// + public int Insert(params AppConfig[] configs) + { + try + { + return CommonTool.DbServe.Insertable(configs).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + + /// + /// 返回所有的配置信息 + /// + /// + /// + public List? GetAllConfig(string? configKey) + { + try + { + List configs = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(configKey), w => w.ConfigKey!.Contains(configKey!)) + .OrderBy(o => o.ConfigType).ToList(); + return configs; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 分页查询系统配置信息 + /// + /// + /// + public (List? configs, int totalNumber) GetAllConfigWithPage(GetConfigWithPageRequest request) + { + try + { + int totalNumber = 0; + List configs = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(request.SearchString), w => w.ConfigKey!.Contains(request.SearchString!) + || w.ConfigValue!.Contains(request.SearchString!) + || w.ConfigName!.Contains(request.SearchString!) + || w.ConfigType!.Contains(request.SearchString!) + || w.Remark!.Contains(request.SearchString!)) + .OrderBy(o => o.ConfigType).ToPageList((int)request.PageIndex!, (int)request.PageSize!, ref totalNumber); + return (configs, totalNumber); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppDBDao.cs b/WcsMain/DataBase/Dao/AppDBDao.cs new file mode 100644 index 0000000..16ef481 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppDBDao.cs @@ -0,0 +1,112 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_app_db 表的增删改查 +/// +[Component] +public class AppDBDao +{ + /// + /// 插入数据 + /// + /// + /// + public int Insert(AppDB appDB) + { + try + { + int insertResult = CommonTool.DbServe.Insertable(appDB).ExecuteCommand(); + return insertResult; + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 更新数据,以主键为条件,主键 : DBName + /// + /// + /// + public int Update(AppDB appDB) + { + try + { + var sqlFuc = CommonTool.DbServe.Updateable(appDB).IgnoreColumns(ignoreAllNullColumns: true); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 删除数据,以主键为条件 + /// + /// + /// + public int Delete(AppDB appDB) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable(appDB); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 查找数据 + /// + /// + /// + public List? Select(AppDB appDB) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable(); + if (appDB.DBName != null) + { + sqlFuc = sqlFuc.Where(w => w.DBName == appDB.DBName); + } + if (appDB.DBAddress != null) + { + sqlFuc = sqlFuc.Where(w => w.DBAddress == appDB.DBAddress); + } + if (appDB.IsSystem != null) + { + sqlFuc = sqlFuc.Where(w => w.IsSystem == appDB.IsSystem); + } + if (appDB.Remark != null) + { + sqlFuc = sqlFuc.Where(w => w.Remark == appDB.Remark); + } + return sqlFuc.OrderBy(o => new { o.PlcId, o.DBName }).ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查找所有数据 + /// + /// + public List? Select() => Select(new AppDB()); + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppLocationDao.cs b/WcsMain/DataBase/Dao/AppLocationDao.cs new file mode 100644 index 0000000..6c115f5 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppLocationDao.cs @@ -0,0 +1,206 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Location; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum; +using WcsMain.Enum.Location; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_app_location 的库操作 +/// +[Component] +public class AppLocationDao +{ + + /// + /// 增加一条记录 + /// + /// + /// + public int Insert(AppLocation appLocation) + { + try + { + return CommonTool.DbServe.Insertable(appLocation).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 更新一条记录,根据主键,主键WcsLocation + /// + /// + /// + public int Update(params AppLocation[] appLocation) + { + try + { + var sqlFuc = CommonTool.DbServe.Updateable(appLocation).IgnoreColumns(ignoreAllNullColumns: true); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 删除一条记录,根据主键,主键WcsLocation + /// + /// + /// + public int Delete(AppLocation appLocation) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable(appLocation); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 查找数据 + /// + /// + /// + /// + /// 时间不在筛选行列 + /// + public List? Select(AppLocation appLocation) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(appLocation.WcsLocation), + w => w.WcsLocation == appLocation.WcsLocation) + .WhereIF(!string.IsNullOrEmpty(appLocation.WmsLocation), + w => w.WmsLocation == appLocation.WmsLocation) + .WhereIF(appLocation.LocationType != null, w => w.LocationType == appLocation.LocationType) + .WhereIF(appLocation.TunnelNo != null, w => w.TunnelNo == appLocation.TunnelNo) + .WhereIF(appLocation.EquipmentId != null, w => w.EquipmentId == appLocation.EquipmentId) + .WhereIF(appLocation.LocationStatus != null, w => w.LocationStatus == appLocation.LocationStatus) + .WhereIF(appLocation.Queue != null, w => w.Queue == appLocation.Queue) + .WhereIF(appLocation.Line != null, w => w.Line == appLocation.Line) + .WhereIF(appLocation.Layer != null, w => w.Layer == appLocation.Layer) + .WhereIF(appLocation.Depth != null, w => w.Depth == appLocation.Depth) + .WhereIF(!string.IsNullOrEmpty(appLocation.VehicleNo), w => w.VehicleNo == appLocation.VehicleNo) + .OrderBy(o => new { o.Queue, o.Line, o.Layer, o.Depth }) + .ToList(); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查找所有数据 + /// + /// + public List? Select() => Select(new AppLocation()); + + + /// + /// 查询自起点索引后的多少条数据 + /// + /// + /// + public (List? locations, int totalRows) SelectPage(GetLocationWithPageRequest request) + { + try + { + int totalRows = 0; + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(request.SearchStr), + w => w.WcsLocation!.Contains(request.SearchStr!) + || w.WmsLocation!.Contains(request.SearchStr!) + || w.VehicleNo!.Contains(request.SearchStr!) + || w.Remark!.Contains(request.SearchStr!)); + if (request.LocationStatus != default) // 查询任务类型 + { + List locationStatus = []; + foreach (var ls in request.LocationStatus) + { + if (ls == "空闲") { locationStatus.Add((int)LocationStatusEnum.empty); } + if (ls == "锁定") { locationStatus.Add((int)LocationStatusEnum.locked); } + if (ls == "占用") { locationStatus.Add((int)LocationStatusEnum.used); } + if (ls == "禁用") { locationStatus.Add((int)LocationStatusEnum.forbidden); } + if (ls == "特殊点位") { locationStatus.Add((int)LocationStatusEnum.special); } + } + sqlFuc.Where(w => locationStatus.Contains(w.LocationStatus)); + } + sqlFuc.OrderBy(o => new { o.EquipmentId, o.Queue, o.Line, o.Layer, o.Depth }); + var queryResult = sqlFuc.ToPageList(request.Page!.PageIndex, request.Page!.PageSize, ref totalRows); + return (queryResult, totalRows); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查询一个堆垛机可用的站台 + /// + /// + /// + /// + public List? QueryCanUseStand(int? stackerId, StandTypeEnum standType) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(stackerId != null, w => w.EquipmentId == stackerId) + .Where(w => w.LocationType.ToString()!.Contains(standType.ToString())) + .Where(w => w.LocationStatus == (int)LocationStatusEnum.empty) + .OrderBy(o => new { o.Queue, o.Line, o.Layer, o.Depth }); + //var ss = sqlFuc.ToSql(); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查找所有的站台 + /// + /// + public List? SelectStand() + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .Where(w => w.LocationType != (int)StandTypeEnum.storageLocation) + .OrderBy(o => o.WcsLocation) + .ToList(); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppMenuDao.cs b/WcsMain/DataBase/Dao/AppMenuDao.cs new file mode 100644 index 0000000..26be8a5 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppMenuDao.cs @@ -0,0 +1,140 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.Menu; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// 菜单表的操作 +/// +[Component] +public class AppMenuDao +{ + + /// + /// 查询所有数据 + /// + /// + public List? Query() => Query(new AppMenu()); + + /// + /// 查询数据 + /// + /// + /// + public List? Query(AppMenu queryEntity) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(queryEntity.MainMenuIndex != default, w => w.MainMenuIndex == queryEntity.MainMenuIndex) + .WhereIF(queryEntity.MainMenuName != default, w => w.MainMenuName == queryEntity.MainMenuName) + .WhereIF(queryEntity.MainMenuIco != default, w => w.MainMenuIco == queryEntity.MainMenuIco) + .WhereIF(queryEntity.MinorMenuIndex != default, w => w.MinorMenuIndex == queryEntity.MinorMenuIndex) + .WhereIF(queryEntity.MinorMenuName != default, w => w.MinorMenuName == queryEntity.MinorMenuName) + .WhereIF(queryEntity.MinorMenuIco != default, w => w.MinorMenuIco == queryEntity.MinorMenuIco) + .WhereIF(queryEntity.MinorMenuRouter != default, w => w.MinorMenuRouter == queryEntity.MinorMenuRouter) + .WhereIF(queryEntity.MenuStatus != default, w => w.MenuStatus == queryEntity.MenuStatus) + .WhereIF(queryEntity.Remark != default, w => w.Remark == queryEntity.Remark) + .OrderBy(o => o.MainMenuIndex).OrderBy(o => o.MinorMenuIndex); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 根据主键更新数据 + /// + /// + /// + public int Update(AppMenu updateEntity) + { + try + { + var sqlFuc = CommonTool.DbServe.Updateable(updateEntity) + .IgnoreColumns(ignoreAllNullColumns: true); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 插入一些数据 + /// + /// + /// + public int Insert(params AppMenu[] menus) + { + try + { + var sqlFuc = CommonTool.DbServe.Insertable(menus); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + + + + /*--------------------------业务方法---------------------------------------*/ + + + /// + /// 根据用户组查找菜单 + /// + /// + /// + public List? GetMenuWithGroupId(string groupId) + { + try + { + string sql = $"select * from tbl_app_menu where minor_menu_index in (select minor_menu_index from tbl_app_user_rule where group_id = '{groupId}') and menu_status = 1 order by minor_menu_index asc"; + + var sqlFuc = CommonTool.DbServe.Ado.SqlQuery(sql); + return [.. sqlFuc]; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 返回分页查询数据 + /// + /// + /// + public (List quertResult, int totalRows) SelectPage(GetMenuWithPageRequest request) + { + try + { + int totalRows = 0; + var sqlFuc = CommonTool.DbServe.Queryable() + .OrderBy(o => new { o.MainMenuIndex, o.MinorMenuIndex }); + var queryResult = sqlFuc.ToPageList(request.Page!.PageIndex, request.Page!.PageSize, ref totalRows); + return (queryResult, totalRows); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppPLCDao.cs b/WcsMain/DataBase/Dao/AppPLCDao.cs new file mode 100644 index 0000000..4b643ab --- /dev/null +++ b/WcsMain/DataBase/Dao/AppPLCDao.cs @@ -0,0 +1,92 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppPLCDao +{ + + /// + /// 查询PLC数据 + /// + /// + public List? Query() + { + try + { + List appPLCs = CommonTool.DbServe.Queryable().OrderBy(o => o.PLCId).ToList(); + return appPLCs; + + } + catch (Exception ex) + { + _ = ex; + } + return default; + } + + + /// + /// 根据主键返回更新条数 + /// + /// + /// + public int Update(AppPLC plcInfo) + { + try + { + var sqlFuc = CommonTool.DbServe.Updateable(plcInfo).IgnoreColumns(ignoreAllNullColumns: true); + return sqlFuc.ExecuteCommand(); + + } + catch (Exception ex) + { + _ = ex; + } + return default; + } + + + /// + /// 插入一条新记录 + /// + /// + /// + public int Insert(AppPLC plcInfo) + { + try + { + var sqlFuc = CommonTool.DbServe.Insertable(plcInfo); + return sqlFuc.ExecuteCommand(); + + } + catch (Exception ex) + { + _ = ex; + } + return default; + } + + + /// + /// 根据状态查询PLC数据 + /// + /// + /// + public List? GetDataWithStatus(int status) + { + try + { + List appPLCs = CommonTool.DbServe.Queryable().Where(w => w.PLCStatus == status).ToList(); + return appPLCs; + + } + catch (Exception ex) + { + _ = ex; + } + return default; + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppRouterMethodDao.cs b/WcsMain/DataBase/Dao/AppRouterMethodDao.cs new file mode 100644 index 0000000..cd23609 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppRouterMethodDao.cs @@ -0,0 +1,39 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppRouterMethodDao +{ + + /// + /// 查询数据 + /// + /// + /// + public List? Query(AppRouterMethod routerMethod) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(routerMethod.Area == default, w => w.Area == routerMethod.Area) + .WhereIF(routerMethod.ClassName == default, w => w.ClassName == routerMethod.ClassName) + .WhereIF(routerMethod.Remark == default, w => w.Remark == routerMethod.Remark); + return sqlFuc.ToList(); + } + catch(Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查询所有 + /// + /// + public List? Query() => Query(new AppRouterMethod()); + +} diff --git a/WcsMain/DataBase/Dao/AppSettingsDao.cs b/WcsMain/DataBase/Dao/AppSettingsDao.cs new file mode 100644 index 0000000..2b80896 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppSettingsDao.cs @@ -0,0 +1,135 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_app_settings 表的增删改查 +/// +[Component] +public class AppSettingsDao +{ + + /// + /// 添加一条记录 + /// + /// + /// + public int Insert(AppSettings appSetting) + { + try + { + int insertResult = CommonTool.DbServe.Insertable(appSetting).ExecuteCommand(); + return insertResult; + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 更新一条记录,主键:SettingKey + /// + /// + /// + public int Update(AppSettings appSetting) + { + try + { + var sqlFuc = CommonTool.DbServe.Updateable(appSetting).IgnoreColumns(ignoreAllNullColumns: true); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 删除一条记录,以主键为条件 + /// + /// + /// + public int Delete(AppSettings appSetting) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable(appSetting); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 以不为 null 为条件查询 + /// + /// + /// + public List? Select(AppSettings appSetting) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable(); + if (appSetting.SettingKey != null) + { + sqlFuc = sqlFuc.Where(w => w.SettingKey == appSetting.SettingKey); + } + if (appSetting.SettingName != null) + { + sqlFuc = sqlFuc.Where(w => w.SettingName == appSetting.SettingName); + } + if (appSetting.SettingValue != null) + { + sqlFuc = sqlFuc.Where(w => w.SettingValue == appSetting.SettingValue); + } + if (appSetting.SettingType != null) + { + sqlFuc = sqlFuc.Where(w => w.SettingType == appSetting.SettingType); + } + if (appSetting.Remark != null) + { + sqlFuc = sqlFuc.Where(w => w.Remark == appSetting.Remark); + } + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查找所有数据 + /// + /// + public List? Select() => Select(new AppSettings()); + + + /// + /// 返回设置信息 + /// + /// + public List? GetSetting(string settingKey) + { + try + { + List settings = CommonTool.DbServe.Queryable().Where(w => w.SettingKey == settingKey).ToList(); + return settings; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppStackerDao.cs b/WcsMain/DataBase/Dao/AppStackerDao.cs new file mode 100644 index 0000000..5381c81 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppStackerDao.cs @@ -0,0 +1,99 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_app_stocker 操作类 +/// +[Component] +public class AppStackerDao +{ + + /// + /// 插入数据 + /// + /// + /// + public int? Insert(params AppStacker[] data) + { + try + { + return CommonTool.DbServe.Insertable(data).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 删除一条数据,根据主键 + /// + /// + /// + public int? Delete(AppStacker appStacker) + { + try + { + return CommonTool.DbServe.Deleteable(appStacker).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 修改一条数据 + /// + /// + /// + public int? Update(AppStacker appStacker) + { + try + { + return CommonTool.DbServe.Updateable(appStacker).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 根据条件查询 ---- 不包括站台 + /// + /// + /// + public List? Select(AppStacker appStacker) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(appStacker.StackerId != default, w => w.StackerId == appStacker.StackerId) + .WhereIF(appStacker.StackerName != default, w => w.StackerName == appStacker.StackerName) + .WhereIF(appStacker.StackerStatus != default, w => w.StackerStatus == appStacker.StackerStatus) + .WhereIF(appStacker.ActionPlc != default, w => w.ActionPlc == appStacker.ActionPlc) + .WhereIF(appStacker.Remark != default, w => w.Remark == appStacker.Remark); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + + } + + /// + /// 查询所有的数据 + /// + /// + public List? Select() => Select(new AppStacker()); + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppTcpDao.cs b/WcsMain/DataBase/Dao/AppTcpDao.cs new file mode 100644 index 0000000..9122ec2 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppTcpDao.cs @@ -0,0 +1,121 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppTcpDao +{ + + /// + /// 查询所有socket数据 + /// + /// + public List? Query() => Query(new AppTcp()); + + /// + /// 条件查询 + /// + /// + /// + public List? Query(AppTcp socket) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(socket.TcpId != default, w => w.TcpId == socket.TcpId) + .WhereIF(socket.TcpIp != default, w => w.TcpIp == socket.TcpIp) + .WhereIF(socket.TcpPort != default, w => w.TcpPort == socket.TcpPort) + .WhereIF(socket.TcpType != default, w => w.TcpType == socket.TcpType) + .WhereIF(socket.TcpStatus != default, w => w.TcpStatus == socket.TcpStatus) + .WhereIF(socket.DisplayName != default, w => w.DisplayName == socket.DisplayName) + .WhereIF(socket.Remark != default, w => w.Remark == socket.Remark); + return sqlFuc.ToList(); + + } + catch (Exception ex) + { + _ = ex; + } + return default; + } + + /// + /// 插入一条记录 + /// + /// + /// + public int Insert(AppTcp socket) + { + try + { + int insertRows = CommonTool.DbServe.Insertable(socket).ExecuteCommand(); + return insertRows; + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 根据主键更新记录,忽略 null + /// + /// + /// + public int Update(AppTcp socket) + { + try + { + int insertRows = CommonTool.DbServe.Updateable(socket).IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + return insertRows; + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 删除一条记录 ---- 根据主键 + /// + /// + /// + public int Delete(AppTcp socket) + { + try + { + int insertRows = CommonTool.DbServe.Deleteable(socket).ExecuteCommand(); + return insertRows; + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 根据状态查询 socket 数据 + /// + /// + /// + public List? GetNeedUseSocket(int status) + { + try + { + List sockets = CommonTool.DbServe.Queryable().Where(w => w.TcpStatus == status).ToList(); + return sockets; + + } + catch (Exception ex) + { + _ = ex; + } + return default; + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppUserDao.cs b/WcsMain/DataBase/Dao/AppUserDao.cs new file mode 100644 index 0000000..3555a3b --- /dev/null +++ b/WcsMain/DataBase/Dao/AppUserDao.cs @@ -0,0 +1,86 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.User; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// 用户表操作类 +/// +[Component] +public class AppUserDao +{ + + + /// + /// 查询用户 + /// + /// + /// + public List? Query(AppUser user) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(user.UserId != default, w => w.UserId == user.UserId) + .WhereIF(user.UserName != default, w => w.UserName == user.UserName) + .WhereIF(user.UserPassword != default, w => w.UserPassword == user.UserPassword) + .WhereIF(user.UserStatus != default, w => w.UserStatus == user.UserStatus) + .WhereIF(user.UserGroup != default, w => w.UserGroup == user.UserGroup); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + /*------------------------------------业务代码-------------------------------------*/ + + + /// + /// 分页查询所有用户信息 + /// + /// + /// + public (List users, int totalRows) QueryWithPage(GetUserWithPageRequest request) + { + try + { + int totalRows = 0; + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(request.SearchStr), + w => w.UserId!.Contains(request.SearchStr!) + || w.UserName!.Contains(request.SearchStr!) + || w.UserGroup!.Contains(request.SearchStr!)); // 模糊查询 + + if (request.UserStatus != default) // 查询任务状态 + { + List userStatuses = []; + foreach (var userStatus in request.UserStatus) + { + if (userStatus == "禁用") { userStatuses.Add((int)UserStatusEnum.disabled); } + if (userStatus == "正常") { userStatuses.Add((int)UserStatusEnum.normal); } + } + sqlFuc.Where(w => userStatuses.Contains(w.UserStatus)); + } + if (request.TimeRange is { Count: 2 }) // 时间范围 + { + sqlFuc.Where(w => w.CreateTime > request.TimeRange[0] && w.CreateTime < request.TimeRange[1]); + } + sqlFuc.OrderByDescending(o => new { o.CreateTime }); + var queryResult = sqlFuc.ToPageList(request.Page!.PageIndex, request.Page!.PageSize, ref totalRows); + return (queryResult, totalRows); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppUserGroupDao.cs b/WcsMain/DataBase/Dao/AppUserGroupDao.cs new file mode 100644 index 0000000..f29aac5 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppUserGroupDao.cs @@ -0,0 +1,69 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppUserGroupDao +{ + + public List? Query() => Query(new AppUserGroup()); + + + public List? Query(AppUserGroup queryEntity) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(queryEntity.GroupId != default, w => w.GroupId == queryEntity.GroupId) + .WhereIF(queryEntity.GroupName != default, w => w.GroupName == queryEntity.GroupName) + .WhereIF(queryEntity.GroupStatus != default, w => w.GroupStatus == queryEntity.GroupStatus) + .OrderBy(o => o.GroupId); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 添加用户组 + /// + /// + /// + public int Insert(params AppUserGroup[] userGroups) + { + try + { + var result = CommonTool.DbServe.Insertable(userGroups).ExecuteCommand(); + return result; + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 删除用户组,根据主键 + /// + /// + /// + public int Delete(AppUserGroup userGroup) + { + try + { + var result = CommonTool.DbServe.Deleteable(userGroup).ExecuteCommand(); + return result; + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppUserRuleDao.cs b/WcsMain/DataBase/Dao/AppUserRuleDao.cs new file mode 100644 index 0000000..03a6102 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppUserRuleDao.cs @@ -0,0 +1,68 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.UserRule; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppUserRuleDao +{ + + public List? Query() => Query(new AppUserRule()); + + /// + /// 查询用户权限 + /// + /// + /// + public List? Query(AppUserRule queryEntity) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(queryEntity.GroupId != default, w => w.GroupId == queryEntity.GroupId) + .WhereIF(queryEntity.MinorMenuIndex != default, w => w.MinorMenuIndex == queryEntity.MinorMenuIndex) + .OrderBy(o => o.GroupId); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 删除用户的权限,并添加新的权限 + /// + /// + /// + public bool UpdateUserRule(UpdateUserRuleRequest request) + { + try + { + var result = CommonTool.DbServe.Ado.UseTran(() => + { + CommonTool.DbServe.Deleteable().Where(w => w.GroupId == request.UserGroupId).ExecuteCommand(); + if (request.UserRules == default) return; + List userRules = []; + foreach (var userRule in request.UserRules) + { + userRules.Add(new AppUserRule() + { + GroupId = request.UserGroupId, + MinorMenuIndex = userRule + }); + } + CommonTool.DbServe.Insertable(userRules).ExecuteCommand(); + }); + return result.Data; + } + catch (Exception e) + { + _ = e; + return false; + } + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppVehicleBindingDao.cs b/WcsMain/DataBase/Dao/AppVehicleBindingDao.cs new file mode 100644 index 0000000..2f74216 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppVehicleBindingDao.cs @@ -0,0 +1,93 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +[Component] +public class AppVehicleBindingDao +{ + + /// + /// 插入一条数据 + /// + /// + /// + public int Insert(AppVehicleBinding entity) + { + try + { + var sqlFuc = CommonTool.DbServe.Insertable(entity); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 查询所有 + /// + /// + public List? Query() => Query(new AppVehicleBinding()); + + /// + /// 查询数据 + /// + /// + /// + public List? Query(AppVehicleBinding queryEntity) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(queryEntity.VehicleNo), w => w.VehicleNo == queryEntity.VehicleNo) + .WhereIF(queryEntity.PlcId == default, w => w.PlcId == queryEntity.PlcId); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + + } + + + + + + /*------------------------------业务方法-----------------------------------------------*/ + + + /// + /// 根据载具号删除条目 + /// + /// + /// + public int DeleteWithVehicleNo(string vehicleNo) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable() + .Where(w => w.VehicleNo == vehicleNo); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + + + + + + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppWcsTaskDao.cs b/WcsMain/DataBase/Dao/AppWcsTaskDao.cs new file mode 100644 index 0000000..c37f0e4 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppWcsTaskDao.cs @@ -0,0 +1,451 @@ +using System.Text; +using WcsMain.ApiServe.Controllers.Dto.WcsDto.WcsTask; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.TaskEnum; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_app_wcs_task 表操作类 +/// +[Component] +public class AppWcsTaskDao +{ + + /// + /// 新增一条记录 + /// + /// + /// + public int Insert(params AppWcsTask[] appWcsTask) + { + try + { + return CommonTool.DbServe.Insertable(appWcsTask).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 更新一条记录,根据主键,主键PlcId + /// + /// + /// + public int Update(AppWcsTask appWcsTask) + { + try + { + var sqlFuc = CommonTool.DbServe.Updateable(appWcsTask).IgnoreColumns(ignoreAllNullColumns: true); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 删除一条记录,根据主键,主键PlcId + /// + /// + /// + public int Delete(AppWcsTask appWcsTask) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable(appWcsTask); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 查找数据 + /// + /// + /// + /// + /// 时间不在筛选行列 + /// + public List? Select(AppWcsTask appWcsTask) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(appWcsTask.PlcId != default, w => w.PlcId == appWcsTask.PlcId) + .WhereIF(appWcsTask.NextPlcId != default, w => w.NextPlcId == appWcsTask.NextPlcId) + .WhereIF(appWcsTask.TaskCategory != default, w => w.TaskCategory == appWcsTask.TaskCategory) + .WhereIF(appWcsTask.TaskId != default, w => w.TaskId == appWcsTask.TaskId) + .WhereIF(appWcsTask.TaskType != default, w => w.TaskType == appWcsTask.TaskType) + .WhereIF(appWcsTask.TaskSort != default, w => w.TaskSort == appWcsTask.TaskSort) + .WhereIF(appWcsTask.TaskStatus != default, w => w.TaskStatus == appWcsTask.TaskStatus) + .WhereIF(appWcsTask.Origin != default, w => w.Origin == appWcsTask.Origin) + .WhereIF(appWcsTask.Destination != default, w => w.Destination == appWcsTask.Destination) + .WhereIF(appWcsTask.PlcVehicleNo != default, w => w.PlcVehicleNo == appWcsTask.PlcVehicleNo) + .WhereIF(appWcsTask.VehicleNo != default, w => w.VehicleNo == appWcsTask.VehicleNo) + .WhereIF(appWcsTask.VehicleSize != default, w => w.VehicleSize == appWcsTask.VehicleSize) + .WhereIF(appWcsTask.Weight != default, w => w.Weight == appWcsTask.Weight) + .OrderByDescending(o => o.CreateTime).OrderBy(o => o.TaskSort); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查找所有数据 + /// + /// + public List? Select() => Select(new AppWcsTask()); + + + + + + /// + /// 根据 TaskId 删除任务 + /// + /// + /// + public int DeleteWithTaskId(string taskId) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable().Where(w => w.TaskId == taskId); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 带参数分页查询 + /// + /// + /// + public (List? wcsTasks, int totalRows) SelectPage(GetWcsTaskWithPageRequest pageRequest) + { + try + { + int totalRows = 0; + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(pageRequest.SearchStr), + w => w.Destination!.Contains(pageRequest.SearchStr!) + || w.PlcId.ToString()!.Contains(pageRequest.SearchStr!) + || w.Origin!.Contains(pageRequest.SearchStr!) + || w.VehicleNo!.Contains(pageRequest.SearchStr!) + || w.TaskId!.Contains(pageRequest.SearchStr!) + || w.Remark!.Contains(pageRequest.SearchStr!)); // 模糊查询 + if (pageRequest.TaskType != default) // 查询任务类型 + { + List taskTypes = []; + foreach (var taskType in pageRequest.TaskType) + { + if (taskType == "入库任务") { taskTypes.Add((int)TaskTypeEnum.inTask); } + if (taskType == "出库任务") { taskTypes.Add((int)TaskTypeEnum.outTask); } + if (taskType == "拣选任务") { taskTypes.Add((int)TaskTypeEnum.pick); } + if (taskType == "盘点任务") { taskTypes.Add((int)TaskTypeEnum.check); } + if (taskType == "移库任务") { taskTypes.Add((int)TaskTypeEnum.moveTask); } + } + sqlFuc.Where(w => taskTypes.Contains(w.TaskType)); + } + if (pageRequest.TaskStatus != default) // 查询任务状态 + { + List taskStatuss = []; + foreach (var taskStatus in pageRequest.TaskStatus) + { + if (taskStatus == "待执行") { taskStatuss.Add((int)WcsTaskStatusEnum.create); } + if (taskStatus == "离开起点") { taskStatuss.Add((int)WcsTaskStatusEnum.leaveOrigin); } + if (taskStatus == "执行中") { taskStatuss.Add((int)WcsTaskStatusEnum.running); } + if (taskStatus == "到达终点") { taskStatuss.Add((int)WcsTaskStatusEnum.arriveDestination); } + if (taskStatus == "执行完成") { taskStatuss.Add((int)WcsTaskStatusEnum.complete); } + if (taskStatus == "执行异常") { taskStatuss.Add((int)WcsTaskStatusEnum.err); } + } + sqlFuc.Where(w => taskStatuss.Contains(w.TaskStatus)); + } + if (pageRequest.TimeRange is { Count: 2 }) // 时间范围 + { + sqlFuc.Where(w => w.CreateTime > pageRequest.TimeRange[0] && w.CreateTime < pageRequest.TimeRange[1]); + } + sqlFuc.OrderByDescending(o => new { o.CreateTime }); + var queryResult = sqlFuc.ToPageList(pageRequest.Page!.PageIndex, pageRequest.Page!.PageSize, ref totalRows); + return (queryResult, totalRows); + } + catch (Exception ex) + { + _ = ex; + return default; + } + + } + + + + /******************************************************************** 业务方法 *********************************************/ + + /// + /// 保留多少天前数据 ---- 删除的是备份表 + /// + /// + /// + public int ClearData(int days) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable().AS("[tbl_app_wcs_task_bak]").Where(w => w.CreateTime < DateTime.Now.AddDays(-days)); + return sqlFuc.ExecuteCommand(); + + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + /// + /// 转换WMS任务到WCS任务 + /// + /// + /// + public string TransWmsTaskToWcsTask(params AppWcsTask[]? wcsTasks) + { + if (wcsTasks == default || wcsTasks.Length < 1) + { + return "传入的任务为空"; + } + var result = CommonTool.DbServe.Ado.UseTran(() => + { + CommonTool.DbServe.Insertable(wcsTasks).ExecuteCommand(); + foreach (var wcsTask in wcsTasks) + { + CommonTool.DbServe.Updateable(new AppWmsTask() + { TaskId = wcsTask.TaskId, TaskStatus = (int)WmsTaskStatusEnum.queuing }) + .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand(); + } + }); + return result.Data ? string.Empty : result.ErrorException.Message; + } + + /// + /// 查找各组 taskId 中最前的任务 + /// + /// + public List? GetNeedExecuteTasks() + { + try + { + const string sql = "SELECT * FROM tbl_app_wcs_task a WHERE task_sort = (SELECT MIN(task_sort) from tbl_app_wcs_task where a.task_id = task_id) and task_status = 0 ORDER BY create_time asc"; + List tasks = CommonTool.DbServe.Ado.SqlQuery(sql); + return tasks; + + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 校验除了这个任务以外,该组是否有其他任务 + /// + /// + /// + public List? CheckIsHaveOtherTask(AppWcsTask wcsTask) + { + try + { + List wcsTasks = CommonTool.DbServe.Queryable() + .Where(w => w.TaskId == wcsTask.TaskId && w.TaskSort != wcsTask.TaskSort).ToList(); + return wcsTasks; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 根据任务ID查询所有的wcs任务数据,包括备份表内的数据 + /// + /// /// + /// + public List? GetAllTasksWithBakData(string taskId) + { + try + { + string selectSql = $"select * from (select * from tbl_app_wcs_task union all select * from tbl_app_wcs_task_bak) as a where task_id = '{taskId}' order by create_time asc "; + List wcsTasks = CommonTool.DbServe.SqlQueryable(selectSql).ToList(); + return wcsTasks; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + /// + /// 根据 PlcId 查找任务数据,包括备份表 + /// + /// + /// + public List? GetAllTasksWithBakDataUsePlcId(int? plcId) + { + try + { + string selectSql = $"select * from (select * from tbl_app_wcs_task union all select * from tbl_app_wcs_task_bak) as a where plc_id = '{plcId}' order by create_time asc "; + List wcsTasks = CommonTool.DbServe.SqlQueryable(selectSql).ToList(); + return wcsTasks; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + + /// + /// 根据堆垛机编号查询该堆垛机下需要执行的入库任务 + /// + /// + /// + /// + public List? SelectInTaskWithStacker(int stackerId, string? vehicleNo = default) + { + try + { + StringBuilder sql = new(); + sql.AppendLine($"select * from tbl_app_wcs_task where origin in (select wcs_location from tbl_app_location where equipment_id = {stackerId}) and task_type = {(int)TaskTypeEnum.inTask} "); + sql.AppendLine($"and task_category = {(int)TaskCategoryEnum.stacker} "); + sql.AppendLine($"and task_status = {(int)WcsTaskStatusEnum.create} "); + if (!string.IsNullOrEmpty(vehicleNo)) + { + sql.AppendLine($"and vehicle_no = '{vehicleNo}' "); + } + sql.AppendLine("order by priority desc, wms_time asc "); + var sqlFuc = CommonTool.DbServe.Ado.SqlQuery(sql.ToString()); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 根据堆垛机编号查询该堆垛机下需要执行的出库任务 + /// + /// + /// + /// + public List? SelectOutTaskWithStacker(int stackerId, string? vehicleNo = default) + { + try + { + StringBuilder sql = new(); + sql.AppendLine($"select * from tbl_app_wcs_task where origin in (select wcs_location from tbl_app_location where equipment_id = {stackerId}) and task_type = {(int)TaskTypeEnum.outTask} "); + sql.AppendLine($"and task_category = {(int)TaskCategoryEnum.stacker} "); + sql.AppendLine($"and task_status = {(int)WcsTaskStatusEnum.create} "); + if (!string.IsNullOrEmpty(vehicleNo)) + { + sql.AppendLine($"and vehicle_no = '{vehicleNo}' "); + } + sql.AppendLine("order by priority desc, create_time asc "); + var sqlFuc = CommonTool.DbServe.Ado.SqlQuery(sql.ToString()); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + + /// + /// 根据堆垛机编号查询该堆垛机下需要执行的拣选出库任务 + /// + /// + /// + /// + public List? SelectPickOutTaskWithStacker(int stackerId, string? vehicleNo = "") + { + try + { + StringBuilder sql = new(); + sql.AppendLine($"select * from tbl_app_wcs_task where origin in (select wcs_location from tbl_app_location where equipment_id = {stackerId}) and task_type = {(int)TaskTypeEnum.pick} "); + sql.AppendLine($"and task_category = {(int)TaskCategoryEnum.stacker} "); + sql.AppendLine($"and task_status = {(int)WcsTaskStatusEnum.create} "); + if (!string.IsNullOrEmpty(vehicleNo)) + { + sql.AppendLine($"and vehicle_no = '{vehicleNo}' "); + } + sql.AppendLine("order by priority desc, create_time asc "); + var sqlFuc = CommonTool.DbServe.Ado.SqlQuery(sql.ToString()); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 根据堆垛机编号查询该堆垛机下需要执行的移库任务 + /// + /// + /// + /// + public List? SelectMoveTaskWithStacker(int stackerId, string? vehicleNo = "") + { + try + { + StringBuilder sql = new(); + sql.AppendLine($"select * from tbl_app_wcs_task where origin in (select wcs_location from tbl_app_location where equipment_id = {stackerId}) and task_type = {(int)TaskTypeEnum.moveTask} "); + sql.AppendLine($"and task_category = {(int)TaskCategoryEnum.stacker} "); + sql.AppendLine($"and task_status = {(int)WcsTaskStatusEnum.create} "); + if (!string.IsNullOrEmpty(vehicleNo)) + { + sql.AppendLine($"and vehicle_no = '{vehicleNo}' "); + } + sql.AppendLine("order by priority desc, create_time asc "); + var sqlFuc = CommonTool.DbServe.Ado.SqlQuery(sql.ToString()); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/AppWmsTaskDao.cs b/WcsMain/DataBase/Dao/AppWmsTaskDao.cs new file mode 100644 index 0000000..10ca691 --- /dev/null +++ b/WcsMain/DataBase/Dao/AppWmsTaskDao.cs @@ -0,0 +1,484 @@ +using WcsMain.ApiServe.Controllers.Dto.WcsDto.WmsTask; +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.TaskEnum; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_app_wms_task 表的增删改查 +/// +[Component] +public class AppWmsTaskDao +{ + /// + /// 添加记录 + /// 注意:尚未清楚是否为事务插入 + /// + /// + /// + public int Insert(params AppWmsTask[] appWmsTasks) + { + try + { + return CommonTool.DbServe.Insertable(appWmsTasks).ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + + /// + /// 更新数据,以主键为条件,主键 : TaskId + /// + /// + /// + public int Update(AppWmsTask appWmsTask) + { + try + { + var sqlFuc = CommonTool.DbServe.Updateable(appWmsTask).IgnoreColumns(ignoreAllNullColumns: true); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 删除数据,以主键为条件 + /// + /// + /// + public int Delete(AppWmsTask appWmsTask) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable(appWmsTask); + return sqlFuc.ExecuteCommand(); + } + catch (Exception ex) + { + _ = ex; + return 0; + } + } + + /// + /// 查找数据 + /// + /// + /// + /// + /// 时间不在筛选行列 + /// + public List? Select(AppWmsTask appWmsTask) + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(appWmsTask.TaskId), w => w.TaskId == appWmsTask.TaskId) + .WhereIF(appWmsTask.TaskType != null, w => w.TaskType == appWmsTask.TaskType) + .WhereIF(appWmsTask.TaskStatus != null, w => w.TaskStatus == appWmsTask.TaskStatus) + .WhereIF(!string.IsNullOrEmpty(appWmsTask.Origin), w => w.Origin == appWmsTask.Origin) + .WhereIF(!string.IsNullOrEmpty(appWmsTask.Destination), + w => w.Destination == appWmsTask.Destination) + .WhereIF(!string.IsNullOrEmpty(appWmsTask.VehicleNo), w => w.VehicleNo == appWmsTask.VehicleNo) + .WhereIF(appWmsTask.VehicleSize != null, w => w.VehicleSize == appWmsTask.VehicleSize) + .WhereIF(appWmsTask.Weight != null, w => w.Weight == appWmsTask.Weight) + .WhereIF(!string.IsNullOrEmpty(appWmsTask.CreatePerson), + w => w.CreatePerson == appWmsTask.CreatePerson) + .WhereIF(!string.IsNullOrEmpty(appWmsTask.TaskMsg), w => w.TaskMsg == appWmsTask.TaskMsg) + .OrderBy(o => o.CreateTime); + + _ = sqlFuc.ToSql(); + return sqlFuc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + /// + /// 查找所有数据 + /// + /// + public List? Select() => Select(new AppWmsTask()); + + + + + /********************************************************* 扩展方法 *****************************************************************/ + + /// + /// 保留多少条数据 + /// + /// + /// + public int ClearData(int days) + { + try + { + var sqlFuc = CommonTool.DbServe.Deleteable().Where(w => w.CreateTime < DateTime.Now.AddDays(-days)); + return sqlFuc.ExecuteCommand(); + + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + + /// + /// 查询数据返回前端 + /// 查询数据,按创建时间倒序排列 + /// + /// + public List? SelectToWeb() + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable().OrderByDescending(o => o.CreateTime); + return sqlFuc.ToList(); + + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查询任务数据返回前端,只查询未结束的任务 + /// 查询数据,按创建时间倒序排列 + /// + /// + public List? SelectWmsTaskNotEnd() + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable().Where(w => w.TaskStatus == (int)WmsTaskStatusEnum.queuing + || w.TaskStatus == (int)WmsTaskStatusEnum.create + || w.TaskStatus == (int)WmsTaskStatusEnum.running).OrderByDescending(o => o.CreateTime); + return sqlFuc.ToList(); + + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 查询自起点索引后的多少条数据 + /// + /// + /// + public (List? wmsTasks, int totalRows) SelectPage(GetWmsTaskWithPageRequest pageRequest) + { + try + { + int totalRows = 0; + var sqlFuc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(pageRequest.SearchStr), + w => w.Destination!.Contains(pageRequest.SearchStr!) + || w.Origin!.Contains(pageRequest.SearchStr!) + || w.VehicleNo!.Contains(pageRequest.SearchStr!) + || w.TaskId!.Contains(pageRequest.SearchStr!) + || w.TaskMsg!.Contains(pageRequest.SearchStr!)); // 模糊查询 + if (pageRequest.TaskType != default) // 查询任务类型 + { + List taskTypes = []; + pageRequest.TaskType.ForEach(item => taskTypes.Add(item)); + sqlFuc.Where(w => taskTypes.Contains(w.TaskType)); + } + if (pageRequest.TaskStatus != default) // 查询任务状态 + { + List taskStatuses = []; + pageRequest.TaskStatus.ForEach(item => taskStatuses.Add(item)); + sqlFuc.Where(w => taskStatuses.Contains(w.TaskStatus)); + } + if (pageRequest.TimeRange is { Count: 2 }) // 时间范围 + { + sqlFuc.Where(w => w.CreateTime > pageRequest.TimeRange[0] && w.CreateTime < pageRequest.TimeRange[1]); + } + sqlFuc.OrderByDescending(o => new { o.CreateTime }); + var queryResult = sqlFuc.ToPageList(pageRequest.Page!.PageIndex, pageRequest.Page!.PageSize, ref totalRows); + return (queryResult, totalRows); + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + + + /// + /// 查找未执行完成的任务 + /// + /// + public List? SelectNotComplete() + { + try + { + var sqlFuc = CommonTool.DbServe.Queryable() + .Where(w => w.TaskStatus != (int)WmsTaskStatusEnum.complete && w.TaskStatus != (int)WmsTaskStatusEnum.err) + .ToList(); + return sqlFuc; + } + catch (Exception ex) + { + _ = ex; + return default; + } + } + + /// + /// 重置任务状态 + /// + /// + /// + /// 重置信息 + /// + public string ResetTaskWithTaskId(string? taskId, string? newDestination, string resetMsg) + { + if (string.IsNullOrEmpty(taskId)) + { + return "任务号为空"; + } + /* + 需要执行的操作 + 1、重置WMS任务表状态 + 2、删除WCS任务表数据 + */ + var result = CommonTool.DbServe.Ado.UseTran(() => + { + // -- 更新wms任务状态 + if (string.IsNullOrEmpty(newDestination)) + { + CommonTool.DbServe.Updateable(new AppWmsTask() + { TaskId = taskId, TaskStatus = (int)WmsTaskStatusEnum.create }) + .UpdateColumns(u => new { u.TaskStatus }).WhereColumns(w => new { w.TaskId }) + .ExecuteCommand(); + } + else + { + CommonTool.DbServe.Updateable(new AppWmsTask() + { TaskId = taskId, TaskStatus = (int)WmsTaskStatusEnum.create, Destination = newDestination }) + .UpdateColumns(u => new { u.TaskStatus, u.Destination }).WhereColumns(w => new { w.TaskId }) + .ExecuteCommand(); + } + // -- 更新wcs任务表状态 + CommonTool.DbServe + .Updateable(new AppWcsTask() + { TaskId = taskId, TaskStatus = (int)WcsTaskStatusEnum.err, Remark = $"{resetMsg}{(string.IsNullOrEmpty(newDestination) ? "" : "新的目的地为:")}{newDestination}" }) + .UpdateColumns(u => new { u.TaskStatus, u.Remark }).WhereColumns(w => new { w.TaskId }) + .ExecuteCommand(); + // -- 备份wcs任务表 + CommonTool.DbServe.Ado.ExecuteCommand( + $"insert into tbl_app_wcs_task_bak select * from tbl_app_wcs_task where task_id = '{taskId}'"); + // -- 删除wcs任务表 + CommonTool.DbServe.Deleteable().Where(w => w.TaskId == taskId).ExecuteCommand(); + }); + return result.Data ? string.Empty : result.ErrorMessage; + } + + /// + /// 完成任务 + /// + /// + /// /// + /// + public string CompleteTaskWithTaskId(string? taskId, string completeText = "") + { + if (string.IsNullOrEmpty(taskId)) + { + return "任务号为空"; + } + /* + 需要执行的操作 + 1、完成WMS任务表状态 + 2、删除WCS任务表数据 + */ + var result = CommonTool.DbServe.Ado.UseTran(() => + { + // -- 更新wms任务状态 + CommonTool.DbServe + .Updateable(new AppWmsTask() + { TaskId = taskId, TaskStatus = (int)WmsTaskStatusEnum.complete, EndTime = DateTime.Now, TaskMsg = completeText }) + .IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + // -- 更新wcs任务表状态 + CommonTool.DbServe + .Updateable(new AppWcsTask() + { TaskId = taskId, TaskStatus = (int)WcsTaskStatusEnum.complete, Remark = completeText, CompleteTime = DateTime.Now }) + .UpdateColumns(u => new { u.TaskStatus, u.Remark, u.CompleteTime }).WhereColumns(w => new { w.TaskId }) + .ExecuteCommand(); + // -- 备份WCS任务表 + CommonTool.DbServe.Ado.ExecuteCommand( + $"insert into tbl_app_wcs_task_bak select * from tbl_app_wcs_task where task_id = '{taskId}'"); + // -- 删除WCS任务表 + CommonTool.DbServe.Deleteable().Where(w => w.TaskId == taskId).ExecuteCommand(); + }); + return result.Data ? string.Empty : result.ErrorMessage; + } + + /// + /// 完成任务 ---- 完成最后一个任务 + /// + /// + /// + /// + public string CompleteTaskWithTaskInfo(AppWcsTask wcsTaskUpdateEntity, AppWmsTask wmsTaskUpdateEntity) + { + /* + 需要执行的操作 + 1、完成WMS任务表状态 + 2、删除WCS任务表数据 + */ + var result = CommonTool.DbServe.Ado.UseTran(() => + { + // -- 更新wms任务状态 + CommonTool.DbServe + .Updateable(wmsTaskUpdateEntity) + .IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + // -- 更新wcs任务表状态 + CommonTool.DbServe + .Updateable(wcsTaskUpdateEntity) + .IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + // -- 备份WCS任务表 + CommonTool.DbServe.Ado.ExecuteCommand( + $"insert into tbl_app_wcs_task_bak select * from tbl_app_wcs_task where task_id = '{wmsTaskUpdateEntity.TaskId}'"); + // -- 删除WCS任务表 + CommonTool.DbServe.Deleteable().Where(w => w.TaskId == wmsTaskUpdateEntity.TaskId).ExecuteCommand(); + }); + return result.Data ? string.Empty : result.ErrorMessage; + } + + + /// + /// 删除任务 + /// + /// + /// 删除原因 + /// + public string DeleteTaskWithTaskId(string? taskId, string deleteMsg) + { + if (string.IsNullOrEmpty(taskId)) return "任务号为空"; + var result = CommonTool.DbServe.Ado.UseTran(() => + { + // -- 更新wms表状态 + CommonTool.DbServe.Updateable(new AppWmsTask() + { TaskId = taskId, TaskStatus = (int)WmsTaskStatusEnum.err, EndTime = DateTime.Now, TaskMsg = deleteMsg }) + .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand(); + // -- 更新wcs任务表状态 + CommonTool.DbServe + .Updateable(new AppWcsTask() + { TaskId = taskId, TaskStatus = (int)WcsTaskStatusEnum.err, Remark = deleteMsg }) + .UpdateColumns(u => new { u.TaskStatus, u.Remark }).WhereColumns(w => new { w.TaskId }) + .ExecuteCommand(); + // -- 备份WCS任务表 + CommonTool.DbServe.Ado.ExecuteCommand( + $"insert into tbl_app_wcs_task_bak select * from tbl_app_wcs_task where task_id = '{taskId}'"); + // -- 删除WCS任务表 + CommonTool.DbServe.Deleteable().Where(w => w.TaskId == taskId).ExecuteCommand(); + }); + return result.Data ? string.Empty : result.ErrorMessage; + } + + /// + /// 取消任务 + /// + /// + /// /// + /// + public string CancelTaskWithTaskId(string? taskId, string cancelPerson) + { + if (string.IsNullOrEmpty(taskId)) return "任务号为空"; + var result = CommonTool.DbServe.Ado.UseTran(() => + { + // -- 更新wms表状态 + CommonTool.DbServe.Updateable(new AppWmsTask() + { TaskId = taskId, TaskStatus = (int)WmsTaskStatusEnum.err, EndTime = DateTime.Now, TaskMsg = $"【{cancelPerson}】取消任务" }) + .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand(); + // -- 更新wcs任务表状态 + CommonTool.DbServe + .Updateable(new AppWcsTask() + { TaskId = taskId, TaskStatus = (int)WcsTaskStatusEnum.err, Remark = $"【{cancelPerson}】取消任务", CompleteTime = DateTime.Now }) + .UpdateColumns(u => new { u.TaskStatus, u.Remark, u.CompleteTime }).WhereColumns(w => new { w.TaskId }) + .ExecuteCommand(); + // -- 备份WCS任务表 + CommonTool.DbServe.Ado.ExecuteCommand( + $"insert into tbl_app_wcs_task_bak select * from tbl_app_wcs_task where task_id = '{taskId}'"); + // -- 删除WCS任务表 + CommonTool.DbServe.Deleteable().Where(w => w.TaskId == taskId).ExecuteCommand(); + }); + return result.Data ? string.Empty : result.ErrorMessage; + } + + /// + /// 添加记录 + /// 注意:尚未清楚是否为事务插入 + /// + /// + /// + public int InsertTaskAndMarkErr(params AppWmsTask[] appWmsTasks) + { + if (appWmsTasks.Length < 1) return 0; + try + { + int count = 0; + Action action = () => { }; + foreach (var wmsTask in appWmsTasks) + { + action += () => + { + // -- 更新wms表状态 + CommonTool.DbServe.Updateable(new AppWmsTask() + { TaskStatus = (int)WmsTaskStatusEnum.err, EndTime = DateTime.Now, TaskMsg = $"由于收到新任务,该任务被取消,操作人:{wmsTask.CreatePerson}" }) + .UpdateColumns(u => new { u.TaskStatus, u.TaskMsg, u.EndTime }) + .Where(w => w.VehicleNo == wmsTask.VehicleNo && (w.TaskStatus == (int)WmsTaskStatusEnum.queuing || w.TaskStatus == (int)WmsTaskStatusEnum.create)) + .ExecuteCommand(); + // -- 更新wcs任务表状态 + CommonTool.DbServe.Updateable(new AppWcsTask() + { TaskStatus = (int)WcsTaskStatusEnum.err, CompleteTime = DateTime.Now, Remark = $"由于收到新任务,该任务被取消,操作人:{wmsTask.CreatePerson}" }) + .UpdateColumns(u => new { u.TaskStatus, u.Remark, u.CompleteTime }) + .Where(w => w.VehicleNo == wmsTask.VehicleNo && w.TaskStatus == (int)WcsTaskStatusEnum.create) + .ExecuteCommand(); + // -- 备份WCS任务表 + CommonTool.DbServe.Ado.ExecuteCommand( + $"insert into tbl_app_wcs_task_bak select * from tbl_app_wcs_task where vehicle_no = '{wmsTask.VehicleNo}' and task_type = {wmsTask.TaskType}"); + // -- 删除WCS任务表 + CommonTool.DbServe.Deleteable() + .Where(w => w.VehicleNo == wmsTask.VehicleNo && w.TaskType == wmsTask.TaskType). + ExecuteCommand(); + // -- 插入WMS任务 + CommonTool.DbServe.Insertable(wmsTask).ExecuteCommand(); + }; + count++; + } + var result = CommonTool.DbServe.Ado.UseTran(action); + if (result.IsSuccess) return count; + } + catch (Exception ex) { _ = ex; } + return 0; + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/Dao/BsPickStandDao.cs b/WcsMain/DataBase/Dao/BsPickStandDao.cs new file mode 100644 index 0000000..3fc2de3 --- /dev/null +++ b/WcsMain/DataBase/Dao/BsPickStandDao.cs @@ -0,0 +1,50 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.Dao; + +/// +/// tbl_bs_pick_stand 的操作类 +/// +[Component] +public class BsPickStandDao +{ + + /// + /// 查询所有数据 + /// + /// + public List? Query() => Query(new BsPickStand()); + + /// + /// 根据条件查询数据 + /// + /// + /// + public List? Query(BsPickStand queryEntity) + { + try + { + var sqlFUc = CommonTool.DbServe.Queryable() + .WhereIF(!string.IsNullOrEmpty(queryEntity.PickStand), w => w.PickStand == queryEntity.PickStand) + .WhereIF(queryEntity.StandType != default, w => w.StandType == queryEntity.StandType) + .WhereIF(queryEntity.StandStatus != default, w => w.StandStatus == queryEntity.StandStatus) + .OrderBy(o => o.PickStand); + return sqlFUc.ToList(); + } + catch (Exception ex) + { + _ = ex; + return default; + } + + + + + + } + + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/MixDao/TaskDao.cs b/WcsMain/DataBase/MixDao/TaskDao.cs new file mode 100644 index 0000000..72e4309 --- /dev/null +++ b/WcsMain/DataBase/MixDao/TaskDao.cs @@ -0,0 +1,173 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.TaskEnum; +using WcsMain.ExtendMethod; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataBase.MixDao; + +/* + * 任务表的混合操作类,一般用在此处的都是同时需要操作多个表的 + */ + +/// +/// 任务表的混合操作类 +/// +[Component] +public class TaskDao +{ + /// + /// wcs任务开始 + /// + /// + /// + /// + /// 将该任务状态更新为启动,若该任务是第一个任务,把对应的WMS任务更新为启动 + /// + public string StartTask(AppWcsTask wcsTask) + { + DateTime dateTime = DateTime.Now; + var result = CommonTool.DbServe.Ado.UseTran(() => + { + /* 更新WCS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWcsTask + { + PlcId = wcsTask.PlcId, + TaskStatus = (int)WcsTaskStatusEnum.running, + StartTime = dateTime + }).IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + if(wcsTask.IsFirstTask()) + { + /* 更新WMS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWmsTask + { + TaskId = wcsTask.TaskId, + TaskStatus = (int)WmsTaskStatusEnum.running, + StartTime = dateTime + }).IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + } + }); + return result.Data ? string.Empty : result.ErrorException.Message; + } + + /// + /// 任务异常,取消全部后续任务和该任务号的Wms任务 + /// + /// + /// + /// + public string TaskErrAndCancelOtherTask(AppWcsTask wcsTask, string errMsg) + { + DateTime dateTime = DateTime.Now; + var result = CommonTool.DbServe.Ado.UseTran(() => + { + /* 更新WCS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWcsTask + { + TaskStatus = (int)WcsTaskStatusEnum.err, + CompleteTime = dateTime, + Remark = errMsg + }) + .UpdateColumns(u => new { u.TaskStatus, u.CompleteTime, u.Remark }) + .Where(w => w.TaskSort >= wcsTask.TaskSort && w.TaskId == wcsTask.TaskId) + .ExecuteCommand(); + if (wcsTask.IsFirstTask()) + { + /* 更新WMS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWmsTask + { + TaskId = wcsTask.TaskId, + TaskStatus = (int)WmsTaskStatusEnum.err, + EndTime = dateTime, + TaskMsg = errMsg + }) + .IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + } + }); + return result.Data ? string.Empty : result.ErrorException.Message; + } + + /// + /// 任务异常,只异常当前任务 + /// + /// + /// + /// + public string TaskErr(AppWcsTask wcsTask, string errMsg) + { + DateTime dateTime = DateTime.Now; + var result = CommonTool.DbServe.Ado.UseTran(() => + { + /* 更新WCS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWcsTask + { + TaskStatus = (int)WcsTaskStatusEnum.err, + CompleteTime = dateTime, + Remark = errMsg + }) + .UpdateColumns(u => new { u.TaskStatus, u.CompleteTime, u.Remark }) + .Where(w => w.PlcId == wcsTask.PlcId) + .ExecuteCommand(); + if (wcsTask.IsFirstTask()) + { + /* 更新WMS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWmsTask + { + TaskId = wcsTask.TaskId, + TaskStatus = (int)WmsTaskStatusEnum.err, + EndTime = dateTime, + TaskMsg = errMsg + }) + .IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + } + }); + return result.Data ? string.Empty : result.ErrorException.Message; + } + + /// + /// WCS任务完成 + /// + /// + /// + /// + /// + /// 若完成的是最后一个任务,则完成WMS任务 + /// + public string ComlpeteTask(AppWcsTask wcsTask, string msg) + { + DateTime dateTime = DateTime.Now; + var result = CommonTool.DbServe.Ado.UseTran(() => + { + /* 更新WCS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWcsTask + { + TaskStatus = (int)WcsTaskStatusEnum.complete, + CompleteTime = dateTime, + Remark = msg + }) + .UpdateColumns(u => new { u.TaskStatus, u.CompleteTime, u.Remark }) + .Where(w => w.TaskSort >= wcsTask.TaskSort && w.TaskId == wcsTask.TaskId) + .ExecuteCommand(); + if (wcsTask.IsLastTask()) + { + /* 更新WMS任务表状态 */ + CommonTool.DbServe.Updateable(new AppWmsTask + { + TaskId = wcsTask.TaskId, + TaskStatus = (int)WmsTaskStatusEnum.complete, + EndTime = dateTime, + TaskMsg = msg + }) + .IgnoreColumns(ignoreAllNullColumns: true) + .ExecuteCommand(); + } + }); + return result.Data ? string.Empty : result.ErrorException.Message; + } + + +} diff --git a/WcsMain/DataBase/TableEntity/AppApiAccept.cs b/WcsMain/DataBase/TableEntity/AppApiAccept.cs new file mode 100644 index 0000000..73f66c0 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppApiAccept.cs @@ -0,0 +1,111 @@ +using System.Text; +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 接口接收记录表 +/// +[SugarTable("tbl_app_api_accept")] +public class AppApiAccept +{ + /// + /// 请求编号 + /// + [SugarColumn(ColumnName = "accept_id", IsPrimaryKey = true)] + [JsonPropertyName("acceptId")] + public string? AcceptId { get; set; } + + /// + /// 请求路径 + /// + [SugarColumn(ColumnName = "path")] + [JsonPropertyName("path")] + public string? Path { get; set; } + + /// + /// 请求方法 + /// + [SugarColumn(ColumnName = "method")] + [JsonPropertyName("method")] + public string? Method { get; set; } + + /// + /// 请求的数据类型 + /// + [SugarColumn(ColumnName = "media_type")] + [JsonPropertyName("mediaType")] + public string? MediaType { get; set; } + + /// + /// 客户端地址 + /// + [SugarColumn(ColumnName = "client_address")] + [JsonPropertyName("clientAddress")] + public string? ClientAddress { get; set; } + + /// + /// 请求时间 + /// + [SugarColumn(ColumnName = "request_time")] + [JsonPropertyName("requestTime")] + public DateTime? RequestTime { get; set; } + + /// + /// 响应时间 + /// + [SugarColumn(ColumnName = "response_time")] + [JsonPropertyName("responseTime")] + public DateTime? ResponseTime { get; set; } + + /// + /// 接口耗时 + /// + [SugarColumn(ColumnName = "use_time")] + [JsonPropertyName("useTime")] + public double? UseTime { get; set; } + + /// + /// 请求数据 + /// + [SugarColumn(ColumnName = "request_msg")] + [JsonPropertyName("requestMsg")] + public string? RequestMsg { get; set; } + + /// + /// 响应数据 + /// + [SugarColumn(ColumnName = "response_msg")] + [JsonPropertyName("responseMsg")] + public string? ResponseMsg { get; set; } + + /// + /// 异常信息 + /// + [SugarColumn(ColumnName = "err_msg")] + [JsonPropertyName("errMsg")] + public string? ErrMsg { get; set; } + + + + + public override string ToString() + { + StringBuilder builder = new(); + builder.Append($"[请求路径]{Path}"); + builder.Append($"[请求方式]{Method}"); + builder.Append($"[请求格式]{MediaType}"); + builder.Append($"[用户地址]{ClientAddress}"); + builder.Append($"[请求时间]{RequestTime}"); + builder.Append($"[响应时间]{ResponseTime}"); + builder.Append($"[接口耗时]{UseTime}"); + builder.Append($"[请求数据]{RequestTime}"); + builder.Append($"[响应数据]{ResponseMsg}"); + if (!string.IsNullOrEmpty(ErrMsg)) + { + builder.Append($"[异常信息]{ErrMsg}"); + } + return builder.ToString(); + } +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppApiRequest.cs b/WcsMain/DataBase/TableEntity/AppApiRequest.cs new file mode 100644 index 0000000..519f2e0 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppApiRequest.cs @@ -0,0 +1,84 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 接口请求类,存放请求的信息 +/// +[SugarTable("tbl_app_api_request")] +public class AppApiRequest +{ + /// + /// 请求ID + /// + [SugarColumn(ColumnName = "request_id", IsPrimaryKey = true)] + [JsonPropertyName("requestId")] + public string? RequestId { get; set; } + + /// + /// 请求地址 + /// + [SugarColumn(ColumnName = "request_url")] + [JsonPropertyName("requestUrl")] + public string? RequestUrl { get; set; } + + /// + /// 是否成功 + /// + [SugarColumn(ColumnName = "is_success")] + [JsonPropertyName("isSuccess")] + public int? IsSuccess { get; set; } + + /// + /// 请求方式 + /// + [SugarColumn(ColumnName = "request_method")] + [JsonPropertyName("requestMethod")] + public string? RequestMethod { get; set; } + + + /// + /// 请求信息 + /// + [SugarColumn(ColumnName = "request_msg")] + [JsonPropertyName("requestMsg")] + public string? RequestMsg { get; set; } + + /// + /// 响应信息 + /// + [SugarColumn(ColumnName = "response_msg")] + [JsonPropertyName("responseMsg")] + public string? ResponseMsg { get; set; } + + /// + /// 请求时间 + /// + [SugarColumn(ColumnName = "request_time")] + [JsonPropertyName("requestTime")] + public DateTime? RequestTime { get; set; } + + /// + /// 响应时间 + /// + [SugarColumn(ColumnName = "response_time")] + [JsonPropertyName("responseTime")] + public DateTime? ResponseTime { get; set; } + + /// + /// 耗时 + /// + [SugarColumn(ColumnName = "use_time")] + [JsonPropertyName("useTime")] + public double? UseTime { get; set; } + + /// + /// 错误信息 + /// + [SugarColumn(ColumnName = "err_msg")] + [JsonPropertyName("errMsg")] + public string? ErrMsg { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppConfig.cs b/WcsMain/DataBase/TableEntity/AppConfig.cs new file mode 100644 index 0000000..267130e --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppConfig.cs @@ -0,0 +1,49 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// t_app_config 的实体 +/// +[SugarTable("tbl_app_config")] +public class AppConfig +{ + /// + /// 配置键 + /// + [SugarColumn(ColumnName = "config_key", IsPrimaryKey = true)] + [JsonPropertyName("configKey")] + public string? ConfigKey { get; set; } + + /// + /// 配置名称 + /// + [SugarColumn(ColumnName = "config_name")] + [JsonPropertyName("configName")] + public string? ConfigName { get; set; } + + /// + /// 配置类型 + /// + [SugarColumn(ColumnName = "config_type")] + [JsonPropertyName("configType")] + public string? ConfigType { get; set; } + + /// + /// 配置值 + /// + [SugarColumn(ColumnName = "config_value")] + [JsonPropertyName("configValue")] + public string? ConfigValue { get; set; } + + /// + /// 配置备注 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppDB.cs b/WcsMain/DataBase/TableEntity/AppDB.cs new file mode 100644 index 0000000..fa311b5 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppDB.cs @@ -0,0 +1,51 @@ +using System.Text.Json.Serialization; +using PlcTool.Siemens.PLCAttribute; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// DB地址实体类 tbl_app_db +/// +[SugarTable("tbl_app_db")] +public class AppDB +{ + /// + /// PLC编号 + /// + [SugarColumn(ColumnName = "plc_id")] + [PlcId] + [JsonPropertyName("plcId")] + public int? PlcId { get; set; } + /// + /// 地址名称 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "db_name")] + [PlcDBName] + [JsonPropertyName("dbName")] + public string? DBName { get; set; } + + /// + /// 地址值 + /// + [SugarColumn(ColumnName = "db_address")] + [PlcDBAddress] + [JsonPropertyName("dbAddress")] + public string? DBAddress { get; set; } + + /// + /// 是否系统值 + /// + [SugarColumn(ColumnName = "is_system")] + [JsonPropertyName("isSystem")] + public int? IsSystem { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppLocation.cs b/WcsMain/DataBase/TableEntity/AppLocation.cs new file mode 100644 index 0000000..fd1c75b --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppLocation.cs @@ -0,0 +1,148 @@ +using System.Text.Json.Serialization; +using SqlSugar; +using WcsMain.Enum.Location; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// tbl_app_location +/// 点位信息表 +/// +[SugarTable("tbl_app_location")] +public class AppLocation +{ + /// + /// Wcs点位 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "wcs_location")] + [JsonPropertyName("wcsLocation")] + public string? WcsLocation { get; set; } + + /// + /// Wms点位,该列主要用于映射 + /// + [SugarColumn(ColumnName = "wms_location")] + [JsonPropertyName("wmsLocation")] + public string? WmsLocation { get; set; } + + /// + /// 巷道编号 + /// + [SugarColumn(ColumnName = "tunnel_no")] + [JsonPropertyName("tunnelNo")] + public int? TunnelNo { get; set; } + + /// + /// 设备编号 + /// + [SugarColumn(ColumnName = "equipment_id")] + [JsonPropertyName("equipmentId")] + public int? EquipmentId { get; set; } + + /// + /// 点位状态 + /// + [SugarColumn(ColumnName = "location_status")] + [JsonPropertyName("locationStatus")] + public int? LocationStatus { get; set; } + + /// + /// 排 + /// + [SugarColumn(ColumnName = "queue")] + [JsonPropertyName("queue")] + public int? Queue { get; set; } + + /// + /// 列 + /// + [SugarColumn(ColumnName = "line")] + [JsonPropertyName("line")] + public int? Line { get; set; } + + /// + /// 层 + /// + [SugarColumn(ColumnName = "layer")] + [JsonPropertyName("layer")] + public int? Layer { get; set; } + + /// + /// 深 + /// + [SugarColumn(ColumnName = "depth")] + [JsonPropertyName("depth")] + public int? Depth { get; set; } + + /// + /// 点位类型 + /// + [SugarColumn(ColumnName = "location_type")] + [JsonPropertyName("locationType")] + public int? LocationType { get; set; } + + /// + /// 载具编号 + /// + [SugarColumn(ColumnName = "vehicle_no")] + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 修改时间 + /// + [SugarColumn(ColumnName = "modify_time")] + [JsonPropertyName("modifyTime")] + public DateTime? ModifyTime { get; set; } + + /// + /// 说明信息 + /// + [SugarColumn(ColumnName = "explain")] + [JsonPropertyName("explain")] + public string? Explain { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + + + + /// + /// 创建一个正在使用的信息实例 + /// + /// + /// + /// + public static AppLocation CreateUsedInstance(string? wcsLocation, string? vehicleNo) + { + return new AppLocation() + { + WcsLocation = wcsLocation, + VehicleNo = vehicleNo, + ModifyTime = DateTime.Now, + LocationStatus = (int)LocationStatusEnum.used + }; + } + + /// + /// 创建一个空货位的实例 + /// + /// + /// + public static AppLocation CreateEmptyInstance(string? wcsLocation) + { + return new AppLocation() + { + WcsLocation = wcsLocation, + VehicleNo = "", + ModifyTime = DateTime.Now, + LocationStatus = (int)LocationStatusEnum.empty + }; + } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppMenu.cs b/WcsMain/DataBase/TableEntity/AppMenu.cs new file mode 100644 index 0000000..7baa86b --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppMenu.cs @@ -0,0 +1,75 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 菜单表 +/// +[SugarTable("tbl_app_menu")] +public class AppMenu +{ + /// + /// 主菜单序号 + /// + [SugarColumn(ColumnName = "main_menu_index")] + [JsonPropertyName("mainMenuIndex")] + public string? MainMenuIndex { get; set; } + + /// + /// 主菜单名称 + /// + [SugarColumn(ColumnName = "main_menu_name")] + [JsonPropertyName("mainMenuName")] + public string? MainMenuName { get; set; } + + /// + /// 主菜单图标 + /// + [SugarColumn(ColumnName = "main_menu_ico")] + [JsonPropertyName("mainMenuIco")] + public string? MainMenuIco { get; set; } + + /// + /// 次菜单序号 + /// + [SugarColumn(ColumnName = "minor_menu_index", IsPrimaryKey = true)] + [JsonPropertyName("minorMenuIndex")] + public string? MinorMenuIndex { get; set; } + + /// + /// 次菜单名称 + /// + [SugarColumn(ColumnName = "minor_menu_name")] + [JsonPropertyName("minorMenuName")] + public string? MinorMenuName { get; set; } + + /// + /// 次菜单图标 + /// + [SugarColumn(ColumnName = "minor_menu_ico")] + [JsonPropertyName("minorMenuIco")] + public string? MinorMenuIco { get; set; } + + /// + /// 次菜单路由 + /// + [SugarColumn(ColumnName = "minor_menu_router")] + [JsonPropertyName("minorMenuRouter")] + public string? MinorMenuRouter { get; set; } + + /// + /// 菜单状态 ---- 1 表示可以使用 + /// + [SugarColumn(ColumnName = "menu_status")] + [JsonPropertyName("menuStatus")] + public int? MenuStatus { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppPLC.cs b/WcsMain/DataBase/TableEntity/AppPLC.cs new file mode 100644 index 0000000..1ca7232 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppPLC.cs @@ -0,0 +1,69 @@ +using System.Text.Json.Serialization; +using PlcTool.Siemens.PLCAttribute; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// t_app_plc 表的实体类 +/// +[SugarTable("tbl_app_plc")] +public class AppPLC +{ + /// + /// PLC 编号 + /// + [SugarColumn(ColumnName = "plc_id", IsPrimaryKey = true)] + [PlcId] + [JsonPropertyName("plcId")] + public int? PLCId { get; set; } + + /// + /// PLC IP 地址 + /// + [SugarColumn(ColumnName = "plc_ip")] + [PlcIP] + [JsonPropertyName("plcIp")] + public string? PLCIp { get; set; } + + /// + /// PLC 系列 + /// + [SugarColumn(ColumnName = "plc_kind")] + [PlcKind] + [JsonPropertyName("plcKind")] + public string? PLCKind { get; set; } + + /// + /// PLC 插槽 + /// + [SugarColumn(ColumnName = "rack")] + [Rack] + [JsonPropertyName("rack")] + public int? PLCRack { get; set; } + + /// + /// PLC 机架 + /// + [SugarColumn(ColumnName = "slot")] + [Slot] + [JsonPropertyName("slot")] + public int? PLCSlot { get; set; } + + /// + /// PLC 状态,是否启用 + /// + [SugarColumn(ColumnName = "plc_status")] + [JsonPropertyName("plcStatus")] + public int? PLCStatus { get; set; } + + /// + /// 备注信息 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppRouterMethod.cs b/WcsMain/DataBase/TableEntity/AppRouterMethod.cs new file mode 100644 index 0000000..7b2cc2e --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppRouterMethod.cs @@ -0,0 +1,31 @@ +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// tbl_app_router_method +/// +[SugarTable("tbl_app_router_method")] +public class AppRouterMethod +{ + /// + /// 请求点 + /// + [SugarColumn(ColumnName = "area")] + public string? Area { get; set; } + + /// + /// 调用的类 + /// + [SugarColumn(ColumnName = "class_name")] + public string? ClassName { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + public string? Remark { get; set; } + + + +} diff --git a/WcsMain/DataBase/TableEntity/AppSettings.cs b/WcsMain/DataBase/TableEntity/AppSettings.cs new file mode 100644 index 0000000..6a70a61 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppSettings.cs @@ -0,0 +1,49 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 设置表实体类,tbl_app_settings +/// +[SugarTable("tbl_app_settings")] +public class AppSettings +{ + /// + /// 主键名称 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "setting_key")] + [JsonPropertyName("settingKey")] + public string? SettingKey { get; set; } + + /// + /// 名称 + /// + [SugarColumn(ColumnName = "setting_name")] + [JsonPropertyName("settingName")] + public string? SettingName { get; set; } + + /// + /// 值 + /// + [SugarColumn(ColumnName = "setting_value")] + [JsonPropertyName("settingValue")] + public string? SettingValue { get; set; } + + /// + /// 是否系统数据 + /// + [SugarColumn(ColumnName = "setting_type")] + [JsonPropertyName("settingType")] + public string? SettingType { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppStacker.cs b/WcsMain/DataBase/TableEntity/AppStacker.cs new file mode 100644 index 0000000..4527e96 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppStacker.cs @@ -0,0 +1,64 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 设备表 +/// +[SugarTable("tbl_app_stacker")] +public class AppStacker +{ + /// + /// 设备编号 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "stacker_id")] + [JsonPropertyName("stackerId")] + public int? StackerId { get; set; } + + /// + /// 堆垛机名称 + /// + [SugarColumn(ColumnName = "stacker_name")] + [JsonPropertyName("stackerName")] + public string? StackerName { get; set; } + + /// + /// 堆垛机状态 + /// + /// + /// 0 - 禁用 + /// 1 - 启用 + /// + [SugarColumn(ColumnName = "stacker_status")] + [JsonPropertyName("stackerStatus")] + public int? StackerStatus { get; set; } + + /// + /// 控制该堆垛机的PLC + /// + [SugarColumn(ColumnName = "action_plc")] + [JsonPropertyName("actionPlc")] + public int? ActionPlc { get; set; } + + /// + /// 入库站台,格式 : 101-102-103 + /// + [SugarColumn(ColumnName = "in_stand")] + [JsonPropertyName("inStand")] + public string? InStand { get; set; } + + /// + /// 出库站台,格式 : 101-102-103 + /// + [SugarColumn(ColumnName = "out_stand")] + [JsonPropertyName("outStand")] + public string? OutStand { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppTcp.cs b/WcsMain/DataBase/TableEntity/AppTcp.cs new file mode 100644 index 0000000..e2ca33b --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppTcp.cs @@ -0,0 +1,62 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// tbl_app_tcp +/// +[SugarTable("tbl_app_tcp")] +public class AppTcp +{ + /// + /// tcp 编号 + /// + [SugarColumn(ColumnName = "tcp_id", IsPrimaryKey = true)] + [JsonPropertyName("tcpId")] + public int? TcpId { get; set; } + + /// + /// tcp 地址 + /// + [SugarColumn(ColumnName = "tcp_ip")] + [JsonPropertyName("tcpIp")] + public string? TcpIp { get; set; } + + /// + /// tcp端口 + /// + [SugarColumn(ColumnName = "tcp_port")] + [JsonPropertyName("tcpPort")] + public int? TcpPort { get; set; } + + /// + /// tcp类型 + /// + [SugarColumn(ColumnName = "tcp_type")] + [JsonPropertyName("tcptype")] + public int? TcpType { get; set; } + + /// + /// tcp 状态 + /// + [SugarColumn(ColumnName = "tcp_status")] + [JsonPropertyName("tcpStatus")] + public int? TcpStatus { get; set; } + + /// + /// tcp 别称,不能重复 + /// + [SugarColumn(ColumnName = "display_name")] + [JsonPropertyName("displayName")] + public string? DisplayName { get; set; } + + + /// + /// 备注信息 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppUser.cs b/WcsMain/DataBase/TableEntity/AppUser.cs new file mode 100644 index 0000000..49b186e --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppUser.cs @@ -0,0 +1,60 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 用户表 +/// +[SugarTable("tbl_app_user")] +public class AppUser +{ + /// + /// 用户ID + /// + [SugarColumn(ColumnName = "user_id")] + [JsonPropertyName("userId")] + public string? UserId { get; set; } + + /// + /// 用户名称 + /// + [SugarColumn(ColumnName = "user_name")] + [JsonPropertyName("userName")] + public string? UserName { get; set; } + + /// + /// 用户密码 + /// + [SugarColumn(ColumnName = "user_password")] + [JsonPropertyName("userPassword")] + public string? UserPassword { get; set; } + + /// + /// 用户状态 + /// + [SugarColumn(ColumnName = "user_status")] + [JsonPropertyName("userStatus")] + public int? UserStatus { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "create_time")] + [JsonPropertyName("createTime")] + public DateTime? CreateTime { get; set; } + + /// + /// 修改时间 + /// + [SugarColumn(ColumnName = "modify_time")] + [JsonPropertyName("modifyTime")] + public DateTime? ModifyTime { get; set; } + + /// + /// 用户组 + /// + [SugarColumn(ColumnName = "user_group")] + [JsonPropertyName("userGroup")] + public string? UserGroup { get; set; } +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppUserGroup.cs b/WcsMain/DataBase/TableEntity/AppUserGroup.cs new file mode 100644 index 0000000..3de6ce8 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppUserGroup.cs @@ -0,0 +1,30 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +[SugarTable("tbl_app_user_group")] +public class AppUserGroup +{ + /// + /// 用户组ID + /// + [SugarColumn(ColumnName = "group_id", IsPrimaryKey = true)] + [JsonPropertyName("groupId")] + public string? GroupId { get; set; } + + /// + /// 用户组名称 + /// + [SugarColumn(ColumnName = "group_name")] + [JsonPropertyName("groupName")] + public string? GroupName { get; set; } + + /// + /// 用户组状态 + /// + [SugarColumn(ColumnName = "group_status")] + [JsonPropertyName("groupStatus")] + public int? GroupStatus { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppUserRule.cs b/WcsMain/DataBase/TableEntity/AppUserRule.cs new file mode 100644 index 0000000..72d3aa1 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppUserRule.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +[SugarTable("tbl_app_user_rule")] +public class AppUserRule +{ + /// + /// 用户组 + /// + [SugarColumn(ColumnName = "group_id", IsPrimaryKey = true)] + [JsonPropertyName("groupId")] + public string? GroupId { get; set; } + + /// + /// 二级菜单权限 + /// + [SugarColumn(ColumnName = "minor_menu_index")] + [JsonPropertyName("minorMenuIndex")] + public string? MinorMenuIndex { get; set; } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppVehicleBinding.cs b/WcsMain/DataBase/TableEntity/AppVehicleBinding.cs new file mode 100644 index 0000000..e244d3f --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppVehicleBinding.cs @@ -0,0 +1,30 @@ +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 载具信息和 plcid 绑定 +/// +[SugarTable("tbl_app_vehicle_binding")] +public class AppVehicleBinding +{ + /// + /// plcId + /// + [SugarColumn(ColumnName = "plc_id")] + public int? PlcId { get; set; } + + /// + /// 载具号 + /// + [SugarColumn(ColumnName = "vehicle_no")] + public string? VehicleNo { get; set; } + + /// + /// 绑定时间 + /// + [SugarColumn(ColumnName = "binding_time")] + public DateTime? BindingTime { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppWcsTask.cs b/WcsMain/DataBase/TableEntity/AppWcsTask.cs new file mode 100644 index 0000000..8285659 --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppWcsTask.cs @@ -0,0 +1,167 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// tbl_app_wcs_task +/// Wcs任务表 +/// +[SugarTable("tbl_app_wcs_task")] +public class AppWcsTask +{ + + /// + /// Plc任务号 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "plc_id")] + [JsonPropertyName("plcId")] + public int? PlcId { get; set; } + + /// + /// 下一个任务号,若没有下一个任务则此处是默认值 + /// + [SugarColumn(ColumnName = "next_plc_id")] + [JsonPropertyName("nextPlcId")] + public int? NextPlcId { get; set; } + + /// + /// 任务号 + /// + [SugarColumn(ColumnName = "task_id")] + [JsonPropertyName("taskId")] + public string? TaskId { get; set; } + + + /// + /// 任务类别 + /// + [SugarColumn(ColumnName = "task_category")] + [JsonPropertyName("taskCategory")] + public int? TaskCategory { get; set; } + + + /// + /// 任务类型 + /// + [SugarColumn(ColumnName = "task_type")] + [JsonPropertyName("taskType")] + public int? TaskType { get; set; } + + /// + /// 任务排序 + /// 999表示最后一个任务 + /// + [SugarColumn(ColumnName = "task_sort")] + [JsonPropertyName("taskSort")] + public int? TaskSort { get; set; } + + /// + /// 任务状态 + /// + [SugarColumn(ColumnName = "task_status")] + [JsonPropertyName("taskStatus")] + public int? TaskStatus { get; set; } + + /// + /// 任务优先级 + /// + [SugarColumn(ColumnName = "priority")] + [JsonPropertyName("priority")] + public int? Priority { get; set; } + + /// + /// 任务起点 + /// + [SugarColumn(ColumnName = "origin")] + [JsonPropertyName("origin")] + public string? Origin { get; set; } + + /// + /// 任务终点 + /// + [SugarColumn(ColumnName = "destination")] + [JsonPropertyName("destination")] + public string? Destination { get; set; } + + + /// + /// Wms创建时间 + /// + [SugarColumn(ColumnName = "wms_time")] + [JsonPropertyName("wmsTime")] + public DateTime? WmsTime { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "create_time")] + [JsonPropertyName("createTime")] + public DateTime? CreateTime { get; set; } + + /// + /// 写入PLC的载具编号 + /// + [SugarColumn(ColumnName = "plc_vehicle_no")] + [JsonPropertyName("plcVehicleNo")] + public int? PlcVehicleNo { get; set; } + + /// + /// 载具编号 + /// + [SugarColumn(ColumnName = "vehicle_no")] + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 载具尺寸 + /// + [SugarColumn(ColumnName = "vehicle_size")] + [JsonPropertyName("vehicleSize")] + public int? VehicleSize { get; set; } + + /// + /// 重量 + /// + [SugarColumn(ColumnName = "weight")] + [JsonPropertyName("weight")] + public decimal? Weight { get; set; } + + + /// + /// 任务创建人 + /// + [SugarColumn(ColumnName = "create_person")] + [JsonPropertyName("createPerson")] + public string? CreatePerson { get; set; } + + + /// + /// 开始时间 + /// + [SugarColumn(ColumnName = "start_time")] + [JsonPropertyName("startTime")] + public DateTime? StartTime { get; set; } + + /// + /// 完成时间 + /// + [SugarColumn(ColumnName = "complete_time")] + [JsonPropertyName("completeTime")] + public DateTime? CompleteTime { get; set; } + + /// + /// 备注信息 + /// + [SugarColumn(ColumnName = "remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + + + + public override string ToString() + { + return $"任务号:{TaskId},Plc任务号:{PlcId}"; + } + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/AppWmsTask.cs b/WcsMain/DataBase/TableEntity/AppWmsTask.cs new file mode 100644 index 0000000..13ae70e --- /dev/null +++ b/WcsMain/DataBase/TableEntity/AppWmsTask.cs @@ -0,0 +1,128 @@ +using System.Text.Json.Serialization; +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// tbl_app_wms_task +/// wms任务表 +/// +[SugarTable("tbl_app_wms_task")] +public class AppWmsTask +{ + /// + /// Wms任务号 + /// + [SugarColumn(IsPrimaryKey = true, ColumnName = "task_id")] + [JsonPropertyName("taskId")] + public string? TaskId { get; set; } + + /// + /// 任务类型 + /// + [SugarColumn(ColumnName = "task_type")] + [JsonPropertyName("taskType")] + public int? TaskType { get; set; } + + /// + /// 任务状态 + /// + [SugarColumn(ColumnName = "task_status")] + [JsonPropertyName("taskStatus")] + public int? TaskStatus { get; set; } + + + /// + /// 任务优先级 + /// + [SugarColumn(ColumnName = "priority")] + [JsonPropertyName("priority")] + public int? Priority { get; set; } + + /// + /// 任务起点 + /// + [SugarColumn(ColumnName = "origin")] + [JsonPropertyName("origin")] + public string? Origin { get; set; } + + /// + /// 任务起点 + /// + [SugarColumn(ColumnName = "midpoint")] + [JsonPropertyName("midPoint")] + public string? MidPoint { get; set; } + + /// + /// 任务目的地 + /// + [SugarColumn(ColumnName = "destination")] + [JsonPropertyName("destination")] + public string? Destination { get; set; } + + /// + /// 载具编号 + /// + [SugarColumn(ColumnName = "vehicle_no")] + [JsonPropertyName("vehicleNo")] + public string? VehicleNo { get; set; } + + /// + /// 载具尺寸 + /// + [SugarColumn(ColumnName = "vehicle_size")] + [JsonPropertyName("vehicleSize")] + public int? VehicleSize { get; set; } + + /// + /// 重量 + /// + [SugarColumn(ColumnName = "weight")] + [JsonPropertyName("weight")] + public decimal? Weight { get; set; } + + /// + /// 创建时间 + /// + [SugarColumn(ColumnName = "create_time")] + [JsonPropertyName("createTime")] + public DateTime? CreateTime { get; set; } + + /// + /// 修改时间 + /// + [SugarColumn(ColumnName = "modify_time")] + [JsonPropertyName("modifyTime")] + public DateTime? ModifyTime { get; set; } + + /// + /// 任务开始时间 + /// + [SugarColumn(ColumnName = "start_time")] + [JsonPropertyName("startTime")] + public DateTime? StartTime { get; set; } + + + /// + /// 任务结束时间 + /// + [SugarColumn(ColumnName = "end_time")] + [JsonPropertyName("endTime")] + public DateTime? EndTime { get; set; } + + /// + /// 创建人 + /// + [SugarColumn(ColumnName = "create_person")] + [JsonPropertyName("createPerson")] + public string? CreatePerson { get; set; } + + /// + /// 错误信息 + /// + [SugarColumn(ColumnName = "task_msg")] + [JsonPropertyName("taskMsg")] + public string? TaskMsg { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/DataBase/TableEntity/BsPickStand.cs b/WcsMain/DataBase/TableEntity/BsPickStand.cs new file mode 100644 index 0000000..11ab4ca --- /dev/null +++ b/WcsMain/DataBase/TableEntity/BsPickStand.cs @@ -0,0 +1,30 @@ +using SqlSugar; + +namespace WcsMain.DataBase.TableEntity; + +/// +/// 拣选站台信息 +/// +[SugarTable("tbl_bs_pick_stand")] +public class BsPickStand +{ + /// + /// 拣选站台名称 + /// + [SugarColumn(ColumnName = "pick_stand")] + public string? PickStand { get; set; } + + /// + /// 拣选站台类型 + /// + [SugarColumn(ColumnName = "stand_type")] + public int? StandType { get; set; } + + /// + /// 站台状态 + /// + [SugarColumn(ColumnName = "stand_status")] + public int? StandStatus { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/DataService/DataBaseData.cs b/WcsMain/DataService/DataBaseData.cs new file mode 100644 index 0000000..6c6b9ba --- /dev/null +++ b/WcsMain/DataService/DataBaseData.cs @@ -0,0 +1,116 @@ +using System.Text.RegularExpressions; +using WcsMain.Common; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.DataService; + +/// +/// +/// +[Component] +public class DataBaseData(AppSettingsDao settingsDao) +{ + private AppSettingsDao _settingsDao = settingsDao; + + /// + /// 获取一个设置值 + /// + /// + /// + public string? GetSetting(string settingKey) + { + List? settings = _settingsDao.GetSetting(settingKey); + if (settings == default || settings.Count < 1) + { + return string.Empty; + } + return settings[0].SettingValue; + } + + + private static readonly object getNewPlcTaskIdLock = new(); + /// + /// 获取新的 PLC 任务号,发生异常则返回默认值 + /// + /// + /// + public int[]? GetNewPlcTaskId(int count) + { + lock (getNewPlcTaskIdLock) + { + string? oldPlcTaskIdstr = GetSetting("plc_task_id"); + if (string.IsNullOrEmpty(oldPlcTaskIdstr)) { return default; } + if (!Regex.IsMatch(oldPlcTaskIdstr, "^\\d+$")) { return default; } + int oldPlcTaskId = Convert.ToInt32(oldPlcTaskIdstr); + if (oldPlcTaskId > 2000000000) + { + oldPlcTaskId = 100000; + } + oldPlcTaskId++; + int[] ints = new int[count]; + for (int i = 0; i < count; i++) + { + ints[i] = oldPlcTaskId + i; + } + int updateNewTaskPlcId = _settingsDao.Update(new AppSettings() { SettingKey = "plc_task_id", SettingValue = ints.Last().ToString() }); + if (updateNewTaskPlcId < 0) { return default; } + return ints; + } + } + /// + /// 获取一个PldId + /// + /// + public int? GetNewPlcTaskId() + { + var ints = GetNewPlcTaskId(1); + if (ints == default || ints.Length < 1) { return default; } + return ints.First(); + } + + + + private static readonly object getNewUUIDLock = new(); + private string lastUUID = string.Empty; + private string lasTimeTick = DateTime.Now.ToString("yyyyMMddHHmmssfff"); + private ushort sortUUID = 0; + /// + /// 返回一个唯一识别号 + /// + /// + public string GetNewUUID() + { + lock (getNewUUIDLock) + { + while (true) + { + string? wcsId = CommonData.AppConfig.WcsId; + if (string.IsNullOrEmpty(wcsId)) + { + wcsId = "0"; + } + string timeTick = DateTime.Now.ToString("yyyyMMddHHmmssfff"); + if (timeTick != lasTimeTick) + { + lasTimeTick = timeTick; + sortUUID = 0; + } + string idNo = wcsId.PadLeft(4, '0'); + string sort = sortUUID.ToString().PadLeft(5, '0'); + string newUUID = $"{timeTick}{idNo}{sort}"; + sortUUID++; + if (sortUUID > 60000) + { + sortUUID = 0; + } + if (newUUID != lastUUID) + { + lastUUID = newUUID; + return newUUID; + } + } + } + } +} \ No newline at end of file diff --git a/WcsMain/Enum/ApiServer/ApiResponseCodeEnum.cs b/WcsMain/Enum/ApiServer/ApiResponseCodeEnum.cs new file mode 100644 index 0000000..a14769d --- /dev/null +++ b/WcsMain/Enum/ApiServer/ApiResponseCodeEnum.cs @@ -0,0 +1,18 @@ +namespace WcsMain.Enum.ApiServer; + +/// +/// WMS 接口返回代码 +/// +public enum ApiResponseCodeEnum +{ + success = 0, // 正常响应 + fail = 1, // 正常返回失败 + dataRepetition = 200, // 数据重复 + undefinedErr = 999, // 未知异常 + requestDataErr = 998, // 请求的数据格式错误 + dataBaseErr = 997, // 数据库操作异常 + + serviceErr = 9999, // 服务器异常,无法处理数据 + + +} \ No newline at end of file diff --git a/WcsMain/Enum/FucResultEnum.cs b/WcsMain/Enum/FucResultEnum.cs new file mode 100644 index 0000000..466a327 --- /dev/null +++ b/WcsMain/Enum/FucResultEnum.cs @@ -0,0 +1,11 @@ +namespace WcsMain.Enum; + +/// +/// 动作执行的结果 +/// +public enum FucResultEnum +{ + offline, + success, + fail, +} \ No newline at end of file diff --git a/WcsMain/Enum/General/TrueFalseEnum.cs b/WcsMain/Enum/General/TrueFalseEnum.cs new file mode 100644 index 0000000..186a762 --- /dev/null +++ b/WcsMain/Enum/General/TrueFalseEnum.cs @@ -0,0 +1,10 @@ +namespace WcsMain.Enum.General; + +/// +/// 通用枚举,0 1表示true or false +/// +public enum TrueFalseEnum +{ + FALSE = 0, + TRUE = 1, +} diff --git a/WcsMain/Enum/Location/LocationStatusEnum.cs b/WcsMain/Enum/Location/LocationStatusEnum.cs new file mode 100644 index 0000000..f18dd5f --- /dev/null +++ b/WcsMain/Enum/Location/LocationStatusEnum.cs @@ -0,0 +1,13 @@ +namespace WcsMain.Enum.Location; + +/// +/// 库位状态枚举 +/// +public enum LocationStatusEnum +{ + empty = 0, // 空闲 + used = 2, // 占用中,有库存 + locked = 1, // 锁定 + forbidden = 9, // 禁用 + special = 999, // 特殊点位 +} \ No newline at end of file diff --git a/WcsMain/Enum/Plc/PickTaskRouterEnum.cs b/WcsMain/Enum/Plc/PickTaskRouterEnum.cs new file mode 100644 index 0000000..dfa80fe --- /dev/null +++ b/WcsMain/Enum/Plc/PickTaskRouterEnum.cs @@ -0,0 +1,11 @@ +namespace WcsMain.Enum.Plc; + +/// +/// 拣选移栽机路向枚举 +/// +public enum PickTaskRouterEnum +{ + straight = 3, // 通过, + down = 1, // 移栽 + up = 2, // 左 +} \ No newline at end of file diff --git a/WcsMain/Enum/Plc/StackerConveyModelEnum.cs b/WcsMain/Enum/Plc/StackerConveyModelEnum.cs new file mode 100644 index 0000000..367ac1b --- /dev/null +++ b/WcsMain/Enum/Plc/StackerConveyModelEnum.cs @@ -0,0 +1,6 @@ +namespace WcsMain.Enum.Plc; + +public enum StackerConveyModelEnum +{ + +} \ No newline at end of file diff --git a/WcsMain/Enum/Plc/StackerConveyStatusEnum.cs b/WcsMain/Enum/Plc/StackerConveyStatusEnum.cs new file mode 100644 index 0000000..147d541 --- /dev/null +++ b/WcsMain/Enum/Plc/StackerConveyStatusEnum.cs @@ -0,0 +1,6 @@ +namespace WcsMain.Enum.Plc; + +public enum StackerConveyStatusEnum +{ + +} \ No newline at end of file diff --git a/WcsMain/Enum/SendWmsTaskStatusEnum.cs b/WcsMain/Enum/SendWmsTaskStatusEnum.cs new file mode 100644 index 0000000..219f7ad --- /dev/null +++ b/WcsMain/Enum/SendWmsTaskStatusEnum.cs @@ -0,0 +1,20 @@ +namespace WcsMain.Enum; + +/// +/// 发送给 WMS 的任务状态 +/// +public enum SendWmsTaskStatusEnum +{ + queuing = 1, // 任务排队中 + start = 2, // 任务开始 + leaveOrigin = 3, // 任务离开初始位置 + arriveMid = 4, // 任务到达中间点 + arrive = 5, // 任务到达目的地 + complete = 100, // 任务完成 + emptyOut = 700, // 空出库 + doubleIn = 800, // 重复入库 + cancel = 998, // 任务取消 + err = 999, // 任务异常 + other = 0, + +} \ No newline at end of file diff --git a/WcsMain/Enum/Stacker/StackerControlModeEnum.cs b/WcsMain/Enum/Stacker/StackerControlModeEnum.cs new file mode 100644 index 0000000..6118e2c --- /dev/null +++ b/WcsMain/Enum/Stacker/StackerControlModeEnum.cs @@ -0,0 +1,17 @@ +namespace WcsMain.Enum.Stacker; + +/// +/// 堆垛机控制方式 +/// +public enum StackerControlModeEnum +{ + offline = 0, // 离线 + selfLearning = 1, // 自学习 + debug = 2, // 调试 + manual = 3, // 手动 + standAlone = 4, // 单机,本机自动 + online = 5, // 联机、在线 + + non = -1, // 未知 + +} \ No newline at end of file diff --git a/WcsMain/Enum/Stacker/StackerStatusEnum.cs b/WcsMain/Enum/Stacker/StackerStatusEnum.cs new file mode 100644 index 0000000..83550c3 --- /dev/null +++ b/WcsMain/Enum/Stacker/StackerStatusEnum.cs @@ -0,0 +1,22 @@ +namespace WcsMain.Enum.Stacker; + +/// +/// 堆垛机状态 +/// +public enum StackerStatusEnum +{ + offline = 0, // 脱机、失联 + free = 1, // 空闲 + acceptTask = 2, // 任务接收 + getMove = 3, // 取货移动 + getting = 4, // 取货中 + getComplete = 5, // 取货完成 + setMove = 6, // 卸货移动 + setting = 7, // 卸货中 + setComplete = 8, // 卸货完成 + taskComplete = 9, // 任务完成 + deleteTask = 10, // 删除任务 + checking = 11, // 盘点中 + applyTask = 21, // 二次预约申请 + non = -1, // 未知 +} \ No newline at end of file diff --git a/WcsMain/Enum/Stacker/StackerUseStatusEnum.cs b/WcsMain/Enum/Stacker/StackerUseStatusEnum.cs new file mode 100644 index 0000000..cf3557f --- /dev/null +++ b/WcsMain/Enum/Stacker/StackerUseStatusEnum.cs @@ -0,0 +1,11 @@ +namespace WcsMain.Enum.Stacker; + +/// +/// 堆垛机使用状态 +/// +public enum StackerUseStatusEnum +{ + BusyOrErr, // 堆垛机不可用 + Free, // 堆垛机可用 + waitTask, // 堆垛机正在等待任务,重复入库时会有 +} diff --git a/WcsMain/Enum/StandTypeEnum.cs b/WcsMain/Enum/StandTypeEnum.cs new file mode 100644 index 0000000..a29a140 --- /dev/null +++ b/WcsMain/Enum/StandTypeEnum.cs @@ -0,0 +1,15 @@ +namespace WcsMain.Enum; + +/// +/// 用于指示 点位的类型 +/// +public enum StandTypeEnum +{ + storageLocation = 0, // 库位 + stackerInStand = 1, // 堆垛机入库站台 + stackerOutStand = 2, // 堆垛机出库站台 + stackerPickStand = 4, // 堆垛机拣选盘点站台 + + conveyInStand = -1, // 输送机入库站台 + conveyOutStand = -2, // 输送机出库站台 +} \ No newline at end of file diff --git a/WcsMain/Enum/TaskEnum/TaskCategoryEnum.cs b/WcsMain/Enum/TaskEnum/TaskCategoryEnum.cs new file mode 100644 index 0000000..2af8f7f --- /dev/null +++ b/WcsMain/Enum/TaskEnum/TaskCategoryEnum.cs @@ -0,0 +1,12 @@ +namespace WcsMain.Enum.TaskEnum; + +/// +/// 任务类别 +/// +public enum TaskCategoryEnum +{ + stacker = 1, // 堆垛机任务 + stackerConvey = 2, // 库前输送任务 + + +} diff --git a/WcsMain/Enum/TaskEnum/TaskTypeEnum.cs b/WcsMain/Enum/TaskEnum/TaskTypeEnum.cs new file mode 100644 index 0000000..4219d70 --- /dev/null +++ b/WcsMain/Enum/TaskEnum/TaskTypeEnum.cs @@ -0,0 +1,15 @@ +namespace WcsMain.Enum.TaskEnum; + +/// +/// 任务类型 +/// +public enum TaskTypeEnum +{ + conveyTask = -1, // 输送机任务 + inTask = 1, // 入库任务 + outTask = 2, // 出库任务 + pick = 4, // 拣选任务 + check = 10, // 盘点任务 + moveTask = 9, // 移库任务 + newTaskForDoubleIn = 11, // 重复入库的新任务 +} \ No newline at end of file diff --git a/WcsMain/Enum/TaskEnum/WcsTaskStatusEnum.cs b/WcsMain/Enum/TaskEnum/WcsTaskStatusEnum.cs new file mode 100644 index 0000000..f5d8a0e --- /dev/null +++ b/WcsMain/Enum/TaskEnum/WcsTaskStatusEnum.cs @@ -0,0 +1,14 @@ +namespace WcsMain.Enum.TaskEnum; + +/// +/// WCS 表状态 +/// +public enum WcsTaskStatusEnum +{ + create = 0, + leaveOrigin = 1, + running = 2, + arriveDestination = 3, + complete = 4, + err = 9, +} \ No newline at end of file diff --git a/WcsMain/Enum/TaskEnum/WcsTaskTypeEnum.cs b/WcsMain/Enum/TaskEnum/WcsTaskTypeEnum.cs new file mode 100644 index 0000000..9dad01e --- /dev/null +++ b/WcsMain/Enum/TaskEnum/WcsTaskTypeEnum.cs @@ -0,0 +1,10 @@ +namespace WcsMain.Enum.TaskEnum; + +public enum WcsTaskTypeEnum +{ + inTask = 1, // 入库任务 + outTask = 2, // 出库任务 + pick = 4, // 拣选任务 + check = 10, // 盘点任务 + moveTask = 9, // 移库任务 +} diff --git a/WcsMain/Enum/TaskEnum/WmsTaskStatusEnum.cs b/WcsMain/Enum/TaskEnum/WmsTaskStatusEnum.cs new file mode 100644 index 0000000..9febcb1 --- /dev/null +++ b/WcsMain/Enum/TaskEnum/WmsTaskStatusEnum.cs @@ -0,0 +1,13 @@ +namespace WcsMain.Enum.TaskEnum; + +/// +/// WMS任务状态枚举 +/// +public enum WmsTaskStatusEnum +{ + create = 0, // 任务创建 + queuing = 1, // 排队中 + running = 2, // 执行中 + complete = 3, // 执行完成 + err = 9, // 执行异常 +} \ No newline at end of file diff --git a/WcsMain/Enum/TaskEnum/WmsTaskTypeEnum.cs b/WcsMain/Enum/TaskEnum/WmsTaskTypeEnum.cs new file mode 100644 index 0000000..30027e7 --- /dev/null +++ b/WcsMain/Enum/TaskEnum/WmsTaskTypeEnum.cs @@ -0,0 +1,13 @@ +namespace WcsMain.Enum.TaskEnum; + +/// +/// Wms 的任务枚举 +/// +public enum WmsTaskTypeEnum +{ + inTask = 1, // 入库任务 + outTask = 2, // 出库任务 + pick = 4, // 拣选任务 + check = 10, // 盘点任务 + moveTask = 9, // 移库任务 +} diff --git a/WcsMain/Enum/TaskFeedBackTypeEnum.cs b/WcsMain/Enum/TaskFeedBackTypeEnum.cs new file mode 100644 index 0000000..87f077d --- /dev/null +++ b/WcsMain/Enum/TaskFeedBackTypeEnum.cs @@ -0,0 +1,13 @@ +namespace WcsMain.Enum; + +/// +/// 过账反馈类型 +/// +public enum TaskFeedBackTypeEnum +{ + complete = 1, // 任务完成 + cancel = 2, // 任务取消 + doubleIn = 3, // 重复入库 + emptyOut = 4, // 空出库 + +} \ No newline at end of file diff --git a/WcsMain/Enum/Tcp/TcpType.cs b/WcsMain/Enum/Tcp/TcpType.cs new file mode 100644 index 0000000..af97bcd --- /dev/null +++ b/WcsMain/Enum/Tcp/TcpType.cs @@ -0,0 +1,12 @@ +namespace WcsMain.Enum.Tcp; + +/// +/// Tcp 类型 +/// +public enum TcpType +{ + PLC = 0, + SCAN = 1, + + +} diff --git a/WcsMain/Enum/UserStatusEnum.cs b/WcsMain/Enum/UserStatusEnum.cs new file mode 100644 index 0000000..2bc01be --- /dev/null +++ b/WcsMain/Enum/UserStatusEnum.cs @@ -0,0 +1,10 @@ +namespace WcsMain.Enum; + +/// +/// 用户状态枚举 +/// +public enum UserStatusEnum +{ + disabled = 0, // 禁用 + normal = 1, // 正常 +} \ No newline at end of file diff --git a/WcsMain/ExtendMethod/AppLocationExtendMethod.cs b/WcsMain/ExtendMethod/AppLocationExtendMethod.cs new file mode 100644 index 0000000..8ed38db --- /dev/null +++ b/WcsMain/ExtendMethod/AppLocationExtendMethod.cs @@ -0,0 +1,49 @@ +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ExtendMethod; + +/// +/// 库位的扩展方法 +/// +public static class AppLocationExtendMethod +{ + /// + /// 检验是否存在Wmslocation + /// + /// + /// + /// + public static bool ExistWmsLocation(this List? value, params string?[] wmsLocations) + { + if(value == default || wmsLocations == default || wmsLocations.Length < 1) return false; + foreach (var wmsLocation in wmsLocations) + { + if(!value.Exists(e => e.WmsLocation == wmsLocation)) return false; + } + return true; + } + + /// + /// 根据 wmsLocation 获取库位的详细信息 + /// + /// + /// + /// + public static AppLocation? DetailWithWmsLocation(this List? value, string? wmsLocation) + { + if(value == default || wmsLocation == default) return default; + return value.Find(f => f.WmsLocation == wmsLocation); + } + + /// + /// 根据 wcsLocation 获取库位的详细信息 + /// + /// + /// + /// + public static AppLocation? DetailWithWcsLocation(this List? value, string? wcsLocation) + { + if (value == default || wcsLocation == default) return default; + return value.Find(f => f.WcsLocation == wcsLocation); + } +} diff --git a/WcsMain/ExtendMethod/AppStackerExtendMethod.cs b/WcsMain/ExtendMethod/AppStackerExtendMethod.cs new file mode 100644 index 0000000..831eafb --- /dev/null +++ b/WcsMain/ExtendMethod/AppStackerExtendMethod.cs @@ -0,0 +1,22 @@ +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ExtendMethod; + +/// +/// 堆垛机操作扩展方法 +/// +public static class AppStackerExtendMethod +{ + /// + /// 查找运行使用的 PLC + /// + /// + /// + public static List Open(this List? value) + { + if(value == default) return []; + return value.FindAll(f => f.StackerStatus == 1); + } + + +} diff --git a/WcsMain/ExtendMethod/AppWcsTaskExtendMethod.cs b/WcsMain/ExtendMethod/AppWcsTaskExtendMethod.cs new file mode 100644 index 0000000..267699b --- /dev/null +++ b/WcsMain/ExtendMethod/AppWcsTaskExtendMethod.cs @@ -0,0 +1,37 @@ +using WcsMain.DataBase.TableEntity; + +namespace WcsMain.ExtendMethod; + +/// +/// wcs 任务表的扩展方法 +/// +public static class AppWcsTaskExtendMethod +{ + /// + /// 是否是第一个任务 + /// + /// + /// + /// 序号是 1 表示第一个任务 + /// + /// + public static bool IsFirstTask(this AppWcsTask wcsTask) + { + if (wcsTask == default) return false; + return wcsTask.TaskSort == 1; + } + + /// + /// 是否是最后一个任务 + /// + /// + /// + /// 最后一个任务下一任务号是空值 + /// + /// + public static bool IsLastTask(this AppWcsTask wcsTask) + { + if (wcsTask == default) return false; + return wcsTask.NextPlcId == default; + } +} diff --git a/WcsMain/ExtendMethod/StackerExtendMethod.cs b/WcsMain/ExtendMethod/StackerExtendMethod.cs new file mode 100644 index 0000000..8530fbc --- /dev/null +++ b/WcsMain/ExtendMethod/StackerExtendMethod.cs @@ -0,0 +1,53 @@ +using WcsMain.Enum.Stacker; + +namespace WcsMain.ExtendMethod; + +public static class StackerExtendMethod +{ + /// + /// 堆垛机状态转换为文字 + /// + /// + /// + public static string ToMsg(this StackerStatusEnum value) + { + return value switch + { + StackerStatusEnum.offline => "脱机", + StackerStatusEnum.free => "空闲", + StackerStatusEnum.acceptTask => "任务接收", + StackerStatusEnum.getMove => "取货移动", + StackerStatusEnum.getting => "取货中", + StackerStatusEnum.getComplete => "取货完成", + StackerStatusEnum.setMove => "卸货移动", + StackerStatusEnum.setting => "卸货中", + StackerStatusEnum.setComplete => "卸货完成", + StackerStatusEnum.taskComplete => "任务完成", + StackerStatusEnum.deleteTask => "删除任务", + StackerStatusEnum.checking => "盘点中", + StackerStatusEnum.applyTask => "二次预约申请", + _ => "未知状态" + }; + } + + + /// + /// 堆垛机控制方式 + /// + /// + /// + public static string ToMsg(this StackerControlModeEnum value) + { + return value switch + { + StackerControlModeEnum.offline => "离线", + StackerControlModeEnum.selfLearning => "自学习", + StackerControlModeEnum.debug => "调试", + StackerControlModeEnum.manual => "手动", + StackerControlModeEnum.standAlone => "单机", + StackerControlModeEnum.online => "联机", + _ => "未知" + }; + } + +} \ No newline at end of file diff --git a/WcsMain/ExtendMethod/StringExtendMethod.cs b/WcsMain/ExtendMethod/StringExtendMethod.cs new file mode 100644 index 0000000..966cc43 --- /dev/null +++ b/WcsMain/ExtendMethod/StringExtendMethod.cs @@ -0,0 +1,83 @@ +using System.Text.RegularExpressions; + +namespace WcsMain.ExtendMethod; + +/// +/// 扩展方法,检查基础数据 +/// +public static partial class StringExtendMethod +{ + /// + /// 检测一个字符串是不是 NoRead + /// + /// + /// + public static bool IsNoRead(this string? value) + { + if (string.IsNullOrEmpty(value)) return false; + return value.Replace(" ", "").Equals("noread", StringComparison.CurrentCultureIgnoreCase); + } + + /// + /// 检查一个字符串是否是数字 + /// + /// + /// + public static bool IsNumber(this string? value) + { + if (string.IsNullOrEmpty(value)) return false; + return IsNumberRegex().IsMatch(value); + } + + /// + /// 将字符串转换为 bool,只有等于null和0的情况下是false + /// + /// + /// + public static bool ToBool(this string? value) + { + if(value == null) return false; + return value != "0"; + } + + /// + /// 检测一个字符串是不是时间格式,如果是返回时间,如果不是返回 default + /// + /// + /// + public static DateTime? ToDateTime(this string? value) + { + try + { + DateTime time = Convert.ToDateTime(value); + return time; + } + catch + { + return default; + } + } + + + + /// + /// 将载具号转换为 plc 可识别的载具号 + /// + /// + /// + public static int ToPlcVehicleNo(this string? value) + { + if (string.IsNullOrEmpty(value)) return 0; + try + { + return Convert.ToInt32(Regex.Replace(value, "\\D", "")); + } + catch + { + return 0; + } + } + + [GeneratedRegex("^\\d+$")] + private static partial Regex IsNumberRegex(); +} \ No newline at end of file diff --git a/WcsMain/ExtendMethod/TaskExtendMethod.cs b/WcsMain/ExtendMethod/TaskExtendMethod.cs new file mode 100644 index 0000000..bad40bd --- /dev/null +++ b/WcsMain/ExtendMethod/TaskExtendMethod.cs @@ -0,0 +1,25 @@ +namespace WcsMain.ExtendMethod; + +/// +/// 任务扩展方法 +/// +public static class TaskExtendMethod +{ + /// + /// 转换任务类型为文字 + /// + /// + /// + public static string ToTaskTypeStr(this int? task) + { + return task switch + { + 1 => "入库任务", + 2 => "出库任务", + 4 => "拣选任务", + 9 => "移库任务", + -1 => "输送任务", + _ => "未知任务" + }; + } +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/ConnectPLCs.cs b/WcsMain/PlcOperation/ConnectPLCs.cs new file mode 100644 index 0000000..300879a --- /dev/null +++ b/WcsMain/PlcOperation/ConnectPLCs.cs @@ -0,0 +1,48 @@ +using PlcTool.Siemens; +using WcsMain.Common; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.PlcOperation; + +/// +/// 连接PLC +/// +[Component] +public class ConnectPLCs(AppPLCDao pLCDao, AppDBDao dBDao) +{ + private readonly AppPLCDao _plcDao = pLCDao; + private readonly AppDBDao _dbDao = dBDao; + + /// + /// 连接PLC + /// + /// 返回值表示是否继续检测PLC连接状态 + public bool ConnectPlc() + { + /* 查询所有PLC */ + List? plcs = _plcDao.GetDataWithStatus(1); + if (plcs == default || plcs.Count == 0) + { + ConsoleLog.Tip("$[异常]PLC 数据查找失败,请检查网络是否正常或者是否录入PLC数据"); + return true; + } + List? dbs = _dbDao.Select(); + CommonTool.Siemens = new SiemensS7(); + CommonTool.Siemens.SetPlcs(plcs).SetPlcDB(dbs); + var connectResult = CommonTool.Siemens.ConnectPlcs(); + if (connectResult.Success) + { + CommonData.IsConnectPlc = true; + } + else + { + CommonData.IsConnectPlc = false; + ConsoleLog.Error($"[异常]{connectResult.Message}"); + ConsoleLog.Error($"请检查设备网络后重新启动 WCS "); + } + return true; + } + +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/ConveyOperation.cs b/WcsMain/PlcOperation/ConveyOperation.cs new file mode 100644 index 0000000..f536aa2 --- /dev/null +++ b/WcsMain/PlcOperation/ConveyOperation.cs @@ -0,0 +1,233 @@ +using System.Text; +using System.Text.RegularExpressions; +using WcsMain.Common; +using WcsMain.PlcOperation.Entity; + +namespace WcsMain.PlcOperation; + +/// +/// 输送机操作 ---- 箱式线,不包含于立库库前设备,库前请参考堆垛机操作 +/// +public class ConveyOperation +{ + private static ConveyOperation? _instance; + + public static ConveyOperation Instance() + { + return _instance ??= new ConveyOperation(); + } + + /// + /// 写入箱式线任务 + /// + /// + /// + /// + public string WriteTask(string? equipmentId, ConveyPLCTask task) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return "PLC尚未连接。"; + } + var (writeResult, _) = CommonTool.Siemens.WritePlcWhithName($"箱式线写任务{equipmentId}", + task.PlcId, + task.Router); + if (writeResult.Success) + { + return string.Empty; + } + return writeResult.Message ?? "写入失败,未知原因"; + } + + /// + /// 写入输送机心跳 + /// + /// + public string WriteHeartBeat() + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return "PLC尚未连接。"; + } + var (writeResult, _) = CommonTool.Siemens.WritePlcWhithName($"箱式线写心跳", (short)0); + if (writeResult.Success) + { + return string.Empty; + } + return writeResult.Message ?? "写入失败,未知原因"; + } + + /// + /// 获取箱式线出库站台状态 + /// + /// + /// + public bool GetOutConveyStatus(string? standId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return false; + } + var readGoodsExistResult = CommonTool.Siemens.ReadBoolWithName($"站台货物检测{standId}"); + if (!readGoodsExistResult.Success || readGoodsExistResult.Value) // 读取失败,或者有货 就不允许出库 + { + return false; + } + var readAGVExistResult = CommonTool.Siemens.ReadBoolWithName($"站台AGV检测{standId}"); + if (!readAGVExistResult.Success || readAGVExistResult.Value) // 读取失败,或者有AGV 就不允许出库 + { + return false; + } + if (!readGoodsExistResult.Value && !readAGVExistResult.Value) // 无货并且没有AGV才能出库 + { + return true; + } + return false; + } + + + // 10.40.200.210 + + /// + /// 获取入库站台状态 --- 是否可以入库 + /// + /// + /// + public bool GetInConveyStatus(string? standId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return false; + } + if (string.IsNullOrEmpty(standId)) { return false; } + if (standId.StartsWith('P')) + { + var readGoodsNeedIn = CommonTool.Siemens.ReadBoolWithName($"站台请求入库{standId}"); + if (!readGoodsNeedIn.Success || !readGoodsNeedIn.Value) // 读取失败,或者没有货 就不允许入库 + { + return false; + } + return true; + } + var readGoodsExistResult = CommonTool.Siemens.ReadBoolWithName($"站台货物检测{standId}"); + if (!readGoodsExistResult.Success || !readGoodsExistResult.Value) // 读取失败,或者没有货 就不允许入库 + { + return false; + } + var readAGVExistResult = CommonTool.Siemens.ReadBoolWithName($"站台AGV检测{standId}"); + if (!readAGVExistResult.Success || readAGVExistResult.Value) // 读取失败,或者有AGV 就不允许入库 + { + return false; + } + if (readGoodsExistResult.Value && !readAGVExistResult.Value) // 有货并且没有AGV才能入库 + { + return true; + } + return false; + } + + /// + /// 获取箱式线拣选站台状态 + /// + /// + /// + public bool GetPickConveyStatus(string? standId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return false; + } + var readGoodsExistResult = CommonTool.Siemens.ReadBoolWithName($"站台货物检测{standId}"); + if (!readGoodsExistResult.Success) // 读取失败,或者有货 就不允许出库 + { + return false; + } + return !readGoodsExistResult.Value; + } + + /// + /// 获取输送机箱子号 + /// + /// + /// + public string GetStandCode(int stackerId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return string.Empty; + } + var readResult1 = CommonTool.Siemens.ReadStringWithName($"箱式线入库载具号{stackerId}", 10, Encoding.ASCII); + if (!readResult1.Success) + { + // 读取失败 + return string.Empty; + } + // 返回读取到的任务号 + return Regex.Replace(readResult1.Value ?? "", "\\W", ""); + } + + + /// + /// 读取扫码点信息 + /// + /// + /// + public (string? errText, short scanOk, string code) ReadScanInfo(string scanId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return ("PLC尚未连接。", 0, ""); + } + var readResult = CommonTool.Siemens.ReadByteWithName($"扫码读取{scanId}", 22); + if (!readResult.Success || readResult.Value == default) // 读取失败 + { + return (readResult.Message, 0, ""); + } + try + { + var readData = readResult.Value; + short status = Convert.ToInt16(CommonTool.Siemens.Trans(readData, 0)); // PLC 返回任务状态 + string code = Regex.Replace(Encoding.ASCII.GetString(readData, 2, 20), "\\W", ""); + return (string.Empty, status, code); + } + catch (Exception ex) + { + return (ex.Message, 0, ""); + } + } + + /// + /// 清除扫码状态 + /// + /// + /// + public string ClearScanStatus(string scanId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return "PLC尚未连接。"; + } + var (writeResult, _) = CommonTool.Siemens.WritePlcWhithName($"扫码读取{scanId}", (short)0); + if (!writeResult.Success) // 读取失败 + { + return writeResult.Message ?? "写入失败"; + } + try + { + return string.Empty; + } + catch (Exception ex) + { + return ex.Message; + } + } + +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Entity/ConveyPLCTask.cs b/WcsMain/PlcOperation/Entity/ConveyPLCTask.cs new file mode 100644 index 0000000..19697fd --- /dev/null +++ b/WcsMain/PlcOperation/Entity/ConveyPLCTask.cs @@ -0,0 +1,23 @@ +namespace WcsMain.PlcOperation.Entity; + +/// +/// 给输送机任务 +/// +public class ConveyPLCTask +{ + /// + /// Plc任务号 + /// + public int PlcId { get; set; } + + /// + /// 路向 + /// + public short Router { get; set; } + + + public override string ToString() + { + return $"<{PlcId} | {Router}>"; + } +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Entity/Stacker/StackerInfo.cs b/WcsMain/PlcOperation/Entity/Stacker/StackerInfo.cs new file mode 100644 index 0000000..d4e59a5 --- /dev/null +++ b/WcsMain/PlcOperation/Entity/Stacker/StackerInfo.cs @@ -0,0 +1,118 @@ +using WcsMain.Enum.Stacker; + +namespace WcsMain.PlcOperation.Entity.Stacker; + +/// +/// 堆垛机信息,读取的时候赋值 +/// +public class StackerInfo +{ + + /// + /// 任务号 + /// + public int PlcId { get; set; } + + /// + /// 控制方式,int16 + /// + public StackerControlModeEnum ControlModel { get; set; } + + /// + /// 设备状态,int16 + /// + public StackerStatusEnum StackerStatus { get; set; } + + + + /// + /// 当前巷道 + /// + public short TunnelId { get; set; } + + /// + /// 当前排 + /// + public short Row { get; set; } + + + /// + /// 当前列 + /// + public short Line { get; set; } + + + /// + /// 当前层 + /// + public short Layer { get; set; } + + + /// + /// 当前深 + /// + public short Depth { get; set; } + + /// + /// 条码值 + /// + public int Code { get; set; } + + /// + /// 故障号 + /// + public short ErrCode { get; set; } + + /// + /// 行走里程 + /// + public float WorkLength { get; set; } + + /// + /// 提升里程 + /// + public float UpLength { get; set; } + + /// + /// 货叉次数计数 + /// + public int ForkCount { get; set; } + + /// + /// 提交任务 + /// + /// + /// 当前已经弃用 + /// + public int SubmitPlcId { get; set; } + + /// + /// 删除任务 + /// + /// + /// 当前已经弃用 + /// + public int DeletePlcId { get; set; } + + /// + /// 备用1 + /// + public int Spare1 { get; set; } + + /// + /// 备用2 + /// + public short Spare2 { get; set; } + + /// + /// 判断堆垛机是否可用 + /// + /// + public bool CanUse() + { + return ControlModel == StackerControlModeEnum.online + && StackerStatus == StackerStatusEnum.free + && ErrCode == 0; + } + +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Entity/Stacker/StackerPlcTask.cs b/WcsMain/PlcOperation/Entity/Stacker/StackerPlcTask.cs new file mode 100644 index 0000000..12cd2ca --- /dev/null +++ b/WcsMain/PlcOperation/Entity/Stacker/StackerPlcTask.cs @@ -0,0 +1,135 @@ +using WcsMain.Enum.TaskEnum; + +namespace WcsMain.PlcOperation.Entity.Stacker; + +/// +/// 写入PLC的任务 ---- 堆垛机 +/// +public class StackerPlcTask +{ + /// + /// 设备号,用于识别写入哪个堆垛机 + /// + public int? StackerId { get; set; } + + + + /// + /// 任务号 + /// + public int? PlcId { get; set; } = 0; + + /// + /// 任务类型 + /// + public short? TaskType { get; set; } = 0; + + /// + /// 取货站台 + /// + public short? GetStand { get; set; } = 0; + + /// + /// 入库巷道号 + /// + public short? InTunnelId { get; set; } = 0; + + /// + /// 出库巷道号 + /// + public short? OutTunnelId { get; set; } = 0; + + /// + /// 卸货站台 + /// + public short? SetStand { get; set; } = 0; + + /// + /// 取货排 + /// + public short? GetQueue { get; set; } = 0; + + /// + /// 取货列 + /// + public short? GetLine { get; set; } = 0; + + /// + /// 取货层 + /// + public short? GetLayer { get; set; } = 0; + + /// + /// 卸货排 + /// + public short? SetQueue { get; set; } = 0; + + /// + /// 卸货列 + /// + public short? SetLine { get; set; } = 0; + + /// + /// 卸货层 + /// + public short? SetLayer { get; set; } = 0; + + /// + /// 取货深度 + /// + public short? GetDeep { get; set; } = 0; + + /// + /// 卸货深度 + /// + public short? SetDeep { get; set; } = 0; + + /// + /// 尺寸 + /// + public short? Size { get; set; } = 0; + + /// + /// 重量 + /// + public short? Weight { get; set; } = 0; + + + /// + /// 料箱码 + /// + public int Code { get; set; } + + /// + /// 默认的直接从入口搬出去的任务 + /// + /// + /// + /// + /// + public static StackerPlcTask DefaultOutTask(int plcId, int stackerId, int vehicleNo = 999999999) + { + StackerPlcTask noTaskStackerTask = new() + { + PlcId = plcId, + TaskType = Convert.ToInt16(TaskTypeEnum.inTask), + GetStand = 0, + InTunnelId = Convert.ToInt16(stackerId), + OutTunnelId = Convert.ToInt16(stackerId), + SetStand = 0, + GetQueue = 1, + GetLine = 46, + GetLayer = 1, + GetDeep = 1, + SetQueue = 2, + SetLine = 46, + SetLayer = 1, + SetDeep = 1, + Size = 0, + Weight = 0, + Code = vehicleNo + }; + return noTaskStackerTask; + } + +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Entity/StackerConvey/StackerConveyInfo.cs b/WcsMain/PlcOperation/Entity/StackerConvey/StackerConveyInfo.cs new file mode 100644 index 0000000..2cc7a61 --- /dev/null +++ b/WcsMain/PlcOperation/Entity/StackerConvey/StackerConveyInfo.cs @@ -0,0 +1,76 @@ +using WcsMain.Enum.Plc; + +namespace WcsMain.PlcOperation.Entity.StackerConvey; + +/// +/// 库前输送机反馈的状态信息 +/// +public class StackerConveyInfo +{ + /// + /// 输送机编号 + /// + public short? ConveyNo { get; set; } + + /// + /// 任务类型 + /// + public short? TaskType { get; set; } + + /// + /// 堆垛机动作禁止 + /// + public short? StackerForbidden { get; set; } + + /// + /// 当前任务号 + /// + public int? PlcId { get; set; } + + /// + /// 控制方式 + /// + public StackerConveyModelEnum? ControlModel { get; set; } + + /// + /// 库前输送机状态 + /// + public StackerConveyStatusEnum? StackerConveyStatus { get; set; } + + /// + /// 载具尺寸 + /// + public short? VehicleSize { get; set; } + + /// + /// 重量 + /// + public short? Weight { get; set; } + + /// + /// 传感器状态 + /// + public uint? SensorStatus { get; set; } + + /// + /// 申请条码 + /// + public int? ApplyCode { get; set; } + + /// + /// 正在运行的条码 + /// + public int? RunningCode { get; set; } + + /// + /// 错误信息 + /// + public short? ErrCode { get; set; } + + /// + /// 备注 + /// + public int? Remark { get; set; } + + +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Entity/StackerConvey/StackerConveyPlcTask.cs b/WcsMain/PlcOperation/Entity/StackerConvey/StackerConveyPlcTask.cs new file mode 100644 index 0000000..1b87454 --- /dev/null +++ b/WcsMain/PlcOperation/Entity/StackerConvey/StackerConveyPlcTask.cs @@ -0,0 +1,97 @@ +namespace WcsMain.PlcOperation.Entity.StackerConvey; + +public class StackerConveyPlcTask +{ + /// + /// 设备号,用于识别写入哪个输送机 + /// + public string? StackerConveyId { get; set; } + + + + /// + /// 任务号 + /// + public int? PlcId { get; set; } = 0; + + /// + /// 任务类型 + /// + public short? TaskType { get; set; } = 0; + + /// + /// 取货站台 + /// + public short? GetStand { get; set; } = 0; + + /// + /// 入库巷道号 + /// + public short? InTunnelId { get; set; } = 0; + + /// + /// 出库巷道号 + /// + public short? OutTunnelId { get; set; } = 0; + + /// + /// 卸货站台 + /// + public short? SetStand { get; set; } = 0; + + /// + /// 取货排 + /// + public short? GetQueue { get; set; } = 0; + + /// + /// 取货列 + /// + public short? GetLine { get; set; } = 0; + + /// + /// 取货层 + /// + public short? GetLayer { get; set; } = 0; + + /// + /// 卸货排 + /// + public short? SetQueue { get; set; } = 0; + + /// + /// 卸货列 + /// + public short? SetLine { get; set; } = 0; + + /// + /// 卸货层 + /// + public short? SetLayer { get; set; } = 0; + + /// + /// 取货深度 + /// + public short? GetDeep { get; set; } = 0; + + /// + /// 卸货深度 + /// + public short? SetDeep { get; set; } = 0; + + /// + /// 尺寸 + /// + public short? Size { get; set; } = 0; + + /// + /// 重量 + /// + public short? Weight { get; set; } = 0; + + + /// + /// 料箱码 + /// + public int Code { get; set; } +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Entity/StackerFeedbackStatus.cs b/WcsMain/PlcOperation/Entity/StackerFeedbackStatus.cs new file mode 100644 index 0000000..33683e2 --- /dev/null +++ b/WcsMain/PlcOperation/Entity/StackerFeedbackStatus.cs @@ -0,0 +1,15 @@ +namespace WcsMain.PlcOperation.Entity; + +/// +/// 堆垛机状态反馈实体 +/// +public class StackerFeedbackStatus +{ + /// + /// plc 任务号 + /// + public int PlcId { get; set; } + + + +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Entity/TaskFeedBackEntity.cs b/WcsMain/PlcOperation/Entity/TaskFeedBackEntity.cs new file mode 100644 index 0000000..ae518f4 --- /dev/null +++ b/WcsMain/PlcOperation/Entity/TaskFeedBackEntity.cs @@ -0,0 +1,27 @@ +namespace WcsMain.PlcOperation.Entity; + +/// +/// 过账数据实体 +/// +public class TaskFeedBackEntity +{ + /// + /// 设备号 + /// + public int StackerId { get; set; } + + /// + /// 过账任务号 + /// + public int PlcId { get; set; } + + /// + /// 过账类型 + /// + public short FeedBackType { get; set; } + + /// + /// 序列号 + /// + public int CountNo { get; set; } +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/Stacker/StackerOperation.cs b/WcsMain/PlcOperation/Stacker/StackerOperation.cs new file mode 100644 index 0000000..0cdef34 --- /dev/null +++ b/WcsMain/PlcOperation/Stacker/StackerOperation.cs @@ -0,0 +1,306 @@ +using WcsMain.Common; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.Stacker; +using WcsMain.PlcOperation.Entity; +using WcsMain.PlcOperation.Entity.Stacker; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.PlcOperation.Stacker; + +/// +/// 堆垛机操作 +/// +[Component] +public class StackerOperation +{ + + + /********************************** 总结方法 *******************************************/ + + /// + /// 判断堆垛机状态,若是等待(二次申请)状态则带出当前的PlcId + /// + /// + /// + /// + public StackerUseStatusEnum StackerCanUse(int? stackerId, out int plcId) + { + plcId = 0; + if (stackerId == default) return StackerUseStatusEnum.BusyOrErr; + /* 获取堆垛机状态 */ + var (errMsg, stackerInfo) = GetStackerInfo((int)stackerId!); + if(!string.IsNullOrEmpty(errMsg) || stackerInfo == default) return StackerUseStatusEnum.BusyOrErr; + /* 堆垛机空闲条件 */ + var canUse = stackerInfo.PlcId == 0 && stackerInfo.ControlModel == StackerControlModeEnum.online + && stackerInfo.StackerStatus == StackerStatusEnum.free && stackerInfo.ErrCode == 0; + if (canUse) return StackerUseStatusEnum.Free; + /* 堆垛机等待任务条件(二次申请) */ + var waitTask = stackerInfo.ControlModel == StackerControlModeEnum.online && stackerInfo.StackerStatus == StackerStatusEnum.applyTask + && stackerInfo.ErrCode == 0; + if(waitTask) + { + plcId = stackerInfo.PlcId; + return StackerUseStatusEnum.waitTask; + } + return StackerUseStatusEnum.BusyOrErr; + } + + + + + + + + + + + + + + /********************************** 子方法 *******************************************/ + + + + /// + /// 读取堆垛机反馈信息 + /// + /// + /// + public (string? errText, StackerInfo? stackerInfo) GetStackerInfo(int stackerId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return ("设备尚未连接", default); // 未连接PLC + } + var readResult = CommonTool.Siemens.ReadByteWithName($"堆垛机状态反馈{stackerId}", 24); + if (!readResult.Success || readResult.Value == default) + { + return (readResult.Message, default); // 读取失败 + } + var data = readResult.Value; + StackerInfo stackerInfo = new() + { + PlcId = Convert.ToInt32(CommonTool.Siemens.Trans(data, 0)), // 当前运行任务号 + ControlModel = (StackerControlModeEnum)Convert.ToInt16(CommonTool.Siemens.Trans(data, 4)), // 控制方式 + StackerStatus = (StackerStatusEnum)Convert.ToInt16(CommonTool.Siemens.Trans(data, 6)), // 堆垛机状态 + TunnelId = Convert.ToInt16(CommonTool.Siemens.Trans(data, 8)), // 当前巷道 + Row = Convert.ToInt16(CommonTool.Siemens.Trans(data, 10)), // 当前排 + Line = Convert.ToInt16(CommonTool.Siemens.Trans(data, 12)), // 当前列 + Layer = Convert.ToInt16(CommonTool.Siemens.Trans(data, 14)), // 当前层 + Depth = Convert.ToInt16(CommonTool.Siemens.Trans(data, 16)), // 当前深度 + Code = Convert.ToInt32(CommonTool.Siemens.Trans(data, 18)), // 料箱码 + ErrCode = Convert.ToInt16(CommonTool.Siemens.Trans(data, 22)), // 错误码 + // WorkLength = Convert.ToSingle(CommonTool.Siemens.Trans(data, 24)), // 行走距离 + // UpLength = Convert.ToSingle(CommonTool.Siemens.Trans(data, 28)), // 提升距离 + // ForkCount = Convert.ToInt32(CommonTool.Siemens.Trans(data, 32)), // 货叉动作次数 + // SubmitPlcId = Convert.ToInt32(CommonTool.Siemens.Trans(data, 36)), // 提交的任务 + // DeletePlcId = Convert.ToInt32(CommonTool.Siemens.Trans(data, 40)), // 删除的任务 + // Spare1 = Convert.ToInt32(CommonTool.Siemens.Trans(data, 44)), // 备用1 + // Spare2 = Convert.ToInt16(CommonTool.Siemens.Trans(data, 48)), // 备用2 + }; + return (string.Empty, stackerInfo); + } + + /// + /// 读取所有故障 + /// + /// + /// + public bool[]? GetStackerErrInfo(int stackerId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return default; // 未连接PLC + } + var readResult = CommonTool.Siemens.ReadBoolWithName($"堆垛机当前报警{stackerId}", 96); + if (!readResult.Success || readResult.Value == default) + { + return default; + } + var data = readResult.Value; + return [.. data]; + } + + + /// + /// 复位堆垛机 + /// + /// + /// + public string ResetStacker(string? stackerId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return "PLC尚未连接"; + } + var (readResult, _) = CommonTool.Siemens.WritePlcWhithName($"堆垛机复位{stackerId}", (short)1); + if (readResult.Success) + { + return string.Empty; + } + return readResult.Message ?? "请求失败,请检查网络"; + } + + /// + /// 堆垛机继续运行 + /// + /// + /// + public string StackerContinue(string? stackerId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return "PLC尚未连接"; + } + var (readResult, _) = CommonTool.Siemens.WritePlcWhithName($"堆垛机继续运行{stackerId}", (short)1); + if (readResult.Success) + { + return string.Empty; + } + return readResult.Message ?? "请求失败,请检查网络"; + } + + /// + /// 获取报警编号 + /// + /// + /// + public int GetErrCode(int? stackerNo) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return -1; // 未连接PLC + } + var readResult = CommonTool.Siemens.ReadInt16WithName($"报警编号{stackerNo}"); + return readResult.Success ? readResult.Value : -1; + } + + /// + /// 堆垛机任务写入确认 + /// + /// + /// + public string WriteTaskConfirm(int stackerId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return "PLC尚未连接。"; + } + var (writeResult, _) = CommonTool.Siemens.WritePlcWhithName($"堆垛机写任务确认{stackerId}", (short)1); + if (writeResult.Success) + { + return string.Empty; + } + return writeResult.Message ?? "写入失败"; + } + + + /// + /// 写入堆垛机任务,返回错误信息 + /// + /// + /// + public string WriteTask(StackerPlcTask task) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) return "PLC尚未连接。"; // 未连接PLC + var (writeResult, _) = CommonTool.Siemens.WritePlcWhithName($"堆垛机写任务{task.StackerId}", + task.PlcId!, + task.TaskType!, + task.GetStand!, + task.InTunnelId!, + task.OutTunnelId!, + task.SetStand!, + task.GetQueue!, + task.GetLine!, + task.GetLayer!, + task.SetQueue!, + task.SetLine!, + task.SetLayer!, + task.GetDeep!, + task.SetDeep!, + task.Size!, + task.Weight!, + task.Code + ); + return writeResult.Success ? string.Empty : writeResult.Message ?? "写入失败"; + } + + + /// + /// 获取过账数据 + /// + /// + /// + /// + public List? GetTaskFeedBackData(int dataNum, List stackerList) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return default; // 未连接PLC + } + List taskFeedBackEntities = []; + foreach (var stacker in stackerList) + { + var readResult = CommonTool.Siemens.ReadByteWithName($"过账区{stacker.StackerId}", (ushort)(6 * dataNum)); + if (!readResult.Success) { continue; } + var readData = readResult.Value; + if (readData == default) { continue; } + for (var i = 0; i < dataNum; i++) + { + TaskFeedBackEntity taskFeedBackEntity = new() + { + StackerId = stacker.StackerId ?? 0, + PlcId = Convert.ToInt32(CommonTool.Siemens.Trans(readData, 0 + i * 6)), + FeedBackType = Convert.ToInt16(CommonTool.Siemens.Trans(readData, 4 + i * 6)), + CountNo = i + }; + taskFeedBackEntities.Add(taskFeedBackEntity); + } + } + return taskFeedBackEntities; + } + + /// + /// 重置过账缓冲区 --- 写反馈区间接清除 + /// + /// + public string? ResetFeedBackData(TaskFeedBackEntity taskFeedBackData) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return "PLC 未连接"; // 未连接PLC + } + var dbAddress = CommonTool.Siemens.GetAddressWithNameAndBit($"过账区反馈区{taskFeedBackData.StackerId}", 4 * taskFeedBackData.CountNo); + if (string.IsNullOrEmpty(dbAddress)) + { + return "无法计算偏移量"; + } + var plcNo = taskFeedBackData.StackerId; + var writeResult = CommonTool.Siemens.WritePlcWhithAddress(plcNo, dbAddress, taskFeedBackData.PlcId); + return writeResult.Success ? default : $"清除过账失败,异常信息:{writeResult.Message}"; + } + + + /// + /// 重置过账缓冲区 --- 直接清除 + /// + /// + public string? ClearFeedBackData(TaskFeedBackEntity taskFeedBackData) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return "PLC 未连接"; // 未连接PLC + } + var dbAddress = CommonTool.Siemens.GetAddressWithNameAndBit($"过账区{taskFeedBackData.StackerId}", 6 * taskFeedBackData.CountNo); + if (string.IsNullOrEmpty(dbAddress)) + { + return "无法计算偏移量"; + } + var writeResult = CommonTool.Siemens.WritePlcWhithAddress(1, dbAddress, 0); + return !writeResult.Success ? $"清除过账失败,异常信息:{writeResult.Message}" : default; + } + +} \ No newline at end of file diff --git a/WcsMain/PlcOperation/StackerConvey/StackerConveyOperation.cs b/WcsMain/PlcOperation/StackerConvey/StackerConveyOperation.cs new file mode 100644 index 0000000..a7df500 --- /dev/null +++ b/WcsMain/PlcOperation/StackerConvey/StackerConveyOperation.cs @@ -0,0 +1,255 @@ +using WcsMain.Common; +using WcsMain.Enum.Plc; +using WcsMain.PlcOperation.Entity; +using WcsMain.PlcOperation.Entity.StackerConvey; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.PlcOperation.StackerConvey; + +[Component] +public class StackerConveyOperation +{ + + /// + /// 读取输送机状态 + /// + /// + /// + public (string? errText, StackerConveyInfo? stackerConveyInfo) GetStackerConveyInfo(string standId) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return ("设备尚未连接", default); // 未连接PLC + } + var readResult = CommonTool.Siemens.ReadByteWithName($"输送机状态反馈{standId}", 36); + if (!readResult.Success || readResult.Value == default) + { + return (readResult.Message, default); // 读取失败 + } + var data = readResult.Value; + StackerConveyInfo stackerConveyInfo = new() + { + ConveyNo = Convert.ToInt16(CommonTool.Siemens.Trans(data, 0)), // 输送机编号 + TaskType = Convert.ToInt16(CommonTool.Siemens.Trans(data, 2)), // 任务类型 + StackerForbidden = Convert.ToInt16(CommonTool.Siemens.Trans(data, 4)), // 堆垛机动作禁止 + PlcId = Convert.ToInt32(CommonTool.Siemens.Trans(data, 6)), // 当前任务号 + ControlModel = (StackerConveyModelEnum)Convert.ToInt16(CommonTool.Siemens.Trans(data, 10)), // 控制方式 + StackerConveyStatus = (StackerConveyStatusEnum)Convert.ToInt16(CommonTool.Siemens.Trans(data, 12)), // 库前输送机状态 + VehicleSize = Convert.ToInt16(CommonTool.Siemens.Trans(data, 14)), // 载具尺寸 + Weight = Convert.ToInt16(CommonTool.Siemens.Trans(data, 16)), // 重量 + SensorStatus = Convert.ToUInt32(CommonTool.Siemens.Trans(data, 18)), // 传感器状态 + ApplyCode = Convert.ToInt32(CommonTool.Siemens.Trans(data, 22)), // 申请条码 + RunningCode = Convert.ToInt32(CommonTool.Siemens.Trans(data, 26)), // 正在运行的条码 + ErrCode = Convert.ToInt16(CommonTool.Siemens.Trans(data, 30)), // 错误信息 + Remark = Convert.ToInt32(CommonTool.Siemens.Trans(data, 32)), // 备注 + }; + return (string.Empty, stackerConveyInfo); + } + + + /// + /// 获取输送机任务号 + /// + /// 输送机编号 + /// + public int GetConveyPlcId(string? conveyNo) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return -1; + } + var readResult = CommonTool.Siemens.ReadInt32WithName($"输送机当前任务号{conveyNo}"); + if (readResult.Success) + { + return readResult.Value; + } + return -1; + } + + /// + /// 读取输送机条码 + /// + /// + /// + public string? ReadConveyCode(string? conveyNo) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return default; + } + var readResult = CommonTool.Siemens.ReadInt32WithName($"输送机读码{conveyNo}"); + if (readResult.Success) + { + return readResult.Value.ToString(); + } + return default; + } + + /// + /// 输送机卸货完成 + /// + /// + /// + public string? SetConveyUnloadSuccess(string? conveyNo) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return "PLC尚未连接"; + } + var writeResult = CommonTool.Siemens.WriteBoolWhithName($"输送机卸货完成{conveyNo}", true); + if (writeResult.Success) + { + return string.Empty; + } + return writeResult.Message; + } + + + + /// + /// 获取输送机是否空闲 + /// + /// 输送机编号 + /// + public int GetConveyIsEasy(string? conveyNo) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return -1; + } + var readResult = CommonTool.Siemens.ReadInt16WithName($"输送机空闲{conveyNo}"); + if (readResult.Success) + { + return readResult.Value; + } + return -1; + } + + /// + /// 获取输送机是否有货 + /// + /// 输送机编号 + /// + public int GetConveyIsHaveGoods(string? conveyNo) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + // 未连接PLC + return -1; + } + var readResult = CommonTool.Siemens.ReadInt32WithName($"输送机是否有货{conveyNo}"); + if (readResult.Success) + { + return readResult.Value; + } + return -1; + } + + /// + /// 写入输送机任务,返回错误信息 + /// + /// + /// + public string WriteTask(StackerConveyPlcTask task) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return "PLC尚未连接。"; // 未连接PLC + } + var (writeResult, _) = CommonTool.Siemens.WritePlcWhithName($"输送机写任务{task.StackerConveyId}", + task.PlcId!, + task.TaskType!, + task.GetStand!, + task.InTunnelId!, + task.OutTunnelId!, + task.SetStand!, + task.GetQueue!, + task.GetLine!, + task.GetLayer!, + task.SetQueue!, + task.SetLine!, + task.SetLayer!, + task.GetDeep!, + task.SetDeep!, + task.Size!, + task.Weight!, + task.Code + ); + return writeResult.Success ? string.Empty : "写入失败"; + } + + + + + /// + /// 获取过账数据 ---- 地面站控制 + /// + /// + /// + public List? GetConveyTaskFeedBackData(int dataNum) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return default; // 未连接PLC + } + List taskFeedBackEntities = []; + var readResult = CommonTool.Siemens.ReadByteWithName($"过账区", (ushort)(6 * dataNum)); + if (!readResult.Success || readResult.Value == default) { return default; } + var readData = readResult.Value; + for (var i = 0; i < dataNum; i++) + { + TaskFeedBackEntity taskFeedBackEntity = new() + { + PlcId = Convert.ToInt32(CommonTool.Siemens.Trans(readData, 0 + i * 6)), + FeedBackType = Convert.ToInt16(CommonTool.Siemens.Trans(readData, 4 + i * 6)), + CountNo = i + }; + taskFeedBackEntities.Add(taskFeedBackEntity); + } + return taskFeedBackEntities; + } + + /// + /// 重置过账缓冲区 --- 写反馈区间接清除 ---- 地面站控制 + /// + /// + public string? ResetFeedBackData(TaskFeedBackEntity taskFeedBackData) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return "PLC 未连接"; // 未连接PLC + } + var dbAddress = CommonTool.Siemens.GetAddressWithNameAndBit($"过账区反馈区", 4 * taskFeedBackData.CountNo); + if (string.IsNullOrEmpty(dbAddress)) + { + return "无法计算偏移量"; + } + var writeResult = CommonTool.Siemens.WritePlcWhithAddress(1, dbAddress, taskFeedBackData.PlcId); + return writeResult.Success ? default : $"清除过账失败,异常信息:{writeResult.Message}"; + } + + + /// + /// 重置过账缓冲区 --- 直接清除 ---- 地面站控制 + /// + /// + public string? ClearFeedBackData(TaskFeedBackEntity taskFeedBackData) + { + if (!CommonData.IsConnectPlc || CommonTool.Siemens == default) + { + return "PLC 未连接"; // 未连接PLC + } + var dbAddress = CommonTool.Siemens.GetAddressWithNameAndBit($"过账区", 6 * taskFeedBackData.CountNo); + if (string.IsNullOrEmpty(dbAddress)) + { + return "无法计算偏移量"; + } + var writeResult = CommonTool.Siemens.WritePlcWhithAddress(1, dbAddress, 0); + return !writeResult.Success ? $"清除过账失败,异常信息:{writeResult.Message}" : default; + } + +} \ No newline at end of file diff --git a/WcsMain/Plugins/WcsCirculation.cs b/WcsMain/Plugins/WcsCirculation.cs new file mode 100644 index 0000000..8a5bd89 --- /dev/null +++ b/WcsMain/Plugins/WcsCirculation.cs @@ -0,0 +1,54 @@ +using Autofac; +using CirculateTool; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Plugins; + +/// +/// 新的 WCS 定时任务类,添加 IOC 容器支持,添加非静态变量支持 +/// +[Component] +public class WcsCirculation(IComponentContext componentContext) : StartCirculation +{ + private readonly IComponentContext _componentContext = componentContext; + + public override void StartTask(Type type, object[]? instanceParams = null) + { + object? instance = null; + var methods = type.GetMethods(); + foreach (var method in methods) + { + var attributes = method.GetCustomAttributes(false); + foreach (var attribute in attributes) + { + if (attribute is not CirculationAttribute needDurable) continue; + string methodDescription = needDurable.MethodDescription ?? $"{type.Name}.{method.Name}"; + instance ??= CreateInstance(type); + bool Action() => (bool)(method.Invoke(instance, []) ?? false); + StartTask(Action, methodDescription, needDurable.CirculationTime); + break; + } + } + } + + + private object? CreateInstance(Type type) + { + var constructors = type.GetConstructors(); + var constructorList = constructors.ToList(); + constructorList = [.. constructorList.OrderByDescending(s => s.GetParameters().Length)]; + foreach (var constructor in constructorList) + { + var parameters = constructor.GetParameters(); + if (parameters.Length == 0) return Activator.CreateInstance(type); + List arguments = []; + foreach (var parameter in parameters) + { + object par = _componentContext.Resolve(parameter.ParameterType); + arguments.Add(par); + } + return Activator.CreateInstance(type, [.. arguments]); + } + return Activator.CreateInstance(type); + } +} diff --git a/WcsMain/Plugins/WmsWebApiPost.cs b/WcsMain/Plugins/WmsWebApiPost.cs new file mode 100644 index 0000000..97f01a5 --- /dev/null +++ b/WcsMain/Plugins/WmsWebApiPost.cs @@ -0,0 +1,19 @@ +using ApiTool; +using WcsMain.Business.CommonAction; +using WcsMain.Common; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Plugins; + +/// +/// Wms 的API工具 +/// +[Component] +public class WmsWebApiPost : WebApiPost +{ + public WmsWebApiPost(WMSApiResponseAction wmsApiResponseAction) + { + SetResponseAction(wmsApiResponseAction.WMSApiResponse); + SetBaseUrl(CommonData.AppConfig.WmsBaseAddressApiAddress ?? ""); + } +} diff --git a/WcsMain/Program.cs b/WcsMain/Program.cs new file mode 100644 index 0000000..ae92182 --- /dev/null +++ b/WcsMain/Program.cs @@ -0,0 +1,65 @@ +using Autofac; +using Autofac.Extensions.DependencyInjection; +using System.Text; +using WcsMain; +using WcsMain.Common; +using WcsMain.StartAction; + +Console.Title = "WCS豸ϵͳ"; +Console.OutputEncoding = Encoding.UTF8; +ConsoleLog.DisbleQuickEditMode(); + +var builder = WebApplication.CreateBuilder(args); + +// лز +var env = builder.Environment; +LoadingRunningData.Loading(env.IsDevelopment()); // ϵͳϢ˲豨 + +// Add services to the container. +//builder.Services.Replace(ServiceDescriptor.Transient()); +builder.Services.AddControllers(options => +{ + //options.Filters.Add(); +}).AddJsonOptions(options => +{ + // ޸ķãԭʵ + options.JsonSerializerOptions.PropertyNamingPolicy = null; +}); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddHostedService(); +// ӿκ˷ +builder.Services.AddCors(options => +{ + options.AddPolicy("any", policyBuilder => + { + policyBuilder.WithOrigins("*").AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); + }); +}); + +builder.WebHost.UseUrls(CommonData.Settings.UseUrls ?? ["http://*:890"]); // ַ appSettings.json ãĬֵ + +// ʹ autoFac 滻ע +builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); +builder.Host.ConfigureContainer(builder => +{ + builder.RegisterModule(); +}); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseCors("any"); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/WcsMain/Properties/PublishProfiles/FolderProfile.pubxml b/WcsMain/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..e3bd2c3 --- /dev/null +++ b/WcsMain/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,23 @@ + + + + + true + false + true + Release + Any CPU + FileSystem + bin\Release\net8.0\publish\ + FileSystem + <_TargetId>Folder + + net8.0 + win-x64 + true + ed59f010-b3e5-4e19-be65-18053645dfc5 + true + + \ No newline at end of file diff --git a/WcsMain/Properties/PublishProfiles/FolderProfile.pubxml.user b/WcsMain/Properties/PublishProfiles/FolderProfile.pubxml.user new file mode 100644 index 0000000..567fc04 --- /dev/null +++ b/WcsMain/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -0,0 +1,11 @@ + + + + + <_PublishTargetUrl>F:\AProject\A菲达宝开项目\2024-02_隆成立库\应用程序\wcs_serve_cs\wcs_serve_cs\bin\Release\net8.0\publish\ + True|2024-03-29T07:42:25.2332590Z;False|2024-03-29T15:41:29.1754215+08:00;True|2024-03-29T15:21:55.1373612+08:00;True|2024-03-28T09:54:32.8968372+08:00;True|2024-01-28T15:05:36.1055501+08:00;True|2024-01-28T15:02:06.6945727+08:00;True|2024-01-28T14:56:23.0500171+08:00;True|2024-01-20T20:29:00.5459863+08:00; + + + \ No newline at end of file diff --git a/WcsMain/Properties/PublishProfiles/FolderProfile2.pubxml b/WcsMain/Properties/PublishProfiles/FolderProfile2.pubxml new file mode 100644 index 0000000..8e9fed3 --- /dev/null +++ b/WcsMain/Properties/PublishProfiles/FolderProfile2.pubxml @@ -0,0 +1,23 @@ + + + + + true + false + true + Release + Any CPU + FileSystem + bin\Release\net8.0\publish\ + FileSystem + <_TargetId>Folder + + net8.0 + win-x86 + true + ed59f010-b3e5-4e19-be65-18053645dfc5 + true + + \ No newline at end of file diff --git a/WcsMain/Properties/PublishProfiles/FolderProfile2.pubxml.user b/WcsMain/Properties/PublishProfiles/FolderProfile2.pubxml.user new file mode 100644 index 0000000..4a31a1c --- /dev/null +++ b/WcsMain/Properties/PublishProfiles/FolderProfile2.pubxml.user @@ -0,0 +1,11 @@ + + + + + <_PublishTargetUrl>F:\AProject\A菲达宝开项目\(2023-11)徐州工厂立库\应用程序\wcs_serve_cs\wcs_serve_cs\bin\Release\net8.0\publish\ + True|2023-12-21T07:04:28.6290873Z;True|2023-12-21T14:59:03.4454135+08:00;True|2023-12-21T14:51:08.6690406+08:00;True|2023-12-21T14:26:42.6801144+08:00;False|2023-12-21T14:26:14.3256943+08:00;True|2023-12-21T14:13:42.5511801+08:00;True|2023-12-21T13:56:38.5871005+08:00;True|2023-12-19T12:19:57.9900187+08:00;True|2023-12-19T11:53:33.6930379+08:00;True|2023-12-17T12:51:32.6510827+08:00;False|2023-12-17T12:49:32.9022541+08:00; + + + \ No newline at end of file diff --git a/WcsMain/Properties/launchSettings.json b/WcsMain/Properties/launchSettings.json new file mode 100644 index 0000000..2507863 --- /dev/null +++ b/WcsMain/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:29065", + "sslPort": 0 + } + }, + "profiles": { + "WcsMain": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:18990", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/WcsMain/Socket/SocketOperation.cs b/WcsMain/Socket/SocketOperation.cs new file mode 100644 index 0000000..8e86bc3 --- /dev/null +++ b/WcsMain/Socket/SocketOperation.cs @@ -0,0 +1,76 @@ +using System.Text; +using SocketTool; +using SocketTool.Entity; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.Business.CommonAction; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Socket; + +/// +/// socket 连接类 +/// +[Component] +public class SocketOperation(AppTcpDao socketDao) +{ + private readonly AppTcpDao _socketDao = socketDao; + + /// + /// 连接 socket + /// + public void Connect() + { + /* 查找所有待连接的 socket 信息 */ + List? sockets = _socketDao.GetNeedUseSocket(1); + if (sockets == default || sockets.Count < 1) + { + ConsoleLog.Info($"[提示]没有找到需要连接的 socket 信息,将不会进行连接。"); + return; + } + List socketInfo = []; + foreach (var socket in sockets) + { + socketInfo.Add(socket.TcpIp); + } + /* 注册事件,连接 socket */ + SocketClient socketClient = new(Encoding.UTF8, [.. socketInfo]); + socketClient.SocketConnecting += address => + { + ConsoleLog.Info($"socket {address} 正在连接..."); + }; + socketClient.SocketOffline += address => + { + ConsoleLog.Error($"[警告]socket {address} 失去连接..."); + }; + socketClient.SocketOnline += address => + { + ConsoleLog.Info($"socket {address} 连接成功。"); + }; + socketClient.SocketConnectFail += (address, exception) => + { + ConsoleLog.Error($"[警告]socket {address} 连接失败,异常信息:{exception.Message}"); + }; + socketClient.RecevErrEvent += (address, exception) => + { + ConsoleLog.Error($"[警告]socket {address} 接收数据异常,异常信息:{exception.Message}"); + }; + socketClient.HandleCodeInfo += SocketClientOnHandleCodeInfo; + socketClient.Connect(); + } + + //private ScanCodeAction? scanCodeAction; + + /// + /// 处理收到的数据 + /// + /// + /// + /// 扫码器方法所在的类为 + /// + private void SocketClientOnHandleCodeInfo(ScanCodeClass codeEntity) + { + // 后面单独表配置 + // TODO + } +} \ No newline at end of file diff --git a/WcsMain/StartAction/AutofacModule.cs b/WcsMain/StartAction/AutofacModule.cs new file mode 100644 index 0000000..c1df4a9 --- /dev/null +++ b/WcsMain/StartAction/AutofacModule.cs @@ -0,0 +1,31 @@ +using Autofac; +using System.Reflection; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.StartAction; + +public class AutofacModule : Autofac.Module +{ + /* + * 此处为依赖注入,注入的是单例模式 + */ + + protected override void Load(ContainerBuilder builder) + { + var assembly = Assembly.GetExecutingAssembly(); + // 注册 Service + builder.RegisterAssemblyTypes(assembly) + .Where(w => w.GetCustomAttribute(typeof(ServiceAttribute)) != default) + .SingleInstance(); + // 注册 Component + builder.RegisterAssemblyTypes(assembly) + .Where(w => w.GetCustomAttribute(typeof(ComponentAttribute)) != default) + .SingleInstance(); + // 添加属性注入 --- 一般不建议使用 + builder.RegisterAssemblyTypes(assembly) + .Where(w => w.GetCustomAttribute(typeof(AutowiredAttribute)) != default) + .PropertiesAutowired(new AutowiredSelector()); + + + } +} diff --git a/WcsMain/StartAction/AutowiredSelector.cs b/WcsMain/StartAction/AutowiredSelector.cs new file mode 100644 index 0000000..b2bb043 --- /dev/null +++ b/WcsMain/StartAction/AutowiredSelector.cs @@ -0,0 +1,13 @@ +using Autofac.Core; +using System.Reflection; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.StartAction; + +public class AutowiredSelector : IPropertySelector +{ + public bool InjectProperty(PropertyInfo propertyInfo, object instance) + { + return propertyInfo.GetCustomAttribute(typeof(AutowiredAttribute)) != default; + } +} diff --git a/WcsMain/StartAction/HostService.cs b/WcsMain/StartAction/HostService.cs new file mode 100644 index 0000000..87b174d --- /dev/null +++ b/WcsMain/StartAction/HostService.cs @@ -0,0 +1,75 @@ +using WcsMain.Common; + +namespace WcsMain.StartAction; + +/// +/// 一个类,用于触发启动关闭事件 +/// +public class HostService(ServiceStart serverStart) : IHostedLifecycleService +{ + private readonly ServiceStart _serverStart = serverStart; + + public Task StartAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + public Task StartingAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + public Task StartedAsync(CancellationToken cancellationToken) + { + return Task.Run(() => + { + string? loadingResult = LoadingRunningData.GetResult(); + if (!string.IsNullOrEmpty(loadingResult)) + { + ConsoleLog.Error($"【异常】启动加载运行文件出错,WCS功能受到限制,您可以检查网络连接后重新启动或者联系我们,参考信息:{loadingResult}"); + return; + } + ConsoleLog.Info("WCS服务启动中,请稍后..."); + var apiOnly = CommonData.Settings.ApplicationConfig.ApiOnly; + if (apiOnly == null) + { + ConsoleLog.Error("【异常】配置文件加载失败,WCS 启动失败"); + return; + } + if ((bool)apiOnly) + { + ConsoleLog.Warning("【警告】当前运行在 【仅 API】 模式下"); + } + else + { + _serverStart.Start(); + } + ConsoleLog.Success("WCS服务启动完成"); + }, cancellationToken); + } + + + + /// + /// 关闭事件 + /// + /// + /// + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + public Task StoppedAsync(CancellationToken cancellationToken) + { + return Task.Run(() => + { + ConsoleLog.Info("WCS服务已经关闭"); + }, cancellationToken); + } + + public Task StoppingAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/WcsMain/StartAction/LoadingRunningData.cs b/WcsMain/StartAction/LoadingRunningData.cs new file mode 100644 index 0000000..993e305 --- /dev/null +++ b/WcsMain/StartAction/LoadingRunningData.cs @@ -0,0 +1,116 @@ +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; +using WcsMain.Common; +using SqlSugar; +using WcsMain.AppEntity.SystemData; + +namespace WcsMain.StartAction; + +/// +/// WCS 程序启动前加载运行数据 ---- 链式调用,返回错误信息 +/// +public class LoadingRunningData +{ + /// + /// 错误信息 + /// + private static string _errMsg = string.Empty; + + /// + /// 是否是开发环境 + /// + private static bool _isDevelopment = true; + + /// + /// 加载系统运行数据数据 + /// + /// + public static void Loading(bool isDevelopment) + { + _isDevelopment = isDevelopment;// 将开发环境暴露到此类全局 + + LoadingAppSetting(); // 加载 Appsettings.json 文件里的设置项 + LoadingWcsDataBase(); // 加载 Wcs 数据库连接字符串 + + // 加载数据库中的 + + } + + /// + /// 返回加载结果 + /// + /// + public static string? GetResult() => _errMsg; + + + /// + /// 加载 Appsettings.json 文件里的设置项 + /// + public static void LoadingAppSetting() + { + if (!string.IsNullOrEmpty(_errMsg)) return; + ConsoleLog.Info("正在加载配置文件..."); + string setStr; + try + { + using (StreamReader sr = new("appsettings.json")) + { + setStr = sr.ReadToEnd(); + } + JObject jsonObj = JObject.Parse(setStr); + JObject? settinsOnj = (JObject?)jsonObj["Settings"]; + if (settinsOnj == default) + { + _errMsg = "加载系统设置文件失败,请检查是否存在 Settings 键"; + return; + } + CommonData.Settings = JsonConvert.DeserializeObject(settinsOnj.ToString()); + } + catch(Exception ex) + { + _ = ex; + _errMsg = "加载系统设置文件失败,请检查是否存在 appsettings.json 文件"; + } + } + + + + /// + /// 加载数据库文件 + /// + private static void LoadingWcsDataBase() + { + if (!string.IsNullOrEmpty(_errMsg)) return; + ConsoleLog.Info("正在加载数据库配置..."); + string wcsDataBaseConnectString; + if (_isDevelopment) + { + if(string.IsNullOrEmpty(CommonData.Settings.DBMysqlLocal)) + { + _errMsg = "调试环境下加载WCS数据库连接字符串失败"; + return; + } + wcsDataBaseConnectString = CommonData.Settings.DBMysqlLocal; + } + else + { + if (string.IsNullOrEmpty(CommonData.Settings.DBMysql)) + { + _errMsg = "运行环境下加载WCS数据库连接字符串失败"; + return; + } + wcsDataBaseConnectString = CommonData.Settings.DBMysql; + } + CommonTool.DbServe = new SqlSugarScope(new ConnectionConfig() + { + IsAutoCloseConnection = true, + ConfigId = "0", + DbType = DbType.MySql, + ConnectionString = wcsDataBaseConnectString + }); + } + + + + +} diff --git a/WcsMain/StartAction/ServiceStart.cs b/WcsMain/StartAction/ServiceStart.cs new file mode 100644 index 0000000..d1928a9 --- /dev/null +++ b/WcsMain/StartAction/ServiceStart.cs @@ -0,0 +1,175 @@ +using WcsMain.Socket; +using WcsMain.PlcOperation; +using WcsMain.Common; +using WcsMain.WcsAttribute.AutoFacAttribute; +using WcsMain.Plugins; +using System.Reflection; +using WcsMain.AppEntity.SystemData; +using WcsMain.DataBase.Dao; +using WcsMain.DataBase.TableEntity; +using WcsMain.WcsAttribute.AppConfig; +using WcsMain.Business.Convey; + +namespace WcsMain.StartAction; + +/// +/// 服务启动主体类 +/// +[Component] +public class ServiceStart(WcsCirculation wcsCirculation, ConnectPLCs connectPLCs, SocketOperation socketOperation, + AppStackerDao appStackerDao, AppLocationDao appLocationDao, AppConfigDao appConfigDao, ConnectPlcServe connectPlcServe) +{ + private readonly AppConfigDao _appconfigDao = appConfigDao; + private readonly AppLocationDao _applocationDao = appLocationDao; + private readonly AppStackerDao _appStackerDao = appStackerDao; + private readonly SocketOperation _socketOperation = socketOperation; + private readonly ConnectPLCs _connectPlcs = connectPLCs; + private readonly WcsCirculation _wcsCirculation = wcsCirculation; + private readonly ConnectPlcServe _connectPlcServe = connectPlcServe; + + private static string _errMsg = string.Empty; + /// + /// 启动 ——-- 主方法 + /// + public void Start() + { + /* 指定线程池规格 */ + ThreadPool.SetMinThreads(30, 10); + LoadingConfig(); // 加载数据库中的配置项 (config 表) + LoadingStackerData(); // 加载数据库中的堆垛机信息 + LoadingLocationData(); // 加载数据库中的库位信息 + + if(!string.IsNullOrEmpty(_errMsg)) + { + ConsoleLog.Error($"【异常】启动加载运行文件出错,WCS功能受到限制,您可以检查网络连接后重新启动或者联系我们,参考信息:{_errMsg}"); + return; + } + + CreatePlcClient(); // 连接 PLC 客户端 + CreateSocketClient(); // Socket客户端 + CreateCieculateTask();// 创建并启用定时器 + } + + /// + /// 创建并连接 Plc + /// + public void CreatePlcClient() + { + if (CommonData.AppConfig.UseConnectPlc == "1") // 1 表示允许连接PLC + { + _connectPlcs.ConnectPlc(); + } + } + + /// + /// 创建并运行 Socket 客户端 + /// + public void CreateSocketClient() + { + if (CommonData.AppConfig.UseSocket == "1") // 1 表示允许开启Socket + { + _socketOperation.Connect(); + } + } + + + public void CreateTcpClient() + { + _connectPlcServe.SetBaseAction(); + _connectPlcServe.ConnectPlc(); + } + + + /// + /// 创建并启用定时器 + /// + public void CreateCieculateTask() + { + if (CommonData.AppConfig.UseCirculation == "1") // 1 表示允许开启 定时器 + { + _wcsCirculation.ExceptionHandler += (methodDescription, ex) => + { + ConsoleLog.Error($"定时器:{methodDescription} 发生异常,异常信息:{ex}"); + }; + _wcsCirculation.MessageHandler += (msg) => + { + //ConsoleLog.Tip(msg); + }; + _wcsCirculation.StartAssemblyCirculation(GetType().Assembly); + } + } + + + /// + /// 加载数据库内的 Config 配置信息 + /// + public void LoadingConfig() + { + if (!string.IsNullOrEmpty(_errMsg)) return; + ConsoleLog.Info("正在加载数据库配置信息..."); + List? Configs = _appconfigDao.Query(); + if (Configs == default) + { + _errMsg = "加载 Config 资源失败,请检查数据库服务器连接是否正常"; + return; + } + AppConfigEntity? appConfigEntity = new(); + var type = appConfigEntity.GetType(); + var propertys = type.GetProperties(); + foreach (var property in propertys) + { + string? propertyName = property.Name; + var attribute = property.GetCustomAttribute(typeof(ConfigKeyAttribute)); + if (attribute != default) + { + var configKeyAttribute = attribute as ConfigKeyAttribute; + if (configKeyAttribute != default && configKeyAttribute.KeyName != default) + { + propertyName = configKeyAttribute.KeyName; + } + } + AppConfig? appConfig = Configs.Find(f => f.ConfigKey == propertyName); + if (appConfig == default) continue; + property.SetValue(appConfigEntity, appConfig.ConfigValue); + } + CommonData.AppConfig = appConfigEntity; + } + + /// + /// 加载堆垛机数据 + /// + public void LoadingStackerData() + { + if (!string.IsNullOrEmpty(_errMsg)) return; + ConsoleLog.Info("正在加载堆垛机参数信息..."); + List? appStackers = _appStackerDao.Select(); + if (appStackers == default) + { + _errMsg = "加载堆垛机参数信息失败,请检查数据库服务器连接是否正常"; + CommonData.AppStackers = []; + return; + } + CommonData.AppStackers = appStackers; + } + + + /// + /// 加载库位信息 + /// + public void LoadingLocationData() + { + if (!string.IsNullOrEmpty(_errMsg)) return; + ConsoleLog.Info("正在加载库位信息..."); + List? appLocations = _applocationDao.Select(); + if (appLocations == default) + { + _errMsg = "加载库位信息失败,请检查数据库服务器连接是否正常"; + CommonData.AppLocations = []; + return; + } + CommonData.AppLocations = appLocations; + } + + + +} \ No newline at end of file diff --git a/WcsMain/StaticData/StaticString.cs b/WcsMain/StaticData/StaticString.cs new file mode 100644 index 0000000..5182285 --- /dev/null +++ b/WcsMain/StaticData/StaticString.cs @@ -0,0 +1,13 @@ +namespace WcsMain.StaticData; + +/// +/// 常量字符串 +/// +public static class StaticString +{ + public const string WMS = "WMS"; + public const string WCS = "WCS"; + public const string PLC = "PLC"; + + +} diff --git a/WcsMain/Tcp/Client/BaseTcpClient.cs b/WcsMain/Tcp/Client/BaseTcpClient.cs new file mode 100644 index 0000000..c03c22c --- /dev/null +++ b/WcsMain/Tcp/Client/BaseTcpClient.cs @@ -0,0 +1,261 @@ +using System.Text; +using System.Text.RegularExpressions; +using WcsMain.DataBase.TableEntity; +using WcsMain.Tcp.Entity; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Tcp.Client; + +/// +/// Wcs 的Tcp 客户端 +/// +[Component] +public class BaseTcpClient +{ + /// + /// 连接中事件 + /// + private Action? _connecting; + + /// + /// 连接失败事件 + /// + private Action? _connectFail; + + /// + /// 连接成功事件 + /// + private Action? _connectSuccess; + + /// + /// 连接断开事件 + /// + private Action? _connectOffline; + + /// + /// 获取数据事件 + /// + private Action? _getMessage; + + + public void SetConnecting(Action action) => _connecting = action; + public void SetConnectFailAction(Action action) => _connectFail = action; + public void SetConnectSuccess(Action action) => _connectSuccess = action; + public void SetConnectOffline(Action action) => _connectOffline = action; + public void GetMessage(Action action) => _getMessage = action; + + /// + /// 当前需要连接的服务端数量 + /// + protected List tcpServeConnectionDatas = []; + + /// + /// 添加服务端基础数据 + /// + /// + public void SetBaseTcpServe(List? tcps) + { + if (tcps == default || tcps.Count == 0) return; + foreach (var tcp in tcps) + { + if (!CheckIpAndPort(tcp.TcpIp, tcp.TcpPort)) + { + ConsoleLog.Warning($"【警告】TCP服务端地址:{tcp.TcpIp}:{tcp.TcpPort} 格式不满足要求"); + continue; + } + tcpServeConnectionDatas.Add(new() + { + DisplayName = tcp.DisplayName, + TcpServe = tcp + }); + } + } + + /// + /// 开始连接服务端 + /// + public void Connect() + { + if (tcpServeConnectionDatas.Count < 1) return; + tcpServeConnectionDatas.ForEach(ConnectAsync); + ReConnectAsync(); // 开启重连属性 + MonitorServeConnectedAsync(); // 检测客户端是否断开 + } + + /// + /// 连接到服务端并接收数据 + /// + /// + private async void ConnectAsync(TcpServeConnectionData serveData) + { + try + { + if(serveData.IsConnected == Enum.General.TrueFalseEnum.TRUE) return; + _connecting?.Invoke(serveData); + serveData.TcpClient = new System.Net.Sockets.TcpClient(); + serveData.TcpClient.Connect(serveData.TcpServe!.TcpIp!, (int)serveData.TcpServe.TcpPort!); + tcpServeConnectionDatas.Find(tcp => tcp.DisplayName == serveData.DisplayName)!.IsConnected = Enum.General.TrueFalseEnum.TRUE; + _connectSuccess?.Invoke(serveData); + while (true) + { + var networkStream = serveData.TcpClient.GetStream(); + byte[] bytes = new byte[1024]; + int readLength = await networkStream.ReadAsync(bytes); + if (readLength > 0) + { + serveData.RecvMsgTime = DateTime.Now; + _getMessage?.BeginInvoke(serveData, Encoding.ASCII.GetString(bytes), null, null); + continue; + } + _connectOffline?.Invoke(serveData); + tcpServeConnectionDatas.Find(tcp => tcp.DisplayName == serveData.DisplayName)!.IsConnected = Enum.General.TrueFalseEnum.FALSE; + break; + } + } + catch (Exception ex) + { + _ = ex; + tcpServeConnectionDatas.Find(tcp => tcp.DisplayName == serveData.DisplayName)!.IsConnected = Enum.General.TrueFalseEnum.FALSE; + _connectFail?.Invoke(serveData, ex); + } + } + + /// + /// 重连 + /// + private async void ReConnectAsync() + { + if (tcpServeConnectionDatas.Count < 1) return; + CancellationTokenSource cts = new(); + PeriodicTimer timer = new(new TimeSpan(0, 0, 0, 1, 0)); + while (await timer.WaitForNextTickAsync(cts.Token)) + { + foreach (var tcpServe in tcpServeConnectionDatas) + { + if (tcpServe.IsConnected != Enum.General.TrueFalseEnum.FALSE) continue; + tcpServe.IsConnected = default; + ConnectAsync(tcpServe); + } + } + } + + /// + /// 监控客户端是否断开 + /// + public virtual async void MonitorServeConnectedAsync() + { + if (tcpServeConnectionDatas.Count < 1) return; + CancellationTokenSource cts = new(); + PeriodicTimer timer = new(new TimeSpan(0, 0, 0, 1, 0)); + while (await timer.WaitForNextTickAsync(cts.Token)) + { + List checkTasks = []; + foreach (var tcpServe in tcpServeConnectionDatas) + { + if (tcpServe.IsConnected == Enum.General.TrueFalseEnum.FALSE || tcpServe.IsConnected == default) continue; + // 检测与服务端是否断开 ---- 多种检测方式并存 + checkTasks.Add(Task.Factory.StartNew(() => + { + // Ping 地址 + System.Net.NetworkInformation.Ping ping = new(); + var pingResult = ping.Send(tcpServe.TcpServe!.TcpIp!, 100); + if(pingResult.Status != System.Net.NetworkInformation.IPStatus.Success) + { + tcpServe.TcpClient?.Close(); + //tcpServe.IsConnected = Enum.General.TrueFalseEnum.FALSE; + return; + } + if (tcpServe.TcpClient == default) return; + // 尝试发送消息 + var networkStream = tcpServe.TcpClient.GetStream(); + byte[] bytes = []; + try + { + networkStream.Write(bytes); + } + catch + { + tcpServe.TcpClient?.Close(); + //tcpServe.IsConnected = Enum.General.TrueFalseEnum.FALSE; + return; + } + })); + } + Task.WaitAll([.. checkTasks]); + } + } + + /// + /// 向指定别称的客户端发送消息 + /// + /// + /// + /// + public TcpClientSendResult Send(string? value, params string[] displayNames) + { + if(string.IsNullOrEmpty(value)) + { + return new() { Success = false, Exception = new Exception("传入的值为空") }; + } + TcpClientSendResult tcpClientSendResult = new() { Success = true }; + // 指定发送 + List sendTasks = []; + foreach (var tcpServe in tcpServeConnectionDatas) + { + if (displayNames.Length > 0 && !displayNames.Contains(tcpServe.DisplayName)) { continue; } + if (tcpServe.TcpClient == default || tcpServe.IsConnected != Enum.General.TrueFalseEnum.TRUE) + { + tcpClientSendResult = new() { Success = false, Exception = new Exception($"别称:{tcpServe.DisplayName} 的Tcp连接不可用") }; + } + else + { + sendTasks.Add(Task.Factory.StartNew(() => + { + var sendNetworkStream = tcpServe.TcpClient.GetStream(); + try + { + sendNetworkStream.Write(Encoding.ASCII.GetBytes(value)); + } + catch (Exception ex) + { + tcpClientSendResult = new() { Success = false, Exception = ex }; + } + })); + } + } + if(sendTasks.Count == 0) return new() { Success = false, Exception = new Exception("没有要发送的客户端") }; + Task.WaitAll([.. sendTasks]); + return tcpClientSendResult; + } + + + + + + + + + + + + + + /// + /// 检查IP地址和端口号是否满足格式 + /// 如果格式错误返回0,否则返回Int格式的端口号 + /// + /// + /// + /// + private static bool CheckIpAndPort(string? ip, int? port) + { + /* 检测 ip 格式是否正确 */ + if (string.IsNullOrEmpty(ip)) return false; + string ipRegexString = "^((1[0-9][0-9]\\.)|(2[0-4][0-9]\\.)|(25[0-5]\\.)|([1-9][0-9]\\.)|([0-9]\\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]))$"; + bool isIpOk = Regex.IsMatch(ip, ipRegexString); + if (!isIpOk) return false; + /* 检测 port 端口是否正确 */ + return port >= 1 && port < 65535; + } + +} diff --git a/WcsMain/Tcp/Client/PlcTcpClient.cs b/WcsMain/Tcp/Client/PlcTcpClient.cs new file mode 100644 index 0000000..7c978b3 --- /dev/null +++ b/WcsMain/Tcp/Client/PlcTcpClient.cs @@ -0,0 +1,117 @@ +using System.Diagnostics; +using System.Text.RegularExpressions; +using WcsMain.Tcp.Entity; +using WcsMain.Tcp.Entity.Message; +using WcsMain.WcsAttribute.AutoFacAttribute; + +namespace WcsMain.Tcp.Client; + +/// +/// 专用与连接 PLC 的Tcp客户端 +/// +[Component] +public partial class PlcTcpClient : BaseTcpClient +{ + + /// + /// 存储收到的消息 + /// + private Dictionary msgInfos = []; + + /// + /// 重写检测离线方法 ---- 上一次传输数据的时间和当前时间差 3 秒判断断开 + /// + public async override void MonitorServeConnectedAsync() + { + if (tcpServeConnectionDatas.Count < 1) return; + CancellationTokenSource cts = new(); + PeriodicTimer timer = new(new TimeSpan(0, 0, 0, 1, 0)); + while (await timer.WaitForNextTickAsync(cts.Token)) + { + foreach (var tcpServe in tcpServeConnectionDatas) + { + if (tcpServe.IsConnected == Enum.General.TrueFalseEnum.FALSE || tcpServe.IsConnected == default) continue; + // 计算上一次接收消息的时间和当前的时间差,超过三秒判断断开 + var lastRevMsgTime = tcpServe.RecvMsgTime; + var timespan = DateTime.Now - lastRevMsgTime; + var timespanSeconds = timespan.TotalSeconds; + if (timespanSeconds > 3) // 心跳超时时间 + { + tcpServe.TcpClient?.Close(); + tcpServe.IsConnected = Enum.General.TrueFalseEnum.FALSE; + continue; + } + } + } + } + + /// + /// 发送信息到指定别称的客户端 + /// + /// + /// + /// + /// + public PlcTcpClientSendResult SendWithResult(string? value, string? displayName, int timeout) + { + if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(displayName)) + { + return new() { Success = false, Exception = new Exception("传入的参数为空") }; + } + MsgHeader? header = GetMsgHeader(value); + if(header == default || string.IsNullOrEmpty(header.MsgId)) return new() { Success = false, Exception = new Exception("发送的信息不是标准报文格式") }; + Stopwatch stopwatch = Stopwatch.StartNew(); + var sendResult = Send(value, displayName); // 发送消息 + if(!sendResult.Success) return new() { Success = sendResult.Success, Exception = sendResult.Exception }; // 发送失败 + MsgInfo? msgInfo = default; + while (stopwatch.ElapsedMilliseconds < timeout) + { + bool exist = msgInfos.TryGetValue(header.MsgId, out msgInfo); + if (exist) break; + } + if(msgInfo == default) return new() { Success = false, Exception = new Exception("发送的信息不是标准报文格式"), UseTime = stopwatch.ElapsedMilliseconds}; + return new() + { + Success = true, + ResponseData = msgInfo, + UseTime = stopwatch.ElapsedMilliseconds + }; + } + + /// + /// 获取msg的Header + /// + /// + /// + public MsgHeader? GetMsgHeader(string? value) + { + if (string.IsNullOrEmpty(value)) return default; + if (!RegexMsgFormat().IsMatch(value)) return default; + string[] msgDatas = value.Split(';'); + if(msgDatas.Length < 4 ) return default; + var msgHeader = new MsgHeader() + { + MsgType = msgDatas[0].Replace("<", ""), + ClientId = msgDatas[1], + MsgId = msgDatas[2], + MsgTag = msgDatas[3], + }; + return msgHeader; + } + + + + + + + + + + + + + + + [GeneratedRegex("^<.+\\>$")] + private static partial Regex RegexMsgFormat(); +} diff --git a/WcsMain/Tcp/Entity/Convey/GetRouterData.cs b/WcsMain/Tcp/Entity/Convey/GetRouterData.cs new file mode 100644 index 0000000..171343a --- /dev/null +++ b/WcsMain/Tcp/Entity/Convey/GetRouterData.cs @@ -0,0 +1,63 @@ +using WcsMain.Tcp.Entity.Message; + +namespace WcsMain.Tcp.Entity.Convey; + +/// +/// PLC 向WCS请求分拣口时的请求数据 +/// +public class GetRouterData : MsgHeader +{ + /// + /// 请求位置 + /// + public string? Area { get; set; } + + /// + /// 分拣口庄涛 + /// + public string? SortStatus { get; set; } + + /// + /// 条码 + /// + public string? Code { get; set; } + + /// + /// 尺寸 + /// + public string? Size { get; set; } + + /// + /// 重量 + /// + public decimal? Weight { get; set; } + + /// + /// 长 + /// + public decimal? Length { get; set; } + + /// + /// 宽 + /// + public decimal? Width { get; set; } + + /// + /// 高 + /// + public decimal? Hight { get; set; } + + /// + /// 备用1 + /// + public string? Spare1 { get; set; } + + /// + /// 备用2 + /// + public string? Spare2 { get; set; } + + + + +} diff --git a/WcsMain/Tcp/Entity/Convey/SetRouterData.cs b/WcsMain/Tcp/Entity/Convey/SetRouterData.cs new file mode 100644 index 0000000..57c9c62 --- /dev/null +++ b/WcsMain/Tcp/Entity/Convey/SetRouterData.cs @@ -0,0 +1,78 @@ +using WcsMain.Tcp.Entity.Message; + +namespace WcsMain.Tcp.Entity.Convey; + +/// +/// 回复 PLC 路向的实体 +/// +public class SetRouterData : MsgHeader +{ + /// + /// 消息标记 + /// + public string MagTag { get; set; } = "STROUTER"; + + /// + /// 请求位置 + /// + public string? Area { get; set; } + + /// + /// 条码 + /// + public string? Code { get; set; } + + /// + /// 尺寸 + /// + public string? Size { get; set; } = "0"; + + /// + /// 重量 + /// + public decimal Weight { get; set; } = decimal.Zero; + + /// + /// 长 + /// + public decimal Length { get; set; } = decimal.Zero; + + /// + /// 宽 + /// + public decimal Width { get; set; } = decimal.Zero; + + /// + /// 高 + /// + public decimal Hight { get; set; } = decimal.Zero; + + /// + /// 任务号 + /// + public int? PlcId { get; set; } + + /// + /// 路向 + /// + public int? Router { get; set; } + + /// + /// 备用1 + /// + public string? Spare1 { get; set; } + + /// + /// 备用2 + /// + public string? Spare2 { get; set; } + + + public override string ToString() + { + string body = string.Join(';', MsgType, ClientId, MsgId, MsgTag, Area, Code, Size, Weight.ToString("N4"), + Length.ToString("N4"), Width.ToString("N4"), Hight.ToString("N4"), PlcId, Router, Spare1, Spare2); + return string.Concat("<", body, ">"); + } + +} diff --git a/WcsMain/Tcp/Entity/Message/MsgHeader.cs b/WcsMain/Tcp/Entity/Message/MsgHeader.cs new file mode 100644 index 0000000..1d8729f --- /dev/null +++ b/WcsMain/Tcp/Entity/Message/MsgHeader.cs @@ -0,0 +1,29 @@ +namespace WcsMain.Tcp.Entity.Message; + +/// +/// PLC 报文的消息头 +/// +public class MsgHeader +{ + /// + /// 消息类型 + /// + public string? MsgType { get; set; } + + /// + /// 客户端编号 + /// + public string? ClientId { get; set; } + + /// + /// 消息号 + /// + public string? MsgId { get; set; } + + /// + /// 消息标记 + /// + public string? MsgTag { get; set; } + + +} diff --git a/WcsMain/Tcp/Entity/Message/MsgInfo.cs b/WcsMain/Tcp/Entity/Message/MsgInfo.cs new file mode 100644 index 0000000..84002fc --- /dev/null +++ b/WcsMain/Tcp/Entity/Message/MsgInfo.cs @@ -0,0 +1,35 @@ +namespace WcsMain.Tcp.Entity.Message; + +/// +/// PLC报文的详细信息 +/// +public class MsgInfo +{ + /// + /// 收到消息的服务端的别称 + /// + public string? DisplayName { get; set; } + + /// + /// 消息编号 + /// + public string? MsgId { get; set; } + + /// + /// 消息头 + /// + public MsgHeader? Header { get; set; } + + /// + /// 完整消息内容 + /// + public string? Message { get; set; } + + /// + /// 收到消息的时间 + /// + public DateTime RecvDatetime { get; set; } + + + +} diff --git a/WcsMain/Tcp/Entity/PlcTcpClientSendResult.cs b/WcsMain/Tcp/Entity/PlcTcpClientSendResult.cs new file mode 100644 index 0000000..00cb4fe --- /dev/null +++ b/WcsMain/Tcp/Entity/PlcTcpClientSendResult.cs @@ -0,0 +1,16 @@ +using WcsMain.Tcp.Entity.Message; + +namespace WcsMain.Tcp.Entity; + +public class PlcTcpClientSendResult : TcpClientSendResult +{ + /// + /// 返回的信息 + /// + public MsgInfo? ResponseData { get; set; } + + /// + /// 耗时 + /// + public long? UseTime { get; set; } +} diff --git a/WcsMain/Tcp/Entity/TcpClientSendResult.cs b/WcsMain/Tcp/Entity/TcpClientSendResult.cs new file mode 100644 index 0000000..2fd0933 --- /dev/null +++ b/WcsMain/Tcp/Entity/TcpClientSendResult.cs @@ -0,0 +1,19 @@ +namespace WcsMain.Tcp.Entity; + +/// +/// 作为 Tcp客户端发送时的返回信息 +/// +public class TcpClientSendResult +{ + /// + /// 发送是否成功 + /// + public bool Success { get; set; } + + /// + /// 发送时的异常 + /// + public Exception? Exception { get; set; } + + +} diff --git a/WcsMain/Tcp/Entity/TcpServeConnectionData.cs b/WcsMain/Tcp/Entity/TcpServeConnectionData.cs new file mode 100644 index 0000000..5e93bea --- /dev/null +++ b/WcsMain/Tcp/Entity/TcpServeConnectionData.cs @@ -0,0 +1,49 @@ +using System.Net.Sockets; +using WcsMain.DataBase.TableEntity; +using WcsMain.Enum.General; + +namespace WcsMain.Tcp.Entity; + + +/// +/// 用于存储 TCP 连接的服务端信息 +/// +public class TcpServeConnectionData +{ + + /// + /// 基础信息 + /// + public AppTcp? TcpServe { get; set; } + + /// + /// 别称 + /// + public string? DisplayName { get; set; } + + /// + /// Tcp客户端连接 + /// + public TcpClient? TcpClient { get; set; } + + /// + /// 是否连接 + /// + /// + /// 刚创建时是null,断开是false,连接正常是true + /// + public TrueFalseEnum? IsConnected { get; set; } + + /// + /// 上次接收消息的事件 + /// + public DateTime RecvMsgTime { get; set; } = DateTime.Now; + + + public override string ToString() + { + return $"{TcpServe?.TcpIp}:{TcpServe?.TcpPort}"; + } + + +} diff --git a/WcsMain/WcsAttribute/AppConfig/ConfigKeyAttribute.cs b/WcsMain/WcsAttribute/AppConfig/ConfigKeyAttribute.cs new file mode 100644 index 0000000..d585ca7 --- /dev/null +++ b/WcsMain/WcsAttribute/AppConfig/ConfigKeyAttribute.cs @@ -0,0 +1,16 @@ +namespace WcsMain.WcsAttribute.AppConfig; + +/// +/// 数据库配置键的映射 +/// +/// +[AttributeUsage(AttributeTargets.Property)] +public class ConfigKeyAttribute(string? keyName) : Attribute +{ + /// + /// 配置键名称 + /// + public string? KeyName { get; set; } = keyName; + + +} diff --git a/WcsMain/WcsAttribute/AutoFacAttribute/AutowiredAttribute.cs b/WcsMain/WcsAttribute/AutoFacAttribute/AutowiredAttribute.cs new file mode 100644 index 0000000..b757e9c --- /dev/null +++ b/WcsMain/WcsAttribute/AutoFacAttribute/AutowiredAttribute.cs @@ -0,0 +1,10 @@ +namespace WcsMain.WcsAttribute.AutoFacAttribute; + + +/// +/// 属性注入标记 +/// +[AttributeUsage(AttributeTargets.All)] +public class AutowiredAttribute : Attribute +{ +} diff --git a/WcsMain/WcsAttribute/AutoFacAttribute/ComponentAttribute.cs b/WcsMain/WcsAttribute/AutoFacAttribute/ComponentAttribute.cs new file mode 100644 index 0000000..93f4e3e --- /dev/null +++ b/WcsMain/WcsAttribute/AutoFacAttribute/ComponentAttribute.cs @@ -0,0 +1,7 @@ +namespace WcsMain.WcsAttribute.AutoFacAttribute; + +/// +/// 组件 +/// +[AttributeUsage(AttributeTargets.Class)] +public class ComponentAttribute : Attribute { } diff --git a/WcsMain/WcsAttribute/AutoFacAttribute/ServiceAttribute.cs b/WcsMain/WcsAttribute/AutoFacAttribute/ServiceAttribute.cs new file mode 100644 index 0000000..bf7478c --- /dev/null +++ b/WcsMain/WcsAttribute/AutoFacAttribute/ServiceAttribute.cs @@ -0,0 +1,10 @@ +namespace WcsMain.WcsAttribute.AutoFacAttribute; + + +/// +/// 服务特性标记,添加该特性的类会被IOC容器接管 +/// +[AttributeUsage(AttributeTargets.Class)] +public class ServiceAttribute : Attribute +{ +} diff --git a/WcsMain/WcsMain.csproj b/WcsMain/WcsMain.csproj new file mode 100644 index 0000000..b6c2598 --- /dev/null +++ b/WcsMain/WcsMain.csproj @@ -0,0 +1,54 @@ + + + + net8.0 + enable + enable + Exe + AnyCPU;x64;x86 + + + + + + + + + + + + + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WcsMain/WebSocket/WebSocketOperation.cs b/WcsMain/WebSocket/WebSocketOperation.cs new file mode 100644 index 0000000..637ecda --- /dev/null +++ b/WcsMain/WebSocket/WebSocketOperation.cs @@ -0,0 +1,63 @@ +namespace WcsMain.WebSocket; + +public class WebSocketOperation +{ + + //private static WebSocketOperation? _instance; + + //public static WebSocketOperation Instance() => _instance ??= new WebSocketOperation(); + + + //private string websocketServe => DataService.DataBaseData.Instance().GetConfig("webSocketAddress") ?? ""; + + //private List _connection = []; + + //public void OpenWebSocket() + //{ + // if (string.IsNullOrEmpty(websocketServe)) + // { + // return; + // } + // CommonTool.Websocket = new WebSocketServer(websocketServe) + // { + // RestartAfterListenError = true + // }; + + // CommonTool.Websocket.Start(serve => + // { + // serve.OnError += obj => + // { + // ConsoleLog.Error($"websocket 发生异常,{obj}"); + // }; + // serve.OnOpen += () => + // { + // _connection.Add(serve); + // ConsoleLog.Info($"webSocket 已经连接,在:{serve.ConnectionInfo.ClientIpAddress}"); + // }; + // serve.OnMessage += _ => + // { + // // 收到消息 + // }; + // serve.OnClose += () => + // { + // _connection.Remove(serve); + // ConsoleLog.Info($"webSocket 已经断开,在:{serve.ConnectionInfo.ClientIpAddress}"); + // }; + + // }); + //} + + + + //public void Send(string msg) + //{ + // if (_connection.Count < 1) + // { + // return; + // } + // foreach (var con in _connection) + // { + // con.Send(msg); + // } + //} +} \ No newline at end of file diff --git a/WcsMain/appsettings.Development.json b/WcsMain/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/WcsMain/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/WcsMain/appsettings.json b/WcsMain/appsettings.json new file mode 100644 index 0000000..9fb58e0 --- /dev/null +++ b/WcsMain/appsettings.json @@ -0,0 +1,22 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Settings": { + "DBMysql": "server=192.168.103.200;port=3306;user=developer;password=developer;database=wcs_main;", + "DBMysqlLocal": "server=192.168.234.128;port=3306;user=developer;password=developer;database=wcs_main;", + + "DBMssql": "Data Source=192.168.142.131;Initial Catalog=wcs;User Id=sa;Password=Sa123;", + "DBMssqlLocal": "Data Source=192.168.142.131;Initial Catalog=wcs_stacker;User Id=sa;Password=Sa123;", + + "ApplicationConfig": { + "ApiOnly": true + }, + "UseUrls": [ "http://*:890" ] + + } +} diff --git a/WcsService.sln b/WcsService.sln new file mode 100644 index 0000000..64824da --- /dev/null +++ b/WcsService.sln @@ -0,0 +1,176 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33213.308 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WcsMain", "WcsMain\WcsMain.csproj", "{ED59F010-B3E5-4E19-BE65-18053645DFC5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogTool", "Tools\LogTool\LogTool.csproj", "{7CF69CDD-413B-465C-9299-AA56B27F15BD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataCheck", "Tools\DataCheck\DataCheck.csproj", "{BF5AEA66-624D-485E-AB10-7DC1627E953D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTool", "Tools\ApiTool\ApiTool.csproj", "{1E37935C-5FE4-4D8E-90A8-95A007758231}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CirculateTool", "Tools\CirculateTool\CirculateTool.csproj", "{9A2E14E7-527B-4FA4-8D03-04C14E638879}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocketTool", "Tools\SocketTool\SocketTool.csproj", "{8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlcTool", "Tools\PlcTool\PlcTool.csproj", "{65E9651B-9F78-408F-A3CB-B30348CDF263}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HkCamera", "Tools\HkCamera\HkCamera.csproj", "{E2359626-2C4E-4B90-ABC3-1813E9C695F7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LedSimple", "Tools\LedSimple\LedSimple.csproj", "{00AF8F06-22FA-4482-B143-6775EEB6D1F4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EncryptTool", "Tools\EncryptTool\EncryptTool.csproj", "{95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{0EB56869-36A2-48C3-80E7-C50E6D1BF8EB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Debug|x64.ActiveCfg = Debug|x64 + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Debug|x64.Build.0 = Debug|x64 + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Debug|x86.ActiveCfg = Debug|x86 + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Debug|x86.Build.0 = Debug|x86 + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Release|Any CPU.Build.0 = Release|Any CPU + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Release|x64.ActiveCfg = Release|x64 + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Release|x64.Build.0 = Release|x64 + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Release|x86.ActiveCfg = Release|x86 + {ED59F010-B3E5-4E19-BE65-18053645DFC5}.Release|x86.Build.0 = Release|x86 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Debug|x64.ActiveCfg = Debug|x64 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Debug|x64.Build.0 = Debug|x64 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Debug|x86.ActiveCfg = Debug|x86 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Debug|x86.Build.0 = Debug|x86 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Release|Any CPU.Build.0 = Release|Any CPU + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Release|x64.ActiveCfg = Release|x64 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Release|x64.Build.0 = Release|x64 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Release|x86.ActiveCfg = Release|x86 + {7CF69CDD-413B-465C-9299-AA56B27F15BD}.Release|x86.Build.0 = Release|x86 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Debug|x64.ActiveCfg = Debug|x64 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Debug|x64.Build.0 = Debug|x64 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Debug|x86.ActiveCfg = Debug|x86 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Debug|x86.Build.0 = Debug|x86 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Release|Any CPU.Build.0 = Release|Any CPU + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Release|x64.ActiveCfg = Release|x64 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Release|x64.Build.0 = Release|x64 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Release|x86.ActiveCfg = Release|x86 + {BF5AEA66-624D-485E-AB10-7DC1627E953D}.Release|x86.Build.0 = Release|x86 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Debug|x64.ActiveCfg = Debug|x64 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Debug|x64.Build.0 = Debug|x64 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Debug|x86.ActiveCfg = Debug|x86 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Debug|x86.Build.0 = Debug|x86 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Release|Any CPU.Build.0 = Release|Any CPU + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Release|x64.ActiveCfg = Release|x64 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Release|x64.Build.0 = Release|x64 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Release|x86.ActiveCfg = Release|x86 + {1E37935C-5FE4-4D8E-90A8-95A007758231}.Release|x86.Build.0 = Release|x86 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Debug|x64.ActiveCfg = Debug|x64 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Debug|x64.Build.0 = Debug|x64 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Debug|x86.ActiveCfg = Debug|x86 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Debug|x86.Build.0 = Debug|x86 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Release|Any CPU.Build.0 = Release|Any CPU + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Release|x64.ActiveCfg = Release|x64 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Release|x64.Build.0 = Release|x64 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Release|x86.ActiveCfg = Release|x86 + {9A2E14E7-527B-4FA4-8D03-04C14E638879}.Release|x86.Build.0 = Release|x86 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Debug|x64.ActiveCfg = Debug|x64 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Debug|x64.Build.0 = Debug|x64 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Debug|x86.ActiveCfg = Debug|x86 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Debug|x86.Build.0 = Debug|x86 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Release|Any CPU.Build.0 = Release|Any CPU + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Release|x64.ActiveCfg = Release|x64 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Release|x64.Build.0 = Release|x64 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Release|x86.ActiveCfg = Release|x86 + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240}.Release|x86.Build.0 = Release|x86 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Debug|x64.ActiveCfg = Debug|x64 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Debug|x64.Build.0 = Debug|x64 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Debug|x86.ActiveCfg = Debug|x86 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Debug|x86.Build.0 = Debug|x86 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Release|Any CPU.Build.0 = Release|Any CPU + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Release|x64.ActiveCfg = Release|x64 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Release|x64.Build.0 = Release|x64 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Release|x86.ActiveCfg = Release|x86 + {65E9651B-9F78-408F-A3CB-B30348CDF263}.Release|x86.Build.0 = Release|x86 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Debug|x64.ActiveCfg = Debug|x64 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Debug|x64.Build.0 = Debug|x64 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Debug|x86.ActiveCfg = Debug|x86 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Debug|x86.Build.0 = Debug|x86 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Release|Any CPU.Build.0 = Release|Any CPU + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Release|x64.ActiveCfg = Release|x64 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Release|x64.Build.0 = Release|x64 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Release|x86.ActiveCfg = Release|x86 + {E2359626-2C4E-4B90-ABC3-1813E9C695F7}.Release|x86.Build.0 = Release|x86 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Debug|x64.ActiveCfg = Debug|x64 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Debug|x64.Build.0 = Debug|x64 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Debug|x86.ActiveCfg = Debug|x86 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Debug|x86.Build.0 = Debug|x86 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Release|Any CPU.Build.0 = Release|Any CPU + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Release|x64.ActiveCfg = Release|x64 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Release|x64.Build.0 = Release|x64 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Release|x86.ActiveCfg = Release|x86 + {00AF8F06-22FA-4482-B143-6775EEB6D1F4}.Release|x86.Build.0 = Release|x86 + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Debug|x64.ActiveCfg = Debug|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Debug|x64.Build.0 = Debug|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Debug|x86.ActiveCfg = Debug|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Debug|x86.Build.0 = Debug|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Release|Any CPU.Build.0 = Release|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Release|x64.ActiveCfg = Release|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Release|x64.Build.0 = Release|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Release|x86.ActiveCfg = Release|Any CPU + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {7CF69CDD-413B-465C-9299-AA56B27F15BD} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {BF5AEA66-624D-485E-AB10-7DC1627E953D} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {1E37935C-5FE4-4D8E-90A8-95A007758231} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {9A2E14E7-527B-4FA4-8D03-04C14E638879} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {8320A0F8-6A9E-49AE-BAE7-4B9A3590A240} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {65E9651B-9F78-408F-A3CB-B30348CDF263} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {E2359626-2C4E-4B90-ABC3-1813E9C695F7} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {00AF8F06-22FA-4482-B143-6775EEB6D1F4} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + {95FDB297-9B97-490A-9DDF-F03DBEE0EC8C} = {0EB56869-36A2-48C3-80E7-C50E6D1BF8EB} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D6F2CF8D-8897-4230-BF2F-17629B5FE425} + EndGlobalSection +EndGlobal