using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace HighWayIot.Common { /// /// 工具类 /// public sealed class MsgUtil { private static readonly Lazy lazy = new Lazy(() => new MsgUtil()); public static MsgUtil Instance { get { return lazy.Value; } } private MsgUtil() { } #region 数据解析公共方法 /// /// 字节数组转换成结构体 /// /// /// /// /// 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; } //// /// 结构体转byte数组 /// /// 要转换的结构体 /// 转换后的byte数组 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 消息验证方法 /// /// CS和校验 /// /// /// 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; } /// /// BCC异或取反校验 /// /// /// 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; } /// /// 将字符串强制转换成int,转换失败则返回0 /// /// /// 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(); } /// /// 从十进制转换到十六进制 /// /// /// 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 消息公用的头尾 /// /// 能源通讯协议结构体 /// 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; }; /// /// 头文件 /// [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; //数据长度 } /// /// 结尾 /// [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; } /// /// 写入反馈 125+5 /// [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 长度个字节数据 } /// /// 自报数据 125+6 /// [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct RecAutoData { public Head head; public int num;//合并编号 public RecDataCell recDatas;//自报数据 public Tail tail; } /// ///心跳 101 /// [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct Heart { public Head head; public Tail tail; } #endregion #region 与上层应用层 消息指令 /// /// 收到的消息指令 /// enum RecAppMsgType { _ReadEpc = 125 + 3, _ReadData = 125 + 4, _WirteData = 125 + 5, _AutoSendData, _HeartBeat = 101, _ReadEquipState = 125 + 102, _SendGetSoftState = 125 + 103, } /// /// 发送的消息指令 /// 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 }