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.

360 lines
15 KiB
C#

using CompressorXN_Common;
using CompressorXN_Model.ViewModel.Plc;
using HslCommunication;
using HslCommunication.Profinet.Omron;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace CompressorXN_Communication.MyPlc
{
public class OmronCIPHelper
{
private static OmronCipNet omronCipNet = null;
/// <summary>
/// 获取欧姆龙PLC连接对象
/// </summary>
/// <param name="plcIp"></param>
/// <param name="plcPort"></param>
/// <param name="connectTimeOut"></param>
/// <returns></returns>
public static OmronCipNet GetOmronCipNet(string plcIp, int plcPort, int connectTimeOut = 10000)
{
omronCipNet = new OmronCipNet(plcIp, plcPort)
{
ConnectTimeOut = connectTimeOut
};
var connect = omronCipNet.ConnectServer();
isConnected = connect.IsSuccess;
if (connect.IsSuccess)
{
return omronCipNet;
}
else
{
return null;
}
}
/// <summary>
/// 链接状态
/// </summary>
private static bool isConnected = false;
public static bool IsConnected
{
get { return isConnected; }
}
/// <summary>
/// 获取PLC值--单点位
/// </summary>
/// <param name="pointAddress">点位地址</param>
/// <param name="dataType">数据类型</param>
/// <param name="length">读取长度</param>
/// <returns></returns>
public static (bool ok, string val) SingleReadPlcVal(string pointAddress, string dataType, int length = 1, Encoding encoding = null)
{
var strVal = string.Empty;
try
{
if (!isConnected || omronCipNet == null)
{
return (false, strVal);
}
switch (dataType)
{
case "bool":
var operateBoolResult = omronCipNet.ReadBool(pointAddress);
if (!operateBoolResult.IsSuccess)
{
return (false, strVal);
}
else
{
var boolVal = operateBoolResult.Content;
strVal = boolVal.ToString();
return (true, strVal);
}
case "int":
var operateIntResult = omronCipNet.ReadInt32(pointAddress);
if (!operateIntResult.IsSuccess)
{
return (false, strVal);
}
else
{
var intVal = operateIntResult.Content;
strVal = intVal.ToString();
return (true, strVal);
}
case "short":
var operateShortResult = omronCipNet.ReadInt16(pointAddress);
if (!operateShortResult.IsSuccess)
{
return (false, strVal);
}
else
{
var shortVal = operateShortResult.Content;
strVal = shortVal.ToString();
return (true, strVal);
}
case "ushort":
var operateUshortResult = omronCipNet.ReadUInt16(pointAddress);
if (!operateUshortResult.IsSuccess)
{
return (false, strVal);
}
else
{
var ushortVal = operateUshortResult.Content;
strVal = ushortVal.ToString();
return (true, strVal);
}
case "float":
var operateFloatResult = omronCipNet.ReadFloat(pointAddress);
if (!operateFloatResult.IsSuccess)
{
return (false, strVal);
}
else
{
var floatVal = operateFloatResult.Content;
strVal = floatVal.ToString("f3");
return (true, strVal);
}
case "string":
var operateStringResult = omronCipNet.ReadString(pointAddress, (ushort)length, encoding == null ? Encoding.UTF8 : encoding);
if (!operateStringResult.IsSuccess)
{
return (false, strVal);
}
else
{
strVal = operateStringResult.Content;
return (true, strVal);
}
case "byte":
var operateByteResult = omronCipNet.Read(pointAddress, (ushort)length);
if (!operateByteResult.IsSuccess)
{
return (false, strVal);
}
else
{
if (encoding == null)
{
strVal = Encoding.ASCII.GetString(operateByteResult.Content);
}
else
{
strVal = encoding.GetString(operateByteResult.Content);
}
return (true, strVal);
}
default:
return (false, strVal);
}
}
catch (Exception)
{
return (false, strVal);
}
}
/// <summary>
/// 值写入PLC
/// </summary>
/// <param name="pointAddress">点位地址</param>
/// <param name="dataType">数据类型</param>
/// <param name="value">值</param>
/// <param name="len">长度</param>
/// <param name="encoding">编码格式</param>
/// <returns></returns>
public static (bool isOk, string msg) SingleWriteValToPlc(string pointAddress, string dataType, object value, int len = 1, Encoding encoding = null)
{
try
{
if (!isConnected || omronCipNet == null)
{
return (false, "PLC未连接");
}
OperateResult operateResult = new OperateResult
{
IsSuccess = false
};
switch (dataType)
{
case "bool":
operateResult = omronCipNet.Write(pointAddress, Convert.ToBoolean(value));
break;
case "int":
operateResult = omronCipNet.Write(pointAddress, Convert.ToInt32(value));
break;
case "short":
operateResult = omronCipNet.Write(pointAddress, Convert.ToInt16(value));
break;
case "ushort":
operateResult = omronCipNet.Write(pointAddress, Convert.ToUInt16(value));
break;
case "float":
operateResult = omronCipNet.Write(pointAddress, Convert.ToSingle(value));
break;
case "string":
operateResult = omronCipNet.Write(pointAddress, value.ToString(), len, encoding ?? Encoding.ASCII);
break;
case "byte":
var bytes = Encoding.ASCII.GetBytes(value.ToString());
operateResult = omronCipNet.WriteTag(pointAddress, 0xD1, bytes, len);
break;
}
if (operateResult.IsSuccess)
{
return (operateResult.IsSuccess, "操作成功");
}
return (operateResult.IsSuccess, operateResult.Message);
}
catch (Exception ex)
{
return (false, ex.Message);
}
}
//private static Stopwatch stopwatch = new Stopwatch();
/// <summary>
/// 不连续的地址批量读取
/// </summary>
/// <param name="addressArr"></param>
public static (bool isSucess, string msg) ReadPlcBatch(List<Variable> variables, Encoding encoding = null)
{
try
{
foreach (var item in variables)
{
switch (item.DataType)
{
case "float":
OperateResult<float> read = omronCipNet.ReadFloat(item.VariableName);
item.ReadVal = read.Content;
break;
}
GlobalVar.deviceInfo.CommGroupList.FirstOrDefault().VariableList.FirstOrDefault(m => m.VariableName == item.VariableName).ReadVal = item.ReadVal;
}
return (true, string.Empty);
//var addressArrTest = new string[1] { "D770" };
//OperateResult<byte[]> readTest = omronCipNet.Read("D770", 4);
//var aa = Encoding.ASCII.GetString(readTest.Content, 0, 4);
//short占2字节Real占4个字节bool占2个字节
//stopwatch.Restart();
int readLen = 40;//每次读取40个地址
int plcPointTotalCount = variables.Count;
int readCount = plcPointTotalCount / readLen;//轮询次数
int remainder = plcPointTotalCount % readLen;//余数
readCount = remainder > 0 ? readCount + 1 : readCount;
string[] sourceAddressArr = variables.Select(m => m.VariableName).ToArray();
for (int i = 0; i < readCount; i++)
{
int surplusLen = sourceAddressArr.Length - i * readLen;//剩余长度
int subLen = surplusLen > readLen ? readLen : surplusLen;//应该Take的长度
//本次需要读取的地址数组
var addressArr = sourceAddressArr.Skip(i * readLen).Take(subLen).ToArray();
OperateResult<byte[]> read = omronCipNet.Read(addressArr);
if (!read.IsSuccess)
{
return (read.IsSuccess, read.Message);
}
int startIndex = 0;//起始地址
for (int j = 0; j < addressArr.Length; j++)
{
var item = variables.First(m => m.VariableName == addressArr[j]);
if (j > 0)
{
var lastItem = variables.First(m => m.VariableName == addressArr[j - 1]);
startIndex = j == 0 ? 0 : startIndex + lastItem.Offset;
}
switch (item.DataType)
{
case "string":
item.ReadVal = encoding == null ? Encoding.ASCII.GetString(read.Content, startIndex, item.Offset) : encoding.GetString(read.Content, startIndex, item.Offset);
break;
case "float":
item.ReadVal = omronCipNet.ByteTransform.TransSingle(read.Content, startIndex).ToString("f3");
break;
case "bool":
item.ReadVal = GetBoolFromByte(read.Content, startIndex, item.Offset).ToString();
break;
case "short":
item.ReadVal = omronCipNet.ByteTransform.TransInt16(read.Content, startIndex).ToString();
break;
case "ushort":
item.ReadVal = omronCipNet.ByteTransform.TransUInt16(read.Content, startIndex).ToString();
break;
case "byte":
if (encoding == null)
{
item.ReadVal = Encoding.ASCII.GetString(read.Content, startIndex, item.Offset);
}
else
{
item.ReadVal = encoding.GetString(read.Content, startIndex, item.Offset);
}
break;
}
GlobalVar.deviceInfo.CommGroupList.FirstOrDefault().VariableList.FirstOrDefault(m => m.VariableName == item.VariableName).ReadVal = item.ReadVal;
}
}
//stopwatch.Stop();
//Console.WriteLine($"读取PLC点位值耗时={stopwatch.ElapsedMilliseconds}ms");
return (true, string.Empty);
}
catch (Exception ex)
{
return (false, $"批量读取异常:{ex.Message}");
}
}
/// <summary>
/// 根据起始索引和长度截取字节数组
/// </summary>
/// <param name="bytes"></param>
/// <param name="startIndex"></param>
/// <param name="len"></param>
/// <returns></returns>
private static bool GetBoolFromByte(byte[] bytes, int startIndex, int len)
{
var getBytes = SubArray(bytes, startIndex, len);
return BitConverter.ToBoolean(getBytes, 0);
}
/// <summary>
/// 根据起始索引和截取长度获取新的数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data">原始数组</param>
/// <param name="index">起始索引</param>
/// <param name="length">长度</param>
/// <returns></returns>
public static T[] SubArray<T>(T[] data, int index, int length)
{
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
return result;
}
}
}