using System;
|
using System.Collections.Generic;
|
using System.Drawing.Drawing2D;
|
using System.Linq;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using Microsoft.Office.Interop.Word;
|
using NLog;
|
using Sharp7;
|
using thinger.DataConvertLib;
|
|
namespace Commom.DotNetDevices
|
{
|
public class PlcIO
|
{
|
private Sharp7.S7Client S77;
|
private object objLock = new object();
|
private object objLock1 = new object();
|
|
#region 构造函数
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
/// <param name="IP">IP地址</param>
|
/// <param name="Slot">槽号300=2 1200;1500 = 1或2 其他型号不确定</param>
|
public PlcIO(string IP, int Slot, ref string message)
|
{
|
S77 = new Sharp7.S7Client();
|
// 连接到plc 0=机架号
|
int Result = S77.ConnectTo(IP, 0, Slot);
|
if (Result != 0)
|
{
|
//for (int i = 0; i < 8; i++)
|
//{
|
// Thread.Sleep(500);
|
// Result = S77.ConnectTo(IP, 0, Slot);
|
// if (Result == 0)
|
// {
|
// break;
|
// }
|
//}
|
|
message = "未通电或线路故障!";
|
}
|
}
|
#endregion
|
|
#region DB点读写设备
|
/// <summary>
|
/// 读取PLC值
|
/// </summary>
|
/// <param name="dBNumber">DB区指定值 其他默认为0 V区只能为1</param>
|
/// <param name="type">字符类型</param>
|
/// <param name="pos">偏移量/地址</param>
|
/// <returns></returns>
|
public string GetPlcDBValue(int dBNumber, string type, string pos)
|
{
|
lock (objLock)
|
{
|
Logger logger = LogManager.GetCurrentClassLogger();
|
try
|
{
|
byte[] Buffer = new byte[2000];
|
string[] poss = pos.Split('.');
|
int size = Sharp7.S7.DataSizeByte(this.GetDataType(type));
|
if (type == "String")
|
{
|
size = 20;
|
}
|
int Result = S77.DBRead(dBNumber, int.Parse(poss[0]), size, Buffer);
|
|
string returnStr = "读取" + pos + "---DB点:" + dBNumber.ToString() + "偏移量:" + pos + "类型:" + type + "\t";
|
|
string valueStr = string.Empty;
|
if (Result == 0)
|
{
|
switch (type)
|
{
|
case "Bit":
|
valueStr = Sharp7.S7.GetBitAt(Buffer, int.Parse(poss[0]), int.Parse(poss[1])).ToString();
|
break;
|
case "Byte":
|
valueStr = Sharp7.S7.GetByteAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "Char":
|
valueStr = Sharp7.S7.GetCharsAt(Buffer, int.Parse(poss[1]), size);
|
break;
|
case "Word":
|
valueStr = Sharp7.S7.GetWordAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "Int":
|
valueStr = Sharp7.S7.GetIntAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "DWord":
|
valueStr = Sharp7.S7.GetDWordAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "DInt":
|
valueStr = Sharp7.S7.GetDIntAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "Real":
|
valueStr = Sharp7.S7.GetRealAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "LReal":
|
valueStr = Sharp7.S7.GetLRealAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "String":
|
valueStr = Sharp7.S7.GetStringAt(Buffer, int.Parse(poss[1])).ToString();
|
break;
|
case "String1":
|
valueStr = Sharp7.S7.GetCharsAt(Buffer, int.Parse(poss[1]), 12);
|
break;
|
}
|
|
|
logger.Error(returnStr + "值:" + valueStr, "读取PLC值:");
|
return valueStr;
|
}
|
|
return S77.ErrorText(Result);
|
}
|
catch (Exception ex)
|
{
|
logger.Error(ex.Message, "读取PLC值错误:");
|
throw ex;
|
}
|
}
|
}
|
|
/// <summary>
|
/// 读取PLC数组格式
|
/// </summary>
|
/// <param name="dBNumber">槽位</param>
|
/// <param name="start">起始位/偏移点</param>
|
/// <param name="leng">数组长度</param>
|
/// <returns>null:读取失败 byte[]:数组结果</returns>
|
public byte[] GetPlcArrayDBValues(int dBNumber, int start, int leng)
|
{
|
byte[] arrayValues = new byte[leng];
|
var result1 = S77.DBRead(dBNumber, start, leng, arrayValues);
|
if (result1 == 0)
|
{
|
return arrayValues;
|
}
|
|
return null;
|
}
|
|
/// <summary>
|
/// 写入PLC值
|
/// </summary>
|
/// <param name="dBNumber">db点</param>
|
/// <param name="pos">偏移量</param>
|
/// <param name="type">类型</param>
|
/// <param name="value">值</param>
|
/// <param name="isPos">是否是控制字</param>
|
/// <returns>true:写入成功 false:写入失败</returns>
|
public bool SetPlcDBValue(int dBNumber, string type, string value, string pos, bool isPos = false)
|
{
|
lock (objLock1)
|
{
|
bool bl = false;
|
try
|
{
|
// 写入值
|
int size = Sharp7.S7.DataSizeByte(this.GetDataType(type));
|
if (type == "String")
|
{
|
size = 18;
|
}
|
|
var Buffer = new byte[600];
|
int Result = S77.DBRead(dBNumber, 0, size, Buffer);
|
string[] poss = pos.Split('.');
|
switch (type)
|
{
|
case "Bit":
|
Sharp7.S7.SetBitAt(ref Buffer, int.Parse(poss[0]), int.Parse(poss[1]), bool.Parse(value));
|
break;
|
case "Byte":
|
Sharp7.S7.SetByteAt(Buffer, int.Parse(poss[1]), byte.Parse(value));
|
break;
|
case "Char":
|
Sharp7.S7.SetCharsAt(Buffer, int.Parse(poss[1]), value);
|
break;
|
case "Word":
|
Sharp7.S7.SetWordAt(Buffer, int.Parse(poss[1]), ushort.Parse(value));
|
break;
|
case "Int":
|
Sharp7.S7.SetIntAt(Buffer, int.Parse(poss[1]), short.Parse(value));
|
break;
|
case "DWord":
|
Sharp7.S7.SetDWordAt(Buffer, int.Parse(poss[1]), uint.Parse(value));
|
break;
|
case "DInt":
|
Sharp7.S7.SetDIntAt(Buffer, int.Parse(poss[1]), int.Parse(value));
|
break;
|
case "Real":
|
Sharp7.S7.SetRealAt(Buffer, int.Parse(poss[1]), float.Parse(value));
|
break;
|
case "LReal":
|
Sharp7.S7.SetLRealAt(Buffer, int.Parse(poss[1]), float.Parse(value));
|
break;
|
case "String":
|
Sharp7.S7.SetStringAt(Buffer, int.Parse(poss[1]), size, value);
|
break;
|
}
|
|
|
int Result2 = S77.DBWrite(dBNumber, int.Parse(poss[0]), size, Buffer);
|
string value1 = this.GetPlcDBValue(dBNumber, type, pos);
|
if (isPos) //写入的是控制字
|
{
|
if (Result2 == 0)
|
{
|
bl = true;
|
string returnStr = "写入" + pos + "---DB点:" + dBNumber.ToString() + "偏移量:" + pos + "值:" + value + "\t";
|
Logger logger = LogManager.GetCurrentClassLogger();
|
logger.Error(returnStr, "写入PLC值:");
|
return bl;
|
}
|
else
|
{
|
string returnStr = $"写入{pos}---DB点:{dBNumber.ToString()}偏移量:{pos}值:{value},返回结果{Result2}" + "\t";
|
Logger logger = LogManager.GetCurrentClassLogger();
|
logger.Error(returnStr, "写入PLC值失败:");
|
bool bll = this.SetPlcDBValue(dBNumber, type, value, pos);
|
if (bll)
|
{
|
bl = true;
|
}
|
}
|
}
|
else //写入托盘号、任务号等信息
|
{
|
if (value1 == value && Result2 == 0)
|
{
|
string returnStr = "写入" + pos + "---DB点:" + dBNumber.ToString() + "偏移量:" + pos + "值:" + value + "\t";
|
Logger logger = LogManager.GetCurrentClassLogger();
|
logger.Error(returnStr, "写入PLC值:");
|
return true;
|
}
|
else
|
{
|
string returnStr = $"写入{pos}---DB点:{dBNumber.ToString()}偏移量:{pos}值:{value},返回结果{Result2}--读取{value1}" + "\t";
|
Logger logger = LogManager.GetCurrentClassLogger();
|
logger.Error(returnStr, "写入PLC值失败:");
|
}
|
//else
|
//{
|
// // 暂时停止重复写入
|
// //bool bll = this.SetPlcDBValue(dBNumber, type, value, pos);
|
// //if (bll)
|
// //{
|
// // bl = true;
|
// //}
|
//}
|
}
|
#endregion
|
|
return bl;
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
}
|
}
|
|
/// <summary>
|
/// 写入数组类型PLC值 未测试
|
/// </summary>
|
/// <param name="dBNumber">DB点</param>
|
/// <param name="start">起始字节、偏移量</param>
|
/// <param name="leng">数组长度+1</param>
|
/// <param name="arrayValues">写入的值</param>
|
/// <returns></returns>
|
public bool SetPlcArrayDBValues(int dBNumber, int start, int leng, byte[] arrayValues)
|
{
|
try
|
{
|
bool bl = false;
|
var result1 = S77.DBWrite(dBNumber, start, leng, arrayValues);
|
if (result1 == 0)
|
{
|
bl = true;
|
}
|
|
return bl;
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
}
|
|
public static bool GetBitAt(byte[] Buffer, int Pos, int Bit)
|
{
|
byte[] Mask = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
|
if (Bit < 0) Bit = 0;
|
if (Bit > 7) Bit = 7;
|
return (Buffer[Pos] & Mask[Bit]) != 0;
|
}
|
#region MB点读写设备
|
/// <summary>
|
/// 读取PLC值
|
/// </summary>
|
/// <param name="start">起始字节</param>
|
/// <param name="type">字符类型</param>
|
/// <param name="pos">偏移量/地址</param>
|
/// <returns></returns>
|
public string GetPlcMBValue(string type, string pos)
|
{
|
try
|
{
|
byte[] Buffer = new byte[5000];
|
string[] poss = pos.Split('.');
|
int size = Sharp7.S7.DataSizeByte(this.GetDataType(type));
|
|
int Result = S77.MBRead(int.Parse(poss[0]), Buffer.Length, Buffer);
|
|
string valueStr = string.Empty;
|
valueStr = Convert.ToString(Sharp7.S7.GetBitAt(Buffer, 0, int.Parse(poss[1])));
|
if (Result == 0)
|
{
|
return valueStr;
|
}
|
|
return S77.ErrorText(Result);
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
}
|
|
/// <summary>
|
/// 多点读取PLC值
|
/// </summary>
|
/// <param name="pos">报警信息的第一个偏移量</param>
|
/// <returns>报警集合</returns>
|
public bool[] GetPlcMBValues(string pos)
|
{
|
try
|
{
|
string[] poss = pos.Split('.');
|
byte[] Buffer = new byte[400];
|
int Result = S77.MBRead(int.Parse(poss[0]), 300, Buffer);
|
bool[] de = BitLib.GetBitArrayFromByteArray(Buffer, Buffer.Length);
|
return de;
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
}
|
|
/// <summary>
|
/// 写入PLC值
|
/// </summary>
|
/// <param name="pos">偏移量</param>
|
/// <param name="type">类型</param>
|
/// <param name="value">值</param>
|
/// <returns>true:写入成功 false:写入失败</returns>
|
public bool SetPlcMBValue(string type, string value, string pos)
|
{
|
bool bl = false;
|
try
|
{
|
// 写入值
|
int size = Sharp7.S7.DataSizeByte(this.GetDataType(type));
|
var Buffer = new byte[600];
|
int Result = S77.MBRead(0, size, Buffer);
|
string[] poss = pos.Split('.');
|
switch (type)
|
{
|
case "Bit":
|
Sharp7.S7.SetBitAt(ref Buffer, int.Parse(poss[0]), int.Parse(poss[1]), bool.Parse(value));
|
break;
|
case "Byte":
|
Sharp7.S7.SetByteAt(Buffer, int.Parse(poss[1]), byte.Parse(value));
|
break;
|
case "Char":
|
Sharp7.S7.SetCharsAt(Buffer, int.Parse(poss[1]), value);
|
break;
|
case "Word":
|
Sharp7.S7.SetWordAt(Buffer, int.Parse(poss[1]), ushort.Parse(value));
|
break;
|
case "Int":
|
Sharp7.S7.SetIntAt(Buffer, int.Parse(poss[1]), short.Parse(value));
|
break;
|
case "DWord":
|
Sharp7.S7.SetDWordAt(Buffer, int.Parse(poss[1]), uint.Parse(value));
|
break;
|
case "DInt":
|
Sharp7.S7.SetDIntAt(Buffer, int.Parse(poss[1]), int.Parse(value));
|
break;
|
case "Real":
|
Sharp7.S7.SetRealAt(Buffer, int.Parse(poss[1]), float.Parse(value));
|
break;
|
case "String":
|
Sharp7.S7.SetStringAt(Buffer, int.Parse(poss[1]), size, value);
|
break;
|
}
|
|
|
Result = S77.MBWrite(int.Parse(poss[0]), size, Buffer);
|
// 验证是否写入成功,不成功再次写入。4秒内尝试写入8次。
|
for (int i = 0; i < 8; i++)
|
{
|
Thread.Sleep(100);
|
string plcValue = this.GetPlcMBValue(type, pos);
|
if (value == plcValue)
|
{
|
bl = true;
|
break;
|
}
|
else
|
{
|
// 再次写入值
|
Result = S77.MBWrite(int.Parse(poss[0]), size, Buffer);
|
}
|
|
bl = false;
|
}
|
|
return bl;
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
}
|
#endregion
|
|
/// <summary>
|
/// 关闭连接
|
/// </summary>
|
public void ClosePlc()
|
{
|
try
|
{
|
S77.Disconnect();
|
}
|
catch (Exception ex)
|
{
|
Logger logger = LogManager.GetCurrentClassLogger();
|
logger.Error(ex.Message, "关闭连接错误:");
|
}
|
}
|
|
#region 数据处理
|
/// <summary>
|
/// 获取类型对应长度
|
/// </summary>
|
/// <param name="type">数据类型</param>
|
/// <returns>所需长度</returns>
|
private int GetDataType(string type)
|
{
|
switch (type)
|
{
|
case "Bit":
|
return Sharp7.S7Consts.S7WLBit;
|
case "Byte":
|
return Sharp7.S7Consts.S7WLByte;
|
case "Char":
|
return Sharp7.S7Consts.S7WLChar;
|
case "Word":
|
return Sharp7.S7Consts.S7WLWord;
|
case "Int":
|
return Sharp7.S7Consts.S7WLInt;
|
case "DWord":
|
return Sharp7.S7Consts.S7WLDWord;
|
case "DInt":
|
return Sharp7.S7Consts.S7WLDInt;
|
case "Real":
|
return Sharp7.S7Consts.S7WLReal;
|
case "Counter":
|
return Sharp7.S7Consts.S7WLCounter;
|
case "Timer":
|
return Sharp7.S7Consts.S7WLTimer;
|
case "String":
|
return 255;
|
default:
|
return 0;
|
}
|
|
}
|
#endregion
|
}
|
}
|