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#

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 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;
}
}
}