/// <summary> /// 创建包-同步时间 /// </summary> /// <param name="dt"></param> /// <returns></returns> private static byte[] BuildBag_SyncTime(DateTime dt) { byte[] arrRtn = new byte[23]; int iIndex = 0; //帧起始符 高位 arrRtn[iIndex++] = 0x55; //帧起始符 低位 arrRtn[iIndex++] = 0xFF; //数据长度 高位 arrRtn[iIndex++] = 0x00; //数据长度 低位 arrRtn[iIndex++] = 0x12; //命令字 arrRtn[iIndex++] = 0x9A; //广播地址 5字节 arrRtn[iIndex++] = 0xFF; arrRtn[iIndex++] = 0xFF; arrRtn[iIndex++] = 0xFF; arrRtn[iIndex++] = 0xFF; arrRtn[iIndex++] = 0xFF; //主管理机地址 5字节 arrRtn[iIndex++] = 0x01; arrRtn[iIndex++] = 0x00; arrRtn[iIndex++] = 0x00; arrRtn[iIndex++] = 0x00; arrRtn[iIndex++] = 0x00; //时间 7字节 string strYear = dt.Year.ToString(); //年 arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(strYear.Substring(2, 2)); //月 arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(dt.Month)); //日 arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(dt.Day)); //周 arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(Functions.GetWeekOfYear(dt))); //时 arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(dt.Hour)); //分 arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(dt.Minute)); //秒 arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(dt.Second)); //CRC8校验 arrRtn[iIndex++] = CRC8A.GetCRC8(arrRtn, 0, arrRtn.Length - 1); return(arrRtn); }
/// <summary> /// 创建包-ping指令 /// </summary> /// <param name="bArrTargetAddress">目的地址5个字节</param> /// <returns></returns> private static byte[] BuildBag_Ping(DeviceAddress objDeviceAddress) { if (objDeviceAddress == null || string.IsNullOrEmpty(objDeviceAddress.DeviceNo)) { return(new byte[0]); } byte[] arrRtn = new byte[18]; int iIndex = 0; //帧起始符 高位 arrRtn[iIndex++] = 0x55; //帧起始符 低位 arrRtn[iIndex++] = 0xFF; //数据长度 高位 arrRtn[iIndex++] = 0x00; //数据长度 低位 arrRtn[iIndex++] = 0x0D; //命令字 arrRtn[iIndex++] = 0x92; //目的地址 5字节 arrRtn[iIndex++] = GetDeviceTypeByte(objDeviceAddress.DeviceType); byte[] bArrDeviceNo = ScaleConverter.HexStr2ByteArr(objDeviceAddress.DeviceNo); for (int i = 0; i < 4; i++) { arrRtn[iIndex++] = bArrDeviceNo[i]; } //源地址 5字节 arrRtn[iIndex++] = 0x01; arrRtn[iIndex++] = 0x00; arrRtn[iIndex++] = 0x00; arrRtn[iIndex++] = 0x00; arrRtn[iIndex++] = 0x00; //序号 2字节 BCD码:0~9999(每次序号不一样) byte[] bArrPingNum = ScaleConverter.Int2ByteArr(objDeviceAddress.PingNum); arrRtn[iIndex++] = bArrPingNum[1]; arrRtn[iIndex++] = bArrPingNum[0]; //CRC8校验 arrRtn[iIndex++] = CRC8A.GetCRC8(arrRtn, 0, arrRtn.Length - 1); return(arrRtn); }
/// <summary> /// 主机应答 /// </summary> /// <param name="bArrTargetAddress">5字节目标地址</param> /// <param name="bArrOrigialAddress">5字节源地址</param> /// <returns></returns> public static byte[] BuildBag_MainDeviceResponse(byte[] bArrTargetAddress, byte[] bArrOrigialAddress) { byte[] arrRtn = new byte[0]; if (bArrTargetAddress.Length == 5 && bArrOrigialAddress.Length == 5) { //55 FF 00 0C 21 06 12 34 00 01 01 00 00 00 00 00 xx 主机应答 byte[] arrRtnTemp = new byte[1450]; int iIndex = 0; //帧起始符 高位 arrRtnTemp[iIndex++] = 0x55; //帧起始符 低位 arrRtnTemp[iIndex++] = 0xFF; //数据长度 高位 arrRtnTemp[iIndex++] = 0x00; //数据长度 低位 arrRtnTemp[iIndex++] = 0x0C; //命令字 arrRtnTemp[iIndex++] = 0x21; //源地址转成目的地址 for (int i = 0; i <= 4; i++) { arrRtnTemp[iIndex++] = bArrOrigialAddress[i]; } //目的地址转成源地址 for (int i = 0; i <= 4; i++) { arrRtnTemp[iIndex++] = bArrTargetAddress[i]; } //未定义 arrRtnTemp[iIndex++] = 0x00; //CRC8校验 arrRtnTemp[iIndex++] = CRC8A.GetCRC8(arrRtnTemp, 0, iIndex - 1); arrRtn = new byte[iIndex]; Array.Copy(arrRtnTemp, arrRtn, arrRtn.Length); } return(arrRtn); }
/// <summary> /// 创建包-扇区查询 /// </summary> /// <returns></returns> private static byte[] BuildBag_ChsSel() { byte[] arrRtn = new byte[6]; int iIndex = 0; //帧起始符 高位 arrRtn[iIndex++] = 0x55; //帧起始符 低位 arrRtn[iIndex++] = 0xFF; //数据长度 高位 arrRtn[iIndex++] = 0x00; //数据长度 低位 arrRtn[iIndex++] = 0x01; //命令字 arrRtn[iIndex++] = 0x36; //CRC8校验 arrRtn[iIndex++] = CRC8A.GetCRC8(arrRtn, 0, arrRtn.Length - 1); return(arrRtn); }
/// <summary> /// 主机链路层ACK-响应ping /// </summary> /// <param name="bArrTargetAddress">5字节目标地址</param> /// <param name="bArrOrigialAddress">5字节源地址</param> /// <returns></returns> public static byte[] BuildBag_MainDeviceACK4Ping(byte[] bArrTargetAddress, byte[] bArrOrigialAddress) { byte[] arrRtn = new byte[0]; if (bArrTargetAddress.Length == 5 && bArrOrigialAddress.Length == 5) { //55 FF 00 0D 93 01 00 00 00 00 06 01 01 00 00 00 01 22 byte[] arrRtnTemp = new byte[100]; int iIndex = 0; //帧起始符 高位 arrRtnTemp[iIndex++] = 0x55; //帧起始符 低位 arrRtnTemp[iIndex++] = 0xAA; //数据长度 高位 arrRtnTemp[iIndex++] = 0x00; //数据长度 低位 arrRtnTemp[iIndex++] = 0x0B; //命令字 arrRtnTemp[iIndex++] = 0x93; //目的地址照搬回去 for (int i = 0; i <= 4; i++) { arrRtnTemp[iIndex++] = bArrTargetAddress[i]; } //源地址照搬回去 for (int i = 0; i <= 4; i++) { arrRtnTemp[iIndex++] = bArrOrigialAddress[i]; } //CRC8校验 arrRtnTemp[iIndex++] = CRC8A.GetCRC8(arrRtnTemp, 0, iIndex - 1); arrRtn = new byte[iIndex]; Array.Copy(arrRtnTemp, arrRtn, arrRtn.Length); } return(arrRtn); }
/// <summary> /// 创建包-写卡 /// </summary> /// <param name="objCard"></param> /// <returns></returns> private static byte[] BuildBag_WriteCard(Card objCard) { byte[] arrRtn = new byte[0]; if (objCard != null) { int iAreaCode, iBuidCode, iUnitCode, iRoomCode; iAreaCode = objCard.RAreaCode; iBuidCode = objCard.RBuildCode; iUnitCode = objCard.RUnitCode; iRoomCode = objCard.RRoomCode; if ((iAreaCode >= 0 && iAreaCode <= 99) && (iBuidCode >= 0 && iBuidCode <= 99) && (iUnitCode >= 0 && iUnitCode <= 99) && (iRoomCode >= 0 && iRoomCode <= 9999)) { byte[] arrRtnTemp = new byte[1450]; int iIndex = 0; //帧起始符 高位 arrRtnTemp[iIndex++] = 0x55; //帧起始符 低位 arrRtnTemp[iIndex++] = 0xFF; //数据长度 高位 arrRtnTemp[iIndex++] = 0x00; //数据长度 低位 arrRtnTemp[iIndex++] = 0x21; //命令字 arrRtnTemp[iIndex++] = GetCommandCodeByType(ECommandType.WriteCard_Send); //区编码 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(iAreaCode)); //栋编码 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(iBuidCode)); //单元编码 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(iUnitCode)); string strRoomCode = FormatRoomCode(iRoomCode); //楼层编码 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(strRoomCode.Substring(0, 2))); //房间编码 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(strRoomCode.Substring(2, 2))); //过期时间 DateTime dt = Functions.ConvertToNormalTime(objCard.ExpiryDate); string strYear = dt.Year.ToString(); //年-高位 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(strYear.Substring(0, 2)); //年-低位 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(strYear.Substring(2, 2)); //月 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(dt.Month)); //日 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(dt.Day)); //卡片类型 arrRtnTemp[iIndex++] = Convert.ToByte(objCard.CardType); DateTime CreateDt = System.DateTime.Now; //预留6个字节 //iIndex += 6; //发卡时间 当前 年 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(CreateDt.Year.ToString().Substring(2, 2))); //发卡时间 当前 月 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(CreateDt.Month)); //发卡时间 当前 日 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(CreateDt.Day)); //发卡时间 当前 时 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(CreateDt.Hour)); //发卡时间 当前 分 arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(CreateDt.Minute)); //发卡时间 当前 写扇区 先转成16进制再转成字符串 string chsStr = ""; switch (Convert.ToInt32(objCard.listChsInfo[1][0])) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: chsStr = objCard.listChsInfo[1][0].ToString(); break; case 10: chsStr = string.Format("A"); break; case 11: chsStr = string.Format("B"); break; case 12: chsStr = string.Format("C"); break; case 13: chsStr = string.Format("D"); break; case 14: chsStr = string.Format("E"); break; case 15: chsStr = string.Format("F"); break; } arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(chsStr)); //序号 16个字节 string strSerialNo = objCard.SerialNo.Replace(" ", "").PadLeft(32, '0'); for (int i = 1; i <= 16; i++) { arrRtnTemp[iIndex++] = ScaleConverter.OneHexStr2Byte(strSerialNo.Substring((i - 1) * 2, 2)); } //CRC8校验 arrRtnTemp[iIndex++] = CRC8A.GetCRC8(arrRtnTemp, 0, iIndex - 1); arrRtn = new byte[iIndex]; Array.Copy(arrRtnTemp, arrRtn, arrRtn.Length); } } return(arrRtn); }
/// <summary> /// 创建发送包 /// </summary> /// <param name="CommandType">指令类型</param> /// <param name="objCard">写卡指令专用</param> /// <param name="dt">时间,同步时间专用</param> /// <param name="objDeviceAddress">地址,Ping指令专用</param> /// <param name="chs">扇区重置,写卡专用</param> /// <returns></returns> public static byte[] BuildBag(ECommandType CommandType, Card objCard = null, String chs = null, DateTime?dt = null, DeviceAddress objDeviceAddress = null) { byte[] arrRtn = new byte[0]; byte[] arrTemp; switch (CommandType) { case ECommandType.WriteCard_Send: arrTemp = BuildBag_WriteCard(objCard); if (arrTemp.Length > 0) { arrRtn = new byte[arrTemp.Length]; Array.Copy(arrTemp, arrRtn, arrRtn.Length); } break; case ECommandType.ReadCard_Send: arrRtn = new byte[6]; arrTemp = ScaleConverter.HexStr2ByteArr("55 FF 00 01 34"); Array.Copy(arrTemp, arrRtn, arrTemp.Length); arrRtn[5] = CRC8A.GetCRC8(arrTemp); break; case ECommandType.Ping: if (objDeviceAddress != null) { arrTemp = BuildBag_Ping(objDeviceAddress); if (arrTemp.Length > 0) { arrRtn = new byte[arrTemp.Length]; Array.Copy(arrTemp, arrRtn, arrRtn.Length); } } break; case ECommandType.SyncTime_Send: //同步时间 if (dt != null) { byte[] arrRtnTemp2 = BuildBag_SyncTime(Convert.ToDateTime(dt)); if (arrRtnTemp2.Length > 0) { arrRtn = new byte[arrRtnTemp2.Length]; Array.Copy(arrRtnTemp2, arrRtn, arrRtn.Length); } } break; case ECommandType.ChsSel: //扇区查询 arrTemp = BuildBag_ChsSel(); if (arrTemp.Length > 0) { arrRtn = new byte[arrTemp.Length]; Array.Copy(arrTemp, arrRtn, arrRtn.Length); } break; case ECommandType.ChsClean: //扇区重置 arrTemp = BuildBag_ChsClean(chs); if (arrTemp.Length > 0) { arrRtn = new byte[arrTemp.Length]; Array.Copy(arrTemp, arrRtn, arrRtn.Length); } break; } return(arrRtn); }
/// <summary> /// 创建包-扇区重置 /// </summary> /// <param name="chs">需要重置的扇区</param> /// <returns></returns> private static byte[] BuildBag_ChsClean(String chs) { byte[] arrRtn = new byte[7]; int iIndex = 0; //帧起始符 高位 arrRtn[iIndex++] = 0x55; //帧起始符 低位 arrRtn[iIndex++] = 0xFF; //数据长度 高位 arrRtn[iIndex++] = 0x00; //数据长度 低位 arrRtn[iIndex++] = 0x02; //命令字 arrRtn[iIndex++] = 0x38; //数据 要重置的扇区 string chsStr = ""; switch (Convert.ToInt32(chs)) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: chsStr = chs; break; case 10: chsStr = string.Format("A"); break; case 11: chsStr = string.Format("B"); break; case 12: chsStr = string.Format("C"); break; case 13: chsStr = string.Format("D"); break; case 14: chsStr = string.Format("E"); break; case 15: chsStr = string.Format("F"); break; } arrRtn[iIndex++] = ScaleConverter.OneHexStr2Byte(BQ2(chsStr)); //CRC8校验 arrRtn[iIndex++] = CRC8A.GetCRC8(arrRtn, 0, arrRtn.Length - 1); return(arrRtn); }
/// <summary> /// 检测响应包类型 /// </summary> /// <param name="bArrBag"></param> /// <param name="strErrMsg"></param> /// <returns></returns> public static ECommandType GetResponseType(byte[] bArrBag, out string strErrMsg) { ECommandType eResponseType = ECommandType.UnKnown; strErrMsg = ""; //数据校验 if (bArrBag != null && bArrBag.Length >= 6) { //1.数据CRC8校验 byte bCRCResult = CRC8A.GetCRC8(bArrBag, 0, bArrBag.Length - 1); byte bCRCSource = bArrBag[bArrBag.Length - 1]; if (bCRCSource.Equals(bCRCResult)) { //2.识别帧起始符 if (bArrBag[0].Equals(0x55) && bArrBag[1].Equals(0xFF)) { //3.识别数据长度 byte[] bArrDataLength = new byte[4]; bArrDataLength[0] = bArrBag[3]; bArrDataLength[1] = bArrBag[2]; uint iDataLength = Functions.ConverToUInt(bArrDataLength);//低字节在前,高字节在后 if (bArrBag.Length == (iDataLength + 2 + 2 + 1)) { //4.识别命令包类型 eResponseType = GetCommandTypeByCode(bArrBag[4]); if (eResponseType.Equals(ECommandType.UnKnown)) { strErrMsg = "数据包指令位不正确!"; } else if (eResponseType.Equals(ECommandType.SwipingCard)) { if (bArrBag.Length < 23) { eResponseType = ECommandType.UnKnown; } } else if (eResponseType.Equals(ECommandType.PingResponse)) { if (bArrBag.Length < 18) { eResponseType = ECommandType.UnKnown; } } } else { strErrMsg = "数据长度位与数据包实际长度不一致!"; } } else if (bArrBag[0].Equals(0x55) && bArrBag[1].Equals(0xAA)) { //刷卡头链路层ACK eResponseType = ECommandType.UnKnown; if (bArrBag.Length >= 16) { if (bArrBag[4].Equals(0x21)) { eResponseType = ECommandType.CardHeadDeviceACK; } if (bArrBag[4].Equals(0x92)) { eResponseType = ECommandType.MainDeviceACK4PingResponse; } } } else { strErrMsg = "帧起始符不正确!"; } } else { strErrMsg = "CRC校验不合法!"; } } else { strErrMsg = "数据长度不正确!"; } return(eResponseType); }