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 构造函数
///
/// 构造函数
///
/// IP地址
/// 槽号300=2 1200;1500 = 1或2 其他型号不确定
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点读写设备
///
/// 读取PLC值
///
/// DB区指定值 其他默认为0 V区只能为1
/// 字符类型
/// 偏移量/地址
///
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;
}
}
}
///
/// 读取PLC数组格式
///
/// 槽位
/// 起始位/偏移点
/// 数组长度
/// null:读取失败 byte[]:数组结果
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;
}
///
/// 写入PLC值
///
/// db点
/// 偏移量
/// 类型
/// 值
/// 是否是控制字
/// true:写入成功 false:写入失败
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;
}
}
}
///
/// 写入数组类型PLC值 未测试
///
/// DB点
/// 起始字节、偏移量
/// 数组长度+1
/// 写入的值
///
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点读写设备
///
/// 读取PLC值
///
/// 起始字节
/// 字符类型
/// 偏移量/地址
///
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;
}
}
///
/// 多点读取PLC值
///
/// 报警信息的第一个偏移量
/// 报警集合
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;
}
}
///
/// 写入PLC值
///
/// 偏移量
/// 类型
/// 值
/// true:写入成功 false:写入失败
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
///
/// 关闭连接
///
public void ClosePlc()
{
try
{
S77.Disconnect();
}
catch (Exception ex)
{
Logger logger = LogManager.GetCurrentClassLogger();
logger.Error(ex.Message, "关闭连接错误:");
}
}
#region 数据处理
///
/// 获取类型对应长度
///
/// 数据类型
/// 所需长度
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
}
}