client.on(Event.X, handler) on AsyncClient or Client.
Event types
Register handlers
Init business mode
UseInit helpers to detect service vs vending business mode.
Documentation Index
Fetch the complete documentation index at: /docs/llms.txt
Use this file to discover all available pages before exploring further.
Handle payments, verification, device state, usage, metadata, and active sessions from Python
client.on(Event.X, handler) on AsyncClient or Client.
| Event | Payload | Description |
|---|---|---|
Event.PAYMENT | Payment | Payment updates |
Event.PAYMENT_PENDING | Payment | Payment is pending |
Event.PAYMENT_SUCCESS | Payment | Payment succeeded |
Event.INIT | Init | Initial device configuration, including business mode |
Event.DISPENSE | Dispense | Vending SKU list to dispense |
Event.MERCHANT_STATUS | str | Merchant status changed |
Event.VERIFICATION | Verification | Verification result |
Event.PIN | Verification | PIN displayed on device |
Event.DEVICE_STATUS | DeviceStatus | Device lifecycle change |
Event.ENTITY_COMMAND | EntityCommand | Entity command (all entities) |
Event.ACTIVE_SESSION | ActiveSession | Active paid session |
Event.USAGE | Usage | Usage / limit updates |
Event.METADATA_PENDING | str | Pending-payment metadata JSON |
Event.METADATA_EXPIRED | str | Expired-payment metadata JSON |
Event.METADATA_SUCCESS | str | Successful-payment metadata JSON |
Event.ERROR | Exception | Runtime error |
from firmngin import AsyncClient, ClientConfig, Event, Payment
config = ClientConfig.from_file("keys.json")
async with AsyncClient(config) as client:
@client.on(Event.PAYMENT)
async def handle_payment(payment: Payment) -> None:
if payment.is_success:
print("paid:", payment.order_id)
Init helpers to detect service vs vending business mode.
from firmngin import Event, Init
@client.on(Event.INIT)
def on_init(init: Init) -> None:
if init.is_vending_mode:
print("vending mode")
if init.is_service_mode:
print("service mode")
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)
client.off(Event.PAYMENT, handle_payment)
client.clear_handlers()
import json
@client.on(Event.METADATA_PENDING)
def on_pending(raw_json: str) -> None:
data = json.loads(raw_json)
from firmngin import Event, Usage
@client.on(Event.USAGE)
def on_usage(usage: Usage) -> None:
print(usage.used, usage.limit, usage.near_limit, usage.limit_exceeded)
from firmngin import Entity, EntityCommand
@client.on_entity(Entity("relay"))
def handle_relay(command: EntityCommand) -> None:
print(command.value)
@client.on(Event.ACTIVE_SESSION)
async def handle_session(session: ActiveSession) -> None:
if session.can_run:
await session.end_session()
@client.on(Event.ERROR)
async def handle_error(error: Exception) -> None:
print("error:", error)