You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
14 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mesnac.Equips;
namespace Mesnac.Equip.OMRON.HostLink.COM
{
/// <summary>
/// 三菱通讯封装设备类
/// </summary>
public class Equip : BaseEquip
{
private SerialPortFactory _serialPortFactory = null; //SerialPortFactory.GetInstance("00", "COM3", 9600, "Even", 7, "2", 1024);
private bool _isOpen = false; //是否打开连接
/// <summary>
/// 获取串口工厂
/// </summary>
/// <returns></returns>
private SerialPortFactory GetSerialPortFactory()
{
Mesnac.Equips.Connection.COM.ConnType connType = (Mesnac.Equips.Connection.COM.ConnType)this.Main.ConnType;
string stationNum = connType.StationNum;
string portName = connType.PortName;
int baudRate = connType.BaudRate;
string parity = connType.Parity;
int dataBits = connType.DataBits;
string stopBits = connType.StopBits;
int buffSize = connType.BuffSize;
this._serialPortFactory = SerialPortFactory.GetInstance(stationNum, portName, baudRate, parity, dataBits, stopBits, buffSize);
return this._serialPortFactory;
}
/// <summary>
/// 打开PLC设备
/// </summary>
/// <returns></returns>
public override bool Open()
{
lock (this)
{
try
{
if (this._isOpen == true || (_serialPortFactory != null && _serialPortFactory.MainSerialPort.IsOpen))
{
return true;
}
this.State = false;
this._serialPortFactory = this.GetSerialPortFactory();
this._serialPortFactory.MainSerialPort.Open();
if (!_serialPortFactory.MainSerialPort.IsOpen)
{
ICSharpCode.Core.LoggingService.Warn("PLC连接失败串口未打开失败!");
this.State = false;
return this.State;
}
else
{
this.State = true;
this._isOpen = true;
//Console.WriteLine("连接成功!");
return this.State;
}
}
catch (Exception ex)
{
this.State = false;
this._isOpen = false;
Console.WriteLine(ex.Message);
return this.State;
}
}
}
/// <summary>
/// PLC数据读取方法
/// </summary>
/// <param name="block">要读取的块号</param>
/// <param name="start">要读取的起始字</param>
/// <param name="len">要读取的长度最大255超过255则不读取</param>
/// <param name="buff"></param>
/// <returns></returns>
public override bool Read(string block, int start, int len, out object[] buff)
{
lock (this)
{
buff = new object[len];
try
{
if (len > 256)
{
for (int i = 0; i < len; i++)
{
buff[i] = 0;
}
base.State = false;
return false;
}
int maxOneLen = 20; //单次允许读取的最大长度欧姆龙限制为20个字
int count = len / maxOneLen; //要读取的次数
int mod = len % maxOneLen; //剩余的长度
bool flag = true; //保存读取标志
for (int i = 0; i < count; i++)
{
object[] _buff = new object[maxOneLen];
flag = this.ReadByLen(block, start + i * maxOneLen, maxOneLen, out _buff);
if (flag == false)
{
base.State = flag;
return false;
}
for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++)
{
buff[k] = _buff[k - i * maxOneLen];
}
}
if (mod > 0)
{
object[] _buff = new object[mod];
flag = this.ReadByLen(block, start + count * maxOneLen, mod, out _buff);
if (flag == false)
{
base.State = flag;
return false;
}
for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++)
{
buff[k] = _buff[k - count * maxOneLen];
}
}
base.State = flag;
return flag;
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService.Error(String.Format("读取PLCOMRON设备失败-({0})!", ex.Message));
base.State = false;
return false;
}
}
}
/// <summary>
/// 单次读取最长20个字的方法
/// </summary>
/// <param name="block">块号</param>
/// <param name="start">起始字</param>
/// <param name="len">长度最长不超过100</param>
/// <param name="buff">数据缓冲区,存放读取的数据</param>
/// <returns>读取成功返回true读取失败返回false</returns>
private bool ReadByLen(string block, int start, int len, out object[] buff)
{
lock (this)
{
buff = new object[len];
if (!this.Open())
{
return false;
}
int state = len;
int[] _buff = new int[len];
int iblock = Convert.ToInt32(block);
//iblock = iblock + start;
string result = this._serialPortFactory.Read(iblock, start, len, out _buff);
if (result != "00")
{
ICSharpCode.Core.LoggingService.Warn("PLC读取失败" + this.GetErrInfo(result));
this.State = false;
return false;
}
else
{
this.State = true;
}
int iReadLen = len;
if (iReadLen > state)
{
iReadLen = state;
}
for (int i = 0; i < iReadLen; i++)
{
int value = _buff[i];
if (value > ushort.MaxValue)
{
value = ushort.MaxValue - value;
}
buff[i] = value;
}
return true;
}
}
private ushort ToValue(object obj, ushort defaultValue)
{
ushort result = 0;
if (obj != null
&& obj != DBNull.Value
&& ushort.TryParse(obj.ToString(), out result))
{
return result;
}
return defaultValue;
}
/// <summary>
/// PLC数据写入方法
/// </summary>
/// <param name="block">要写入的块号</param>
/// <param name="start">起始字</param>
/// <param name="buff">要写入PLC的数据</param>
/// <returns>写入成功返回true失败返回false</returns>
public override bool Write(int block, int start, object[] buff)
{
lock (this)
{
try
{
if (buff.Length > 256)
{
return false;
}
int len = buff.Length;
int maxOneLen = 25; //单次允许读取的最大长度OMRON限制为25个字
int count = len / maxOneLen; //要读取的次数
int mod = len % maxOneLen; //剩余的长度
bool flag = true; //保存写入标志
for (int i = 0; i < count; i++)
{
object[] _buff = new object[maxOneLen];
for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++)
{
_buff[k - i * maxOneLen] = buff[k];
}
flag = this.WriteMax25(block, start + i * maxOneLen, _buff);
if (flag == false)
{
return false;
}
}
if (mod > 0)
{
object[] _buff = new object[mod];
for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++)
{
_buff[k - count * maxOneLen] = buff[k];
}
flag = this.WriteMax25(block, start + count * maxOneLen, _buff);
}
return flag;
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService.Error(String.Format("写入PLCOMRON设备失败-({0})!", ex.Message));
//Console.WriteLine(ex.Message);
return false;
}
}
}
/// <summary>
/// 单次写入最多25个字至PLC
/// </summary>
/// <param name="block">要写入的块号</param>
/// <param name="start">要写入的起始字</param>
/// <param name="buff">要写入的数据</param>
/// <returns>写入成功返回true失败返回false</returns>
private bool WriteMax25(int block, int start, object[] buff)
{
lock (this)
{
if (!this.Open())
{
return false;
}
int state = buff.Length;
int[] _buff = new int[buff.Length];
for (int i = 0; i < buff.Length; i++)
{
int value = 0;
int.TryParse(buff[i].ToString(), out value);
_buff[i] = value;
}
string result = this._serialPortFactory.Write(block, start, _buff);
if (result != "00")
{
ICSharpCode.Core.LoggingService.Error("PLC【欧姆龙】写入失败" + this.GetErrInfo(result));
return false;
}
return true;
}
}
/// <summary>
/// 关闭PLC设备
/// </summary>
public override void Close()
{
lock (this)
{
try
{
this._serialPortFactory.MainSerialPort.Close();
if (this._serialPortFactory.MainSerialPort.IsOpen)
{
ICSharpCode.Core.LoggingService.Warn("PLC【欧姆龙】关闭失败端口处于打开状态");
}
else
{
this.State = false;
this._isOpen = false;
//Console.WriteLine("关闭成功!");
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService.Error("PLC【欧姆龙】关闭失败" + ex.Message);
}
}
}
#region 根据错误代码返回错误信息
/// <summary>根据错误代码返回错误信息
/// </summary>
/// <param name="errCode">错误码</param>
/// <returns>错误信息</returns>
public string GetErrInfo(string errCode)
{
string result = "未知错误";
switch (errCode)
{
case "00":
result = "正常完成!";
break;
case "01":
result = "在RUN模式下不可执行";
break;
case "02":
result = "在MONITOR模式下不可执行";
break;
case "04":
result = "地址越界";
break;
case "0B":
result = "在PROGRAM模式下不可执行";
break;
case "13":
result = "FCS错误";
break;
case "14":
result = "格式错误";
break;
case "15":
result = "入口号数据错误";
break;
case "16":
result = "命令不支持";
break;
case "18":
result = "帧长度错误";
break;
case "19":
result = "不可执行";
break;
case "23":
result = "用户存储区写保护";
break;
case "A3":
result = "由于数据传送中FCS错误而终止";
break;
case "A4":
result = "由于数据传送中格式错误而终止";
break;
case "A5":
result = "由于数据传送中入口号数据错误而终止";
break;
case "A8":
result = "由于数据传送中帧长错误而终止";
break;
default:
result = "未知错误";
break;
}
return result;
}
#endregion
}
}