using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace AIK.Common.AIKProtocol { public static class K3ToolUSBProtocol { private static int _totalPackets; private static byte[]? _fileData; private static byte[]? _endEOTData; private static byte[]? _connectData; private static byte[]? _createRemoteData; private static byte[]? _closetheUdiskData; private static byte[]? _opentheUdiskData; private static readonly object _lockObject = new object(); public static readonly string ConnectFileName = "usb connect.bin"; public static readonly string CreateRemoteFileName = "usb create remote.bin"; public static int TotalPackets { get => _totalPackets; set => _totalPackets = value; } public static byte[] FileData { get => _fileData ?? Array.Empty(); set { lock (_lockObject) { _fileData = value; // 当 FileData 不为空时,自动计算 TotalPackets if (_fileData != null && _fileData.Length > 0) { _totalPackets = (int)Math.Ceiling(_fileData.Length / 1024.0); } else { _totalPackets = 0; } } } } public static byte[] EndEOTData { get { if (_endEOTData == null || _endEOTData.Length == 0) { lock (_lockObject) { // 双重检查锁定 if (_endEOTData == null || _endEOTData.Length == 0) { _endEOTData = GetBinData(ResourceEOTName); } } } return _endEOTData; } set => _endEOTData = value; } public static byte[] ConnectData { get { if (_connectData == null || _connectData.Length == 0) { lock (_lockObject) { // 双重检查锁定 if (_connectData == null || _connectData.Length == 0) { _connectData = GetBinData(ResourceConnectName); } } } return _connectData; } set => _connectData = value; } public static byte[] CreateRemoteData { get { if (_createRemoteData == null || _createRemoteData.Length == 0) { lock (_lockObject) { // 双重检查锁定 if (_createRemoteData == null || _createRemoteData.Length == 0) { _createRemoteData = GetBinData(ResourceCreateRemoteName); } } } return _createRemoteData; } set => _createRemoteData = value; } public static byte[] ClosetheUdiskData { get { if (_closetheUdiskData == null || _closetheUdiskData.Length == 0) { lock (_lockObject) { // 双重检查锁定 if (_closetheUdiskData == null || _closetheUdiskData.Length == 0) { _closetheUdiskData = GetBinData(ResourceClosetheUdiskName); } } } return _closetheUdiskData; } set => _closetheUdiskData = value; } public static byte[] OpentheUdiskData { get { if (_opentheUdiskData == null || _opentheUdiskData.Length == 0) { lock (_lockObject) { // 双重检查锁定 if (_opentheUdiskData == null || _opentheUdiskData.Length == 0) { _opentheUdiskData = GetBinData(ResourceOpentheUdiskName); } } } return _opentheUdiskData; } set => _opentheUdiskData = value; } public static string ResourceEOTName { get; set; } = "AIK.Common.Resources.eot.bin"; public static string ResourceConnectName { get; set; } = "AIK.Common.Resources.usb connect.bin"; public static string ResourceCreateRemoteName { get; set; } = "AIK.Common.Resources.usb create remote.bin"; public static string ResourceClosetheUdiskName { get; set; } = "AIK.Common.Resources.Close the U disk.bin"; public static string ResourceOpentheUdiskName { get; set; } = "AIK.Common.Resources.Open the U disk.bin"; #region 头帧 public static byte[] GetSendHeader(string sourceitem) { // 保持原有实现 List bytes = new List(); bytes.Add(0x01); bytes.Add(0x00); bytes.Add(0xFF); int lastSlashIndex = sourceitem.LastIndexOf('/'); string fileName = lastSlashIndex >= 0 ? sourceitem.Substring(lastSlashIndex + 1) : sourceitem; byte[] filenamedata = Encoding.GetEncoding(936).GetBytes(fileName); bytes.AddRange(filenamedata); bytes.Add(0x00); if (FileData == null) return new byte[0]; TotalPackets = (int)Math.Ceiling(FileData.Length / 1024.0); byte[] dataLengthData = Encoding.GetEncoding(936).GetBytes(FileData.Length.ToString()); bytes.AddRange(dataLengthData); bytes.Add(0x00); // 填充到128字节 if (bytes.Count < 128 + 3) { bytes.AddRange(new byte[128 + 3 - bytes.Count]); } var cdata = new byte[128]; Array.Copy(bytes.ToArray(), 3, cdata, 0, 128); var crc = ProtocolHelper.CalculateCRC16(cdata); bytes.Add((byte)((crc >> 8) & 0xFF)); bytes.Add((byte)(crc & 0xFF)); return bytes.ToArray(); } #endregion #region 数据帧 public static List GetSendDataFrame(int page, byte[] filedata) { try { var bytes = new List(); if (page >= TotalPackets) return bytes; bytes.Add(0x02); bytes.Add((byte)(page + 1)); bytes.Add((byte)~(page + 1)); int dataStart = page * 1024; int dataLength = Math.Min(1024, filedata.Length - dataStart); var frameData = new byte[1024]; Array.Copy(filedata, dataStart, frameData, 0, dataLength); var crc = ProtocolHelper.CalculateCRC16(frameData); bytes.AddRange(frameData); bytes.Add((byte)((crc >> 8) & 0xFF)); bytes.Add((byte)(crc & 0xFF)); return bytes; } catch (Exception ex) { Debug.WriteLine($"生成数据帧错误: {ex.Message}"); return new List(); } } #endregion #region 资源文件帧 /// /// 获取bin文件转成byte数组 /// /// /// private static byte[] GetBinData(string resourceName) { try { var assembly = Assembly.GetExecutingAssembly(); // 查看所有资源名称(调试用) // var names = assembly.GetManifestResourceNames(); using var stream = assembly.GetManifestResourceStream(resourceName); if (stream == null) throw new FileNotFoundException($"未找到嵌入资源: {resourceName}"); using var ms = new MemoryStream(); stream.CopyTo(ms); return ms.ToArray(); } catch (Exception ex) { return Array.Empty(); } } #region Connect帧 /// /// 手动刷新 Connect 数据(强制重新加载) /// public static void RefreshConnectData() { lock (_lockObject) { _connectData = GetBinData(ResourceConnectName); } } /// /// 清除缓存的 Connect 数据(下次访问时会重新加载) /// public static void ClearConnectDataCache() { lock (_lockObject) { _connectData = null; } } #endregion #region CreateRemote帧 /// /// 手动刷新 CreateRemote 数据(强制重新加载) /// public static void RefreshCreateRemoteData() { lock (_lockObject) { _createRemoteData = GetBinData(ResourceCreateRemoteName); } } /// /// 清除缓存的 CreateRemote数据(下次访问时会重新加载) /// public static void ClearCreateRemoteDataCache() { lock (_lockObject) { _createRemoteData = null; } } #endregion #region EOT帧 /// /// 手动刷新 EOT 数据(强制重新加载) /// public static void RefreshEndEOTData() { lock (_lockObject) { _endEOTData = GetBinData(ResourceEOTName); } } /// /// 清除缓存的 EOT 数据(下次访问时会重新加载) /// public static void ClearEndEOTDataCache() { lock (_lockObject) { _endEOTData = null; } } #endregion #endregion #region 最终结束帧 /// /// 最终结束帧 /// /// public static byte[] GetEndDataFrame() { var bytes = new byte[133]; bytes[0] = 0x01; bytes[1] = 0x00; bytes[2] = 0xFF; // 其余128字节默认为0,无需手动设置 return bytes; } #endregion #region 工具方法 /// /// 设置文件数据(自动计算 TotalPackets) /// /// 文件数据 public static void SetFileData(byte[] fileData) { FileData = fileData; // 这会自动触发 TotalPackets 计算 } /// /// 从文件路径加载数据(自动计算 TotalPackets) /// /// 文件路径 public static void LoadFileData(string filePath) { if (!File.Exists(filePath)) throw new FileNotFoundException($"文件不存在: {filePath}"); var fileData = File.ReadAllBytes(filePath); FileData = fileData; // 自动计算 TotalPackets } /// /// 获取指定文件的总包数(不设置到全局状态) /// /// 文件数据 /// 总包数 public static int GetTotalPackets(byte[] fileData) { return (int)Math.Ceiling(fileData.Length / 1024.0); } /// /// 重置所有状态 /// public static void Reset() { lock (_lockObject) { _totalPackets = 0; _fileData = null; _endEOTData = null; } } /// /// 将 UTF-8 字符串转换为 GBK 编码的字节数组 /// public static byte[] Utf8StringToGbkBytes(string utf8Text) { if (utf8Text == null) return null; return Encoding.GetEncoding(936).GetBytes(utf8Text); } /// /// 将 UTF-8 字节数组转换为 GBK 字节数组 /// public static byte[] Utf8BytesToGbkBytes(byte[] utf8Bytes) { if (utf8Bytes == null || utf8Bytes.Length == 0) return utf8Bytes; // 1. UTF-8 字节 → 字符串(Unicode) string text = Encoding.UTF8.GetString(utf8Bytes); // 2. 字符串 → GBK 字节 return Encoding.GetEncoding(936).GetBytes(text); } #endregion #region 验证设备响应数据包 private static readonly byte[] NakSignature = { 0x6E, 0x61, 0x6B, 0x00 }; // "nak" private static readonly byte[] AckSignature = { 0x61, 0x63, 0x6B, 0x00 }; // "ack" private static readonly byte[] AckcSignature = { 0x61, 0x63, 0x6B, 0x63, 0x00 }; // "ackc" /// /// NAK响应结果 /// /// usb hid 返回包 /// public static bool IsNakResponse(List buffer) => ContainsSubsequence(buffer.ToArray(), NakSignature); /// /// ACKC响应结果 /// /// usb hid 返回包 /// public static bool IsAckcResponse(List buffer) => ContainsSubsequence(buffer.ToArray(), AckcSignature); /// /// ACK响应结果 /// /// usb hid 返回包 /// public static bool IsReadyForDataFrameResponse(List buffer) => ContainsSubsequence(buffer.ToArray(), AckSignature); private static bool ContainsSubsequence(ReadOnlySpan buffer, ReadOnlySpan pattern) { if (buffer.Length != 195) return false; if (pattern.Length == 0) return false; if (buffer.Length < pattern.Length) return false; for (int i = 0; i <= buffer.Length - pattern.Length; i++) { if (buffer.Slice(i, pattern.Length).SequenceEqual(pattern)) return true; } return false; } #endregion #region 查询固件版本 /// /// 查询固件版本version query /// /// public static byte[] VersionQuery() { string str = "0100FF6765742076657200300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CC85"; byte[] content = new byte[str.Length / 2]; for (int i = 0; i < content.Length; i++) { content[i] = Convert.ToByte(str.Substring(i * 2, 2), 16); } return content; } #endregion } }