Tutorial

Run the gateway
and accept an event.

This tutorial starts netbaiot-server, uploads one device event, then consumes it with netbaiot-client. Standard MQTT 3.1.1 clients work without the optional device SDK. MSRV 1.88.0. Protocol v1.

You will

  1. Start the development listeners on loopback
  2. POST a heartbeat and read HTTP 202
  3. Subscribe in a business client and ACK the delivery

1. Run the development server

Development listeners bind to loopback. HTTP 202 means EventAccepted. Set a 64-character NETBAIOT_ADMIN_SECRET before calling management APIs. Production configurations must specify a confirmed webhook or framed TCP/RPC business sink.

cargo run -p netbaiot-server -- configs/development.json

2. Upload a device event

Device bearer format is credential_id:secret. The JSON schema is DeviceUplink. Retry and restart replay can duplicate delivery; the business sink must deduplicate by event_id.

curl --noproxy '*' -i http://127.0.0.1:8080/v1/device/data \
  -H 'Authorization: Bearer demo-device:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' \
  --data '{"schema_version":1,"source_message_id":"demo:1","kind":"heartbeat","data":{"sequence":1}}'

3. Consume events from a business client

AckMode defaults to Manual. ACK after application processing. One server-confirmed delivery is outstanding per subscription. Dropping an unacknowledged delivery closes the stream so the server may redeliver.

use futures_util::StreamExt;
use netbaiot_client::NetbaIoTClient;
use netbaiot_protocol::EventFilter;

let client = NetbaIoTClient::builder()
    .endpoint(endpoint)
    .token(token)
    .event_address(event_address)
    .connect()
    .await?;
let mut events = client.events().subscribe(EventFilter::default()).await?;
while let Some(delivery) = events.next().await {
    let delivery = delivery?;
    handle(delivery.event()).await?;
    delivery.ack().await?;
}

4. Optional device SDK

netbaiot-device-sdk is convenience, not a requirement. Standard MQTT 3.1.1 clients remain first-class. Disconnected publish is rejected; the SDK does not accumulate an offline RAM queue.

cargo check -p netbaiot-device-sdk --examples

5. Operator CLI

netbaiot is implemented only through netbaiot-client. Tokens are never printed. Drain requires --yes. Exit code 5 is device offline.

netbaiot server status
netbaiot events subscribe
netbaiot command send DEVICE --json JSON
netbaiot server drain --yes

Operating constraints

  • The runtime has no database, durable outbox, or persistent command state.
  • EventAccepted is not business persistence. Consumers must be idempotent on event_id.
  • Commands are not stored for offline devices.
  • Planned restart can spool required work; abrupt crash can lose in-memory accepted events.
  • MQTT 5, WebSockets, shared subscriptions, and $SYS are outside the current broker.

License

NetbaIoT is licensed under AGPL-3.0-or-later. If you modify the program and let users interact with it over a network, you must provide the corresponding source.