1.场景
项目上需要对一些工厂设备状态进行实时状态分析,生成折线图并报警等。
设备外面一般都接入了处理模块(单片机,6017等)(相当于网关设备),对信号进行转化,由网线接出,可进行采集。
2.程序
基础访问使用类库HslCommunication.dll。 github可以下到,无需在csdn花币下载(https://github.com/dathlin/ModBusTcpTools)
(1)所需参数
设备ip,设备端口(一般默认为502),设备各寄存器地址,长度,以及对应描述信息(该信息可能不必须),如下图所示
实际使用中,地址从0开始,长度为下一个地址减上一个地址的值。
所以上图信息为 一通道:起始地址为0,length为2,说明 40001
二通道:起始地址为2,length为2,说明 40003 。。。。。。。。。。。。。。。
(2)程序处理以及类库的使用
使用的诸多方法如下:
public string Ip
{
set; get;
}
public int Port
{
set; get;
}
//private string LogPath
//{
// get
// {
// return @"C:\log.log";
// }
//}
public ModBusRead()
{
//LogNet = new HslCommunication.LogNet.LogNetSingle(LogPath);
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="Ip">通讯网关IP</param>
/// <param name="Port">通讯网关端口,默认端口502</param>
public ModBusRead(string Ip,int Port)
{
this.Ip = Ip;
this.Port = Port;
//LogNet = new HslCommunication.LogNet.LogNetSingle(LogPath);
}
private ModBusTcpClient modBusTcpClient;
/// <summary>
/// 连接通讯网关
/// </summary>
/// <returns></returns>
public bool Connect()
{
modBusTcpClient = new ModBusTcpClient(Ip, Port);
//modBusTcpClient.LogNet = LogNet;
if (!modBusTcpClient.ConnectServer().IsSuccess)
{
return false;
}
return true;
}
/// <summary>
/// 根据变量类型读取变量
/// </summary>
/// <param name="Item">变量类</param>
/// <returns></returns>
public string Read(VarItem Item)
{
return Read(Item.RegisterStart.ToString(), Item.DataLenth.ToString());
}
/// <summary>
/// 根据变量起始地址和长度读取变量
/// </summary>
/// <param name="RegisterStart">变量起始地址</param>
/// <param name="len">长度</param>
/// <returns></returns>
public string Read(string RegisterStart,string len)
{
HslCommunication.OperateResult<ushort, ushort> result = GetAddressAndDataLenth(RegisterStart, len);
if (result.IsSuccess)
{
return MessageResultRecieved(modBusTcpClient.ReadRegister(result.Content1, result.Content2));
}
return "";
}
/// <summary>
/// 读取字符串
/// </summary>
/// <param name="Item">变量类</param>
/// <returns>返回字符串</returns>
public string ReadString(VarItem Item)
{
return ReadString(Item.RegisterStart.ToString(), Item.DataLenth.ToString());
}
/// <summary>
/// 读取字符串
/// </summary>
/// <param name="RegisterStart">变量起始地址</param>
/// <param name="len">长度</param>
/// <returns>返回字符串</returns>
public string ReadString(string RegisterStart, string len)
{
HslCommunication.OperateResult<ushort, ushort> result = GetAddressAndDataLenth(RegisterStart, len);
if (result.IsSuccess)
{
return ResultRecievedString(modBusTcpClient.ReadStringRegister(result.Content1, result.Content2));
}
return "";
}
/// <summary>
/// 读取整数型变量
/// </summary>
/// <param name="Item">变量类</param>
/// <returns>返回整数</returns>
public int ReadInt(VarItem Item)
{
return ReadInt(Item.RegisterStart.ToString(), Item.DataLenth.ToString());
}
/// <summary>
/// 读取整型变量
/// </summary>
/// <param name="RegisterStart">变量起始地址</param>
/// <param name="len">长度</param>
/// <returns></returns>
public int ReadInt(string RegisterStart, string len)
{
HslCommunication.OperateResult<ushort, ushort> result = GetAddressAndDataLenth(RegisterStart, len);
if (result.IsSuccess)
{
return ResultRecievedInt(modBusTcpClient.ReadIntRegister(result.Content1));
}
return -1;
}
/// <summary>
/// 接收返回的字符值
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
private string ResultRecievedString(HslCommunication.OperateResult<string> result)
{
if (result.IsSuccess)
{
return result.Content;
}
return "";
}
/// <summary>
/// 接收返回的整数数据
/// </summary>
/// <param name="result">返回值</param>
/// <returns></returns>
private int ResultRecievedInt(HslCommunication.OperateResult<int> result)
{
if (result.IsSuccess)
{
return result.Content;
}
return -1;
}
/// <summary>
/// 读取float型变量
/// </summary>
/// <param name="RegisterStart">变量起始地址</param>
/// <param name="len">长度</param>
/// <returns>返回float型字符串</returns>
public string ReadFloat(string RegisterStart, string len)
{
HslCommunication.OperateResult<ushort, ushort> result = GetAddressAndDataLenth(RegisterStart.ToString(),len);
if (result.IsSuccess)
{
return ResultRecievedFloat(modBusTcpClient.ReadRegister(result.Content1, 2));
}
return "";
}
/// <summary>
/// 读取float型变量
/// </summary>
/// <param name="Item">变量类</param>
/// <returns>返回浮点型数值字符串</returns>
public string ReadFloat(VarItem Item)
{
return ReadFloat(Item.RegisterStart.ToString(), Item.DataLenth.ToString());
}
/// <summary>
/// default 采用CDAB格式表示float
/// </summary>
/// <param name="result"></param>
/// <returns>返回float型字符串</returns>
private string ResultRecievedFloat(HslCommunication.OperateResult<byte[]> result)
{
if (result.IsSuccess)
{
string HexString =HslCommunication.BasicFramework.SoftBasic.ByteToHexString(result.Content, ' ');
List<string> acts = HexString.Split(' ').ToList();
if (acts.Count == 4)
{
HexString = acts[2] + acts[3] + acts[0] + acts[1];
}
uint num = uint.Parse(HexString, System.Globalization.NumberStyles.AllowHexSpecifier);
byte[] floatVals = BitConverter.GetBytes(num);
float f = BitConverter.ToSingle(floatVals, 0);
return f.ToString();
}
return "";
}
/// <summary>
/// 读取变量返回16进制字符串
/// </summary>
/// <param name="Item">变量类</param>
/// <returns>返回浮点型数值字符串</returns>
public string ReadHexString(VarItem Item)
{
HslCommunication.OperateResult<ushort, ushort> result = GetAddressAndDataLenth(Item.RegisterStart.ToString(), Item.DataLenth.ToString());
if (result.IsSuccess)
{
return MessageResultRecieved(modBusTcpClient.ReadRegister(result.Content1, (ushort)Item.DataLenth));
}
return "";
}
private string MessageResultRecieved(HslCommunication.OperateResult<byte[]> result)
{
string HexString = "";
if (result.IsSuccess)
{
HexString = HslCommunication.BasicFramework.SoftBasic.ByteToHexString(result.Content, ' ');
}
return HexString;
}
private HslCommunication.OperateResult<ushort, ushort> GetAddressAndDataLenth(string Start,string len)
{
HslCommunication.OperateResult<ushort, ushort> result = new HslCommunication.OperateResult<ushort, ushort>();
try
{
result.Content1 = ushort.Parse(Start);
result.Content2 = ushort.Parse(len);
result.IsSuccess = true;
}
catch (Exception ex)
{
result.Message = ex.Message;
}
return result;
}
//public Hashtable ReadMuiltpleFloat(List<VarItem> items)
//{
// Hashtable hash = new Hashtable();
// foreach(var item in items)
// {
// if (!hash.ContainsKey(item.RegisterStart)){
// hash.Add(item.RegisterStart,this.ReadFloat(item));
// }else
// {
// hash[item.RegisterStart] = this.ReadFloat(item);
// }
// }
// return hash;
//}
public string[] ReadMuiltpleFloat(string[] RegisterStarts, string[] DataLenths)
{
string[] strs = new string[RegisterStarts.Length];
for (int i = 0; i < RegisterStarts.Length; i++)
{
strs[i] = ReadFloat(RegisterStarts[i],DataLenths[i]);
}
return strs;
}
/// <summary>
/// default 采用CDAB格式表示float
/// </summary>
/// <param name="result"></param>
/// <returns>返回float型字符串</returns>
private string ResultRecievedFloatForTaigu(HslCommunication.OperateResult<byte[]> result)
{
if (result.IsSuccess)
{
string HexString = HslCommunication.BasicFramework.SoftBasic.ByteToHexString(result.Content, ' ');
//SysEventLog.SysEventLog.WriteLogToFile("16进制:" + HexString, AppDomain.CurrentDomain.BaseDirectory + @"\logs\Hslog" + DateTime.Now.ToString("yyyy-MM-dd") + ".log");
List<string> acts = HexString.Split(' ').ToList();
if (acts.Count == 4)
{
HexString = acts[0] + acts[1];
}
uint num = uint.Parse(HexString, System.Globalization.NumberStyles.AllowHexSpecifier);
//byte[] floatVals = BitConverter.GetBytes(num);
//float f = BitConverter.ToSingle(floatVals, 0);
return num.ToString();
}
return "";
}
public string ReadFloatForTaigu(string RegisterStart, string len)
{
HslCommunication.OperateResult<ushort, ushort> result = GetAddressAndDataLenth(RegisterStart, len);
if (result.IsSuccess)
{
return ResultRecievedFloatForTaigu(modBusTcpClient.ReadRegister(result.Content1, 2));
}
return "";
}
/// <summary>
/// 太古可乐读取float型变量
/// </summary>
/// <param name="Item">变量类</param>
/// <returns>返回浮点型数值字符串</returns>
public string ReadFloatForTaigu(VarItem Item)
{
return ReadFloatForTaigu(Item.RegisterStart.ToString(), Item.DataLenth.ToString());
}
/// <summary>
/// 太古可乐读取 -4/3.2
/// </summary>
/// <param name="items"></param>
/// <returns></returns>
//public Hashtable ReadMuiltpleFloatForTaigu(List<VarItem> items)
//{
// Hashtable hash = new Hashtable();
// foreach (var item in items)
// {
// if (!hash.ContainsKey(item.RegisterStart))
// {
// hash.Add(item.RegisterStart, this.ReadFloatForTaigu(item));
// }
// else
// {
// hash[item.RegisterStart] = this.ReadFloatForTaigu(item);
// }
// }
// return hash;
//}
public string[] ReadMuiltpleFloatForTaigu(string[] RegisterStarts, string[] DataLenths)
{
string[] strs=new string[RegisterStarts.Length];
for (int i = 0; i < RegisterStarts.Length; i++)
{
strs[i]= ReadFloatForTaigu(RegisterStarts[i],DataLenths[i]);
}
return strs;
}
public Hashtable ReadMuiltpleInt(List<VarItem> items)
{
Hashtable hash = new Hashtable();
foreach (var item in items)
{
if (!hash.ContainsKey(item.RegisterStart))
{
hash.Add(item.RegisterStart, this.ReadInt(item));
}
else
{
hash[item.RegisterStart] = this.ReadInt(item);
}
}
return hash;
}
public Hashtable ReadMuiltpleString(List<VarItem> items)
{
Hashtable hash = new Hashtable();
foreach (var item in items)
{
if (!hash.ContainsKey(item.RegisterStart))
{
hash.Add(item.RegisterStart, this.ReadString(item));
}
else
{
hash[item.RegisterStart] = this.ReadString(item);
}
}
return hash;
}
处理时得到是共4位16进制的数据,需要对这4位数据进行转化才能得到真实的数据。上图列取了两种规则,不一一而表了。
得到数据后,再结合所使用的量纲以及上下限推算出真实的带量纲的值。
最后再拿该值与实际设备的量纲上下限进行线性对应,即可得到真实的设备的实际值。