/** *┌──────────────────────────────────────────────────────────────┐ *│ 描 述:ModbusClient的工具类 *│ 作 者:执笔小白 *│ 版 本:1.3 *│ 创建时间:2023-11-24 12:40:56 *└──────────────────────────────────────────────────────────────┘ *┌──────────────────────────────────────────────────────────────┐ *│ 命名空间: Util.NetworkProtocolHelpers *│ 类 名:ModbusClientHelper *└──────────────────────────────────────────────────────────────┘ */ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Ports; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web.Services.Description; using System.Windows; using static EasyModbus.ModbusClient; using ModbusClient = EasyModbus.ModbusClient; namespace ModBusClientSimple.Util { /// /// ModbusTcpClient帮助类 /// public class ModbusClientHelper { #region 变量 /// /// ModbusClient对象 /// private ModbusClient _modbusClient; /// /// 是否是TCP /// true为TCP; /// private ModbusClientConnType _modbusClientConnType = ModbusClientConnType.TCP; #endregion 变量 /// /// 创建ModbusTCP Client /// /// IP /// 端口 /// 检测 是否连接成功 用的寄存器地址(value=1说明连接成功);默认为-1(不推荐),-1代表使用ping IP的形式 /// 是否开始连接 public ModbusClientHelper(string ipAddress = "127.0.0.1", int port = 502, int connected_Register = -1, bool isConn = false) { _modbusClientConnType = ModbusClientConnType.TCP; _connected_Register = connected_Register; _modbusClient = new ModbusClient(ipAddress, port); if (isConn) { Connect(); } } /// /// 创建ModbusRTU Client /// /// COM串口(COM1~COM99) /// Slave ID(默认值0) /// 波特率(默认值9600) /// 停止位(可以为Parity.Even) /// 校验位(可以为StopBits.OnePointFive) public ModbusClientHelper(string serialPort, byte unitIdentifier, int baudrate, StopBits stopBits, Parity parity) { _modbusClientConnType = ModbusClientConnType.SerialPort; _modbusClient = new ModbusClient(); _modbusClient.SerialPort = serialPort; // COM串口(COM1~COM99) _modbusClient.UnitIdentifier = unitIdentifier; // Slave ID(默认值0) _modbusClient.Baudrate = baudrate; // 波特率(默认值9600) _modbusClient.StopBits = stopBits; // 停止位(可以为Parity.Even) _modbusClient.Parity = parity; // 校验位(可以为StopBits.OnePointFive) } #region 连接与断开连接 /// /// 连接-可持续断线重连机制 /// /// 断线重连 /// 断线重连间隔 1000ms //public void Connect(bool isKeep = false, int isKeep_reconnSpace = 1000) public void Connect() { //if (isKeep_reconnSpace != 0) // _reconnSpace = isKeep_reconnSpace; //if (isKeep) //{ // 以下方案不可用 //_modbusClient.ConnectedChanged += new EasyModbus.ModbusClient.ConnectedChangedHandler(UpdateConnectedChanged); // 重连机制 //Task.Run(() => //{ // UpdateConnectedChanged(); //}); //} _modbusClient.Connect(); } /// /// 断开连接 /// public void Disconnect() { if (_modbusClient != null) _modbusClient.Disconnect(); } /// /// 重连 /// public void ReConnect() { try { if (_modbusClient != null) { switch (_modbusClientConnType) { case ModbusClientConnType.TCP: string ip = IPAddress; int port = Port; _modbusClient.Disconnect(); _modbusClient = new ModbusClient(ip, port); _modbusClient.Connect(); break; case ModbusClientConnType.SerialPort: string serialPort = _modbusClient.SerialPort; byte unitIdentifier = _modbusClient.UnitIdentifier; int baudrate = _modbusClient.Baudrate; StopBits stopBits = _modbusClient.StopBits; Parity parity = _modbusClient.Parity; _modbusClient.Disconnect(); _modbusClient = new ModbusClient(); _modbusClient.SerialPort = serialPort; // COM串口(COM1~COM99) _modbusClient.UnitIdentifier = unitIdentifier; // Slave ID(默认值0) _modbusClient.Baudrate = baudrate; // 波特率(默认值9600) _modbusClient.StopBits = stopBits; // 停止位(可以为Parity.Even) _modbusClient.Parity = parity; // 校验位(可以为StopBits.OnePointFive) _modbusClient.Connect(); break; } } } catch (Exception ex) { Debug.Write(ex.Message.ToString()); } } #region 重连机制 /// /// 断线重连间隔,默认为1000ms /// private int _reconnSpace = 1000; /// /// 重连写法一_上次重连时间 /// public DateTime lastReconnTime; /// /// 重连等待锁 /// object threadlock = new object(); // 资源锁 /// /// 重连机制 /// /// /// 断线重连间隔 1000ms //private void UpdateConnectedChanged(object sender) private void UpdateConnectedChanged() { #region 重连写法一 //while (true) //{ // if (!_modbusClient.Connected) // { // if (lastReconnTime < DateTime.Now.AddMilliseconds(-reconnSpace)) // { // lastReconnTime= DateTime.Now; // // 保护机制 // lock (threadlock) // { // Monitor.Wait(threadlock, _reconnSpace); // } // if (!_modbusClient.Connected) // { // _modbusClient.Disconnect(); // _modbusClient.Connect(); // } // } // else // { // lock (threadlock) // { // Monitor.Wait(threadlock, 1000); // 等待1s // } // } // } // else // { // break; // } //} #endregion 重连写法一 #region 重连写法二 //if (!_modbusClient.Connected) //{ // lock (threadlock) // { // Monitor.Wait(threadlock, _reconnSpace); // } // //_modbusClient.Disconnect(); // _modbusClient.Connect(); //} #endregion 重连写法二 #region 重连写法三 while (true) { if (!IsConnected) { lock (threadlock) { Monitor.Wait(threadlock, _reconnSpace); } //_modbusClient.Disconnect(); try { _modbusClient.Connect(); } catch { } } } #endregion 重连写法三 } #endregion 重连机制 #endregion 连接与断开连接 #region 常用属性 /// /// 检查是否连接到Modbus TCP Server /// //public bool Connected => _modbusClient.Connected;// 经测试,_modbusClient.Connected无效 /// /// 检测ModbusClient连接状态 /// private int _connected_Register = -1; /// /// Modbus TCP Server状态 /// private bool connected = false; /// /// 检查是否连接到Modbus TCP Server /// public bool IsConnected { get { if (_modbusClientConnType == ModbusClientConnType.SerialPort) { return _modbusClient.Connected; } else // TCP { if (_connected_Register == -1) // 默认为ping IP的形式;不推荐 { try { Ping p = new Ping(); PingReply r = p.Send(_modbusClient.IPAddress, 3000); connected = r.Status == IPStatus.Success ? true : false; } catch { connected = false; } } else { try { var values = _modbusClient.ReadHoldingRegisters(_connected_Register, 1).FirstOrDefault(); connected = values == 1; } catch { connected = false; } } return connected; } } set { connected = value; } } /// /// 获取 Modbus-TCP Server的IP-Address /// public string IPAddress => _modbusClient.IPAddress; /// /// 获取 Modbus-TCP Server的Port (默认是 502). /// public int Port => _modbusClient.Port; #endregion 常用属性 #region 常用方法 #region 读写值的方法 #region 1、线圈(Coils) /// /// 读线圈(Coils) (FC1) /// /// 第一个要读取的 线圈的地址 /// 要读取的 线圈数量 /// 线圈值的布尔数组 public bool[] ReadCoils(int startingAddress, int quantity) => _modbusClient.ReadCoils(startingAddress, quantity); /// /// 写线圈(Coils)_单个 (FC5) /// /// 线圈的地址 /// 线圈值 public void WriteSingleCoil(int startingAddress, bool value) => _modbusClient.WriteSingleCoil(startingAddress, value); /// /// 写线圈(Coils)_多个 (FC15) /// /// 第一个要写的线圈的地址 /// 线圈值的布尔数组 public void WriteMultipleCoils(int startingAddress, bool[] values) => _modbusClient.WriteMultipleCoils(startingAddress, values); #endregion 1、线圈(Coils) #region 2、离散输入(Discrete Inputs) /// /// 读 离散输入(Discrete Inputs)(FC2) /// /// 要读取的第一个 离散输入的地址 /// 要读取的 离散输入数量 /// 离散输入的布尔数组 public bool[] ReadDiscreteInputs(int startingAddress, int quantity) => _modbusClient.ReadDiscreteInputs(startingAddress, quantity); #endregion 2、离散输入(Discrete Inputs) // 3、浮点寄存器(Modbus协议可能不支持) #region 4、输入寄存器(Input Registers)-只读 /// /// 读 输入寄存器(Input Registers) (FC4) /// /// 第一个要读取的 输入寄存器 的地址 /// 要读取的 输入寄存器 数量 /// public int[] ReadInputRegisters(int startingAddress, int quantity) => _modbusClient.ReadInputRegisters(startingAddress, quantity); /// /// 读 整数类型的输入寄存器(Input Registers)_单个整数/小数(FC4)- 泛型 /// /// /// 第一个要读取的 输入寄存器 的地址 /// 要读取的 输入寄存器 数量 /// Registers数据的读取顺序(默认为LowHigh) /// 返回的值(数字型的值类型为0;其他:时间类型的值类型为default,引用类型默认为null) public T ReadInputRegisters(int startingAddress, int quantity, RegisterOrder registerOrder = RegisterOrder.LowHigh) where T : struct { T result = default; int[] registers; // 解析数据流 string type = typeof(T).ToString(); switch (type) { case "System.Int32": // Int整数 registers = _modbusClient.ReadInputRegisters(startingAddress, 2); // 读取数据流 int int1 = ModbusClient.ConvertRegistersToInt(registers, registerOrder); result = (T)Convert.ChangeType(int1, typeof(T)); break; case "System.Single": // Float单精度小数 registers = _modbusClient.ReadInputRegisters(startingAddress, 2); // 读取数据流 float float1 = ModbusClient.ConvertRegistersToFloat(registers, registerOrder); result = (T)Convert.ChangeType(float1, typeof(T)); break; case "System.Int64": // Long长整数 registers = _modbusClient.ReadInputRegisters(startingAddress, 4); // 读取数据流 long long1 = ModbusClient.ConvertRegistersToLong(registers, registerOrder); result = (T)Convert.ChangeType(long1, typeof(T)); break; case "System.Double": // Double双精度小数 registers = _modbusClient.ReadInputRegisters(startingAddress, 4); // 读取数据流 double double1 = ModbusClient.ConvertRegistersToDouble(registers, registerOrder); result = (T)Convert.ChangeType(double1, typeof(T)); break; //case "System.String": // String字符串 // ModbusClient.ConvertRegistersToString(registers, offset, stringLength); // break; default: break; } return result; } /// /// 读 字符串类型的输入寄存器(Input Registers)_单个字符串(FC4) /// /// /// 第一个要读取的 输入寄存器 的地址 /// 要读取的 输入寄存器 数量 /// 字符串中的字符数(必须为偶数) /// 偏移量(偏移几个Register;默认为0) /// 返回的值(引用类型默认为null;其他:数字型的值类型为0,时间类型的值类型为default) public string ReadInputRegisters(int startingAddress, int quantity, int stringLength, int offset) { // 读取数据流 int[] registers = _modbusClient.ReadInputRegisters(startingAddress, quantity); // 解析数据流 return ModbusClient.ConvertRegistersToString(registers, offset, stringLength); } #endregion 4、输入寄存器(Input Registers)-只读 #region 5、保持寄存器(Holding Registers)-常用 /// /// 读 保持寄存器(Holding Registers) (FC3) /// /// 第一个要读取的 保持寄存器的地址 /// 要读取的 保持寄存器 数量 /// public int[] ReadHoldingRegisters(int startingAddress, int quantity) => _modbusClient.ReadHoldingRegisters(startingAddress, quantity); /// /// 读 整数类型的保持寄存器(Holding Registers)_单个整数/小数(FC3)- 泛型 /// /// /// 第一个要读取的 保持寄存器 的地址 /// Registers数据的读取顺序(默认为LowHigh) /// 返回的值(数字型的值类型为0;其他:时间类型的值类型为default,引用类型默认为null) public T ReadHoldingRegisters(int startingAddress, RegisterOrder registerOrder = RegisterOrder.LowHigh) where T : struct { T result = default; int[] registers; // 解析数据流 string type = typeof(T).ToString(); switch (type) { case "System.Int16": // Int整数 registers = _modbusClient.ReadHoldingRegisters(startingAddress, 1); // 读取数据流 int int16 = registers.FirstOrDefault(); result = (T)Convert.ChangeType(int16, typeof(T)); break; case "System.Int32": // Int整数 registers = _modbusClient.ReadHoldingRegisters(startingAddress, 2); // 读取数据流 int int32 = ModbusClient.ConvertRegistersToInt(registers, registerOrder); result = (T)Convert.ChangeType(int32, typeof(T)); break; case "System.Single": // Float单精度小数 registers = _modbusClient.ReadHoldingRegisters(startingAddress, 2); // 读取数据流 float float1 = ModbusClient.ConvertRegistersToFloat(registers, registerOrder); result = (T)Convert.ChangeType(float1, typeof(T)); break; case "System.Int64": // Long长整数 registers = _modbusClient.ReadHoldingRegisters(startingAddress, 4); // 读取数据流 long long1 = ModbusClient.ConvertRegistersToLong(registers, registerOrder); result = (T)Convert.ChangeType(long1, typeof(T)); break; case "System.Double": // Double双精度小数 registers = _modbusClient.ReadHoldingRegisters(startingAddress, 4); // 读取数据流 double double1 = ModbusClient.ConvertRegistersToDouble(registers, registerOrder); result = (T)Convert.ChangeType(double1, typeof(T)); break; //case "System.String": // String字符串 // ModbusClient.ConvertRegistersToString(registers, offset, stringLength); // break; default: break; } return result; } /// /// 读 字符串类型的保持寄存器(Holding Registers)_单个字符串(FC3) /// /// /// 第一个要读取的 保持寄存器 的地址 /// 要读取的 保持寄存器 数量 /// 字符串中的字符数(必须为偶数) /// 偏移量(偏移几个Register;默认为0) /// 返回的值(引用类型默认为null;其他:数字型的值类型为0,时间类型的值类型为default) public string ReadHoldingRegisters(int startingAddress, int quantity, int stringLength, int offset = 0) { // 读取数据流 int[] registers = _modbusClient.ReadHoldingRegisters(startingAddress, quantity); // 解析数据流 return ModbusClient.ConvertRegistersToString(registers, offset, stringLength); } /// /// 写 保持寄存器(Holding Registers)_单个Register (FC6) /// /// 要写入的 保持寄存器的地址 /// 保持寄存器的值 public void WriteSingleRegister(int startingAddress, int value) => _modbusClient.WriteSingleRegister(startingAddress, value); /// /// 写 保持寄存器(Holding Registers)_多个 (FC16) /// /// 要写入的第一个 保持寄存器的地址 /// 保持寄存器的值的int数组 public void WriteMultipleRegisters(int startingAddress, int[] values) => _modbusClient.WriteMultipleRegisters(startingAddress, values); /// /// 写 保持寄存器(Holding Registers)_单个整数/小数/字符串 (FC16) /// /// 要写入的第一个 保持寄存器的地址 /// 写入的值 /// 寄存器个数限制(字符串专用) /// 读写顺序(默认LowHigh) public void WriteMultipleRegisters(int startingAddress, object value, int quantity = 0, RegisterOrder registerOrder = RegisterOrder.LowHigh) { // 转化为数据流 int[] datas; // 存储数据 string type = typeof(T).ToString(); switch (type) { case "System.Int16": // Int16整数 datas = new int[] { Convert.ToInt16(value) }; break; case "System.Int32": // Int32整数 datas = ModbusClient.ConvertIntToRegisters(Convert.ToInt32(value), registerOrder); break; case "System.Single": // Float单精度小数 datas = ModbusClient.ConvertFloatToRegisters(Convert.ToSingle(value), registerOrder); break; case "System.Int64": // Long长整数 datas = ModbusClient.ConvertLongToRegisters(Convert.ToInt64(value), registerOrder); break; case "System.Double": // Double双精度小数 datas = ModbusClient.ConvertDoubleToRegisters(Convert.ToDouble(value), registerOrder); break; case "System.String": // String字符串 datas = ModbusClient.ConvertStringToRegisters(Convert.ToString(value)); // 限制占用的寄存器个数 if (quantity != 0 && datas.Count() > quantity) { Array.Resize(ref datas, quantity); } _modbusClient.WriteMultipleRegisters(startingAddress, new int[quantity]); // 先清除旧数据 break; default: datas = new int[] { }; break; } if (datas == null || datas.Length == 0) // 未转化成功的不进行写入 { string returnStr = "ModbusTcp协议,地址:" + startingAddress + "值:" + value + "写入失败!类型转化失败..."; Console.WriteLine(returnStr); throw new Exception(returnStr); } _modbusClient.WriteMultipleRegisters(startingAddress, datas); } /// /// 读取+写入保持寄存器(Holding Registers)_多个(FC23) /// /// 第一个要读取的 保持寄存器的地址 /// 要读取的 保持寄存器 数量 /// 要写入的第一个 保持寄存器的地址 /// 保持寄存器的值的int数组 /// public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRead, int startingAddressWrite, int[] values) => _modbusClient.ReadWriteMultipleRegisters(startingAddressRead, quantityRead, startingAddressWrite, values); #endregion 5、保持寄存器(Holding Registers)-常用 // 6、ASCII字符(Modbus协议可能不支持) #endregion 读写值的方法 #region 检查状态-略 /// /// 检查是否连接到Modbus TCP Server /// public bool Connected() => IsConnected; // 1、ping IP地址 // 2、在外面检查DB块状态 #endregion 检查状态-略 #endregion 常用方法 } /// /// ModbusClient的通讯类型 /// public enum ModbusClientConnType { TCP, SerialPort } #region 示例 /// /// 使用示例 /// public class UseClass { /// /// 定义一个字典,存plc对象(通讯) /// Dictionary Funs = new Dictionary(); public void main1() { Funs.Add(1, new ModbusClientHelper("", 502, 499)); // 壳体上料 var dd = new Task(() => { ReadStation_S2(1); }); } /// /// 电性能测试 /// /// PLC编号 private async void ReadStation_S2(int no) { // [S1]装胶圈 // [S2]电性能测试 // [S3]导通性测试 // [S4]气密测试 // [S5]激光标记 // [S6]CCD检测 string stationName = "[S2]电性能测试"; ManualResetEvent MreReadPLC = new ManualResetEvent(false); while (!MreReadPLC.WaitOne(300)) // 运行间隔300ms { try { if (Funs[no].IsConnected) // 检查PLC是否已连接上 { #region 电性能测试-加工数据 try { int iPLC_Flag = Funs[no].ReadHoldingRegisters(908, 1).FirstOrDefault(); // PLC_Flag int iMES_Flag = Funs[no].ReadHoldingRegisters(909, 1).FirstOrDefault(); // MES_Flag bool pLC_Flag = iPLC_Flag == 1 ? true : false; // PLC_Flag bool mES_Flag = iMES_Flag == 1 ? true : false; // MES_Flag if (pLC_Flag && !mES_Flag) // 1 0 { //AddMessage(LogType.Info, Head + stationName + Body); await Task.Run(() => { DoProcessData_电性能测试(no); }); //AddMessage(LogType.Info, stationName + Body + Tail); } else if (!pLC_Flag && mES_Flag) // 0 1 { // 清空写给PLC的数据 // 清空MES_RESULT Funs[no].WriteMultipleRegisters(910, 0); // MES_RESULT // MES_Flag重置为0 Funs[no].WriteSingleRegister(909, 0); // MES_Flag } } catch (Exception ex) { Funs[no].WriteMultipleRegisters(910, 2); // MES_RESULT 为2上位机报错 Funs[no].WriteSingleRegister(909, 1); // MES_Flag //AddMessage(LogType.Error, $"PLC{no}_{stationName}上传加工运行出错!错误信息:" + ex.Message.ToString()); } #endregion 电性能测试-加工数据 #region 电性能测试-点检数据 try { int iPLC_Flag = Funs[no].ReadHoldingRegisters(1100, 1).FirstOrDefault(); // PLC_Flag int iMES_Flag = Funs[no].ReadHoldingRegisters(1101, 1).FirstOrDefault(); // MES_Flag bool pLC_Flag = iPLC_Flag == 1 ? true : false; // PLC_Flag bool mES_Flag = iMES_Flag == 1 ? true : false; // MES_Flag if (pLC_Flag && !mES_Flag) // 1 0 { //AddMessage(LogType.Info, Head + stationName + Body); await Task.Run(() => { DoOneCheckData_电性能测试(no); }); //AddMessage(LogType.Info, stationName + Body + Tail); } else if (!pLC_Flag && mES_Flag) // 0 1 { // 清空写给PLC的数据 // 清空MES_RESULT Funs[no].WriteMultipleRegisters(1102, 0); // MES_RESULT // MES_Flag重置为0 Funs[no].WriteSingleRegister(1101, 0); // MES_Flag } } catch (Exception ex) { Funs[no].WriteMultipleRegisters(1102, 2); // MES_RESULT 为2上位机报错 Funs[no].WriteSingleRegister(1101, 1); // MES_Flag //AddMessage(LogType.Error, $"PLC{no}_{stationName}点检运行出错!错误信息:" + ex.Message.ToString()); } #endregion 电性能测试-点检数据 //UpdatePLCMonitor(no, 1); // 更新PLC状态的UI // 更新PLC状态的UI } else { //UpdatePLCMonitor(no, 0); // 更新PLC状态的UI //WritePLCLog(LogType.Info, "PLC" + no.ToString() + "_" + stationName + "连接失败!"); Funs[no].Connect(); } } catch (Exception ex) { //UpdatePLCMonitor(no, 0); // 更新PLC状态的UI //AddMessage(LogType.Error, $"PLC{no}_{stationName}运行出错!错误信息:" + ex.Message.ToString()); } } } // 上传加工数据_电性能测试 private void DoProcessData_电性能测试(int no) { string equipmentCode = "LineCode" + "-S2"; // 设备编号 string processItem = "电性能测试"; // 测试项目 try { string workorder_code = Funs[no].ReadHoldingRegisters(944, 32, 32); // 车间订单号 workorder_code = string.IsNullOrEmpty(workorder_code) ? "" : workorder_code.Replace("\0", "").Trim(); string batch_num = Funs[no].ReadHoldingRegisters(976, 32, 32); // 批次号 batch_num = string.IsNullOrEmpty(batch_num) ? "" : batch_num.Replace("\0", "").Trim(); string mtltmrk = Funs[no].ReadHoldingRegisters(912, 32, 32); // 产品型号 mtltmrk = string.IsNullOrEmpty(mtltmrk) ? "" : mtltmrk.Replace("\0", "").Trim(); string plcDate_Y = Funs[no].ReadHoldingRegisters(1040, 1).FirstOrDefault().ToString("0000"); // 产品序列号的 当前日期_年 string plcDate_M = Funs[no].ReadHoldingRegisters(1041, 1).FirstOrDefault().ToString("00"); // 产品序列号的 当前日期_月 string plcDate_D = Funs[no].ReadHoldingRegisters(1042, 1).FirstOrDefault().ToString("00"); // 产品序列号的 当前日期_日 string plcDate_YMD = string.Concat(plcDate_Y, plcDate_M, plcDate_D); // 产品序列号的 当前日期 string supplierCode = Funs[no].ReadHoldingRegisters(1008, 32, 32); // 供应商代码 supplierCode = string.IsNullOrEmpty(supplierCode) ? "" : supplierCode.Replace("\0", "").Trim(); int sn_Number = Funs[no].ReadHoldingRegisters(1048); // 产品序列号的 数字序列部分 string sn = mtltmrk + batch_num + plcDate_YMD + supplierCode; // 产品序列号 //List items = new List() //{ // new TestItem(){ // Parameter_name = "结果判定", // Parameter_value = Funs[no].ReadHoldingRegisters(1050,1).FirstOrDefault()==1?"OK":"NG", // Parameter_unit = "" // }, // new TestItem(){ // Parameter_name = "绝缘电阻测试压设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1051).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "绝缘电阻测试时间设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1055).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "绝缘电阻电阻设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1057).ToString(), // Parameter_unit = "Ω" // }, // new TestItem(){ // Parameter_name = "耐电压测试压设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1061).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "耐电压测试时间设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1065).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "漏电流设定上限值", // Parameter_value = Funs[no].ReadHoldingRegisters(1067).ToString(), // Parameter_unit = "mA" // }, // new TestItem(){ // Parameter_name = "漏电流设定下限值", // Parameter_value = Funs[no].ReadHoldingRegisters(1071).ToString(), // Parameter_unit = "mA" // }, // new TestItem(){ // Parameter_name = "绝缘电阻测试压实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1075).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "绝缘电阻测试时间实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1079).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "绝缘电阻电阻实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1081).ToString(), // Parameter_unit = "Ω" // }, // new TestItem(){ // Parameter_name = "耐电压测试压实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1085).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "耐电压测试时间实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1089).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "漏电流实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1091).ToString(), // Parameter_unit = "mA" // }, // new TestItem(){ // Parameter_name = "产品结果", // Parameter_value = Funs[no].ReadHoldingRegisters(1095, 1).FirstOrDefault()==1?"OK":"NG", // Parameter_unit = "" // } //}; int result1 = 1; // 取最后一次的结果 for (int i = 0; i < 4; i++) { string newsn = string.Concat(sn, (sn_Number + i).ToString()); //result1 = SwitctProcessData(items, equipmentCode, processItem //, workorder_code, batch_num, mtltmrk, plcDate_YMD, supplierCode, newsn); // 上传数据 } int result = result1 == 1 ? 1 : ("是否上传数据" == "" ? 4 : 1); Funs[no].WriteMultipleRegisters(910, result); // MES_RESULT 为4MES报错 Funs[no].WriteSingleRegister(909, 1); // MES_Flag //WritePLCLog(LogType.Debug, $"PLC{no}_[{equipmentCode}]{processItem}-Write" + (result == 1 ? "成功!" : "失败!")); } catch (Exception ex) { Funs[no].WriteMultipleRegisters(910, 2); // MES_RESULT 为2上位机报错 Funs[no].WriteSingleRegister(909, 1); // MES_Flag //AddMessage(LogType.Error, $"PLC{no}_[{equipmentCode}]{processItem}上传加工报错!错误信息:" + ex.Message.ToString()); } } // 上传点检数据_电性能测试 private void DoOneCheckData_电性能测试(int no) { string equipmentCode = "LineCode" + "-S2"; // 设备编号 string processItem = "电性能测试"; // 测试项目 try { string workorder_code = Funs[no].ReadHoldingRegisters(1104, 32, 32); // 车间订单号 workorder_code = string.IsNullOrEmpty(workorder_code) ? "" : workorder_code.Replace("\0", "").Trim(); //string accno = Funs[no].ReadHoldingRegisters(1136, 32, 32); // 工序编号 //accno = string.IsNullOrEmpty(accno) ? "" : accno.Replace("\0", "").Trim(); string accno = "2"; // 工序编号 int dxncs = Funs[no].ReadHoldingRegisters(1168); // 电性能测试OK点检 int dxncsTD1 = Funs[no].ReadHoldingRegisters(1170); // 电性能测试通道1NG点检 int dxncsTD2 = Funs[no].ReadHoldingRegisters(1172); // 电性能测试通道2NG点检 int dxncsTD3 = Funs[no].ReadHoldingRegisters(1174); // 电性能测试通道3NG点检 int dxncsTD4 = Funs[no].ReadHoldingRegisters(1176); // 电性能测试通道4NG点检 // 测试参数 //List items = new List() //{ // new TestItem(){ // Parameter_name = "绝缘电阻测试压设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1051).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "绝缘电阻测试时间设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1055).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "绝缘电阻电阻设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1057).ToString(), // Parameter_unit = "Ω" // }, // new TestItem(){ // Parameter_name = "耐电压测试压设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1061).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "耐电压测试时间设定值", // Parameter_value = Funs[no].ReadHoldingRegisters(1065).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "漏电流设定上限值", // Parameter_value = Funs[no].ReadHoldingRegisters(1067).ToString(), // Parameter_unit = "mA" // }, // new TestItem(){ // Parameter_name = "漏电流设定下限值", // Parameter_value = Funs[no].ReadHoldingRegisters(1071).ToString(), // Parameter_unit = "mA" // }, // new TestItem(){ // Parameter_name = "绝缘电阻测试压实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1075).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "绝缘电阻测试时间实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1079).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "绝缘电阻电阻实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1081).ToString(), // Parameter_unit = "Ω" // }, // new TestItem(){ // Parameter_name = "耐电压测试压实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1085).ToString(), // Parameter_unit = "V" // }, // new TestItem(){ // Parameter_name = "耐电压测试时间实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1089).ToString(), // Parameter_unit = "s" // }, // new TestItem(){ // Parameter_name = "漏电流实际值", // Parameter_value = Funs[no].ReadHoldingRegisters(1091).ToString(), // Parameter_unit = "mA" // } //}; string itemsStr = string.Empty; //itemsStr =JsonConvert.SerializeObject(items); #region 上传数据 //List cheItems = new List(); //// 每次只上传一项点检内容;8为不上传 //if (dxncs != 8 && dxncsTD1 == 8 && dxncsTD2 == 8 && dxncsTD3 == 8 && dxncsTD4 == 8) // 电性能测试OK点检 //{ // cheItems.Add(new OneCheckItem() // { // Onecheck_name = "电性能测试OK点检", // Onecheck_content = "OK件点检结果为OK", // Onecheck_result = (OneCheckRD.OneCheckResultDetails.Keys.Contains(dxncs) ? OneCheckRD.OneCheckResultDetails[dxncs] : OneCheckRD.OneCheckResultDetails[9]) // + ";" + itemsStr // }); //} //else if (dxncs == 8 && dxncsTD1 != 8 && dxncsTD2 == 8 && dxncsTD3 == 8 && dxncsTD4 == 8) // 电性能测试通道1NG点检 //{ // cheItems.Add(new OneCheckItem() // { // Onecheck_name = "电性能测试通道1NG点检", // Onecheck_content = "NG样件点检结果为NG", // Onecheck_result = (OneCheckRD.OneCheckResultDetails.Keys.Contains(dxncsTD1) ? OneCheckRD.OneCheckResultDetails[dxncsTD1] : OneCheckRD.OneCheckResultDetails[9]) // + ";" + itemsStr // }); //} //else if (dxncs == 8 && dxncsTD1 == 8 && dxncsTD2 != 8 && dxncsTD3 == 8 && dxncsTD4 == 8) // 电性能测试通道2NG点检 //{ // cheItems.Add(new OneCheckItem() // { // Onecheck_name = "电性能测试通道2NG点检", // Onecheck_content = "NG样件点检结果为NG", // Onecheck_result = (OneCheckRD.OneCheckResultDetails.Keys.Contains(dxncsTD2) ? OneCheckRD.OneCheckResultDetails[dxncsTD2] : OneCheckRD.OneCheckResultDetails[9]) // + ";" + itemsStr // }); //} //else if (dxncs == 8 && dxncsTD1 == 8 && dxncsTD2 == 8 && dxncsTD3 != 8 && dxncsTD4 == 8) // 电性能测试通道3NG点检 //{ // cheItems.Add(new OneCheckItem() // { // Onecheck_name = "电性能测试通道3NG点检", // Onecheck_content = "NG样件点检结果为NG", // Onecheck_result = (OneCheckRD.OneCheckResultDetails.Keys.Contains(dxncsTD3) ? OneCheckRD.OneCheckResultDetails[dxncsTD3] : OneCheckRD.OneCheckResultDetails[9]) // + ";" + itemsStr // }); //} //else if (dxncs == 8 && dxncsTD1 == 8 && dxncsTD2 == 8 && dxncsTD3 == 8 && dxncsTD4 != 8) // 电性能测试通道4NG点检 //{ // cheItems.Add(new OneCheckItem() // { // Onecheck_name = "电性能测试通道4NG点检", // Onecheck_content = "NG样件点检结果为NG", // Onecheck_result = (OneCheckRD.OneCheckResultDetails.Keys.Contains(dxncsTD4) ? OneCheckRD.OneCheckResultDetails[dxncsTD4] : OneCheckRD.OneCheckResultDetails[9]) // + ";" + itemsStr // }); //} //else // 不上传 //{ // Funs[no].WriteMultipleRegisters(1102, 6); // MES_RESULT 为“6未找到唯一点检项” // Funs[no].WriteSingleRegister(1101, 1); // MES_Flag // AddMessage(LogType.Error, $"PLC{no}_[{equipmentCode}]{processItem}点检报错!未找到唯一的点检项目"); //} int result1 = 1; //OneCheckData oneCheckData = new OneCheckData() //{ // Line_code = GlobalContext.LineCode, // Line_name = GlobalContext.LineName, // Equipment_code = equipmentCode, // Equipment_name = equipmentCode, // Workorder_code = workorder_code, // Procedure_code = accno, // Procedure_name = processItem, // Oneckeck_values = cheItems, // Onecheck_empcode = "", // Onecheck_empname = "", // Onecheck_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") //}; //result1 = SwitctOneCheckData(oneCheckData, equipmentCode, processItem); #endregion 上传数据 int result = result1 == 1 ? 1 : ("上传点检数据" == "" ? 4 : 1); Funs[no].WriteMultipleRegisters(1102, result); // MES_RESULT 为4MES报错 Funs[no].WriteSingleRegister(1101, 1); // MES_Flag //WritePLCLog(LogType.Debug, $"PLC{no}_[{equipmentCode}]{processItem}-Write" + (result == 1 ? "成功!" : "失败!")); } catch (Exception ex) { Funs[no].WriteMultipleRegisters(1102, 2); // MES_RESULT 为2上位机报错 Funs[no].WriteSingleRegister(1101, 1); // MES_Flag //AddMessage(LogType.Error, $"PLC{no}_[{equipmentCode}]{processItem}点检报错!错误信息:" + ex.Message.ToString()); } } } #endregion }