diff --git a/MDM/Models/Process/ProcessOperation.cs b/MDM/Models/Process/ProcessOperation.cs
index bf3778f..b13d14e 100644
--- a/MDM/Models/Process/ProcessOperation.cs
+++ b/MDM/Models/Process/ProcessOperation.cs
@@ -37,6 +37,13 @@ namespace MDM.Model.Process
[SugarColumn(ColumnName = "operation_seq", Length = 50)]
public int? OperationSeq { get; set; }
+
+ ///
+ /// 上一站工序序号(工序流转号)
+ ///
+ [SugarColumn(ColumnName = "last_operation_seq", Length = 50)]
+ public int? LastOperationSeq { get; set; }
+
///
/// 工序类别
///
diff --git a/RIZO.Model/MES/product_trace/ProductLifecycle.cs b/RIZO.Model/MES/product_trace/ProductLifecycle.cs
new file mode 100644
index 0000000..66eb260
--- /dev/null
+++ b/RIZO.Model/MES/product_trace/ProductLifecycle.cs
@@ -0,0 +1,92 @@
+namespace RIZO.Model.MES.product_trace
+{
+ ///
+ /// 产品生命周期表
+ ///
+ [SugarTable("product_lifecycle")]
+ public class ProductLifecycle
+ {
+ ///
+ /// 主键ID
+ ///
+ [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ ///
+ /// 工单号
+ ///
+ [SugarColumn(ColumnName = "workorder", Length = 50)]
+ [StringLength(50)]
+ public string Workorder { get; set; }
+
+ ///
+ /// 当前状态(0 未生产,1 生产中,2 完工中,3 返工中,4报废中)
+ ///
+ [SugarColumn(ColumnName = "product_current_status")]
+ public int? ProductCurrentStatus { get; set; }
+
+ ///
+ /// 产品SN
+ ///
+ [SugarColumn(ColumnName = "product_SN", Length = 50)]
+ [StringLength(50)]
+ public string ProductSN { get; set; }
+
+ ///
+ /// 线别
+ ///
+ [SugarColumn(ColumnName = "line_code", Length = 50)]
+ [StringLength(50)]
+ public string LineCode { get; set; }
+
+ ///
+ /// 组别
+ ///
+ [SugarColumn(ColumnName = "group_code", Length = 50)]
+ [StringLength(50)]
+ public string GroupCode { get; set; }
+
+ ///
+ /// 工艺路线
+ ///
+ [SugarColumn(ColumnName = "routing_code", Length = 50)]
+ [StringLength(50)]
+ public string RoutingCode { get; set; }
+
+ ///
+ /// 产品开工时间
+ ///
+ [SugarColumn(ColumnName = "product_start_time")]
+ public DateTime? ProductStartTime { get; set; }
+
+ ///
+ /// 产品返工时间
+ ///
+ [SugarColumn(ColumnName = "product_rework_time")]
+ public DateTime? ProductReworkTime { get; set; }
+
+ ///
+ /// 产品完工时间
+ ///
+ [SugarColumn(ColumnName = "product_finish_time")]
+ public DateTime? ProductFinishTime { get; set; }
+
+ ///
+ /// 产品报废时间
+ ///
+ [SugarColumn(ColumnName = "product_scrap_time")]
+ public DateTime? ProductScrapTime { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "created_time")]
+ public DateTime? CreatedTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "updated_time")]
+ public DateTime? UpdatedTime { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/RIZO.Model/MES/product_trace/ProductPassStationRecord.cs b/RIZO.Model/MES/product_trace/ProductPassStationRecord.cs
new file mode 100644
index 0000000..02887e8
--- /dev/null
+++ b/RIZO.Model/MES/product_trace/ProductPassStationRecord.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RIZO.Model.MES.product_trace
+{
+ ///
+ /// 过站记录表
+ ///
+ [SugarTable("product_passstation_record")]
+ public class ProductPassStationRecord
+ {
+ ///
+ /// 主键ID
+ ///
+ [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
+ public long Id { get; set; }
+
+ ///
+ /// 工单号
+ ///
+ [SugarColumn(ColumnName = "workorder", Length = 50)]
+ [StringLength(50)]
+ public string Workorder { get; set; }
+
+ ///
+ /// 产品SN
+ ///
+ [SugarColumn(ColumnName = "product_SN", Length = 100)]
+ [StringLength(100)]
+ public string ProductSN { get; set; }
+
+ ///
+ /// 工站code
+ ///
+ [SugarColumn(ColumnName = "workstationCode", Length = 50)]
+ [StringLength(50)]
+ public string WorkstationCode { get; set; }
+
+ ///
+ /// 工艺路线code
+ ///
+ [SugarColumn(ColumnName = "routingcode", Length = 50)]
+ [StringLength(50)]
+ public string Routingcode { get; set; }
+
+ ///
+ /// 工序code
+ ///
+ [SugarColumn(ColumnName = "operationCode", Length = 50)]
+ [StringLength(50)]
+ public string OperationCode { get; set; }
+
+ ///
+ /// 当前产品处于的生命周期
+ ///
+ [SugarColumn(ColumnName = "production_life_stage")]
+ public int? ProductionLifeStage { get; set; }
+
+ ///
+ /// 过站类型(0 入站请求,1入站完毕,2出站请求,3出站完毕)
+ ///
+ [SugarColumn(ColumnName = "passtation_type")]
+ public int? PasstationType { get; set; }
+
+ ///
+ /// 过站描述
+ ///
+ [SugarColumn(ColumnName = "passtation_description", Length = 255)]
+ [StringLength(255)]
+ public string PasstationDescription { get; set; }
+
+ ///
+ /// 生效时间
+ ///
+ [SugarColumn(ColumnName = "effect_time")]
+ public DateTime? EffectTime { get; set; }
+
+ ///
+ /// 进站时间
+ ///
+ [SugarColumn(ColumnName = "InStationTime")]
+ public DateTime? InStationTime { get; set; }
+
+ ///
+ /// 出站时间
+ ///
+ [SugarColumn(ColumnName = "OutStationTime")]
+ public DateTime? OutStationTime { get; set; }
+
+ ///
+ /// 加工时间(s)
+ ///
+ [SugarColumn(ColumnName = "DurationSeconds")]
+ public int? DurationSeconds { get; set; }
+
+ ///
+ /// 操作人
+ ///
+ [SugarColumn(ColumnName = "operator", Length = 50)]
+ [StringLength(50)]
+ public string Operator { get; set; }
+
+ ///
+ /// 结果代码1 是OK 其他NG
+ ///
+ [SugarColumn(ColumnName = "result_code")]
+ public int? ResultCode { get; set; }
+
+ ///
+ /// 结果描述
+ ///
+ [SugarColumn(ColumnName = "result_description", Length = 255)]
+ [StringLength(255)]
+ public string ResultDescription { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "created_time")]
+ public DateTime? CreatedTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "updated_time")]
+ public DateTime? UpdatedTime { get; set; }
+ }
+}
diff --git a/RIZO.Service/PLCBackground/PlcConntectHepler.cs b/RIZO.Service/PLCBackground/PlcConntectHepler.cs
new file mode 100644
index 0000000..8da255a
--- /dev/null
+++ b/RIZO.Service/PLCBackground/PlcConntectHepler.cs
@@ -0,0 +1,355 @@
+using S7.Net; // 确保引用 S7.Net 库
+using System;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace RIZO.Service.PLC
+{
+
+
+
+ public class PlcConntectHepler : IDisposable
+ {
+ private Plc _plc;
+ private readonly string _ipAddress;
+ private readonly CpuType _cpuType;
+ private readonly short _rack;
+ private readonly short _slot;
+ private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
+ private bool _disposed;
+
+ public PlcConntectHepler(string ipAddress, CpuType cpuType = CpuType.S71200, short rack = 0, short slot = 1)
+ {
+ _ipAddress = ipAddress;
+ _cpuType = cpuType;
+ _rack = rack;
+ _slot = slot;
+ }
+
+ private async Task ConnectAsync(CancellationToken cancellationToken = default)
+ {
+ int maxRetries = 3;
+ int retryDelayMs = 2000;
+ int attempt = 0;
+
+ while (attempt < maxRetries)
+ {
+ attempt++;
+ try
+ {
+ _plc = new Plc(_cpuType, _ipAddress, _rack, _slot);
+ await Task.Run(() => _plc.Open(), cancellationToken); // 在线程池中执行同步Open
+ Console.WriteLine($"成功连接到PLC: {_ipAddress} (尝试{attempt}/{maxRetries})");
+ return;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"连接尝试 {attempt}/{maxRetries} 失败: {ex.Message}");
+
+ if (attempt < maxRetries)
+ {
+ Console.WriteLine($"{retryDelayMs / 1000}秒后重试...");
+ await Task.Delay(retryDelayMs, cancellationToken);
+ }
+ else
+ {
+ Console.WriteLine("无法建立PLC连接,请检查网络和设备状态");
+ _plc?.Close();
+ _plc = null;
+ }
+ }
+ }
+ }
+ ///
+ /// 读取指定类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+
+ public async Task ReadAsync(string address, CancellationToken cancellationToken = default)
+ {
+ await _semaphore.WaitAsync(cancellationToken);
+ try
+ {
+ if (_plc == null || !_plc.IsConnected)
+ {
+ await ConnectAsync(cancellationToken);
+ if (_plc == null || !_plc.IsConnected)
+ throw new InvalidOperationException("PLC未连接");
+ }
+
+ var result = await Task.Run(() => _plc.Read(address), cancellationToken);
+
+ // 根据泛型类型转换结果
+ return ConvertResult(result);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Read error: {ex.Message}");
+ return default(T);
+ }
+ finally
+ {
+ _semaphore.Release();
+ }
+ }
+
+
+ ///
+ /// 写入指定类型数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task WriteAsync(string address, object value, CancellationToken cancellationToken = default)
+ {
+ await _semaphore.WaitAsync(cancellationToken);
+ try
+ {
+ if (_plc == null || !_plc.IsConnected)
+ {
+ await ConnectAsync(cancellationToken);
+ if (_plc == null || !_plc.IsConnected)
+ throw new InvalidOperationException("PLC未连接");
+ }
+
+ await Task.Run(() => _plc.Write(address, value), cancellationToken);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Write error: {ex.Message}");
+ }
+ finally
+ {
+ _semaphore.Release();
+ }
+ }
+
+
+
+ private T ConvertResult(object result)
+ {
+ if (result == null) return default(T);
+
+ if (typeof(T).IsAssignableFrom(result.GetType()))
+ {
+ return (T)result;
+ }
+
+ return typeof(T) switch
+ {
+ Type t when t == typeof(bool) => (T)(object)Convert.ToBoolean(result),
+ Type t when t == typeof(short) => (T)(object)Convert.ToInt16(result),
+ Type t when t == typeof(int) => (T)(object)Convert.ToInt32(result),
+ Type t when t == typeof(float) => (T)(object)Convert.ToSingle(result),
+ Type t when t == typeof(double) => (T)(object)Convert.ToDouble(result),
+ Type t when t == typeof(string) => (T)(object)result.ToString(),
+ _ => throw new InvalidCastException($"无法将类型 {result.GetType()} 转换为 {typeof(T)}")
+ };
+ }
+
+ ///
+ /// 从PLC读取字符串(主要方法)
+ ///
+ /// 地址字符串(如:"DB1001.DBB1000")
+ /// 读取到的字符串
+ public async Task ReadStringAsync(string address)
+ {
+ return await ReadStringAsync(address, CancellationToken.None);
+ }
+
+ ///
+ /// 从PLC读取字符串(带取消令牌)
+ ///
+ /// 地址字符串(如:"DB1001.DBB1000")
+ /// 取消令牌
+ /// 读取到的字符串
+ public async Task ReadStringAsync(string address, CancellationToken cancellationToken = default)
+ {
+ await _semaphore.WaitAsync(cancellationToken);
+ try
+ {
+ if (_plc == null || !_plc.IsConnected)
+ {
+ await ConnectAsync(cancellationToken);
+ if (_plc == null || !_plc.IsConnected)
+ throw new InvalidOperationException("PLC未连接");
+ }
+
+ // 解析地址
+ if (!ParseAddress(address, out int dbNumber, out int startByte))
+ {
+ throw new ArgumentException($"无效的地址格式: {address}");
+ }
+
+ // 读取第一个字节(字符串长度)
+ byte stringLength = await Task.Run(() =>
+ (byte)_plc.Read(DataType.DataBlock, dbNumber, startByte, VarType.Byte, 1), cancellationToken);
+
+ // 如果长度为0,直接返回空字符串
+ if (stringLength == 0)
+ return string.Empty;
+
+ // 读取字符串内容(从startByte+1开始,读取stringLength个字节)
+ byte[] stringBytes = await Task.Run(() =>
+ (byte[])_plc.Read(DataType.DataBlock, dbNumber, startByte + 1, VarType.Byte, (int)stringLength), cancellationToken);
+
+ // 将字节数组转换为ASCII字符串
+ return Encoding.ASCII.GetString(stringBytes);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ReadString error: {ex.Message}");
+ return string.Empty;
+ }
+ finally
+ {
+ _semaphore.Release();
+ }
+ }
+
+ ///
+ /// 向PLC写入字符串
+ ///
+ /// 地址字符串(如:"DB1001.DBB1000")
+ /// 要写入的字符串
+ /// 是否写入成功
+ public async Task WriteStringAsync(string address, string value)
+ {
+ return await WriteStringAsync(address, value, CancellationToken.None);
+ }
+
+ ///
+ /// 向PLC写入字符串(带取消令牌)
+ ///
+ /// 地址字符串(如:"DB1001.DBB1000")
+ /// 要写入的字符串
+ /// 取消令牌
+ /// 是否写入成功
+ public async Task WriteStringAsync(string address, string value, CancellationToken cancellationToken = default)
+ {
+ await _semaphore.WaitAsync(cancellationToken);
+ try
+ {
+ if (_plc == null || !_plc.IsConnected)
+ {
+ await ConnectAsync(cancellationToken);
+ if (_plc == null || !_plc.IsConnected)
+ throw new InvalidOperationException("PLC未连接");
+ }
+
+ if (value == null)
+ value = string.Empty;
+
+ // 限制字符串长度(S7字符串最大254字符)
+ if (value.Length > 254)
+ {
+ value = value.Substring(0, 254);
+ }
+
+ // 准备写入的数据
+ List writeData = new List();
+
+ // 第一个字节:字符串长度
+ writeData.Add((byte)value.Length);
+
+ // 后续字节:字符串内容(ASCII编码)
+ byte[] contentBytes = Encoding.ASCII.GetBytes(value);
+ writeData.AddRange(contentBytes);
+
+ // 解析地址
+ if (!ParseAddress(address, out int dbNumber, out int startByte))
+ {
+ throw new ArgumentException($"无效的地址格式: {address}");
+ }
+
+ // 写入数据
+ await Task.Run(() =>
+ _plc.WriteBytes(DataType.DataBlock, dbNumber, startByte, writeData.ToArray()), cancellationToken);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"WriteString error: {ex.Message}");
+ return false;
+ }
+ finally
+ {
+ _semaphore.Release();
+ }
+ }
+
+ ///
+ /// 解析PLC地址字符串,提取DB号和起始字节
+ /// 支持格式:DB1001.DBB1000, DB1001.DBW1000, DB1001.DBD1000 等
+ ///
+ private bool ParseAddress(string address, out int dbNumber, out int startByte)
+ {
+ dbNumber = 0;
+ startByte = 0;
+
+ try
+ {
+ // 移除空格并转为大写
+ address = address.Replace(" ", "").ToUpper();
+
+ // 分割DB部分和数据部分
+ string[] parts = address.Split('.');
+ if (parts.Length < 2) return false;
+
+ // 解析DB号
+ string dbPart = parts[0];
+ if (!dbPart.StartsWith("DB") || !int.TryParse(dbPart.Substring(2), out dbNumber))
+ return false;
+
+ // 解析起始字节
+ string dataPart = parts[1];
+
+ // 提取偏移量数字(去掉DBB/DBW/DBD前缀)
+ string offsetStr = "";
+ if (dataPart.StartsWith("DBB"))
+ offsetStr = dataPart.Substring(3);
+ else if (dataPart.StartsWith("DBW"))
+ offsetStr = dataPart.Substring(3);
+ else if (dataPart.StartsWith("DBD"))
+ offsetStr = dataPart.Substring(3);
+ else
+ return false;
+
+ if (!int.TryParse(offsetStr, out startByte))
+ return false;
+
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed) return;
+
+ if (disposing)
+ {
+ _semaphore.Dispose();
+ _plc?.Close();
+ (_plc as IDisposable)?.Dispose();
+ }
+ _disposed = true;
+ }
+ }
+
+}
diff --git a/RIZO.Service/PLCBackground/Stations/PlcPollingService_OP07_01.cs b/RIZO.Service/PLCBackground/Stations/PlcPollingService_OP07_01.cs
new file mode 100644
index 0000000..f76c538
--- /dev/null
+++ b/RIZO.Service/PLCBackground/Stations/PlcPollingService_OP07_01.cs
@@ -0,0 +1,189 @@
+using MDM.Model.Plant;
+using MDM.Model.Process;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using NLog;
+using RIZO.Model.Mes;
+using RIZO.Model.MES.product_trace;
+using RIZO.Repository;
+using RIZO.Service.MES.product_trace;
+using RIZO.Service.PLC;
+using S7.Net;
+using SqlSugar.IOC;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace RIZO.Service.PLCBackground.Stations
+{
+
+
+ public class PlcPollingService_OP07_01 : BackgroundService
+ {
+ private static Logger _logger = LogManager.GetCurrentClassLogger();
+ private PlcConntectHepler _plcService;
+ private readonly TimeSpan _pollingInterval = TimeSpan.FromSeconds(5);
+ private readonly string _ipAddress = "192.168.10.222";
+ private readonly CpuType _cpuType = CpuType.S71500;
+ private string WorkstationCode;
+
+
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ _logger.Info("PLC Polling Service started");
+
+ // 使用工厂方法创建服务实例
+ using (_plcService = new PlcConntectHepler(_ipAddress, _cpuType))
+ {
+
+ // 获取当前的工序/工站
+ WorkstationCode = await DbScoped.SugarScope.CopyNew().Queryable().Where(it => it.PlcIP == _ipAddress)
+ .Select(it => it.WorkstationCode).FirstAsync();
+
+
+ while (!stoppingToken.IsCancellationRequested)
+ {
+ try
+ {
+ //心跳检测
+ await _plcService.WriteAsync("DB1010.DBW0", 1);
+
+ // 轮询进站请求信号/工位开始查询请求
+ int intoStationAsk = await _plcService.ReadAsync("DB1001.DBW2000");
+ if (intoStationAsk == 1)
+ {
+ // 处理进站请求
+ _logger.Info("Processing into station request...");
+
+ //获取产品SN码
+ string productModel = await _plcService.ReadStringAsync("DB1001.DBB1000");
+ string productSN = await _plcService.ReadStringAsync("DB1001.DBB1054");
+
+
+
+
+ //判断该产品是否允许进站
+
+ EntryPermissionResult result = await checkEntryPermission(productModel, productSN, WorkstationCode);
+ await _plcService.WriteAsync("DB1010.DBW2000", (int)result);
+
+
+ }
+ await Task.Delay(_pollingInterval, stoppingToken);
+
+ }
+ catch (OperationCanceledException)
+ {
+ _logger.Info("PLC Polling Service is stopping");
+ break;
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex, "PLC polling error");
+ await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
+ }
+ }
+ }
+
+ _logger.Info("PLC Polling Service stopped");
+ }
+
+ ///
+ /// 校验是否可以进站
+ ///
+ /// 产品型号
+ /// 产品SN
+ ///
+ private async Task checkEntryPermission(string productModel, string productSN, string workstationCode)
+ {
+ // 获取工单
+
+ //获取工艺路线工序
+ List processOperations = await DbScoped.SugarScope.CopyNew().Queryable().LeftJoin((r, o) => r.RoutingCode == o.FkRoutingCode)
+ .Where((r, o) => r.FkProductMaterialCode == productModel && r.Status == 1)
+ .Select((r, o) => o).ToListAsync();
+
+
+
+ //2上工位无记录
+
+ //ProcessOperation LastOperation = processOperations.Where(operation => operation.OperationSeq < processOperations.Where(it => it.OperationCode == workstationCode).Select(it => it.OperationSeq).First()).OrderByDescending(operation => operation.OperationSeq).First();
+ int LastOperationSeq=processOperations.Where(operation => operation.OperationCode == workstationCode).Select(operation => operation.LastOperationSeq??-1).First();
+ ProcessOperation LastOperation = processOperations.Where(it => it.OperationSeq == LastOperationSeq).First();
+ bool isExistLastOperationRecord = await DbScoped.SugarScope.CopyNew().Queryable()
+ .Where(it => it.ProductSN == productSN)
+ .Where(it => it.OperationCode == LastOperation.OperationCode)
+ .AnyAsync();
+ if (!isExistLastOperationRecord)
+ {
+ return EntryPermissionResult.NoRecordAtPreviousStation;
+ }
+
+ // 3 上工位NG 入站或者出站结果 NG
+ bool isExistLastOperationNG = await DbScoped.SugarScope.CopyNew().Queryable()
+ .Where(it => it.ProductSN == productSN)
+ .Where(it => it.OperationCode == LastOperation.OperationCode)
+ .Where(it => it.PasstationType == 2 || it.PasstationType == 4)
+ .Where(it => it.ResultCode != 1)
+ .AnyAsync();
+ if (!isExistLastOperationNG)
+ {
+ return EntryPermissionResult.PreviousStationNG;
+ }
+
+
+ // 4 扫码产品型号错误
+ bool isExistproductSN = await DbScoped.SugarScope.CopyNew().Queryable()
+ .Where(it => it.ProductSN == productSN).AnyAsync();
+ bool isExistproductSNProducting = await DbScoped.SugarScope.CopyNew().Queryable()
+ .Where(it => it.ProductSN == productSN && (it.ProductCurrentStatus != 1 && it.ProductCurrentStatus != 3)).AnyAsync();
+ if (!isExistproductSN || !isExistproductSNProducting)
+ {
+ return EntryPermissionResult.ProductModelError;
+ }
+ //6时间超出规定无法生产
+
+ //查询上一站标准时间
+
+
+
+
+
+
+
+
+ return EntryPermissionResult.UnkownException;
+ }
+
+
+
+
+ }
+ enum EntryPermissionResult
+ {
+ //1之前工位数据正常
+ AllowIntoStation = 1,
+ // 2上工位无记录
+ NoRecordAtPreviousStation = 2,
+ // 3上工位NG
+ PreviousStationNG = 3,
+ // 4扫码产品型号错误
+ ProductModelError = 4,
+ //5本工位NG
+ CurrentStationNG = 5,
+ //6时间超出规定无法生产
+ TimeExceeded = 6,
+ //7固化时间未到规定时间
+ CuringTimeNotReached = 7,
+ // 8未找到时间属性
+ TimeAttributeNotFound = 8,
+ // 10条码为空
+ BarcodeEmpty = 10,
+ //0之前工位数据异常
+ PreviousStationDataAbnormal = 0,
+ //11 未知异常
+ UnkownException = 11
+ }
+}
+
diff --git a/RIZO.Service/RIZO.Service.csproj b/RIZO.Service/RIZO.Service.csproj
index 41a52b3..9cf4869 100644
--- a/RIZO.Service/RIZO.Service.csproj
+++ b/RIZO.Service/RIZO.Service.csproj
@@ -9,6 +9,7 @@
1591
+