Giao thức đầu đọc NRN
Trang này mô tả wire protocol mà Nextwaves SDK triển khai. Bạn cần đến nó trong ba trường hợp: viết công cụ riêng, giải mã một bản capture, hoặc gỡ lỗi một đầu đọc trả về error notification. Khi tích hợp bình thường, SDK đã lo hết mọi thứ trên trang này.
Đây không phải đặc tả air interface giữa thẻ và đầu đọc. Với phần đó, xem bản hiện hành của chuẩn GS1 Gen2 UHF RFID. Với lệnh từ máy chủ tới đầu đọc, tài liệu firmware đi kèm đầu đọc mục tiêu là căn cứ cuối cùng.
Kết nối serial
| Thiết lập | Giá trị |
|---|---|
| Cổng vật lý | RS-232 hoặc CP210x USB-to-serial |
| Baud rate | 115200 |
| Data bit | 8 |
| Stop bit | 1 |
| Parity | Không |
| Flow control | Không |
Cấu trúc frame
5A | PCW(4) | [Address(1) khi dùng RS485] | Length(2, big-endian) | Data(N) | CRC16(2, big-endian)| Trường | Kích thước | Ý nghĩa |
|---|---|---|
| Header | 1 byte | Luôn là 0x5A |
| PCW | 4 byte | Protocol Control Word |
| Address | 1 byte | Chỉ xuất hiện khi flag RS485 được bật |
| Length | 2 byte | Độ dài payload, big-endian |
| Data | N byte | Payload theo từng lệnh |
| CRC16 | 2 byte | Checksum của mọi byte sau header, big-endian |
CRC bao phủ PCW, address tùy chọn, length và data. Nó không bao phủ byte header 0x5A.
Protocol Control Word
byte 0: protocol type 0x00
byte 1: protocol version 0x01
byte 2: flag và category bit 5 = RS485, bit 4 = notify, nibble thấp = category
byte 3: message id trong categoryCategory và message id ghép lại thành hằng số MID của SDK: category 0x02 với message id 0x10 là READ_EPC_TAG = 0x0210. Bit notify phân biệt notification do đầu đọc chủ động gửi với phản hồi cho lệnh của bạn, đó là lý do tag notification của category 0x02 có byte 2 bằng 0x12.
CRC16
Checksum là CRC16 với polynomial 0x1021 và giá trị khởi tạo 0x0000, tính trên mọi byte sau header và truyền theo big-endian.
def crc16(data: bytes) -> int:
crc = 0
for byte in data:
crc ^= byte << 8
for _ in range(8):
crc = ((crc << 1) ^ 0x1021) & 0xFFFF if crc & 0x8000 else (crc << 1) & 0xFFFF
return crcMỗi khi đổi bất kỳ byte nào trong frame thì phải tính lại checksum. Không được chép checksum của frame mẫu sang một frame đã sửa.
Ví dụ giải mã
Lệnh READ_EPC_TAG trên ăng-ten 1, chế độ liên tục, do bản Python dựng:
5A 0001 0210 0005 00000001 01 F487
│ │ │ │ │ │ └─ CRC16 của 0001021000050000000101
│ │ │ │ │ └──── flag liên tục: 0x01
│ │ │ │ └───────────── antenna mask: ăng-ten 1
│ │ │ └────────────────── độ dài payload: 5
│ │ └─────────────────────── category 0x02, message id 0x10
│ └──────────────────────────── protocol type 0x00, version 0x01
└─────────────────────────────── headerMột tag notification trong cùng phiên:
5A 0001 1210 0016 0008 3000112233445566 3000 01 01 80 08 000E0BD4 09 40 B44F
│ │ │ │ │ └ RSSI └ tần số └ phase
│ │ │ │ └─ cổng ăng-ten 1
│ │ │ └────── PC word 0x3000
│ │ └─────────────────────── EPC, 8 byte
│ └──────────────────────────── độ dài EPC: 8
└────────────────────────────────────── bit notify bật, category 0x02, id 0x10Các tham số tùy chọn giải mã thành RSSI 0x80 = 128 thô = -65 dBm, tần số 0x000E0BD4 = 920532 kHz = 920,532 MHz, và phase 0x40 = 64 thô, được SDK báo lại là 64 / 128 × 2π = 3,1416 radian.
Payload của tag notification
Độ dài EPC: 2 byte, big-endian
Dữ liệu EPC: N byte
PC: 2 byte
Antenna ID: 1 byte
Tham số tùy chọn, mỗi tham số mở đầu bằng một byte PID:
0x01 RSSI 1 byte, thô 0-255
0x02 Kết quả đọc 1 byte
0x03 TID 2 byte độ dài rồi tới dữ liệu
0x04 Vùng dữ liệu thẻ 2 byte độ dài rồi tới dữ liệu
0x05 Vùng reserved 2 byte độ dài rồi tới dữ liệu
0x06 Sub-antenna 1 byte
0x07 Thời gian UTC 8 byte
0x08 Tần số 4 byte, kHz, big-endian
0x09 Phase 1 byte, thô 0-128SDK quy đổi RSSI sang dBm, tần số sang MHz và phase sang radian trước khi tới callback của bạn. Cấu trúc tag của 1.0.0 mang các parameter kể trên; các parameter 0x02 và 0x04 tới 0x07 sẽ được bổ sung ở bản sau, và công cụ tự viết muốn dùng chúng thì parse trực tiếp từ payload theo bảng này.
Message id
| Hằng số | Giá trị | Mục đích |
|---|---|---|
QUERY_INFO | 0x0100 | Serial number, firmware, thời gian chạy |
QUERY_RFID_ABILITY | 0x1000 | Dải công suất, số ăng-ten, danh sách tần số và protocol |
READ_EPC_TAG | 0x0210 | Bắt đầu kiểm kê EPC |
WRITE_EPC_TAG | 0x0211 | Ghi EPC bank |
PHASE_INVENTORY | 0x0214 | Kiểm kê có báo phase |
STOP_INVENTORY | 0x02FF | Dừng kiểm kê |
CONFIGURE_READER_POWER | 0x0201 | Đặt công suất phát từng ăng-ten |
QUERY_READER_POWER | 0x0202 | Đọc công suất phát từng ăng-ten |
SET_RF_BAND | 0x0203 | Đặt band theo vùng |
QUERY_RF_BAND | 0x0204 | Đọc band theo vùng |
SET_WORKING_FREQUENCY | 0x0205 | Đặt danh sách kênh làm việc |
QUERY_WORKING_FREQUENCY | 0x0206 | Đọc danh sách kênh làm việc |
SET_FILTER_SETTINGS | 0x0209 | Cửa sổ chống trùng và ngưỡng RSSI phía đầu đọc |
QUERY_FILTER_SETTINGS | 0x020A | Đọc thiết lập filter |
CONFIG_BASEBAND | 0x020B | Session, Q, inventory flag, profile |
QUERY_BASEBAND | 0x020C | Đọc cấu hình baseband |
READER_POWER_CALIBRATION | 0x0103 | Hiệu chuẩn công suất |
CONFIGURE_GPO | 0x0109 | Đặt trạng thái một cổng output |
QUERY_GPI | 0x010A | Đọc một cổng input |
CONFIGURE_GPI_TRIGGER | 0x010B | Cấu hình trigger từ input |
BUZZER_SWITCH | 0x011E | Điều khiển còi |
READ_END | 0x1231 | Kiểm kê đã kết thúc |
ERROR_NOTIFICATION | 0x00 | Lỗi do đầu đọc chủ động báo |
Lưu ý kỹ thuật khi tự dựng lệnh: CONFIGURE_ANTENNA_ENABLE (0x0203) và QUERY_ANTENNA_ENABLE (0x0202) mang cùng giá trị số với các hằng số RF band và công suất, nên phân biệt lệnh bằng payload bạn gửi kèm, đừng dựa vào tên hằng số.
Ăng-ten
Tối đa 32 cổng được địa chỉ hóa bằng bitmask 32-bit, ăng-ten n ở bit n - 1, truyền theo big-endian:
00 00 00 01 -> ăng-ten 1
00 00 00 03 -> ăng-ten 1 và 2
00 00 00 0F -> ăng-ten 1 tới 4
80 00 00 49 -> ăng-ten 1, 4, 7 và 32Đầu đọc quét tuần tự các cổng đã bật và báo lại cổng trong mọi tag notification. Giữ antenna_id xuyên suốt: đó là cách biết mỗi lần đọc đến từ khu vực vật lý nào.
Công suất và RSSI
query_rfid_ability trả về mức công suất tối thiểu và tối đa của chính đầu đọc, tính bằng dBm, cùng số ăng-ten. Cấu hình trong dải đó; SDK không tự giới hạn.
RSSI thô quy đổi sang dBm theo công thức:
dBm = -100 + round((thô × 70) / 255)| Thô | dBm |
|---|---|
| 0 | -100 |
| 64 | -82 |
| 128 | -65 |
| 200 | -45 |
| 255 | -30 |
Công thức quy đổi này gắn với từng model đầu đọc; trước khi áp cho model khác, kiểm chứng lại với firmware của model đó.
Tần số
tần số MHz = 920,0 + chỉ số kênh × 0,5Tag notification báo tần số bằng kHz trong một giá trị 32-bit, SDK quy đổi sang MHz. Chỉ cấu hình những kênh và mức công suất được phép theo chứng nhận thiết bị và quy định hiện hành tại nơi lắp đặt.
Thứ tự lệnh khuyến nghị
- Mở serial port và gửi handshake connect and initialize.
QUERY_INFOlấy danh tính,QUERY_RFID_ABILITYlấy năng lực.- Đặt antenna mask và công suất từng cổng.
- Đặt band và danh sách kênh đã kiểm chứng cho vùng lắp đặt.
- Đặt cửa sổ filter.
- Gửi
READ_EPC_TAG. - Đệm byte nhận được, tách frame theo header
0x5A, kiểm tra CRC và parse notification. - Gửi
STOP_INVENTORY, xử lý hết frame còn chờ, rồi đóng port.
Byte từ serial port không tới theo đúng ranh giới frame. Luôn đệm và quét lại: extract_valid_frames trong bản Python làm việc này, và receive loop tự viết cũng phải làm như vậy.
Vùng nhớ EPC Gen2
| Bank | ID | Nội dung điển hình |
|---|---|---|
| Reserved | 00 | Kill password 32-bit và access password 32-bit |
| EPC | 01 | Định danh 96-bit hoặc dài hơn |
| TID | 10 | Danh tính chip và nhà sản xuất, chỉ đọc |
| User | 11 | Vùng nhớ ứng dụng, tùy chip |
Ghi thẻ ở tầng này đòi bốn thứ, thiếu một là rủi ro: singulation để chắc chắn chỉ một thẻ trong vùng, access password khi thẻ bị lock, đọc lại sau mỗi lần ghi, và lớp bảo vệ quanh lệnh kill vì nó không hoàn tác được. Các khái niệm này giải nghĩa ở trang thuật ngữ.
Tiện ích frame trong SDK
Mỗi package có sẵn các hàm tầng frame để bạn viết công cụ riêng, nạp file capture hoặc tự chạy receive loop, khỏi phải chép lại phần dựng và mổ frame:
| Tiện ích | Python | TypeScript | Go | Rust | C++ |
|---|---|---|---|---|---|
| Dựng frame | build_frame | NRNUtils.buildFrame | BuildFrame | build_frame | build_frame |
| Parse frame | parse_frame | NRNUtils.parseFrame | ParseFrame | parse_frame | parse_frame |
| Tách luồng byte thành frame | extract_valid_frames | NRNUtils.extractValidFrames | theo mẫu ở phụ lục receive loop | theo mẫu ở phụ lục receive loop | theo mẫu ở phụ lục receive loop |
| Parse tag notification | parse_epc | nội bộ | ParseEPC | parse_epc | parse_epc |
| CRC16 | crc16_ccitt | NRNUtils.crc16CCITT | CRC16CCITT | crc16_ccitt | crc16_ccitt |
| RSSI thô sang dBm | calculate_rssi | NRNUtils.calculateRSSI | CalculateRSSI | calculate_rssi | calculate_rssi |
| Chỉ số kênh sang MHz | calculate_frequency | NRNUtils.calculateFrequency | CalculateFrequency | calculate_frequency | calculate_frequency |
parse_frame kiểm tra CRC và báo lỗi hoặc trả về không hợp lệ khi checksum sai, nên dùng nó thay vì tự so CRC.
Vector kiểm thử
Repository có sẵn fixture dùng chung trong sdk/nation/testdata/:
frames/chứa frame request, response và notification dạng hex cho cả hai họ CRC.crc_vectors.jsonchứa đầu vào CRC và giá trị mong đợi cho cả hai polynomial, kèm tham chiếu CCITT-FALSE.rssi_vectors.jsonchứa cặp giá trị thô và dBm.antenna_masks.jsonchứa cặp danh sách ăng-ten và mask.
Hãy chạy parser của bạn qua các fixture này trước khi đấu vào đầu đọc thật.

