Chuyển đến nội dung

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ậpGiá trị
Cổng vật lýRS-232 hoặc CP210x USB-to-serial
Baud rate115200
Data bit8
Stop bit1
ParityKhông
Flow controlKhông

Cấu trúc frame

text
5A | PCW(4) | [Address(1) khi dùng RS485] | Length(2, big-endian) | Data(N) | CRC16(2, big-endian)
TrườngKích thướcÝ nghĩa
Header1 byteLuôn là 0x5A
PCW4 byteProtocol Control Word
Address1 byteChỉ xuất hiện khi flag RS485 được bật
Length2 byteĐộ dài payload, big-endian
DataN bytePayload theo từng lệnh
CRC162 byteChecksum 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

text
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 category

Category và message id ghép lại thành hằng số MID của SDK: category 0x02 với message id 0x10READ_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.

python
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 crc

Mỗ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:

text
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
└─────────────────────────────── header

Một tag notification trong cùng phiên:

text
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 0x10

Cá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

text
Độ 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-128

SDK 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 0x020x04 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_INFO0x0100Serial number, firmware, thời gian chạy
QUERY_RFID_ABILITY0x1000Dải công suất, số ăng-ten, danh sách tần số và protocol
READ_EPC_TAG0x0210Bắt đầu kiểm kê EPC
WRITE_EPC_TAG0x0211Ghi EPC bank
PHASE_INVENTORY0x0214Kiểm kê có báo phase
STOP_INVENTORY0x02FFDừng kiểm kê
CONFIGURE_READER_POWER0x0201Đặt công suất phát từng ăng-ten
QUERY_READER_POWER0x0202Đọc công suất phát từng ăng-ten
SET_RF_BAND0x0203Đặt band theo vùng
QUERY_RF_BAND0x0204Đọc band theo vùng
SET_WORKING_FREQUENCY0x0205Đặt danh sách kênh làm việc
QUERY_WORKING_FREQUENCY0x0206Đọc danh sách kênh làm việc
SET_FILTER_SETTINGS0x0209Cửa sổ chống trùng và ngưỡng RSSI phía đầu đọc
QUERY_FILTER_SETTINGS0x020AĐọc thiết lập filter
CONFIG_BASEBAND0x020BSession, Q, inventory flag, profile
QUERY_BASEBAND0x020CĐọc cấu hình baseband
READER_POWER_CALIBRATION0x0103Hiệu chuẩn công suất
CONFIGURE_GPO0x0109Đặt trạng thái một cổng output
QUERY_GPI0x010AĐọc một cổng input
CONFIGURE_GPI_TRIGGER0x010BCấu hình trigger từ input
BUZZER_SWITCH0x011EĐiều khiển còi
READ_END0x1231Kiểm kê đã kết thúc
ERROR_NOTIFICATION0x00Lỗ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:

text
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:

text
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ố

text
tần số MHz = 920,0 + chỉ số kênh × 0,5

Tag 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ị

  1. Mở serial port và gửi handshake connect and initialize.
  2. QUERY_INFO lấy danh tính, QUERY_RFID_ABILITY lấy năng lực.
  3. Đặt antenna mask và công suất từng cổng.
  4. Đặt band và danh sách kênh đã kiểm chứng cho vùng lắp đặt.
  5. Đặt cửa sổ filter.
  6. Gửi READ_EPC_TAG.
  7. Đệm byte nhận được, tách frame theo header 0x5A, kiểm tra CRC và parse notification.
  8. 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

BankIDNội dung điển hình
Reserved00Kill password 32-bit và access password 32-bit
EPC01Định danh 96-bit hoặc dài hơn
TID10Danh tính chip và nhà sản xuất, chỉ đọc
User11Vù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 íchPythonTypeScriptGoRustC++
Dựng framebuild_frameNRNUtils.buildFrameBuildFramebuild_framebuild_frame
Parse frameparse_frameNRNUtils.parseFrameParseFrameparse_frameparse_frame
Tách luồng byte thành frameextract_valid_framesNRNUtils.extractValidFramestheo mẫu ở phụ lục receive looptheo mẫu ở phụ lục receive looptheo mẫu ở phụ lục receive loop
Parse tag notificationparse_epcnội bộParseEPCparse_epcparse_epc
CRC16crc16_ccittNRNUtils.crc16CCITTCRC16CCITTcrc16_ccittcrc16_ccitt
RSSI thô sang dBmcalculate_rssiNRNUtils.calculateRSSICalculateRSSIcalculate_rssicalculate_rssi
Chỉ số kênh sang MHzcalculate_frequencyNRNUtils.calculateFrequencyCalculateFrequencycalculate_frequencycalculate_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.json chứa đầu vào CRC và giá trị mong đợi cho cả hai polynomial, kèm tham chiếu CCITT-FALSE.
  • rssi_vectors.json chứa cặp giá trị thô và dBm.
  • antenna_masks.json chứ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.

Tài liệu vận hành Easy Inventory và tích hợp RFID