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.
Aucma.Scada/HighWayIot.Common/MsgUtil.cs

512 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace HighWayIot.Common
{
/// <summary>
/// 工具类
/// </summary>
public sealed class MsgUtil
{
private static readonly Lazy<MsgUtil> lazy = new Lazy<MsgUtil>(() => new MsgUtil());
public static MsgUtil Instance
{
get
{
return lazy.Value;
}
}
private MsgUtil() { }
#region 数据解析公共方法
/// <summary>
/// 字节数组转换成结构体
/// </summary>
/// <param name="buf"></param>
/// <param name="len"></param>
/// <param name="type"></param>
/// <returns></returns>
public static object BytesToStruct(byte[] buf, int len, Type type)
{
object rtn;
IntPtr buffer = Marshal.AllocHGlobal(len);
Marshal.Copy(buf, 0, buffer, len);
try
{
rtn = Marshal.PtrToStructure(buffer, type);
Marshal.FreeHGlobal(buffer);
}
catch (Exception)
{
return null;
}
return rtn;
}
public string StringToHexString(string s, Encoding encode)
{
byte[] b = encode.GetBytes(s); //按照指定编码将string编程字节数组
string result = string.Empty;
for (int i = 0; i < b.Length; i++) //逐字节变为16进制字符以%隔开
{
result += "%" + Convert.ToString(b[i], 16);
}
return result;
}
//// <summary>
/// 结构体转byte数组
/// </summary>
/// <param name="structObj">要转换的结构体</param>
/// <returns>转换后的byte数组</returns>
public static byte[] StructToBytes(object structObj)
{
//得到结构体的大小
int size = Marshal.SizeOf(structObj);
//创建byte数组
byte[] bytes = new byte[size];
//分配结构体大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将结构体拷到分配好的内存空间
Marshal.StructureToPtr(structObj, structPtr, false);
//从内存空间拷到byte数组
Marshal.Copy(structPtr, bytes, 0, size);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回byte数组
return bytes;
}
#endregion
#region 消息验证方法
/// <summary>
/// CS和校验
/// </summary>
/// <param name="Abyte"></param>
/// <returns></returns>
public byte Check_CS(byte[] Abyte)
{
byte result = new byte();
try
{
int num = 0;
for (int i = 0; i < Abyte.Length; i++)
{
num = (num + Abyte[i]) % 256;
}
result = (byte)num;
}
catch
{
result = 0;
}
return result;
}
/// <summary>
/// BCC异或取反校验
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string getBCC(byte[] data)
{
String ret = "";
byte[] BCC = new byte[1];
for (int i = 0; i < data.Length; i++)
{
BCC[0] = (byte)(BCC[0] ^ data[i]);
}
String hex = ((~BCC[0]) & 0xFF).ToString("X");//取反操作
if (hex.Length == 1)
{
hex = '0' + hex;
}
ret += hex.ToUpper();
return ret;
}
static int BytesToInt(byte[] b, int length)
{
int temp = 0;
for (int i = 0; i <= length - 1 && i < 4; i++)
{
temp += (int)(b[i] << (i * 8));
}
return temp;
}
public static byte[] CalculateVerify(byte[] pMessage, int iLength)
{
UInt16 i;
int iVerify = 0;
iVerify = pMessage[0];
for (i = 0; i < iLength - 1; i++)
{
iVerify = iVerify + pMessage[i + 1];
}
return BitConverter.GetBytes(Convert.ToUInt16(iVerify));
}
#endregion
public byte[] HexStrTorbytes(string strHex)//e.g. " 01 01" ---> { 0x01, 0x01}
{
strHex = strHex.Replace(" ", "");
if ((strHex.Length % 2) != 0)
strHex += " ";
byte[] returnBytes = new byte[strHex.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(strHex.Substring(i * 2, 2), 16);
return returnBytes;
}
/// <summary>
/// 将字符串强制转换成int转换失败则返回0
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public int ParseToInt(string str)
{
int returnInt = 0;
if (str == null || str.Trim().Length < 1)
{
return returnInt;
}
if (int.TryParse(str, out returnInt))
{
return returnInt;
}
else
{
return 0;
}
}
public byte[] HexToString(string Str)
{
byte[] str = new byte[Str.Length / 2];
for (int i = 0; i < str.Length; i++)
{
int temp = Convert.ToInt32(Str.Substring(i * 2, 2), 16);
str[i] = (byte)temp;
}
return str;
}
public string ConverToString(byte[] data)
{
string str;
StringBuilder stb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
if ((int)data[i] > 15)
{
stb.Append(Convert.ToString(data[i], 16).ToUpper()); //添加字符串
}
else //如果是小于0F需要加个零
{
stb.Append("0" + Convert.ToString(data[i], 16).ToUpper());
}
}
str = stb.ToString();
return str;
}
public string bytesToHexStr(byte[] bytes, int iLen)
{
StringBuilder sb = new StringBuilder();
if (bytes != null)
{
for (int i = 0; i < iLen; i++)
{
sb.Append(bytes[i].ToString("X2"));
}
}
return sb.ToString();
}
/// <summary>
/// 从十进制转换到十六进制
/// </summary>
/// <param name="ten"></param>
/// <returns></returns>
public string Ten2Hex(string ten)
{
ulong tenValue = Convert.ToUInt64(ten);
ulong divValue, resValue;
string hex = "";
do
{
//divValue = (ulong)Math.Floor(tenValue / 16);
divValue = (ulong)Math.Floor((decimal)(tenValue / 16));
resValue = tenValue % 16;
hex = tenValue2Char(resValue) + hex;
tenValue = divValue;
}
while (tenValue >= 16);
if (tenValue != 0)
hex = tenValue2Char(tenValue) + hex;
return hex;
}
public static string tenValue2Char(ulong ten)
{
switch (ten)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
return ten.ToString();
case 10:
return "A";
case 11:
return "B";
case 12:
return "C";
case 13:
return "D";
case 14:
return "E";
case 15:
return "F";
default:
return "";
}
}
}
#region 消息公用的头尾
/// <summary>
/// 能源通讯协议结构体
/// </summary>
public enum CallbackSendData
{
_LoginIn = 0XA1,
_SetTime = 0X08,
_HeartBeat = 0XA4,
_ERealFlag = 0XB3,
_SRealFlag = 0XB4,
_TRealFlag = 0XB5,
_IRealFlag = 0XB6,
_EFlag = 0XC3,
_SFlag = 0XC4,
_TFlag = 0XC5,
_IFlag = 0XC6,
}
public struct struFrame
{
//帧开始
public byte BeginChar_State;
//采集器类型
public byte Collection_Type;
//采集器地址
public byte[] Collection_Addr;
//命令序列号
public byte[] Command_Id;
//起始符
public byte StartChar_State;
//控制码
public byte Ctrl_State;
//数据长度
public byte[] DataLen_State;
//数据域
public byte[] Data_State;
//校验码
public byte CSChar_State;
//结束符
public byte EndChar_State;
//终端类型
public byte flagDTN;
//逻辑编号
public byte[] addrDNL;
//主站地址
public byte flagMSTA;
//帧内序号
public byte flagISEQ;
//帧序号
public byte flagFSEQ;
//控制码
public byte flagCtrl;
//传送方向
public byte flagCtrlD;
//异常标志
public byte flagCtrlE;
//功能标志
public byte flagCtrlF;
//数据长度
public int lenData;
//数据字符串
public byte[] strData;
public object userData;
public string tName;
public object userData2;
//public bool isCtrl;
//public bool isData;
public bool isTimeCorrectting;
};
/// <summary>
/// 头文件
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct Head
{
public byte start; //起始
public short addr; //软件地址
public byte mstaseq; //主站地址与命令序号
public byte control; //控制码
public short length; //数据长度
}
/// <summary>
/// 结尾
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct Tail
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] verifica; //校验码
public byte end; //结束码
}
#endregion
#region 与MES通讯协议
//识别一条EPC数据 125+3
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct ReadEPC
{
public Head head;
public int num;//合并编号
public Tail tail;
}
/// <summary>
/// 写入反馈 125+5
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct RecWrite
{
public Head head;
public int num;//合并编号
public byte state;//1成功0失败2写失败读成功
public Tail tail;
}
//
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct RecDataCell
{
public byte len;//Data长度
public byte[] data;//len 长度个字节数据
}
/// <summary>
/// 自报数据 125+6
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct RecAutoData
{
public Head head;
public int num;//合并编号
public RecDataCell recDatas;//自报数据
public Tail tail;
}
/// <summary>
///心跳 101
/// </summary>
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct Heart
{
public Head head;
public Tail tail;
}
#endregion
#region 与上层应用层 消息指令
/// <summary>
/// 收到的消息指令
/// </summary>
enum RecAppMsgType
{
_ReadEpc = 125 + 3,
_ReadData = 125 + 4,
_WirteData = 125 + 5,
_AutoSendData,
_HeartBeat = 101,
_ReadEquipState = 125 + 102,
_SendGetSoftState = 125 + 103,
}
/// <summary>
/// 发送的消息指令
/// </summary>
enum RetAppMsgType
{
_RetEpc = 125 + 3,
_RetData = 125 + 4,
_RetDataBack = 125 + 5,
_RetAutoSendData,
_RetEquipState = 125 + 102,
_RetGetSoftState = 125 + 103,
}
#endregion
#region 与设备层 适配层消息指令
//收到设备层消息
enum RecEquipMsgType
{
_GetEquipInfo = 0X01, //收到适配软件所需设备信息
_GetSensor = 0x02, //收到适配软件传感器信息
_EPCinfo = 0x03, //收到设备返回数据 将数据发送MES 并保存数据库
_SendData = 0x04, //收到读取到的数据 收到数据后上传给MES并保存数据库
_RecGetData = 0x05, //收到写入的数据是否成功反馈
_RecAutoData = 0x06, //收到设备自报数据
_HeartBeat = 101, //心跳
_EquipState, //设备状态
}
//发送给设备层消息
enum RetEquipMsgType
{
_RetEquipInfo = 0X01, //获取适配软件所需设备信息
_RetSensor = 0x02, //获取适配软件传感器信息
_GetEPCinfo = 0x03, //向设备发送命令识别EPC数据
_GetData = 0x04, //向设备发送命令,读取数据
_WirteData = 0x05, //向设备发送命令,写入数据
_RetAutoData = 0x06, //收到设备自爆数据反馈
}
#endregion
}