|
|
|
|
using HighWayIot.Common;
|
|
|
|
|
using HighWayIot.Log4net;
|
|
|
|
|
using HslCommunication;
|
|
|
|
|
using HslCommunication.Profinet.Melsec;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace HighWayIot.Plc.Impl
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 三菱Q系列Plc-Binary
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class MelsecBinaryPlc : IPlc
|
|
|
|
|
{
|
|
|
|
|
private LogHelper log = LogHelper.Instance;
|
|
|
|
|
|
|
|
|
|
private StringChange stringChange = StringChange.Instance;
|
|
|
|
|
|
|
|
|
|
private MelsecMcNet melsec_net = null;
|
|
|
|
|
|
|
|
|
|
public MelsecBinaryPlc()
|
|
|
|
|
{
|
|
|
|
|
if (!HslCommunication.Authorization.SetAuthorizationCode("ed1415f8-e06a-43ad-95f7-c04f7ae93b41"))
|
|
|
|
|
{
|
|
|
|
|
log.Info("HslCommunication 11.0.6.0激活失败");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
log.Info("HslCommunication 11.0.6.0激活成功");
|
|
|
|
|
this.melsec_net = new MelsecMcNet();
|
|
|
|
|
this.melsec_net.ConnectTimeOut = 2000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsConnected { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 读取心跳
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<bool> ReadHeart(string address)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
melsec_net.ReceiveTimeOut = 2000;
|
|
|
|
|
|
|
|
|
|
OperateResult<bool> read = melsec_net.ReadBool(address);
|
|
|
|
|
if (read.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
IsConnected = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var k = read.ErrorCode < 0 ? false : true;
|
|
|
|
|
if (k)
|
|
|
|
|
{
|
|
|
|
|
IsConnected = true;
|
|
|
|
|
return await Task.FromResult(IsConnected);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
IsConnected = false;
|
|
|
|
|
return await Task.FromResult(IsConnected);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("读取心跳方法异常" + ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 建立连接
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="IP"></param>
|
|
|
|
|
/// <param name="port"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public bool Connect(string IP, int port)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog("三菱Q系列PLC连接开始");
|
|
|
|
|
melsec_net.IpAddress = IP;
|
|
|
|
|
melsec_net.Port = port;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult connect = melsec_net.ConnectServer();
|
|
|
|
|
if (connect.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
this.IsConnected = true;
|
|
|
|
|
log.PlcLog("三菱Q系列PLC建立连接成功!!!");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
log.PlcLog("三菱Q系列PLC建立连接失败!!!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
log.Error("三菱Q系列PLC建立连接异常", ex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 断开连接
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public bool DisConnect()
|
|
|
|
|
{
|
|
|
|
|
return melsec_net.ConnectClose().IsSuccess;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过地址和长度读取PLC数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="len"></param>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public byte[] readValueByAddress(int len, string address)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog("开始通过PLC地址和长度读取PLC数据");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult<byte[]> read = melsec_net.Read(address, (ushort)(len));
|
|
|
|
|
if (read.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
byte[] result = stringChange.ConvertFloatToINt(read.Content);
|
|
|
|
|
log.PlcLog(String.Format("通过地址和长度读取PLC数据成功:{0}", stringChange.bytesToHexStr(result, result.Length)));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog("通过地址和长度读取PLC数据失败!!!");
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return new byte[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("通过地址和长度读取PLC数据异常", ex);
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return new byte[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址写入int类型数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public bool writeValueByAddress(int value, string address)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("开始通过PLC地址{0}写入int类型数据{1}",address,value));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult operateResult = melsec_net.Write(address, Convert.ToInt32(value));
|
|
|
|
|
if (operateResult.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("开始通过PLC地址{0}写入int类型数据{1}成功", address, value));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("开始通过PLC地址{0}写入int类型数据{1}失败!!!", address, value));
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("通过PLC地址写入int类型数据", ex);
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址清零数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <param name="len"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public bool resetByAddress(string address, int len)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("开发通过PLC地址{0}清零数据", address));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
byte[] write = new byte[len * 2];
|
|
|
|
|
for (int i = 0; i < len * 2; i++)
|
|
|
|
|
{
|
|
|
|
|
write[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
OperateResult operateResult = melsec_net.Write(address, write);
|
|
|
|
|
|
|
|
|
|
if (operateResult.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}清零数据成功", address));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}清零数据失败!!!", address));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error(String.Format("通过PLC地址{0}清零数据异常", address), ex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址读取EA值
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public string readEaByAddress(string address)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("通过PLC地址{0}读取EA值", address));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult<Byte[]> read = melsec_net.Read(address, (ushort)(8));
|
|
|
|
|
|
|
|
|
|
if (read.IsSuccess && read.Content != null)
|
|
|
|
|
{
|
|
|
|
|
string result = Convert.ToString(read.Content);
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取EA值成功:{1}", address, result));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取EA值失败!!!", address));
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("通过PLC地址读取EA值异常", ex);
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址读取交互信号
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public int readInteractiveSignal(string address)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("开始通过PLC地址{0}读取交互信号", address));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult<short> read = melsec_net.ReadInt16(address);
|
|
|
|
|
if (read.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取交互信号成功:{1}", address, read.Content));
|
|
|
|
|
return read.Content;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取交互信号失败!!!", address));
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("通过PLC地址读取交互信号异常", ex);
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址读取int32类型数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public int readInt32ByAddress(string address)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("开始通过PLC地址{0}读取int32类型数据",address));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult<short> read = melsec_net.ReadInt16(address);
|
|
|
|
|
if (read.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取int32类型数据成功:{1}", address, read.Content));
|
|
|
|
|
return read.Content;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取int32类型数据失败!!!", address));
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("通过PLC地址读取int32类型数据异常", ex);
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址写入int32类型数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public bool writeInt32ByAddress(string address, int value)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("开始通过PLC地址{0}写入int32类型数据{1}", address, value));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult write = melsec_net.Write(address, short.Parse(Convert.ToString(value)));
|
|
|
|
|
if (write.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入int32类型数据{1}成功", address, value));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入int32类型数据{1}失败!!!", address, value));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error(String.Format("通过PLC地址{0}写入int32类型数据异常", address), ex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址写入String类型数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public bool writeStringByAddress(string address, string value)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("通过PLC地址{0}写入String类型数据{1}",address,value));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult operateResult = melsec_net.Write(address, value);
|
|
|
|
|
if (operateResult.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入String类型数据{1}成功", address, value));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入String类型数据{1}失败!!!", address, value));
|
|
|
|
|
//this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error(String.Format("通过PLC地址{0}写入String类型数据异常", address), ex);
|
|
|
|
|
//this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址读取string类型数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public string readStringByAddress(string address, ushort length)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("开始通过PLC地址{0}读取string类型数据", address));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult<String> read = melsec_net.ReadString(address, length);
|
|
|
|
|
if (read.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取string类型数据成功:{1}", address, read.Content));
|
|
|
|
|
return read.Content;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取string类型数据失败!!!", address));
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("通过PLC地址读取int32类型数据异常", ex);
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址读取Bool类型数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public bool readBoolByAddress(string address)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("开始通过PLC地址{0}读取bool类型数据", address));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult<bool> read = melsec_net.ReadBool(address);
|
|
|
|
|
if (read.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取bool类型数据成功:{1}", address, read.Content));
|
|
|
|
|
return read.Content;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}读取bool类型数据失败!!!", address));
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error("通过PLC地址读取int32类型数据异常", ex);
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC地址写入Bool类型数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public bool writeBoolByAddress(string address, bool value)
|
|
|
|
|
{
|
|
|
|
|
//log.PlcLog(String.Format("开始通过PLC地址{0}写入bool类型数据{1}", address, value));
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult write = melsec_net.Write(address, short.Parse(stringChange.ParseToInt(value ? "1" : "0").ToString()));
|
|
|
|
|
if (write.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入bool类型数据{1}成功", address, value));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入bool类型数据{1}失败!!!", address, value));
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error(String.Format("通过PLC地址{0}写入bool类型数据异常", address), ex);
|
|
|
|
|
this.IsConnected = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 写入Double类型
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="address"></param>
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public bool writeDoubleByAddress(string address, int value)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
OperateResult write = melsec_net.Write(address, Convert.ToDouble(value));
|
|
|
|
|
|
|
|
|
|
if (write.IsSuccess)
|
|
|
|
|
{
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入Double类型数据{1}成功", address, value));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
log.PlcLog(String.Format("通过PLC地址{0}写入Double类型数据{1}失败!!!", address, value));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Error(String.Format("通过PLC地址{0}写入Double类型数据异常", address), ex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|