Quickstart
The goal of this page: within about fifteen minutes, you connect an NRN reader and watch EPCs print to the console every time a tag enters the read zone. You need an NRN reader, a cable to your computer, and at least one RFID tag; if the hardware has not arrived yet, read integrating with your software first, since the code side can be built without a physical reader. Every example uses the public 1.0.0 API of the Nextwaves SDK.
Before you start
- Install the CP210x driver from the repository's
driver/folder if your reader uses the USB-to-UART bridge. - Identify the serial port:
/dev/ttyUSB0on Linux,/dev/tty.usbserial-*on macOS,COM3on Windows. - On Linux, add your account to the
dialoutgroup, or opening the port fails with a permission error. - Keep the default serial settings,
115200baud, 8 data bits, 1 stop bit, no parity, no flow control: the SDK already uses exactly these values, so change them only if your device's documentation says otherwise.
What a session looks like
Every example below, regardless of language, walks the same four steps:
See this frame once and every code sample below becomes instantly readable.
Python
pip install nrn-sdkimport logging
import time
from nrn import create_reader
reader = create_reader("/dev/ttyUSB0", baudrate=115200, log_level=logging.INFO)
reader.open()
try:
reader.Connect_Reader_And_Initialize()
print(reader.Query_Reader_Information())
print(reader.query_rfid_ability())
reader.configure_reader_power({1: 25}, persistence=False)
def on_tag(tag):
print(tag["epc"], tag["rssi"], tag["antenna_id"])
reader.start_inventory_with_mode(antenna_mask=[1], callback=on_tag)
time.sleep(5)
reader.stop_inventory()
finally:
reader.close()start_inventory_with_mode takes a list of antenna numbers counted from 1 and converts it into the antenna mask itself. It starts a background thread that receives data from the reader and calls on_tag for every tag read; stop_inventory stops that thread and tells the reader to stop.
TypeScript and Web Serial
npm install @nextwaves/nrn-sdkimport { createNRNReader, NRNWebSerial, type TagData } from "@nextwaves/nrn-sdk";
if (!NRNWebSerial.isSupported()) {
throw new Error("This browser does not support the Web Serial API");
}
const reader = createNRNReader({ baudrate: 115200 });
// connect() opens the browser's port picker; it must run inside a user gesture.
await reader.connect();
try {
console.log(await reader.queryReaderInformation());
await reader.startInventory([1], (tag: TagData) => {
console.log(tag.epc, tag.rssi, tag.antenna_id);
});
// The receive loop keeps invoking the callback until stopped.
} finally {
await reader.stopInventory();
await reader.disconnect();
}Web Serial needs a secure context, meaning HTTPS or localhost, a Chromium-based browser, and a user gesture such as a button click before the port picker opens. startInventory calls stopInventory first, so restarting an inventory is safe.
Go
go get github.com/Nextwaves-Industries/nextwaves-sdk/sdk/nation/go@v1.0.0package main
import (
"fmt"
nrn "github.com/Nextwaves-Industries/nextwaves-sdk/sdk/nation/go"
)
func main() {
reader, err := nrn.NewNRNReader("/dev/ttyUSB0", 115200)
if err != nil {
panic(err)
}
defer reader.Close()
if err := reader.ConnectAndInitialize(); err != nil {
panic(err)
}
info, err := reader.QueryReaderInformation()
if err != nil {
panic(err)
}
fmt.Println(info.SerialNumber, info.AppVersion)
if err := reader.StartInventory(nrn.BuildAntennaMask([]int{1}), func(tag nrn.TagData) {
fmt.Println(tag.EPC, tag.AntennaID)
}); err != nil {
panic(err)
}
_ = reader.StopInventory()
}For continuous inventory inside a long-running service, use the complete Go receive loop in the receive loop appendix, ready to copy into your project.
Rust
[dependencies]
nrn-sdk = "1.0.0"use nrn_sdk::NRNReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut reader = NRNReader::new("/dev/ttyUSB0", 115200)?;
reader.connect_and_initialize()?;
let info = reader.query_reader_information()?;
println!("{} {}", info.serial_number, info.app_version);
reader.start_inventory(0x0000_0001, |tag| println!("{}", tag.epc))?;
reader.stop_inventory()?;
Ok(())
}The complete Rust receive loop also lives in the receive loop appendix.
C++
include(FetchContent)
FetchContent_Declare(
nrn_sdk
GIT_REPOSITORY https://github.com/Nextwaves-Industries/nextwaves-sdk.git
GIT_TAG v1.0.0
SOURCE_SUBDIR sdk/nation/cpp
)
FetchContent_MakeAvailable(nrn_sdk)
target_link_libraries(your_target PRIVATE nrn-sdk)#include "nrn.hpp"
int main() {
nrn::NRNReader reader("/dev/ttyUSB0", 115200);
if (!reader.open()) {
return 1;
}
reader.connect_and_initialize();
auto info = reader.query_reader_information();
reader.start_inventory(0x00000001, [] (const nrn::TagData& tag) {
std::cout << tag.epc << std::endl;
});
std::this_thread::sleep_for(std::chrono::seconds(5));
reader.stop_inventory();
reader.close();
return 0;
}Requires C++17 and CMake 3.14 or later. The complete C++ receive loop lives in the receive loop appendix.
When you go to production, follow this order
The quickstart above deliberately skips steps so you see tags fast. A production integration walks all eight:
- Record the reader's model and firmware version, and keep the firmware documentation with the project.
- Open the serial port and initialize the connection.
- Query the reader's identity and abilities, and log both on every session.
- Configure the antenna mask, per-port power, RF band, and the channels legal at the site.
- Set the deduplication filter window from the business event, not the maximum read rate.
- Start the inventory and deduplicate EPCs over your own business window.
- Turn raw reads into business events that can be replayed safely.
- Stop the inventory, let the SDK drain what is pending, then close the serial port.
Read next
- Reading tags and deduplication: the complete read pipeline with three-layer deduplication.
- SDK reference: the full method list and parameters.
- Integrating with your software: grafting the tag event stream onto an ERP.

