// 根据当前的所有元素,设置 Content parameter 元素内容 // parameters: // trim_right 是否要截掉右侧多余的连续 0?截掉是一般做法。而不截掉,也就是保留足够 byte 数,足以应对以后元素增多以后的局面,保证 content parameter 本身耗用的空间和以前一致,有利于芯片以后修改内容时的布局。 public void SetContentParameter(bool trim_right) { var content_parameter = this.FindElement(ElementOID.ContentParameter); if (content_parameter == null) content_parameter = this.NewElement(ElementOID.ContentParameter, null); UInt64 value = 0; foreach (Element element in this._elements) { int oid = (int)element.OID; if (oid >= 3) { // TODO: 测试 0x80000000 >> 0 会不会有问题 value |= 0x8000000000000000 >> (oid - 3); } } if (value == 0) { this.RemoveElement(ElementOID.ContentParameter); return; } var bytes = Compact.ReverseBytes(BitConverter.GetBytes(value)); if (trim_right) bytes = Compact.TrimRight(bytes); content_parameter.Content = bytes; content_parameter.Text = Element.GetHexString(content_parameter.Content); }
// 解析 Long Numeric String // 注意 start 位置的 byte 应该是 0xfb // parameters: // used_bytes 返回用掉的 bytes 数 public static string DecodeLongNumericString(byte[] data, int start, out int used_bytes) { used_bytes = 0; byte lead = data[start]; if (lead != 0xfb) { throw new ArgumentException("开始的第一个 byte 必须为 0xfb", $"{nameof(data)}, {nameof(start)}"); } byte second = data[start + 1]; // 解码后的数字应有的字符数 int decimal_length = ((second >> 4) & 0x0f) + 9; // 编码后的 bytes 数 int encoded_bytes = (second & 0x0f) + 4; if (encoded_bytes > 19) { throw new Exception($"Long Numeric String 的编码后 bytes 数({encoded_bytes})不合法,应小于等于 19"); } string result = ""; { byte[] bytes = new byte[encoded_bytes]; Array.Copy(data, start + 2, bytes, 0, encoded_bytes); result = Compact.IntegerExtract(bytes); } // 补齐前方的 '0' result.PadLeft(decimal_length, '0'); used_bytes = encoded_bytes + 2; return(result); }
// 编码范围在 'A'-'9' 内的三个字符为两个 bytes public static byte[] EncodeTriple(int c1, int c2, int c3) { List <byte> results = new List <byte>(); uint v = (1600 * (uint)c1) + (40 * (uint)c2) + (uint)c3 + 1; if (v > UInt16.MaxValue) { throw new Exception($"{v} 溢出 16 bit 整数范围"); } return(Compact.ReverseBytes(BitConverter.GetBytes((UInt16)v))); }
// 以 long numeric string 方式编码一个数字字符串 // 算法可参考: // https://www.ipc.be/~/media/documents/public/operations/rfid/ipc%20rfid%20standard%20for%20test%20letters.pdf?la=en public static byte[] EncodeLongNumericString(string text) { if (text.Length < 9) { throw new ArgumentException($"用于编码的数字字符串不应短于 9 字符(但现在是 {text.Length} 字符)"); } byte[] bytes = Compact.IntegerCompact(text); if (bytes.Length < 4) { throw new ArgumentException($"数字字符串编码后不应短于 4 bytes(但现在是 {bytes.Length} bytes)"); } byte second = (byte)((((text.Length - 9) << 4) & (byte)0xf0) | ((bytes.Length - 4) & 0x0f)); List <byte> results = new List <byte>(); results.Add(0xfb); results.Add(second); results.AddRange(bytes); return(results.ToArray()); }