namespace JiLinApp.Docking.FenceAlarm; public class AlarmEncode { #region Fields public static readonly byte Version = 0x12; public static readonly byte[] Head = new byte[] { 0xF0, 0xFA }; public static readonly byte End = 0x0D; public static readonly byte[] TEA_key = new byte[16] { 0x08,0x01,0x08,0x06,0x07,0x08,0x07,0x08, 0x08,0x90,0xC5,0x04,0x0D,0x0E,0x0F,0x10 }; #endregion Fields public static byte[] EncodeMessage(byte[] msg) { if (!CheckMessage(msg)) return Array.Empty(); return GetMessage(msg[0], BteaEncrypt(GetContent(msg, msg[0] - 1))); } public static byte[] DecodeMessage(byte[] msg) { if (!CheckMessage(msg)) return Array.Empty(); return GetMessage(msg[0], BteaDecrpyt(GetContent(msg, msg[0] - 1))); } private static bool CheckMessage(byte[] msg) { if (msg == null) return false; if (msg[0] > msg.Length) return false; return true; } private static byte[] GetMessage(byte msgLen, byte[] msg) { byte[] outMsg = new byte[msg.Length + 1]; outMsg[0] = msgLen; for (int i = 0; i < msg.Length; i++) { outMsg[i + 1] = msg[i]; } return outMsg; } private static byte[] GetContent(byte[] msg, int len) { byte[] bytes = new byte[len]; for (int i = 0; i < len; i++) { bytes[i] = msg[i + 1]; } return bytes; } public static byte[] GetSendMessage(byte command, byte[] data) { byte[] msg = data != null ? new byte[data.Length + 8] : new byte[8]; msg[0] = (byte)msg.Length; msg[1] = Version; msg[2] = Head[0]; msg[3] = Head[1]; msg[4] = command; if (data != null) { for (int i = 0; i < data.Length; i++) { msg[i + 5] = data[i]; } } byte[] subMsg = data != null ? new byte[data.Length + 4] : new byte[4]; for (int i = 0; i < subMsg.Length; i++) { subMsg[i] = msg[i + 1]; } byte[] crc = CRC16(subMsg); msg[^3] = crc[1]; msg[^2] = crc[0]; msg[^1] = End; return msg; } public static byte[] CRC16(byte[] data) { int len = data.Length; if (len > 0) { ushort crc = 0xFFFF; for (int i = 0; i < len; i++) { crc = (ushort)(crc ^ (data[i])); for (int j = 0; j < 8; j++) { crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1); } } byte hi = (byte)((crc & 0xFF00) >> 8); //高位置 byte lo = (byte)(crc & 0x00FF); //低位置 return new byte[] { hi, lo }; } return new byte[] { 0, 0 }; } private static byte[] BteaEncrypt(byte[] bytes) { byte[] output = new byte[bytes.Length]; for (int i = 0; i < bytes.Length; i++) { byte abyte = (byte)(bytes[i] ^ TEA_key[i % 16]); output[i] = (byte)(((byte)(abyte >> 3)) | ((byte)(abyte << 5))); } return output; } private static byte[] BteaDecrpyt(byte[] bytes) { byte[] output = new byte[bytes.Length]; for (int i = 0; i < bytes.Length; i++) { byte abyte = (byte)(((byte)(bytes[i] << 3)) | ((byte)(bytes[i] >> 5))); output[i] = (byte)(abyte ^ TEA_key[i % 16]); } return output; } } public enum DeviceCmd : byte { /// /// 心跳 /// HeartBeatCmd = 0x01, /// /// 报警 /// AlarmCmd = 0x02, /// /// 所有防区状态 /// AllSectorStateCmd = 0x03, /// /// 实时防区状态 /// RtSectorStateCmd = 0x04, /// /// 最大防区号 /// MaxSectorTotalCmd = 0x05, /// /// 报警主机设置参数返回服务器 /// BackSettingsCmd = 0x08, /// /// 布防指令 /// DefenceCmd = 0x80, /// /// 校对时间指令 /// CheckTimeCmd = 0x8D, /// /// 正确应答指令 /// OkCmd = 0x8F, /// /// 主机重启指令 /// RebootCmd = 0xA0, } public enum DeviceSectorType : byte { /// /// 防区未使用 /// NotUsed = 0x00, /// /// 防区撤防 /// Withdraw = 0x01, /// /// 防区布防 /// Deploy = 0x02, /// /// 防区旁路 /// Byway = 0x03, /// /// 防区报警 /// Alarm = 0x04, /// /// 无线防区欠压 /// Undervoltage = 0x05, /// /// 防区掉线(与主线总线脱离) /// OffBus = 0x06, /// /// 未准备就绪 /// Unprepared = 0x07, } public enum DeviceDefenceState : byte { /// /// 撤防状态 /// Withdraw = 0x00, /// /// 外出布防(普通布防最常用) /// GoOut = 0x01, /// /// 即时布防(所有防区没有延时) /// Immediately = 0x02, /// /// 在家布防(留守布防有些防区可能是在旁路状态) /// Home = 0x04, /// /// 即时留守布防(有些防区可能旁路,但是没有旁路防区没有延时) /// HomeImmediately = 0x08, /// /// 部分防区布防部分防区撤防 /// Part = 0x09 }