Skip to content

CoAP Client Guide

This guide covers how to connect constrained IoT devices to the N-Hub platform using CoAP (Constrained Application Protocol).

Supported Authentication

Method Transport Status Use case
DTLS PSK UDP (port 5684) Implemented Production — constrained sensors, smart meters
Plain (none) UDP (port 5683) Implemented, disabled in prod Dev/test only

PSK (Pre-Shared Key) is the recommended authentication method. It is the industry standard for utility IoT deployments per DLMS/COSEM, Wi-SUN FAN, and OneM2M specifications.

Certificate-based DTLS (X.509 over UDP) is not supported — aiocoap's TinyDTLS backend only supports PSK for DTLS. This is not a limitation in practice: PSK is the standard for constrained device authentication.

CoAP over TCP/TLS (RFC 8323) is not supported. The platform serves CoAP over UDP only. If a gateway deployment requires CoAP/TCP (e.g. to traverse enterprise firewalls that block UDP), contact your N-Hub representative — it would need to be provisioned on a separate load balancer.

Connection Options

URI Scheme Port Transport Security Auth Status
coaps:// 5684 UDP + DTLS DTLS 1.2 PSK (DeviceCredential lookup) Implemented (recommended)
coap:// 5683 UDP None None (placeholder ID from IP) Implemented, disabled in prod

Server hostname: coap.<environment>.nnnco.io

Example: coaps://coap.dev-au-03.nnnco.io:5684/telemetry

Important: Plain CoAP (port 5683) is disabled by default in production. Use DTLS PSK for production deployments.

Device Provisioning

Step 1: Create the device in N-Hub

Create the device in the N-Hub portal with its model, serial/IMEI, and SIM details.

Step 2: Generate PSK credentials

Generate a pre-shared key credential via the API:

POST /api/v4/manage/devices/{device_id}/credentials/
Content-Type: application/json

{
    "auth_type": "psk"
}

Response:

{
    "id": "uuid",
    "auth_type": "psk",
    "psk_identity": "koru-869181072798893",
    "psk_key": "<random-32-byte-hex>",
    "server": "coaps://coap.dev-au-03.nnnco.io:5684",
    "status": "active"
}

The PSK key is shown only once. Save it and configure it on the device.

Note: PSK over DTLS is the only supported production auth method. Certificate-based DTLS (X.509 over UDP) is not supported by the underlying DTLS library (TinyDTLS).

Step 3: Configure the device

Enter the PSK credentials into the device's DTLS configuration: - PSK identity: The psk_identity value from the credential response (e.g., koru-869181072798893) - PSK key: The psk_key hex string from the credential response

Step 4: Power on

The device connects to the CoAP server and starts sending telemetry. It will appear as "online" in the N-Hub portal when the first message arrives.

Sending Telemetry

Devices push sensor data to the /telemetry resource using POST.

URI format

POST coaps://coap.<env>.nnnco.io:5684/telemetry?id=<device_id>

The id query parameter identifies the device. For DTLS-authenticated connections, the server also verifies identity from the DTLS handshake.

Content formats

Set the Content-Format CoAP option to indicate the payload format:

Content-Format ID Description
application/json 50 JSON payload
application/cbor 60 CBOR-encoded payload
application/octet-stream 42 Raw binary

Example: JSON telemetry

echo '{"temperature": 23.5, "humidity": 45.2}' | \
  aiocoap-client coap://coap.dev-au-03.nnnco.io:5683/telemetry?id=test-001 \
    -m POST --content-format application/json

Example: CBOR telemetry

# Using python-cbor2 to encode, then aiocoap-client to send
python3 -c "import cbor2,sys; sys.stdout.buffer.write(cbor2.dumps({'temperature':23.5}))" | \
  aiocoap-client coap://coap.dev-au-03.nnnco.io:5683/telemetry?id=test-001 \
    -m POST --content-format application/cbor --payload -

Block1 (large payloads)

For payloads larger than ~1KB, CoAP automatically uses Block1 transfer. The client library handles chunking — no special configuration needed.

Response codes

Code Meaning
2.01 Created Telemetry published successfully
4.00 Bad Request Missing device_id or malformed payload
4.01 Unauthorized DTLS required but plain CoAP used (production)
5.03 Service Unavailable Backend (NATS) is temporarily unavailable

Receiving Commands (Observe)

Devices subscribe to downlink commands using CoAP Observe on the /commands/{device_id} resource.

Register for notifications

aiocoap-client coaps://coap.dev-au-03.nnnco.io:5684/commands/my-device-001 \
  --observe

The device receives a 2.05 Content response whenever a command is published for it. The connection stays open and the server pushes notifications as they arrive.

Cancel observation

Send a GET without the Observe option, or reset the connection.

Firmware Download

Devices download firmware using GET on the /firmware/{version} resource. Block2 transfer handles chunking automatically.

aiocoap-client coaps://coap.dev-au-03.nnnco.io:5684/firmware/v2.1.0 \
  -o firmware-v2.1.0.bin

Response codes

Code Meaning
2.05 Content Firmware chunk (Block2 transfer)
4.04 Not Found Firmware version does not exist

Testing with CLI Tools

aiocoap-client (Python)

pip install aiocoap
# Plain CoAP test
aiocoap-client coap://coap.dev-au-03.nnnco.io:5683/telemetry?id=test-001 \
  -m POST --content-format application/json \
  --payload '{"temperature": 23.5}'

coap-client (libcoap, C)

# Plain CoAP
coap-client -m post \
  -t application/json \
  -e '{"temperature": 23.5}' \
  "coap://coap.dev-au-03.nnnco.io:5683/telemetry?id=test-001"

# DTLS with PSK
coap-client -m post \
  -t application/json \
  -e '{"temperature": 23.5}' \
  -u "koru-869181072798893" \
  -k "<psk-key-hex>" \
  "coaps://coap.dev-au-03.nnnco.io:5684/telemetry?id=869181072798893"

Revoking Credentials

To revoke a device's credentials:

POST /api/v4/manage/devices/{device_id}/credentials/{credential_id}/revoke/

The device will be rejected on the next DTLS handshake after the credential cache expires (default: 5 minutes).