Firmngin Python SDK
Python SDK for Firmngin device clients, Raspberry Pi. Supports async and sync styles with mTLS, E2EE, entity state, payments, and optional image upload.
Docs: Introduction — Python SDK menu on firmngin.dev/docs
Install
pip install firmngin
Image upload (optional):
pip install firmngin[http]
From Git:
pip install git+https://github.com/firmngin/firmngin-sdk-python.git
Client vs AsyncClient
There are two client classes: Client (sync, blocking) and AsyncClient (async, non-blocking). Both support the same events and payloads. Use AsyncClient in an async context with await client.connect() and await client.run(). Use Client in a sync context with client.connect() and client.run().
Both use ClientConfig.from_file("keys.json") and support the same events.
Quickstart
from firmngin import Client, ClientConfig, Entity, EntityCommand
relay = Entity("relay")
temperature = Entity("temperature")
with Client(ClientConfig.from_file("keys.json")) as client:
@client.on_entity(relay)
def handle_relay(command: EntityCommand) -> None:
print("relay:", command.value)
client.connect()
client.push_entity(temperature, 27.5)
client.run()
Debug mode
Debug is off by default — no banner or console output.
client.set_debug(True)
client.connect()
With debug enabled, connect() prints the Firmngin banner, connection details, and connect/disconnect messages.
Events
Register handlers with client.on(Event.X, handler):
| Event | Payload | Description |
|---|---|---|
Event.PAYMENT |
Payment |
Payment updates |
Event.PAYMENT_PENDING |
Payment |
Payment pending |
Event.PAYMENT_SUCCESS |
Payment |
Payment succeeded |
Event.POSTPAID_READY |
Payment |
Postpaid order ready |
Event.INIT |
Init |
Device init payload |
Event.DISPENSE |
Dispense |
Vending SKU list to dispense |
Event.MERCHANT_STATUS |
str |
Merchant status string |
Event.VERIFICATION |
Verification |
Verification result |
Event.PIN |
Verification |
PIN display |
Event.DEVICE_STATUS |
DeviceStatus |
Device lifecycle |
Event.ENTITY_COMMAND |
EntityCommand |
Any entity command |
Event.ACTIVE_SESSION |
ActiveSession |
Active paid session |
Event.METADATA_PENDING |
str |
Pending-payment metadata JSON |
Event.METADATA_ACTIVE_SERVICE |
str |
Active-service metadata JSON |
Event.METADATA_EXPIRED |
str |
Expired-payment metadata JSON |
Event.METADATA_SUCCESS |
str |
Successful-payment metadata JSON |
Event.METADATA_POSTPAID_READY |
str |
Postpaid-ready metadata JSON |
Event.ERROR |
Exception |
Runtime error |
Metadata events pass the decrypted payload as a JSON string — parse it in your handler.
Event.POSTPAID_READY uses the same Payment fields as pending and successful
payments: item title, price, order ID, and quantity (always 1 for postpaid).
When the catalog item has postpaid-ready metadata, it is delivered separately
through Event.METADATA_POSTPAID_READY.
Every Payment also exposes mutually exclusive payment-type booleans:
is_post_paid / is_pre_paid. These flags are separate from
is_pending and is_success.
Init business mode
Use is_service_mode / is_vending_mode to detect business mode:
@client.on(Event.INIT)
def on_init(init: Init) -> None:
if init.is_vending_mode:
print("vending mode")
Vending dispense
When business mode is vending, a paid order delivers catalog SKUs to dispense.
Handle with Event.DISPENSE / Dispense:
from firmngin import Dispense, Event
@client.on(Event.DISPENSE)
def on_dispense(dispense: Dispense) -> None:
if not dispense.is_valid:
return
for sku in dispense.skus:
print("dispense:", sku)
When the service enters on_active_service, optional catalog metadata is
delivered separately through Event.METADATA_ACTIVE_SERVICE. Like the other
metadata events, the payload remains a decrypted raw JSON string.
import json
@client.on(Event.METADATA_PENDING)
def on_metadata(raw_json: str) -> None:
data = json.loads(raw_json)
Per-entity commands:
@client.on_entity(Entity("relay"))
def on_relay(command: EntityCommand) -> None:
print(command.value)
API overview
| Import | Role |
|---|---|
AsyncClient |
Async device client |
Client |
Sync blocking client |
ClientConfig |
Runtime settings |
KeysConfig |
keys.json loader |
Event |
Event names for client.on(...) |
Entity, Payment, Init, Dispense, … |
Typed payloads |
Device keys
Download keys.json from the Firmngin dashboard. The SDK accepts dashboard fields including server_fingerprint_bytes (20-byte Arduino-style fingerprint) and picks the right TLS validation mode automatically.
The generated service_ca_cert is the trust anchor for HTTPS device services at
ota.firmngin.dev, including image upload. MQTT continues to use ca_cert
independently.
Never commit real keys. See keys.json.example.
For a local development broker, add these fields to keys.json:
{
"firmngin_broker_addr": "192.168.100.31",
"firmngin_broker_port": 1883,
"firmngin_no_tls": true,
"firmngin_api_base_url": "http://192.168.100.31:8080/api/v1",
"firmngin_ota_base_url": "http://192.168.100.31:8080/api/v1/ota"
}
The broker fields only change the MQTT connection. firmngin_no_tls sends MQTT
traffic without TLS and must only be used in a trusted development network.
firmngin_api_base_url configures HTTP device-service requests. The OTA URL is
reserved for OTA support and is not consumed by an OTA executor yet.
Image upload
pip install firmngin[http]
await client.upload_image(Entity("camera"), "snapshot.jpg")
Examples
See examples/.
License
MIT — see LICENSE.
Metadata
Release files for firmngin 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| firmngin-0.0.2.tar.gz | 34.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| firmngin-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 70.2 kB
Release files / firmngin-0.0.2.tar.gz
| Download URL | firmngin-0.0.2.tar.gz |
|---|---|
| Size | 34.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2f7198e83e80c0857ea69cd224606252e59fb1c386dbf7557e306b287b94a248
|
|
BLAKE2b-256 checksum How to use checksums |
41341637a0f732448be618a1228f69ddbf2283ac070b804c75170be03c0796f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.10
|
Release files / firmngin-0.0.2-py3-none-any.whl
| Download URL | firmngin-0.0.2-py3-none-any.whl |
|---|---|
| Size | 36.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0d342c59f31ff14425dd3ff411f9550594ad5374fb9b8c8779fc7be0e06cf8c6
|
|
BLAKE2b-256 checksum How to use checksums |
fbb141cb7208fc9d1f4643bba10825b86af9e15b771d4457160d9b9a795f6cad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.10
|