diff --git a/ConsoleApp/ConsoleApp.csproj b/ConsoleApp/ConsoleApp.csproj index 4da1d6b..0faf8a4 100644 --- a/ConsoleApp/ConsoleApp.csproj +++ b/ConsoleApp/ConsoleApp.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/ConsoleApp/MainCentralControl.cs b/ConsoleApp/MainCentralControl.cs new file mode 100644 index 0000000..9303d43 --- /dev/null +++ b/ConsoleApp/MainCentralControl.cs @@ -0,0 +1,541 @@ +using HslCommunication.Core; +using Mesnac.Compressor.Entity; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Newtonsoft.Json.Linq; +using SlnMesnac.Common; +using SlnMesnac.Config; +using SlnMesnac.Model.domain; +using SlnMesnac.Plc; +using SlnMesnac.Serilog; +using SqlSugar; +using System.Collections; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace ConsoleApp +{ + internal class MainCentralControl + { + private IHost host; + // 新增一个标志位,用于表示方法是否正在执行 + private static String StationCode; + private bool isExecuting = false; + private AppConfig _appConfig; + private readonly SerilogHelper _logger; + private IServiceProvider serviceProvider; + private ISqlSugarClient SqlSugarClient; + public List plcList; + IByteTransform ByteTransform = new ReverseBytesTransform(); + public bool isConnect; + public string State; + private StationInfo _stationInfo; + private object _mcValue; + //PLC心跳地址 + private string _plcHeartBeatAddress; + //PLC工作请求地址 + private string _workAskAddress; + //PLC工作完成放行请求地址 + private string _completeAskAddress; + + + public MainCentralControl(IHost host) + { + this.host = host; + _appConfig = host.Services.GetService(); + StationCode = _appConfig.StationCode; + SqlSugarClient = host.Services.GetRequiredService(); + _logger = host.Services.GetRequiredService(); + plcList = host.Services.GetRequiredService>(); + } + public void Start() + { + init(); + StartCheckStatus(); + ListeningPlcValue(); + _logger.Info("iMES系统启动成功!"); + } + private void init() + { + try + { + switch (StationCode) + { + case "S130-1": + _plcHeartBeatAddress = "D7777"; + _completeAskAddress = "D7703"; + break; + case "S130-2": + _plcHeartBeatAddress = "D7777"; + _workAskAddress = ""; + _completeAskAddress = ""; + break; + } + } + catch (Exception ex) + { + + } + } + /// + /// 监听PLC地址值 + /// + private void ListeningPlcValue() + { + Task.Run(async () => + { + while (true) + { + try + { + PlcAbsractFactory? Plc = plcList.FirstOrDefault(x => x.ConfigKey == "plc"); + if (Plc == null || !Plc.IsConnected) + { + _logger.Plc(DateTime.Now + "PLC未连接,请检查网络!"); + continue; + } + //读取PLC工作请求,放行请求 + switch (StationCode) + { + case "S130-1": + if (Plc.readInt16ByAddress(_completeAskAddress) == 1) + { + Plc.writeInt16ByAddress(_completeAskAddress, 0); + + SaveStationDataTask(Plc); + } + break; + case "S130-2": + //读取PLC工作请求 + if (Plc.readInt16ByAddress(_workAskAddress) == 1) + { + Plc.writeInt16ByAddress(_workAskAddress, 0); + //根据转子码查询上工位是否合格 + SelectStationQuality(Plc); + } + //读取PLC放行请求 + if (Plc.readInt16ByAddress(_completeAskAddress) == 1) + { + Plc.writeInt16ByAddress(_completeAskAddress, 0); + //存盘 + } + break; + } + + } + catch (Exception ex) + { + _logger.Error($"ListeningPlcValue方法异常:" + ex.StackTrace); + } + finally + { + Thread.Sleep(1000); + } + } + }); + } + /// + /// 判断数据库表是否已存在条码数据,存在则更新,不存在则插入 + /// + /// + /// + private Datastation IsExistData(string ProductBarCode) + { + Datastation datastation = null; + try + { + SqlSugarClient.Queryable().Any(x => x.Partsns.Contains(ProductBarCode)); + datastation = SqlSugarClient.Queryable().First(it => it.Partsns.Contains(ProductBarCode)); + if (datastation != null) + { + return datastation; + } + return datastation; + } + catch (Exception ex) + { + return datastation; + } + } + /// + /// S130-1工位存盘 + /// + /// + private async void SaveStationDataTask(PlcAbsractFactory Plc) + { + try + { //主线码 + byte[] SemBarCode = Plc.readValueByAddress("D7701", 20); + string barcode = ByteTransform.TransString(SemBarCode, 0, 20, Encoding.ASCII); + partsns partsns = new partsns(); + partsns.sn.Add(barcode); + //数据 + string jsonString = StringChange.ModeToJson(partsns); + D data1 = new D() + { + n = "转子压装位置1压力值", + t = 0, + ng = int.Parse(Plc.readFloatByAddress("D7708").ToString()), + v = Plc.readFloatByAddress("D7705").ToString(), + min = Plc.readFloatByAddress("D7706").ToString(), + max = Plc.readFloatByAddress("D7707").ToString(), + }; + D data2 = new D() + { + n = "转子压装位置2压力值", + t = 0, + ng = int.Parse(Plc.readFloatByAddress("D7712").ToString()), + v = Plc.readFloatByAddress("D7709").ToString(), + min = Plc.readFloatByAddress("D7710").ToString(), + max = Plc.readFloatByAddress("D7711").ToString(), + }; + D data3 = new D() + { + n = "转子压装位置3压力值", + t = 0, + ng = int.Parse(Plc.readFloatByAddress("D7716").ToString()), + v = Plc.readFloatByAddress("D7713").ToString(), + min = Plc.readFloatByAddress("D7714").ToString(), + max = Plc.readFloatByAddress("D7715").ToString(), + }; + D data4 = new D() + { + n = "转子压装位置4位移值", + t = 0, + ng = 1, + v = Plc.readFloatByAddress("D7717").ToString(), + min = Plc.readFloatByAddress("D7718").ToString(), + max = Plc.readFloatByAddress("D7719").ToString(), + }; + D data5 = new D() + { + n = "转子压装位置4压力值", + t = 0, + ng = int.Parse(Plc.readFloatByAddress("D7724").ToString()), + v = Plc.readFloatByAddress("D7721").ToString(), + min = Plc.readFloatByAddress("D7722").ToString(), + max = Plc.readFloatByAddress("D7723").ToString(), + }; + + Root root = new Root(); + root.d.Add(data1); + root.d.Add(data2); + root.d.Add(data3); + root.d.Add(data4); + root.d.Add(data5); + string datastring = StringChange.ModeToJson(root); + //查询是否已经存在数据,存在则更新不存在则保存 + Datastation datastation = IsExistData(barcode); + if (datastation != null) + { + //更新 + datastation.Stime = DateTime.Now; + datastation.Stationid = StationCode; + datastation.Ng = Plc.readFloatByAddress("D7708").ToString() == "1" ? 0 : 1; + datastation.Partsns = jsonString; + datastation.Paratemp = datastring; + int LockFlag = SqlSugarClient.Updateable(datastation).ExecuteCommand(); + Console.WriteLine(StringChange.ModeToJson(datastation)); + _logger.Info(StringChange.ModeToJson(datastation)); + } + else + { + datastation = new Datastation() + { + Stime = DateTime.Now, + Stationid = StationCode, + Productid = "", + Partid = "", + Modelid = "", + Ng = Plc.readFloatByAddress("D7708").ToString() == "1" ? 0 : 1, + Proc = 0, + Sublinenum = 0, + Sublinesnnum = 0, + Partsnnum = 1, + Sublineids = "", + Partsns = jsonString, + Sublinesns = StringChange.ModeToJson(new partsns()), + Paratemp = datastring, + Stringtemp = "", + GroupStationId = "", + Renum = "0", + }; + //存盘 + int id = SqlSugarClient.Insertable(datastation).ExecuteReturnIdentity(); + Plc.writeInt16ByAddress("D7704", 1); + Console.WriteLine(StringChange.ModeToJson(datastation)); + _logger.Info(StringChange.ModeToJson(datastation)); + } + + } + catch (Exception ex) + { + _logger.Error($"存盘异常{ex.Message}"); + } + } + /// + /// 查询上工位是否有数据,无数据或NG则下发PLC报警提示 + /// + /// + private async void SelectStationQuality(PlcAbsractFactory Plc) + { + try + { + byte[] SemBarCode = Plc.readValueByAddress("D7701", 20); + string ZZBarCode = ByteTransform.TransString(SemBarCode, 0, 20, Encoding.ASCII); + Datastation datastation = IsExistData(ZZBarCode); + if (datastation != null) + { + if (datastation.Ng != 0) + { + //下发PLC上工位不合格 + Plc.writeInt16ByAddress("", 1); + } + } + //上工位无数据 + else + { + //下发PLC上工位不合格 + Plc.writeInt16ByAddress("", 1); + } + } + catch (Exception ex) + { + _logger.Error($"上工位查询异常{ex.Message}"); + } + } + /// + /// PLC心跳检测,重连机制 + /// + private void StartCheckStatus() + { + Task.Run(async () => + { + while (true) + { + try + { + foreach (var plc in plcList) + { + PlcConfig? plcConfig = host.Services.GetService().plcConfig.FirstOrDefault(x => x.plcKey == plc.ConfigKey); + if (plc != null && plc.IsConnected) + { + plc.IsConnected = plc.readHeartByAddress(_plcHeartBeatAddress); //DB100.DBX0.0 + if (!plc.IsConnected) + { + plc.IsConnected = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort); + } + } + else + { + if (plcConfig != null) + { + bool result = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort); + plc.IsConnected = result; + } + } + } + } + catch (Exception ex) + { + _logger.Error($"监听PLC设备状态异常:{ex.Message}"); + } + await Task.Delay(1000 * 10); + } + }); + } + + #region 中际产线弃用逻辑 + private bool TryObject(object value, out object[] arry) + { + arry = null; + try + { + arry = (object[])value; + return true; + } + catch (Exception ex) + { + return false; + } + } + public stationPara ParaFormart(object[] obj, int paraCount) + { + byte[] bytes = obj.Select(o => Convert.ToByte(o)).ToArray(); + string str = Convert.ToString(Convert.ToInt32(bytes[2]), 2).PadLeft(8, '0'); + string[] items = new string[8]; + for (int i = 0; i < items.Length; i++) + { + items[i] = str[i].ToString(); + } + Array.Reverse(items); + //byte[] bools = ByteTransform.TransByte(bytes, 2,1); + isConnect = Convert.ToInt32(items[0]) == 1; + State = Convert.ToInt32(items[1]).ToString(); + stationPara sinfo = new stationPara(); + int index = 0; + //是否重投 + if (sinfo.Restart) + { + //ICSharpCode.Core.LoggingService.Info(StationInfo.StationCode + ",开始重投"); + } + //是否有主线二维码 + sinfo.BarcodeUpdate = Convert.ToInt32(items[3]) == 1; + //是否有支线二维码 + sinfo.MaterialBarcodeUpdate = Convert.ToInt32(items[4]) == 1; + index++; + //自动模式 + + //重构,收到作业或放行请求才进行解析 + //PLC工作请求信号 + sinfo.AskWork = ByteTransform.TransInt16(bytes, 5) > 0; + index++; + //放行请求 + sinfo.MaskID = ByteTransform.TransInt16(bytes, 7); + + sinfo.NewFlag = sinfo.MaskID > 0 ? true : false; + + index += 3; + //当前机种号 + sinfo.machineID = ByteTransform.TransByte(bytes, 13); + string NewMachineID = sinfo.machineID.ToString(); + + + index++; + //托盘号 + int intNum = ByteTransform.TransByte(bytes, 15); + + //支线条码状态 + index++; + bool[] bools2 = ByteTransform.TransBool(bytes, 16, 1); + //ArrayList array2 = ConvertToList(bools2); + + + //数据保存区 + index++; + sinfo.ProductOkNg = ByteTransform.TransByte(bytes, 19); + + index++; + //线体代号ABC' + int gongxu = ByteTransform.TransByte(bytes, 21); + + sinfo.RFIDNo = string.Format("{0:X}", gongxu) + intNum.ToString().PadLeft(2, '0'); + + + index += 1; + //sinfo.productDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");//这里不用日期了 + if (sinfo.BarcodeUpdate || sinfo.MaterialBarcodeUpdate) + { + GetBarcodeList(bytes, index, ref sinfo); + } + + index = 180; + + for (int i = 0; i < paraCount; i++) + { + dataUnite du = new dataUnite(); + du.actValue = ByteTransform.TransSingle(bytes, index).ToString(); + + du.MaxValue = ByteTransform.TransSingle(bytes, index + 4).ToString(); + + du.MinValue = ByteTransform.TransSingle(bytes, index + 8).ToString(); + + du.result = ByteTransform.TransInt32(bytes, index + 12); + + du.Remark = ByteTransform.TransInt32(bytes, index + 16).ToString(); + + index += 20; + + sinfo.SavedataList.Add(du); + } + if (sinfo.MaskID == 1) + { + foreach (var row in sinfo.SavedataList) + { + Console.WriteLine("------------------------"); + Console.WriteLine("|生产值:" + row.actValue + "|"); + Console.WriteLine("------------------------"); + } + } + return sinfo; + } + private void GetBarcodeList(byte[] buffer, int index, ref stationPara sinfo) + { + try + { + //获取条码支线信息 + //for (int i = 1; i <= 5; i++) + //{ + // subLine sl = new subLine(); + // sl.lineID = buffer[index + i].ToString(); + // sl.barcode = ""; + // sinfo.subLineList.Add(sl); + //} + //int barcodeLegth = 10;//设置单个条码长度 + + //获取主条码 + byte[] bytes = new byte[20]; + Array.Copy(buffer, 22, bytes, 0, 20); + //ByteTransform.DataFormat = HslCommunication.Core.DataFormat.DCBA; + //ByteTransform.IsStringReverseByteWord = true; + //if (BitConverter.IsLittleEndian) + //{ + // Array.Reverse(bytes, 0, 4); + // Array.Reverse(bytes, 4, 4); + // Array.Reverse(bytes, 8, 4); + // Array.Reverse(bytes, 12, 4); + // Array.Reverse(bytes, 16, 4); + //} + sinfo.ProductBarcode = ByteTransform.TransString(bytes, 0, 20, Encoding.ASCII); + } + catch (Exception ex) + { + _logger.Error("条码信息获取失败:" + ex.ToString()); + } + } + public object MCValue + { + get + { + return _mcValue; + } + set + { + if (value == null) + { + return; + } + //数据没有变化,直接返回 + object[] objectarray; + if (!TryObject(value, out objectarray)) + { + return; + } + if (value == _mcValue) + { + return; + } + _mcValue = value; + _stationInfo.Data = ParaFormart(objectarray, 0); + if (_stationInfo.Data.AskWork) + { + //这里需要判断上工位结果是否OK + _logger.Info("工位:" + _stationInfo.StationCode + " 收到作业请求信号"); + //PreWorkThread(); + + } + + ////有新数据 + if (isConnect && _stationInfo.Data.NewFlag) + { + + _logger.Info("工位:" + _stationInfo.StationCode + " 收到作业完成信号,开始上传数据。托盘号:" + _stationInfo.Data.RFIDNo); + //OnRerefreshData(); + } + } + } + #endregion + + } +} \ No newline at end of file diff --git a/ConsoleApp/Program.cs b/ConsoleApp/Program.cs index ed0b95f..da75888 100644 --- a/ConsoleApp/Program.cs +++ b/ConsoleApp/Program.cs @@ -8,22 +8,71 @@ using SlnMesnac.Extensions; using Microsoft.AspNetCore.Hosting; using Serilog; using Autofac.Extensions.DependencyInjection; +using SlnMesnac.Serilog; namespace ConsoleApp { internal class Program { + private static SerilogHelper? serilogHelper; static void Main(string[] args) { - var host = CreateHostBuilder(args).Build();//生成宿主。 + try + { + Thread.CurrentThread.Name = "Main"; + Console.ForegroundColor = ConsoleColor.Yellow; + AppDomain.CurrentDomain.UnhandledException += GlobalExceptionHandler; //全局异常捕获 + var host = CreateHostBuilder(args).Build(); - host.StartAsync(); - var appConfig = host.Services.GetService(); - var logPath = $"{appConfig.logPath}/Logs/{DateTime.UtcNow:yyyy-MM-dd}/"; - Log.Information($"系统初始化完成,日志存放路径:{appConfig.logPath}"); - Console.ReadLine(); + var hostTask = host.RunAsync(); + var appConfig = host.Services.GetService(); + //var logPath = $"{appConfig.logPath}/Logs/{DateTime.UtcNow:yyyy-MM-dd}/"; + //Log.Information($"系统初始化完成,日志存放路径:{appConfig.logPath}"); + serilogHelper = host.Services.GetRequiredService(); + + MainCentralControl mainCentralControl = new MainCentralControl(host); + mainCentralControl.Start(); + + serilogHelper.Info("iMES系统启动成功"); + while (true) + { + Console.ReadLine(); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + if (serilogHelper != null) + { + serilogHelper.Error("系统启动失败,异常:" + ex.Message); + } + } + + } + private static void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs e) + { + //当前线程名称 + Thread.CurrentThread.Name = "Error"; + if (e.ExceptionObject is Exception exception) + { + Console.WriteLine("全局异常捕获:"); + Console.WriteLine(exception.Message); + Console.WriteLine(exception.StackTrace); + if (serilogHelper != null) + { + serilogHelper.Error("全局异常捕获:" + exception.Message + "\n" + exception.StackTrace); + } + } + else + { + Console.WriteLine("未知异常捕获:"); + Console.WriteLine(e.ExceptionObject); + if (serilogHelper != null) + { + serilogHelper.Error("未知异常捕获:" + e.ExceptionObject); + } + } } - public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseSerilog() diff --git a/ConsoleApp/Startup.cs b/ConsoleApp/Startup.cs index 926476f..53e4687 100644 --- a/ConsoleApp/Startup.cs +++ b/ConsoleApp/Startup.cs @@ -43,6 +43,8 @@ namespace ConsoleApp [Obsolete] public void ConfigureServices(IServiceCollection services) { + // 注册 SerilogHelper 服务 + services.AddSingleton(); services.AddControllers(); //注册AppConfig @@ -57,7 +59,7 @@ namespace ConsoleApp services.AddSqlSugarSetup(); //注册PLC工厂 - //services.AddPlcFactorySetup(); + services.AddPlcFactorySetup(); //注册httpClient //services.AddHostedService(); @@ -69,7 +71,7 @@ namespace ConsoleApp //services.AddRfidFactorySetup(); //注册任务调度 - services.AddQuartzSetUp(); + //services.AddQuartzSetUp(); } diff --git a/ConsoleApp/appsettings.json b/ConsoleApp/appsettings.json index c35a9e3..1cc7369 100644 --- a/ConsoleApp/appsettings.json +++ b/ConsoleApp/appsettings.json @@ -8,41 +8,36 @@ }, "AllowedHosts": "*", "AppConfig": { - "logPath": "F:\\Mesnac\\2023部门项目\\奥特佳-滁州3期\\源码\\HightWay_Middle_Ware\\ConsoleApp\\bin\\Debug\\net6.0\\log", + "logPath": "F:\\Mesnac\\2025\\奥特佳项目\\奥特佳中继产线MES\\物料绑定\\ConsoleApp\\bin\\Debug\\net6.0-windows\\log", "SqlConfig": [ { "configId": "mes", - "dbType": 1, - "connStr": "server=192.168.1.120;uid=sa;pwd=123456;database=ATJ_581_DB" - }, + "dbType": 0, + //"connStr": "Data Source=119.45.202.115;Port=3306;Initial Catalog=db_iems;uid=root;pwd=haiwei@123;Charset=utf8mb4;SslMode=none;Connect Timeout=100" + "connStr": "Data Source=127.0.0.1;Port=3306;Initial Catalog=test;uid=root;pwd=123456;Charset=utf8mb4;SslMode=none;Connect Timeout=100" + } //{ // "configId": "mcs", // "dbType": 3, // "connStr": "Data Source=175.27.215.92/helowin;User ID=aucma_scada;Password=aucma" //}, - { - "configId": "Local", - "dbType": 2, - "connStr": "Data Source=F:\\Mesnac\\2023部门项目\\奥特佳-滁州3期\\源码\\HightWay_Middle_Ware\\SlnMesnac.WPF\\bin\\Debug\\net6.0-windows\\data\\LSHData.db3" - } + //{ + // "configId": "Local", + // "dbType": 2, + // "connStr": "Data Source=F:\\Mesnac\\2023部门项目\\奥特佳-滁州3期\\源码\\HightWay_Middle_Ware\\SlnMesnac.WPF\\bin\\Debug\\net6.0-windows\\data\\LSHData.db3" + //} ], "PlcConfig": [ { "configId": 1, - "plcType": "MelsecBinaryPlc", - "plcIp": "127.0.0.1", + "plcType": "OmronNJPlc", + "plcIp": "192.168.0.120", + //"plcIp": "127.0.0.1", "plcPort": 6000, - "plcKey": "mcs", - "isFlage": true - }, - { - "configId": 2, - "plcType": "MelsecBinaryPlc", - "plcIp": "127.0.0.1", - "plcPort": 6001, - "plcKey": "cwss", + "plcKey": "plc", "isFlage": true } + ], "RfidConfig": [ { @@ -60,30 +55,8 @@ "isFlage": true } ], - "visionConfig": [ - { - "VisionId": 1, - "VisionIp": "127.0.0.1", - "VisionPort": 7001, - "AGVID": "1", - "VisionState": "1", - "IsFlag": true - }, - { - "VisionId": 2, - "VisionIp": "127.0.0.1", - "VisionPort": 7002, - "AGVID": "2", - "VisionState": "1", - "IsFlag": true - } - ], - "AMRIP": "127.0.0.1", - - "redisConfig": "175.27.215.92:6379,password=redis@2023", - "AGVIpConfig": "http://192.168.40.81:5102", - "TCPVisionConfig": "127.0.0.1:6000" + "StationCode": "S130-1" } } diff --git a/SlnMesnac.Model/domain/Cfgstationattr.cs b/SlnMesnac.Model/domain/Cfgstationattr.cs new file mode 100644 index 0000000..5b2b333 --- /dev/null +++ b/SlnMesnac.Model/domain/Cfgstationattr.cs @@ -0,0 +1,319 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Models +{ + /// + /// 工位表 + /// + [SugarTable("cfgstationattr")] + public class Cfgstationattr + { + + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="id" ,IsPrimaryKey = true,IsIdentity = true) ] + public int Id { get; set; } + + /// + /// 备 注:工位配置顺序号 + /// 默认值: + /// + [SugarColumn(ColumnName="operid" ) ] + public int? Operid { get; set; } + + /// + /// 备 注:工位代码 + /// 默认值: + /// + [SugarColumn(ColumnName="opercode" ) ] + public string? Opercode { get; set; } + + /// + /// 备 注:工位名称 + /// 默认值: + /// + [SugarColumn(ColumnName="opername" ) ] + public string? Opername { get; set; } + + /// + /// 备 注:工位类别:起始工位、普通工位、换线工位、停止工位、半成品停止工位 + /// 默认值: + /// + [SugarColumn(ColumnName="opertype" ) ] + public string? Opertype { get; set; } + + /// + /// 备 注:线路id + /// 默认值: + /// + [SugarColumn(ColumnName="lineid" ) ] + public int? Lineid { get; set; } + + /// + /// 备 注:参数模板id + /// 默认值: + /// + [SugarColumn(ColumnName="tempid" ) ] + public int? Tempid { get; set; } + + /// + /// 备 注:工位流水线顺序号(缺省) + /// 默认值: + /// + [SugarColumn(ColumnName="no" ) ] + public int? No { get; set; } + + /// + /// 备 注:是否排出工位 0 -不是 1- 是 + /// 默认值: + /// + [SugarColumn(ColumnName="outng" ) ] + public SByte? Outng { get; set; } + + /// + /// 备 注:是否是半成品投入位 0 -不是 1- 是 + /// 默认值: + /// + [SugarColumn(ColumnName="semistart" ) ] + public SByte? Semistart { get; set; } + + /// + /// 备 注:半成品结束工位 + /// 默认值: + /// + [SugarColumn(ColumnName="semifinish" ) ] + public SByte? Semifinish { get; set; } + + /// + /// 备 注:离线工位 + /// 默认值: + /// + [SugarColumn(ColumnName="bloffline" ) ] + public SByte? Bloffline { get; set; } + + /// + /// 备 注:所属机种id(modelid) + /// 默认值: + /// + [SugarColumn(ColumnName="productid" ) ] + public int? Productid { get; set; } + + /// + /// 备 注:当前状态:0 - 未启用,1-空闲 + /// 默认值: + /// + [SugarColumn(ColumnName="status" ) ] + public int? Status { get; set; } + + /// + /// 备 注:PLC连接类型:0-三菱mc/slmp UDP协议; 1-欧姆龙 UDP协议;3-西门子 + /// 默认值: + /// + [SugarColumn(ColumnName="plctype" ) ] + public int? Plctype { get; set; } + + /// + /// 备 注:PLC数据区起始地址 + /// 默认值: + /// + [SugarColumn(ColumnName="addrstart" ) ] + public int? Addrstart { get; set; } + + /// + /// 备 注:PLC ip地址 + /// 默认值: + /// + [SugarColumn(ColumnName="ip" ) ] + public string? Ip { get; set; } + + /// + /// 备 注:tcp/udp 端口 + /// 默认值: + /// + [SugarColumn(ColumnName="port" ) ] + public int? Port { get; set; } + + /// + /// 备 注:串口设备名 + /// 默认值: + /// + [SugarColumn(ColumnName="com" ) ] + public string? Com { get; set; } + + /// + /// 备 注:波特率 + /// 默认值: + /// + [SugarColumn(ColumnName="baudrate" ) ] + public int? Baudrate { get; set; } + + /// + /// 备 注:数据位 + /// 默认值: + /// + [SugarColumn(ColumnName="databits" ) ] + public int? Databits { get; set; } + + /// + /// 备 注:校验位 + /// 默认值: + /// + [SugarColumn(ColumnName="parity" ) ] + public int? Parity { get; set; } + + /// + /// 备 注:组态图用。当前操作状态: 正常生产,NG品排出,NG品非排出等 -- 外键:cfgoperstatus + /// 默认值: + /// + [SugarColumn(ColumnName="curOperStatus" ) ] + public int? CurOperStatus { get; set; } + + /// + /// 备 注:生产合格品数量 + /// 默认值: + /// + [SugarColumn(ColumnName="statNormalNum" ) ] + public int? StatNormalNum { get; set; } + + /// + /// 备 注:生产非合格品数量 + /// 默认值: + /// + [SugarColumn(ColumnName="statNGNum" ) ] + public int? StatNGNum { get; set; } + + /// + /// 备 注:当前操作生产人员ID + /// 默认值: + /// + [SugarColumn(ColumnName="curoperid" ) ] + public string? Curoperid { get; set; } + + /// + /// 备 注:连接方式 : 0 -网络;1-excel,通过excel传递数据 + /// 默认值: + /// + [SugarColumn(ColumnName="auto" ) ] + public int? Auto { get; set; } + + /// + /// 备 注:最后状态改变时间 + /// 默认值: + /// + [SugarColumn(ColumnName="ltime" ) ] + public DateTime? Ltime { get; set; } + + /// + /// 备 注:最后读取的PLC数据区号 + /// 默认值: + /// + [SugarColumn(ColumnName="lastRegIndex" ) ] + public int? LastRegIndex { get; set; } + + /// + /// 备 注:当前是否未连接;0-否,1-是 + /// 默认值: + /// + [SugarColumn(ColumnName="bcon" ) ] + public SByte? Bcon { get; set; } + + /// + /// 备 注:当前是否自动:0-否,1-是 + /// 默认值: + /// + [SugarColumn(ColumnName="bauto" ) ] + public SByte? Bauto { get; set; } + + /// + /// 备 注:当前产品是否重投:0-否,1-是 + /// 默认值: + /// + [SugarColumn(ColumnName="bret" ) ] + public SByte? Bret { get; set; } + + /// + /// 备 注:适用机种,用逗号分割,例如机种1,机种2,机种3 + /// 默认值: + /// + [SugarColumn(ColumnName="appmode" ) ] + public string? Appmode { get; set; } + + /// + /// 备 注:节拍指标(单位秒) + /// 默认值: + /// + [SugarColumn(ColumnName="rhythm" ) ] + public int? Rhythm { get; set; } + + /// + /// 备 注:PLC数据块编号 + /// 默认值: + /// + [SugarColumn(ColumnName="dbcode" ) ] + public int? Dbcode { get; set; } + + /// + /// 备 注:PLC上报物料区起始地址 + /// 默认值: + /// + [SugarColumn(ColumnName="matstartaddr" ) ] + public int? Matstartaddr { get; set; } + + /// + /// 备 注:该工位PLC挂接扫描枪只为本工位投料还是为全产线投料共用。0:该工位独用;1:产线共用。 + /// 默认值: + /// + [SugarColumn(ColumnName="fulllinescan" ) ] + public UInt32? Fulllinescan { get; set; } + + /// + /// 备 注:上位机与PLC通信连接正常与否,0:连接断开,1:建立连接 + /// 默认值: + /// + [SugarColumn(ColumnName="commstatus" ) ] + public int? Commstatus { get; set; } + + /// + /// 备 注:建立连接的时间 + /// 默认值: + /// + [SugarColumn(ColumnName="connecttime" ) ] + public DateTime? Connecttime { get; set; } + + /// + /// 备 注:连接断开的时间 + /// 默认值: + /// + [SugarColumn(ColumnName="disconnecttime" ) ] + public DateTime? Disconnecttime { get; set; } + + /// + /// 备 注:超时未连接的次数累计,默认大于2秒为超时,界面可清零 + /// 默认值: + /// + [SugarColumn(ColumnName="timeoutnum" ) ] + public int? Timeoutnum { get; set; } + + /// + /// 备 注:连接断开的次数累计,界面可清零 + /// 默认值: + /// + [SugarColumn(ColumnName="disconectnum" ) ] + public int? Disconectnum { get; set; } + + /// + /// 备 注:暂不用(预留)。该工位产品类别(针对机种下的首工位),是主产品还是部件,1主产品,2一级部件,3二级部件,4其他。 + /// 默认值: + /// + [SugarColumn(ColumnName="statpdtype" ) ] + public int? Statpdtype { get; set; } + + + } + +} \ No newline at end of file diff --git a/SlnMesnac.Model/domain/Datastation.cs b/SlnMesnac.Model/domain/Datastation.cs new file mode 100644 index 0000000..df23926 --- /dev/null +++ b/SlnMesnac.Model/domain/Datastation.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace SlnMesnac.Model.domain +{ + /// + /// 产品生产工位全过程数据(对于同一工位下同一产品码,可能有多条不同记录),表结构完全同datastationcur + /// + [SugarTable("datastation")] + public class Datastation + { + + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="id" ,IsPrimaryKey = true,IsIdentity = true) ] + public int Id { get; set; } + + /// + /// 备 注:工位码 + /// 默认值: + /// + [SugarColumn(ColumnName="stationid" ) ] + public string? Stationid { get; set; } + + /// + /// 备 注:产品码 + /// 默认值: + /// + [SugarColumn(ColumnName="productid" ) ] + public string? Productid { get; set; } + + /// + /// 备 注:部件码 + /// 默认值: + /// + [SugarColumn(ColumnName="partid" ) ] + public string? Partid { get; set; } + + /// + /// 备 注:机种码 + /// 默认值: + /// + [SugarColumn(ColumnName="modelid" ) ] + public string? Modelid { get; set; } + + /// + /// 备 注:记录时间 + /// 默认值: + /// + [SugarColumn(ColumnName="stime" ) ] + public DateTime? Stime { get; set; } + + /// + /// 备 注:是否NG:0 非NG;1 NG品 + /// 默认值: + /// + [SugarColumn(ColumnName="ng" ) ] + public int Ng { get; set; } + + /// + /// 备 注:过程描述 0 正常;1 NG品未加工;2 - NG品排出 + /// 默认值: + /// + [SugarColumn(ColumnName="proc" ) ] + public int Proc { get; set; } + + /// + /// 备 注:支线数 + /// 默认值: + /// + [SugarColumn(ColumnName="sublinenum" ) ] + public int? Sublinenum { get; set; } + + /// + /// 备 注:支线条码数 + /// 默认值: + /// + [SugarColumn(ColumnName="sublinesnnum" ) ] + public int? Sublinesnnum { get; set; } + + /// + /// 备 注:部件条码数 + /// 默认值: + /// + [SugarColumn(ColumnName="partsnnum" ) ] + public int? Partsnnum { get; set; } + + /// + /// 备 注:操作员ID + /// 默认值: + /// + [SugarColumn(ColumnName="operid" ) ] + public string? Operid { get; set; } + + /// + /// 备 注:支线id,json格式:{ids:[1,2,3]} + /// 默认值: + /// + [SugarColumn(ColumnName="sublineids" ) ] + public string? Sublineids { get; set; } + + /// + /// 备 注:部件条码,json格式:{'sn':['10001','10002','20008']} + /// 默认值: + /// + [SugarColumn(ColumnName="partsns" ) ] + public string? Partsns { get; set; } + + /// + /// 备 注:支线条码,json格式:{'sn':['10001','10002','20008']} + /// 默认值: + /// + [SugarColumn(ColumnName="sublinesns" ) ] + public string? Sublinesns { get; set; } + + /// + /// 备 注:参数数据,json格式。 {"d":[{"v":1.2,"max":2.0,"min":1.0,"ng":1},{}]} + /// 默认值: + /// + [SugarColumn(ColumnName="paratemp" ) ] + public string? Paratemp { get; set; } + + /// + /// 备 注:字符串参数。json:{"str":["1111","2222"]} + /// 默认值: + /// + [SugarColumn(ColumnName="stringtemp" ) ] + public string? Stringtemp { get; set; } + + /// + /// 备 注:工位组,同一线路,相同工序号的工位放在一个工位组里,以 ","号分隔 + /// 默认值: + /// + [SugarColumn(ColumnName="groupStationId" ) ] + public string? GroupStationId { get; set; } + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="renum" ) ] + public string? Renum { get; set; } + + + } + +} \ No newline at end of file diff --git a/SlnMesnac.Model/domain/Datastationparam.cs b/SlnMesnac.Model/domain/Datastationparam.cs new file mode 100644 index 0000000..9ef060c --- /dev/null +++ b/SlnMesnac.Model/domain/Datastationparam.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace SlnMesnac.Model.domain +{ + /// + /// 工位数据参数值 + /// + [SugarTable("datastationparam")] + public class Datastationparam + { + + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="id" ,IsPrimaryKey = true,IsIdentity = true) ] + public int Id { get; set; } + + /// + /// 备 注:datastation表索引id + /// 默认值: + /// + [SugarColumn(ColumnName="dsid" ) ] + public int Dsid { get; set; } + + /// + /// 备 注:工位号 + /// 默认值: + /// + [SugarColumn(ColumnName="stationid" ,IsPrimaryKey = true) ] + public string Stationid { get; set; } = null!; + + /// + /// 备 注:产品系统号 + /// 默认值: + /// + [SugarColumn(ColumnName="productid" ,IsPrimaryKey = true) ] + public string Productid { get; set; } = null!; + + /// + /// 备 注:参数名 + /// 默认值: + /// + [SugarColumn(ColumnName="n" ) ] + public string? N { get; set; } + + /// + /// 备 注:数据类别:0 数值浮点数;1 整数 + /// 默认值: + /// + [SugarColumn(ColumnName="t" ) ] + public bool T { get; set; } + + /// + /// 备 注:数据 + /// 默认值: + /// + [SugarColumn(ColumnName="v" ) ] + public string? V { get; set; } + + /// + /// 备 注:最大值 + /// 默认值: + /// + [SugarColumn(ColumnName="max" ) ] + public string Max { get; set; } = null!; + + /// + /// 备 注:最小值 + /// 默认值: + /// + [SugarColumn(ColumnName="min" ) ] + public string? Min { get; set; } + + /// + /// 备 注:是否NG品,1:OK品,2:NG品 + /// 默认值: + /// + [SugarColumn(ColumnName="ng" ) ] + public bool? Ng { get; set; } + + /// + /// 备 注:记录时间 + /// 默认值: + /// + [SugarColumn(ColumnName="stime" ) ] + public DateTime Stime { get; set; } + + /// + /// 备 注:缺省null,在v比较上下限后,超限则拼接"工位号"“参数名”"NG+或NG-或NG其他” + /// 默认值: + /// + [SugarColumn(ColumnName="ngcode" ) ] + public string? Ngcode { get; set; } + + + } + +} \ No newline at end of file diff --git a/SlnMesnac.Model/domain/Dipsn.cs b/SlnMesnac.Model/domain/Dipsn.cs new file mode 100644 index 0000000..ee7a686 --- /dev/null +++ b/SlnMesnac.Model/domain/Dipsn.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace SlnMesnac.Model.domain +{ + /// + /// 使用过的条码记录(一旦成品或半成品就从tmpsnpid导入dipsn) + /// + [SugarTable("dipsn")] + public class Dipsn + { + + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="id" ,IsPrimaryKey = true,IsIdentity = true) ] + public int Id { get; set; } + + /// + /// 备 注:条码 + /// 默认值: + /// + [SugarColumn(ColumnName="sn" ) ] + public string? Sn { get; set; } + + /// + /// 备 注:产品码 + /// 默认值: + /// + [SugarColumn(ColumnName="productid" ) ] + public string? Productid { get; set; } + + /// + /// 备 注:产品类别:0-暂空,1-从主线下来的完成品,2-半成品,5-已被装配到主线上的半成品 + /// 默认值: + /// + [SugarColumn(ColumnName="type" ) ] + public int Type { get; set; } + + /// + /// 备 注:SN使用时间。产品完成时间 + /// 默认值: + /// + [SugarColumn(ColumnName="stime" ) ] + public DateTime? Stime { get; set; } + + + } + +} \ No newline at end of file diff --git a/SlnMesnac.Model/domain/MachineInfo.cs b/SlnMesnac.Model/domain/MachineInfo.cs new file mode 100644 index 0000000..985595e --- /dev/null +++ b/SlnMesnac.Model/domain/MachineInfo.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Mesnac.Compressor.Entity +{ + /// + /// 单工位保存数据 + /// + public class stationPara + { + #region 显示数据 + private string _state = ""; + public string state + { + get + { + return _state; + } + set + { + _state = value; + } + } + + /// + /// 检测值 + /// + private string _data = ""; + public string data + { + get + { + return _data; + } + set + { + _data = value; + } + } + + #endregion + + #region 保存数据 + + //工作完成信号 + public bool NewFlag = false; + //工作请求信号 + public bool AskWork= false; + public bool QGCT = false; + + public bool subLine1 = false; + public bool subLine2 = false; + public bool subLine3 = false; + + /// + /// 动盘扫码枪开关信号 + /// + public bool DP_OpenFlag = false; + + /// + /// 当前工位是否重做 + /// + public bool ReWork = false; + + /// + /// 是否重投 + /// + public bool Restart = false; + + /// + /// + /// + public bool BarcodeUpdate = false; + + + /// + /// 物料条码是否上传 + /// + public bool MaterialBarcodeUpdate = false; + + /// + /// 支线条码上传 + /// + public bool ZhiXianBarUp = false; + + /// + /// 物料条码 + /// + public string MaterialBarcode = ""; + + /// + /// 产品状态 + /// + public int ProductOkNg = 0; + + /// + /// 机种ID + /// + public int machineID = 0; + + /// + /// 任务号 + /// + public int MaskID = 0; + + public string RFIDNo + { + get; + set; + } + + public string productDate + { + get; + set; + } + + public string semibacode = ""; + + public string MainBarcode = ""; + + public string ProductBarcode = ""; + + private List _savedatalist = new List(); + public List SavedataList + { + get + { + return _savedatalist; + } + set + { + _savedatalist = value; + } + } + + #endregion + + public List subLineList = new List(); + + } + + public class subLine + { + public string lineID = ""; + public string barcode = ""; + } + + public class dataUnite + { + public string actValue { get; set; } + + public string MaxValue { get; set; } + + public string MinValue { get; set; } + + public int result { get; set; } + + public string Remark { get; set; } + } + + public class StationInfo + { + public string stationID = ""; + + public string StationCode = ""; + + public string StationName = ""; + + public string TableName = ""; + + public string PreTableName = ""; + + public int ParaCount = 0; + + public string StationType = ""; + + //add by yinzf 2023-3-2 + //设备对应PLC的名称A1 + public string PLCName = ""; + /// + /// PLC地址块号 + /// + public int PLCBlock = 0; + + public bool NGTakeStation = true; + + //end add + + public string lineID = ""; + public string barcodeHead = ""; + public bool IfMainline + { get; set; }//是否是主线 + + /// + /// 数据处理是否处理 + /// + public bool handle = true; + + public stationPara Data = new stationPara(); + } + + public class MachineInfo + { + public string MachineName = ""; + + public string MachineID = ""; + + public int stationCount = 0; + + public StationInfo StationOne = new StationInfo(); + + public StationInfo StationTwo = new StationInfo(); + + } + + +} diff --git a/SlnMesnac.Model/domain/partsns.cs b/SlnMesnac.Model/domain/partsns.cs new file mode 100644 index 0000000..d392fdf --- /dev/null +++ b/SlnMesnac.Model/domain/partsns.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.Model.domain +{ + public class partsns + { + /// + /// + /// + public List sn = new List(); + } + + public class D + { + /// + /// 销钉1压装终点位移 + /// + public string n { get; set; } + /// + /// + /// + public int t { get; set; } + /// + /// + /// + public string v { get; set; } + /// + /// + /// + public string max { get; set; } + /// + /// + /// + public string min { get; set; } + /// + /// + /// + public int ng { get; set; } + } + + public class Root + { + /// + /// + /// + public List d = new List(); + } +} diff --git a/SlnMesnac.Plc/Factory/InovanceFactory.cs b/SlnMesnac.Plc/Factory/InovanceFactory.cs index d9eebc1..8f07e86 100644 --- a/SlnMesnac.Plc/Factory/InovanceFactory.cs +++ b/SlnMesnac.Plc/Factory/InovanceFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using HslCommunication; using HslCommunication.Profinet.Inovance; using SlnMesnac.Common; @@ -342,5 +343,25 @@ namespace SlnMesnac.Plc.Factory throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}"); } } + + public override Task ConnectAsync(string ip, int port) + { + throw new NotImplementedException(); + } + + public override object[] readObjectValueByAddress(string address, int len) + { + throw new NotImplementedException(); + } + + public override float readFloatByAddress(string address) + { + throw new NotImplementedException(); + } + + public override bool readHeartByAddress(string address) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/SlnMesnac.Plc/Factory/MelsecBinaryFactory.cs b/SlnMesnac.Plc/Factory/MelsecBinaryFactory.cs index 28b9a8e..f2b477b 100644 --- a/SlnMesnac.Plc/Factory/MelsecBinaryFactory.cs +++ b/SlnMesnac.Plc/Factory/MelsecBinaryFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using HslCommunication; using HslCommunication.Profinet.Melsec; using SlnMesnac.Common; @@ -283,5 +284,25 @@ namespace SlnMesnac.Plc.Factory throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}"); } } + + public override Task ConnectAsync(string ip, int port) + { + throw new NotImplementedException(); + } + + public override object[] readObjectValueByAddress(string address, int len) + { + throw new NotImplementedException(); + } + + public override float readFloatByAddress(string address) + { + throw new NotImplementedException(); + } + + public override bool readHeartByAddress(string address) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/SlnMesnac.Plc/Factory/OmronNJFactory.cs b/SlnMesnac.Plc/Factory/OmronNJFactory.cs index a3812e9..2e8eb0c 100644 --- a/SlnMesnac.Plc/Factory/OmronNJFactory.cs +++ b/SlnMesnac.Plc/Factory/OmronNJFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using HslCommunication; using HslCommunication.Profinet.Omron; using SlnMesnac.Common; @@ -31,13 +32,14 @@ namespace SlnMesnac.Plc.Factory { private StringChange _stringChange; - private OmronFinsNet omronFinsNet = null; + private OmronCipNet omronFinsNet = null; + public OmronNJFactory(StringChange stringChange) { _stringChange = stringChange; - this.omronFinsNet = new OmronFinsNet(); + this.omronFinsNet = new OmronCipNet(); this.omronFinsNet.ConnectTimeOut = 2000; } @@ -55,10 +57,10 @@ namespace SlnMesnac.Plc.Factory try { omronFinsNet.IpAddress = iP; - omronFinsNet.Port = 9600; - omronFinsNet.SA1 = (byte)192; - omronFinsNet.DA1 = (byte)239; - omronFinsNet.DA2 = (byte)0; + omronFinsNet.Port = 44818; + //omronFinsNet.SA1 = (byte)192; + //omronFinsNet.DA1 = (byte)239; + //omronFinsNet.DA2 = (byte)0; OperateResult connect = omronFinsNet.ConnectServer(); this.IsConnected = connect.IsSuccess; if (!connect.IsSuccess) @@ -104,16 +106,22 @@ namespace SlnMesnac.Plc.Factory /// /// /// - public override byte[] readValueByAddress(string address, int len) + public override object[] readObjectValueByAddress(string address, int len) { try { + object[] buff = null; OperateResult read = omronFinsNet.Read(address, (ushort)(len)); if (!read.IsSuccess) { throw new InvalidOperationException($"根据地址:{address};读取指定长度数据失败:{read.Message}"); } - return _stringChange.ConvertFloatToINt(read.Content); + buff = new object[read.Content.Length]; + for (int i = 0; i < read.Content.Length; i++) + { + buff[i] = read.Content[i]; + } + return buff; } catch (Exception ex) { @@ -134,7 +142,7 @@ namespace SlnMesnac.Plc.Factory OperateResult read = omronFinsNet.ReadInt16(address); if (!read.IsSuccess) { - throw new InvalidOperationException($"根据地址:{address};读取int16数据失败:{read.Content}"); + throw new InvalidOperationException($"根据地址:{address};读取int16数据失败:{read.Message}"); } return read.Content; } @@ -182,7 +190,7 @@ namespace SlnMesnac.Plc.Factory OperateResult read = omronFinsNet.ReadString(address, length); if (!read.IsSuccess) { - throw new InvalidOperationException($"根据地址:{address};读取string数据失败:{read.Content}"); + throw new InvalidOperationException($"根据地址:{address};读取string数据失败:{read.Message}"); } return read.Content; } @@ -229,7 +237,7 @@ namespace SlnMesnac.Plc.Factory OperateResult read = omronFinsNet.ReadBool(address); if (!read.IsSuccess) { - throw new InvalidOperationException($"根据地址:{address};读取bool数据失败:{read.Content}"); + throw new InvalidOperationException($"根据地址:{address};读取bool数据失败:{read.Message}"); } return read.Content; } @@ -286,5 +294,81 @@ namespace SlnMesnac.Plc.Factory throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}"); } } + + public override async Task ConnectAsync(string ip, int port) + { + try + { + omronFinsNet.IpAddress = ip; + omronFinsNet.Port = 44818; + //omronFinsNet.SA1 = (byte)192; + //omronFinsNet.DA1 = (byte)239; + //omronFinsNet.DA2 = (byte)0; + OperateResult connect = await omronFinsNet.ConnectServerAsync(); + this.IsConnected = connect.IsSuccess; + if (!connect.IsSuccess) + { + throw new InvalidOperationException($"欧姆龙PLC连接失败:{connect.Message}"); + } + + return connect.IsSuccess; + } + catch (Exception ex) + { + Console.WriteLine($"欧姆龙PLC连接异常:{ex.Message}"); + return false; + } + } + + public override byte[] readValueByAddress(string address, int len) + { + try + { + OperateResult read = omronFinsNet.Read(address, (ushort)(len)); + if (!read.IsSuccess) + { + throw new InvalidOperationException($"根据地址:{address};读取指定长度数据失败:{read.Message}"); + } + return read.Content; + } + catch (Exception ex) + { + throw new InvalidOperationException($"根据地址:{address};读取指定长度数据异常:{ex.Message}"); + } + } + + public override float readFloatByAddress(string address) + { + try + { + OperateResult read = omronFinsNet.ReadFloat(address); + if (!read.IsSuccess) + { + throw new InvalidOperationException($"根据地址:{address};读取float数据失败:{read.Message}"); + } + return read.Content; + } + catch (Exception ex) + { + throw new InvalidOperationException($"根据地址:{address};读取float数据异常:{ex.Message}"); + } + } + + public override bool readHeartByAddress(string address) + { + try + { + OperateResult read = omronFinsNet.ReadBool(address); + if (!read.IsSuccess) + { + return false; + } + return true; + } + catch (Exception ex) + { + return false; + } + } } } \ No newline at end of file diff --git a/SlnMesnac.Plc/Factory/SiemensFactory.cs b/SlnMesnac.Plc/Factory/SiemensFactory.cs index 2e0ed6d..6f9f8e9 100644 --- a/SlnMesnac.Plc/Factory/SiemensFactory.cs +++ b/SlnMesnac.Plc/Factory/SiemensFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using HslCommunication; using HslCommunication.Profinet.Siemens; using SlnMesnac.Common; @@ -283,5 +284,25 @@ namespace SlnMesnac.Plc.Factory throw new InvalidOperationException($"根据地址:{address};写入double数据异常:{ex.Message}"); } } + + public override Task ConnectAsync(string ip, int port) + { + throw new NotImplementedException(); + } + + public override object[] readObjectValueByAddress(string address, int len) + { + throw new NotImplementedException(); + } + + public override float readFloatByAddress(string address) + { + throw new NotImplementedException(); + } + + public override bool readHeartByAddress(string address) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/SlnMesnac.Plc/PlcAbsractFactory.cs b/SlnMesnac.Plc/PlcAbsractFactory.cs index 049cf0a..b871a10 100644 --- a/SlnMesnac.Plc/PlcAbsractFactory.cs +++ b/SlnMesnac.Plc/PlcAbsractFactory.cs @@ -20,6 +20,8 @@ * 版本:V1.0.0 *--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> +using System.Threading.Tasks; + namespace SlnMesnac.Plc { public abstract class PlcAbsractFactory @@ -39,7 +41,13 @@ namespace SlnMesnac.Plc /// /// public abstract bool Connect(string ip, int port); - + /// + /// 异步建立连接 + /// + /// + /// + /// + public abstract Task ConnectAsync(string ip, int port); /// /// 断开连接 /// @@ -105,5 +113,11 @@ namespace SlnMesnac.Plc /// /// public abstract bool writeDoubleByAddress(string address, int value); + + public abstract object[] readObjectValueByAddress(string address, int len); + + public abstract float readFloatByAddress(string address); + + public abstract bool readHeartByAddress(string address); } } \ No newline at end of file diff --git a/SlnMesnac.Repository/service/ICfgstationattrService.cs b/SlnMesnac.Repository/service/ICfgstationattrService.cs new file mode 100644 index 0000000..175abf8 --- /dev/null +++ b/SlnMesnac.Repository/service/ICfgstationattrService.cs @@ -0,0 +1,15 @@ +using Models; +using SlnMesnac.Repository.service.@base; +using SlnMesnac.Repository.service.Impl; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace SlnMesnac.Repository.service +{ + public interface ICfgstationattrService : IBaseService + { + Task> GetTableListAsync(); + } +} diff --git a/SlnMesnac.Repository/service/Impl/CfgstationattrServiceImpl.cs b/SlnMesnac.Repository/service/Impl/CfgstationattrServiceImpl.cs new file mode 100644 index 0000000..9e4be9f --- /dev/null +++ b/SlnMesnac.Repository/service/Impl/CfgstationattrServiceImpl.cs @@ -0,0 +1,38 @@ +using Models; +using SlnMesnac.Common; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SlnMesnac.Repository.service.Impl +{ + public class CfgstationattrServiceImpl : BaseServiceImpl, ICfgstationattrService + { + private Repository _repository; + public CfgstationattrServiceImpl(Repository rep) : base(rep) + { + _repository = rep; + } + + public async Task> GetTableListAsync() + { + List list = null; + try + { + Expression> exp = x => true; + exp = exp.And(x => + (x.Opername != "") + ); + list = _repository.GetList(exp); + } + catch (Exception ex) + { + + } + return list; + } + } +} diff --git a/SlnMesnac.Serilog/CustomLogLevelAbbreviationEnricher.cs b/SlnMesnac.Serilog/CustomLogLevelAbbreviationEnricher.cs new file mode 100644 index 0000000..1bc8a4e --- /dev/null +++ b/SlnMesnac.Serilog/CustomLogLevelAbbreviationEnricher.cs @@ -0,0 +1,50 @@ +using Serilog.Core; +using Serilog.Events; + +namespace SlnMesnac.Serilog +{ + // 自定义日志级别缩写增强器 + public class CustomLogLevelAbbreviationEnricher : ILogEventEnricher + { + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + string abbreviation; + switch (logEvent.Level) + { + case LogEventLevel.Verbose: + abbreviation = "VRB"; + break; + + case LogEventLevel.Debug: + abbreviation = "DBG"; + break; + + case LogEventLevel.Information: + abbreviation = "INF"; + break; + + case LogEventLevel.Warning: + abbreviation = "WRN"; + break; + + case LogEventLevel.Error: + abbreviation = "ERR"; + break; + + case LogEventLevel.Fatal: + abbreviation = "FTL"; + break; + + //case (LogEventLevel)35: // 自定义的 AgvLevel + // abbreviation = "AGV"; + // break; + + default: + abbreviation = logEvent.Level.ToString(); + break; + } + + logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("LevelAbbreviation", abbreviation)); + } + } +} \ No newline at end of file diff --git a/SlnMesnac.Serilog/SerilogExtensions.cs b/SlnMesnac.Serilog/SerilogExtensions.cs index 5e8dc03..aa32366 100644 --- a/SlnMesnac.Serilog/SerilogExtensions.cs +++ b/SlnMesnac.Serilog/SerilogExtensions.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; using Serilog; using Serilog.Events; using SlnMesnac.Config; @@ -7,6 +6,7 @@ using System; using System.IO; #region << 版 本 注 释 >> + /*-------------------------------------------------------------------- * 版权所有 (c) 2024 WenJY 保留所有权利。 * CLR版本:4.0.30319.42000 @@ -27,7 +27,9 @@ using System.IO; * * 版本:V1.0.0 *--------------------------------------------------------------------*/ + #endregion << 版 本 注 释 >> + namespace SlnMesnac.Serilog { /// @@ -35,27 +37,77 @@ namespace SlnMesnac.Serilog /// public static class SerilogExtensions { + // 定义自定义日志级别 + public static readonly LogEventLevel AgvLevel = (LogEventLevel)35; + + //public static IApplicationBuilder UseSerilogExtensions(this IApplicationBuilder app) + //{ + // // 获取当前程序所在的目录 + // string currentDirectory = Directory.GetCurrentDirectory(); + + // Log.Logger = new LoggerConfiguration() + // .MinimumLevel.Verbose() // 确保能捕获所有级别日志 + // .Enrich.With(new CustomLogLevelAbbreviationEnricher()) // 添加自定义日志级别缩写增强器 + // .WriteTo.Console( + // outputTemplate: "{Timestamp:MM-dd HH:mm:ss} [{LevelAbbreviation}] [{ClassName}] [{LineNumber}] {Message:lj}{NewLine}{Exception}", + // restrictedToMinimumLevel: LogEventLevel.Error + + // ) + // // retainedFileCountLimit: 3, // 保留最近3天日志 + // .WriteTo.File(path: GetDynamicLogPath("Info"), retainedFileCountLimit: 3, restrictedToMinimumLevel: LogEventLevel.Information, rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{ClassName}] [{LineNumber}] {Message:lj}{NewLine}{Exception}") + // .WriteTo.File(path: GetDynamicLogPath("Error"), retainedFileCountLimit: 3, restrictedToMinimumLevel: LogEventLevel.Error, rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{ClassName}] [{LineNumber}] {Message:lj}{NewLine}{Exception}") + // .WriteTo.File(path: GetDynamicLogPath("Agv"), retainedFileCountLimit: 3, restrictedToMinimumLevel: AgvLevel, rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{ClassName}] [{LineNumber}] {Message:lj}{NewLine}{Exception}") // 新增 Agv 日志文件 + // .CreateLogger(); + + // // 启用 Serilog 中间件 + // app.UseSerilogRequestLogging(); + + // return app; + //} + public static IApplicationBuilder UseSerilogExtensions(this IApplicationBuilder app) { - //启用Serilog中间件 - app.UseSerilogRequestLogging(); + // 获取当前程序所在的目录 + string currentDirectory = Directory.GetCurrentDirectory(); + var logPath = Path.Combine(currentDirectory, "Logs"); + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Verbose() // 确保能捕获所有级别日志 + .Enrich.With(new CustomLogLevelAbbreviationEnricher()) // 添加自定义日志级别缩写增强器 + .WriteTo.Console( + outputTemplate: "{Timestamp:MM-dd HH:mm:ss} [{LevelAbbreviation}] [{ClassName}] [{LineNumber}] {Message:lj}{NewLine}{Exception}", + restrictedToMinimumLevel: LogEventLevel.Error - #region 通过配置文件读取日志存放位置 - var appConfig = app.ApplicationServices.GetService(); - var logPath = $"{appConfig.logPath}/Logs/"; - #endregion + ) + // retainedFileCountLimit: 3, // 保留最近3天日志 + .WriteTo.Logger(lc => lc + .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Info")) + .WriteTo.File(Path.Combine($"{logPath}/Info/", "Info.log"), rollingInterval: RollingInterval.Day, retainedFileCountLimit: 3)) + .WriteTo.Logger(lc => lc + .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Plc")) + .WriteTo.File(Path.Combine($"{logPath}/Plc/", "Plc.log"), rollingInterval: RollingInterval.Day, retainedFileCountLimit: 3)) + .WriteTo.Logger(lc => lc + .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Agv")) + .WriteTo.File(Path.Combine($"{logPath}/Agv/", "Agv.log"), rollingInterval: RollingInterval.Day, retainedFileCountLimit: 3)) + .WriteTo.Logger(lc => lc + .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Error")) + .WriteTo.File(Path.Combine($"{logPath}/Error/", "Error.log"), rollingInterval: RollingInterval.Day, retainedFileCountLimit: 3)) + .CreateLogger(); - Log.Logger = new LoggerConfiguration().MinimumLevel.Information().WriteTo.Console() - .WriteTo.File(Path.Combine(logPath, "Info.log"), LogEventLevel.Information,rollingInterval:RollingInterval.Day) - .WriteTo.File(Path.Combine(logPath, "Error.log"), LogEventLevel.Error, rollingInterval: RollingInterval.Day) - .WriteTo.File(Path.Combine(logPath, "data.log"), LogEventLevel.Warning, rollingInterval: RollingInterval.Day) - - //.WriteTo.File(Path.Combine(logPath, "data.log"), LogEventLevel.Debug) - //.WriteTo.File(Path.Combine(logPath, "Debug.log"), LogEventLevel.Debug, fileSizeLimitBytes: 5 * 1024) - .CreateLogger(); + // 启用 Serilog 中间件 app.UseSerilogRequestLogging(); return app; } + + // 新的动态路径生成方法 + private static string GetDynamicLogPath(string logType) + { + return Path.Combine( + Directory.GetCurrentDirectory(), + "Logs", + $"{DateTime.UtcNow:yyyy-MM-dd}", + $"{logType}-.log" + ); + } } -} +} \ No newline at end of file diff --git a/SlnMesnac.Serilog/SerilogHelper.cs b/SlnMesnac.Serilog/SerilogHelper.cs new file mode 100644 index 0000000..b303d0f --- /dev/null +++ b/SlnMesnac.Serilog/SerilogHelper.cs @@ -0,0 +1,114 @@ +using Serilog; +using System; +using System.IO; + +#region << 版 本 注 释 >> + +/*-------------------------------------------------------------------- +* 版权所有 (c) 2024 WenJY 保留所有权利。 +* CLR版本:4.0.30319.42000 +* 机器名称:T14-GEN3-7895 +* 命名空间:SlnMesnac.Serilog +* 唯一标识:fae9d68d-1992-4a03-b299-19edd9fc786d +* +* 创建者:WenJY +* 电子邮箱: +* 创建时间:2024-12-26 8:46:21 +* 版本:V1.0.0 +* 描述: +* +*-------------------------------------------------------------------- +* 修改人: +* 时间: +* 修改说明: +* +* 版本:V1.0.0 +*--------------------------------------------------------------------*/ + +#endregion << 版 本 注 释 >> + +namespace SlnMesnac.Serilog +{ + /// + /// Serilog日志类 + /// + public class SerilogHelper + { + private readonly ILogger Info_logger = Log.ForContext("Module", "Info"); + private readonly ILogger Plc_logger = Log.ForContext("Module", "Plc"); + private readonly ILogger Error_logger = Log.ForContext("Module", "Error"); + //private readonly ILogger Agv_logger = Log.ForContext("Module", "Agv"); // 新增 Agv 日志记录器 + + /// + /// Info日志 + /// + /// + /// + /// + public void Info(string msg, [System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int callerLineNumber = 0) + { + var className = Path.GetFileNameWithoutExtension(callerFilePath); + Info_logger.ForContext("ClassName", className).ForContext("LineNumber", callerLineNumber).Information(msg); + } + + /// + /// Plc日志 + /// + /// + /// + /// + public void Plc(string msg, [System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int callerLineNumber = 0) + { + var className = Path.GetFileNameWithoutExtension(callerFilePath); + Plc_logger.ForContext("ClassName", className).ForContext("LineNumber", callerLineNumber).Information(msg); + } + + /// + /// Error日志 + /// + /// + /// + /// + /// + public void Error(string msg, Exception ex = null, [System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int callerLineNumber = 0) + { + var className = Path.GetFileNameWithoutExtension(callerFilePath); + var logger = Error_logger.ForContext("ClassName", className).ForContext("LineNumber", callerLineNumber); + + if (!string.IsNullOrEmpty(msg) && ex == null) + { + logger.Error("【附加信息】 : {0}
", msg); + } + else if (!string.IsNullOrEmpty(msg) && ex != null) + { + string errorMsg = BeautyErrorMsg(ex); + logger.Error("【附加信息】 : {0}
{1}", msg, errorMsg); + } + else if (string.IsNullOrEmpty(msg) && ex != null) + { + string errorMsg = BeautyErrorMsg(ex); + logger.Error(errorMsg); + } + } + + /// + /// Agv日志 + /// + /// + /// + /// + //public void Agv(string msg, [System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int callerLineNumber = 0) + //{ + // var className = Path.GetFileNameWithoutExtension(callerFilePath); + // Agv_logger.ForContext("ClassName", className).ForContext("LineNumber", callerLineNumber).Write(SerilogExtensions.AgvLevel, msg); + //} + + private string BeautyErrorMsg(Exception ex) + { + string errorMsg = string.Format("【异常类型】:{0}
【异常信息】:{1}
【堆栈调用】:{2}", ex.GetType().Name, ex.Message, ex.StackTrace); + errorMsg = errorMsg.Replace("\r\n", "
"); + errorMsg = errorMsg.Replace("位置", "位置"); + return errorMsg; + } + } +} \ No newline at end of file diff --git a/SlnMesnac.WPF/SlnMesnac.WPF.csproj b/SlnMesnac.WPF/SlnMesnac.WPF.csproj index 787584e..1a36ef7 100644 --- a/SlnMesnac.WPF/SlnMesnac.WPF.csproj +++ b/SlnMesnac.WPF/SlnMesnac.WPF.csproj @@ -1,7 +1,7 @@  - WinExe + Exe net6.0-windows enable true diff --git a/SlnMesnac.WPF/ViewModel/IndexPage/FirstContentViewModel.cs b/SlnMesnac.WPF/ViewModel/IndexPage/FirstContentViewModel.cs new file mode 100644 index 0000000..01e84ca --- /dev/null +++ b/SlnMesnac.WPF/ViewModel/IndexPage/FirstContentViewModel.cs @@ -0,0 +1,57 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Models; +using NVelocity.Runtime.Directive; +using SlnMesnac.Repository.service; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SlnMesnac.WPF.ViewModel.IndexPage +{ + public partial class FirstContentViewModel : ObservableObject + { + private ILogger _logger; + private ICfgstationattrService _cfgstationattrService; + public FirstContentViewModel() + { + _cfgstationattrService = App.ServiceProvider.GetService(); + Init(); + } + private async Task Init() + { + List cfgstationattrs = await _cfgstationattrService.GetTableListAsync(); + } + /// + /// 监听PLC地址值 + /// + private void ListeningPlcValue() + { + try + { + + } + catch (Exception ex) + { + + } + } + private bool TryObject(object value, out object[] arry) + { + arry = null; + try + { + arry = (object[])value; + return true; + } + catch + { + return false; + } + } + } + +} diff --git a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs index abf125f..10343cd 100644 --- a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs @@ -34,6 +34,7 @@ using System.Data; using System.Dynamic; using System.Drawing; using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock; +using Models; #region << 版 本 注 释 >> /*-------------------------------------------------------------------- @@ -81,6 +82,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage private string WritePLCAddress = "D6000"; private String _lastCode = string.Empty; private int stationid = 3; + private ICfgstationattrService _cfgstationattrService; public IndexContentViewModel() { taskInfo = new TaskInfo1(); @@ -100,10 +102,12 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage OKCount = _appSettings.ReadAppSettings("ProductConfig:OKCount"); //_appSettings.WriteAppSettings("ProductConfig", "OKCount", "2"); NGCount = _appSettings.ReadAppSettings("ProductConfig:NGCount"); + _cfgstationattrService = App.ServiceProvider.GetService(); this.Init(); } - private void Init() + private async Task Init() { + List cfgstationattrs =await _cfgstationattrService.GetTableListAsync(); _controlOffLineScanHelper.RecAutoDataAction += ShowBarCode; LoadStationInfo(); #region 测试数据 diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json index 1190500..1cffbf7 100644 --- a/SlnMesnac.WPF/appsettings.json +++ b/SlnMesnac.WPF/appsettings.json @@ -12,9 +12,11 @@ "SqlConfig": [ { "configId": "mes", - "dbType": 1, + "dbType": 0, //"connStr": "server=192.168.1.120;uid=sa;pwd=123456;database=ATJ_581_DB" - "connStr": "server=119.45.202.115;uid=sa;pwd=haiwei@123;database=ATJ_581_DB" + //"connStr": "server=119.45.202.115;uid=sa;pwd=haiwei@123;database=ATJ_581_DB" + //"connStr": "server=119.45.202.115;uid=root;pwd=haiwei@123;database=db_iems", + "connStr": "Data Source=119.45.202.115;Port=3306;Initial Catalog=db_iems;uid=root;pwd=haiwei@123;Charset=utf8mb4;SslMode=none;Connect Timeout=100" }, { "configId": "Local", @@ -71,7 +73,7 @@ "ComPort": "COM1", - "StationCode": "150" + "StationCode": "200" }, "ProductConfig": { @@ -79,7 +81,7 @@ "NGCount": "0" }, "ChangeTypeConfig": { - "ProductType": "E34F", + "ProductType": "E34FU", "KTProductType": "E34F", "OpenFlag": "1" }