Docs / Contact / sdks/micropython/configuration

MicroPython Client Configuration

The MicroPython client is configured through a combination of the config.json file on the device and constructor parameters.

Config File

Create /config.json on the board's filesystem:

json

{
    "api_key": "your_entity_api_key",
    "wifi_ssid": "YourNetwork",
    "wifi_pw": "YourPassword",
    "app_url": "https://app.tendrl.com",
    "mqtt_ssl": true
}

The SDK also checks /lib/tendrl/config.json for built-in defaults. User config overrides built-in values.

Config File Fields

Field Type Default Description
api_key string "" Entity API key for authentication
wifi_ssid string "" WiFi network name
wifi_pw string "" WiFi password
app_url string "https://app.tendrl.com" Tendrl server URL
mqtt_host string Auto MQTT broker hostname (fetched from API if not set)
mqtt_port int Auto MQTT broker port
mqtt_ssl bool true Enable SSL/TLS for MQTT
app_entry string "main" Module a remote deployment imports to start your app (no .py). The device's standing default when a deployment doesn't set its own Entry; set once if your program isn't main.py (e.g. "app" runs /app/app.py).
serial_metrics bool false Emit the TDLMETRIC: serial line (every 10 s by default) that feeds the live-metrics rail while your app runs. Off by default because it prints from the client timer even during an over-serial transfer. The provisioning tools pause it around their own transfers (SDK ≥ 0.2.6), but turn it on for a dev board only; deployed devices report RAM/storage via the heartbeat regardless.
serial_metrics_interval int 10000 Cadence in milliseconds for the serial_metrics heap push (disk is refreshed at most every 15 s regardless). Raise it to cut serial noise, lower it for a snappier rail. Only applies when serial_metrics is on.

Constructor Parameters

python

client = Client(**kwargs)

Core

Parameter Type Default Description
mode str "sync" "sync" (hardware timer) or "async" (asyncio)
debug bool False Enable verbose debug logging
net str "wifi" Network type: "wifi" or "eth"

Callbacks

Parameter Type Default Description
callback function None Catch-all handler when no @client.on() route matches
state_callback function None Fallback handler when @client.on_state is not used

Inbound routing (@client.on())

Register handlers on the client instance after construction. Routes are checked in registration order; first match wins.

Decorator Description
@client.on(msg_type=...) Match a specific message type
@client.on(tag=...) Match a single tag
@client.on(tags=[...]) Match if message has any listed tag
@client.on(tags_all=[...]) Match if message has all listed tags
@client.on_default Catch-all when no route matches

Combine parameters for AND semantics (e.g. @client.on(msg_type="publish", tag="config-update")). See API Reference.

Use @client.on_state to receive remote state table updates; it pairs with REST state reads/writes. Polled at check_msg_rate on Python, Go, and JavaScript; pushed over MQTT on MicroPython.

Timing & Performance

Parameter Type Default Description
timer int 0 Hardware timer ID (0–3, or -1 for virtual)
freq int 3 Timer frequency in Hz
check_msg_rate int 5 Seconds between MQTT message checks
max_batch_size int 15 Maximum messages per batch

Storage

Parameter Type Default Description
client_db bool True Enable local BTree database
client_db_in_memory bool True In-memory database (faster) vs file-based (persists across reboots, best-effort - see durability)
client_db_max_records int None Optional hard cap on the client database (oldest-first eviction). None = unlimited
db_page_size int auto BTree page size in bytes; defaults to 1024 for the in-memory store, 4096 for a file-backed one
offline_storage bool True Queue messages when offline
offline_max_records int 1000 Hard cap on buffered offline messages; oldest are evicted first when exceeded, bounding flash use during outages. 0/None = unlimited (not recommended)
managed bool True Auto-manage database lifecycle

Health

Parameter Type Default Description
send_heartbeat bool True Send periodic memory heartbeats
watchdog int 0 Watchdog timeout in seconds (0 = disabled)

Async Mode

Parameter Type Default Description
event_loop asyncio.Loop None User-provided event loop (async mode only)

Memory Considerations

The client adapts to available RAM:

Flash footprint

SDK install size on flash (precompiled .mpy under /lib/tendrl; every install path ships .mpy, not .py source):

Package Flash
Minimal (MQTT core) ~55 KB
Files add-on +~6 KB
Full (+ MicroTetherDB) ~74 KB
OTA add-on (updater) +~5 KB
Streaming add-on +~8 KB

Use minimal for publish/subscribe only. Add the files package for HTTP file transfer. Use full when you need offline message queuing or the client database. Add the OTA package (updater) for remote app-code deployment; it's a standalone add-on, not bundled into Full. Streaming is a separate add-on for camera boards.

For boards with less than 300KB RAM, consider:

MQTT Connection Details

The client automatically discovers and configures all MQTT connection parameters from your API key: broker address, credentials, and the topics your entity publishes and subscribes to. You don't configure any of this manually; provide a valid API key and the SDK handles the connection for you.

Example Configurations

Basic Sensor (ESP32)

json

{
    "api_key": "your_key",
    "wifi_ssid": "HomeNetwork",
    "wifi_pw": "password123"
}
python

client = Client(debug=True, send_heartbeat=True)

Memory-Constrained (Pico W)

On the Pico W client_db=False is required, not just a memory optimization: stock rp2 firmware has no btree module, so MicroTetherDB cannot load at all. The client detects this and disables storage with a warning rather than failing, but setting it explicitly documents the intent.

Stock rp2 firmware also has no frozen umqtt. You don't need to do anything about that: every Tendrl install path checks whether the board's firmware provides an MQTT client and pushes the vendored umqtt only when it doesn't.

python

client = Client(
    debug=False,
    client_db=False,
    max_batch_size=5,
    send_heartbeat=False
)

Async with Streaming (OpenMV)

python

client = Client(
    mode="async",
    debug=True,
    send_heartbeat=True,
    offline_storage=True
)