using System;
using System.Runtime.InteropServices;
using System.Text;

namespace HighWayAssemble
{
    class 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 e)
            {
                return null;
            }
            return rtn;
        }

        //// <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 消息验证方法

        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

        /// <summary>
        /// 将字符串强制转换成int，转换失败则返回0
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static 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 static 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();
        }

    }

    #region 消息公用的头尾

    /// <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

}
