RelayX Device SDK for Python — IoT device communication over NATS
Project description
RelayX Device SDK for Python
Official Python SDK for connecting IoT devices to the RelayX platform.
Installation
pip install relayx_device_sdk
Quick Start
import asyncio
from relayx_device_sdk import RelayDevice
device = RelayDevice({
"api_key": "<YOUR_API_KEY>",
"secret": "<YOUR_SECRET>",
"mode": "production", # or "test"
})
async def main():
await device.connect()
# Publish telemetry
await device.telemetry.publish("temperature", 22.5)
# Emit logs (batched to backend, mirrored to console)
device.log.info("device booted")
device.log.warn("disk usage at", 87, "%")
# Listen for RPC calls
async def on_reboot(req):
print("Reboot requested:", req.payload)
await req.respond({"status": "rebooting"})
await device.rpc.listen("reboot", on_reboot)
# Listen for commands
def on_firmware_update(msg):
print("Firmware update:", msg.payload)
await device.command.listen("firmware_update", on_firmware_update)
# Disconnect when done
await device.disconnect()
asyncio.run(main())
Configuration
device = RelayDevice({
"api_key": "<YOUR_API_KEY>", # JWT issued by RelayX
"secret": "<YOUR_SECRET>", # NKEY seed
"mode": "production", # "production" | "test"
})
Functionality
Connection
await device.connect() # returns True on success, False if already connected or failed
await device.disconnect() # drains NATS connection, cleans up consumers
# Listen for connection status changes
device.connection.listeners(lambda event: print("Status:", event["type"]))
# event["type"]: "connected" | "disconnected" | "reconnecting" | "reconnected" | "auth_failed"
Telemetry
Fire-and-forget sensor data publishing. Readings are validated against the device schema fetched on connect.
await device.telemetry.publish("temperature", 22.5) # number
await device.telemetry.publish("status", "online") # string
await device.telemetry.publish("active", True) # boolean
await device.telemetry.publish("metadata", {"fw": "1.2"}) # json
Each message is published with a server-synced timestamp.
Schema validation: On connect, the SDK fetches the device schema from the server. If a schema exists, publish() will throw a ValidationError if the metric name is not in the schema or the reading type does not match.
Remote Procedure Calls (RPC)
Register handlers for incoming RPC calls.
# Register a handler
async def on_get_status(req):
print("Payload:", req.payload)
# Respond with success
await req.respond({"uptime": 12345})
# Or respond with error
# await req.error({"code": "UNAVAILABLE", "message": "Device busy"})
await device.rpc.listen("get_status", on_get_status)
# Unregister
await device.rpc.off("get_status")
Duplicate listeners for the same name throw DuplicateListenerError.
Commands
One-way commands delivered for long running tasks that do not require a status update.
def on_firmware_update(msg):
print("Command:", msg.payload)
# Process based on data...
await device.command.listen("firmware_update", on_firmware_update)
await device.command.off("firmware_update")
Config
Get and set device configuration
# Fetch current config
config = await device.config.get()
print(config)
# Update config
success = await device.config.set({"interval": 10000, "name": "sensor-1"})
Events
Fire-and-forget event publishing of events (fault codes, etc).
await device.event.send("door_opened", {"door_id": "front", "timestamp": device.time.now()})
Logs
Structured device logging with three levels (info, warn, error). Each
call accepts a variadic argument list — strings, numbers, booleans, plain
dicts, lists, datetimes, None, and exception instances are all accepted;
callables and other non-serializable values raise ValidationError.
device.log.info("hello world")
device.log.info("a number reading", 42)
device.log.warn("careful — disk usage at 87%")
device.log.error("parse failed", ValueError("bad json"))
device.log.info("an object", {"port": 8080, "retries": 3})
Locally, each call also mirrors to Python's standard logging module
(at INFO/WARNING/ERROR) so you keep your normal dev experience.
Batching. Entries are buffered in memory and flushed to the backend either
when 15 entries accumulate or after 5 seconds, whichever comes first.
disconnect() flushes any pending buffer.
Time
NTP-synchronized clock. Syncs with time.google.com on connect and every 3 hours. Auto-resyncs on reconnect if stale.
# Initialize (called automatically on connect)
await device.time.init()
# Get current server-corrected timestamp (ms)
now = device.time.now()
# Convert SDK timestamp to datetime
dt = device.time.to_date(now)
# Convert datetime to SDK timestamp
ts = device.time.to_timestamp(datetime.now())
# Set timezone for display
device.time.set_timezone("America/New_York")
Error Handling
The SDK exports four error types:
from relayx_device_sdk import (
NotConnectedError, # Operation attempted while disconnected
DuplicateListenerError, # rpc.listen() or command.listen() called twice for same name
ValidationError, # Invalid arguments or schema mismatch
TimeoutError, # Request/reply timed out
)
Offline Behavior
- Telemetry & Events (
publish): Messages are buffered in memory while disconnected and flushed automatically on reconnect. - Logs (
device.log.*): Entries are buffered and flushed on the same 15-entry / 5-second policy. Any buffer left atdisconnect()is flushed before the connection drains. - RPC & Commands (
listen): ThrowNotConnectedErrorif transport is disconnected. - Config (
get/set): ThrowNotConnectedErrorif transport is disconnected.
Testing
pytest
The SDK is designed for full unit testability. All subsystems accept a transport dependency that can be mocked:
from relayx_device_sdk import RelayDevice
mock_transport = ... # mock methods
device = RelayDevice._create_for_test(
{"api_key": "test", "secret": "test", "mode": "test"},
mock_transport,
)
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file relayx_device_sdk-0.1.1.tar.gz.
File metadata
- Download URL: relayx_device_sdk-0.1.1.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64cc99bed7c68b543ce88ee3ce520de83227edebebede47d38714df8eb4644d8
|
|
| MD5 |
0f6edb468d6a5b528ba04248ae1f7449
|
|
| BLAKE2b-256 |
67435b3234a8af2a32f1257bb0c0fc8d15f918bb68340508bb5252b8256e5480
|
File details
Details for the file relayx_device_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: relayx_device_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 21.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa7c9625f4705e8156d5d02147ae76e83e060c27ba3308cc60a7aeb8f73cd387
|
|
| MD5 |
316d5c182df3a5532337d6c75340f1b8
|
|
| BLAKE2b-256 |
fd9a9ae242cda9e480bbc8b4366657ed9e5f1517b74ddbab7910c6b4c8373d56
|