/**
*┌──────────────────────────────────────────────────────────────┐
*│ 描 述: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
}