hxtp-py (Python SDK)
The hxtp-py library lets Python scripts, automation tools, and AI services talk to Hestia Labs devices using HxTP/3.1.
Installationâ
pip install hxtp-py
Quick Startâ
import asyncio
from hxtp_py.client import HxTPClient
async def main():
client = HxTPClient(
url="https://api.hestialabs.in/api/v1",
tenant_id="your-tenant-id",
device_id="your-device-id",
private_key_hex="your-private-key-hex", # Ed25519 private key
client_id="my-app",
)
# Connects â sends HELLO â waits for HELLO_ACK â becomes ACTIVE
await client.connect()
response = await client.send_command({
"action": "set_level",
"params": {"brightness": 85},
})
print(f"Sent! Message ID: {response.message_id}")
await client.disconnect()
asyncio.run(main())
How It Worksâ
The Lifecycleâ
Every client goes through a simple introduction process:
IDLE â HELLO_SENT (sends "hello" with public key)
â ACTIVE (cloud replies "hello_ack")
â DISCONNECTED (connection drops)
- connect() sends a signed
HELLOmessage with your public key. - The cloud replies
HELLO_ACKâ now the client is ACTIVE. - You can only send commands and receive messages while ACTIVE.
- If the connection drops, the client reconnects and repeats the handshake.
Sending Commandsâ
response = await client.send_command({
"action": "toggle_led",
"params": {"brightness": 100},
})
Sending Other Message Typesâ
# Send telemetry data
await client.send_message("telemetry", {"temperature": 22.5})
# Send state update
await client.send_message("state", {"door": "open"})
Receiving Messagesâ
def on_message(event):
print(f"Received: {event.parsed}")
print(f"Action: {event.parsed.get('action')}")
client.on_message(on_message)
Client Configurationâ
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Server address. |
tenant_id | string | Yes | Your organization's ID. |
device_id | string | Yes | Your device's unique ID. |
private_key_hex | string | Yes | Your Ed25519 private key (64 hex chars). |
client_id | string | Yes | A unique name for this app instance. |
previous_private_key_hex | string | No | Previous private key (used during key rotation). |
transport | Transport | No | Transport layer (default: WebSocket). |
replay_protection | bool | No | Prevent replay attacks (default: True). |
Eventsâ
| Method | Payload | When it fires |
|---|---|---|
on_connect(cb) | None | Client becomes ACTIVE. |
on_disconnect(cb) | code, reason | Connection lost. |
on_message(cb) | HxTPMessageEvent | A verified message arrives. |
on_error(cb) | HxTPErrorEvent | Something went wrong. |
Sync Wrapperâ
For non-async code:
from hxtp_py.client import SyncHxTPClient
client = SyncHxTPClient(
url="https://api.hestialabs.in/api/v1",
tenant_id="your-tenant-id",
device_id="your-device-id",
private_key_hex="your-private-key-hex",
client_id="my-app",
)
client.connect()
response = client.send_command({"action": "toggle_led"})
client.disconnect()
Low-Level Protocol Usageâ
Build a Canonical Stringâ
from hxtp_py.core import build_canonical
canonical = build_canonical({
"version": "HxTP/3.1",
"device_id": "device-uuid",
"tenant_id": "tenant-uuid",
"client_id": "client-uuid",
"message_id": "msg-uuid",
"request_id": "req-uuid",
"sequence_number": 1,
"timestamp": 1708444800,
"nonce": "unique-nonce",
"message_type": "command",
"payload_hash": "sha256-of-params",
})
Sign and Verifyâ
from hxtp_py.crypto import sign_ed25519, verify_ed25519
from hxtp_py.crypto import get_public_key
# Sign
priv_key = bytes.fromhex("your-private-key-hex")
signature = sign_ed25519(priv_key, canonical)
# Derive public key from private key
pub_key = get_public_key(priv_key)
# Verify
valid = verify_ed25519(pub_key, canonical, signature)
Validate an Incoming Messageâ
from hxtp_py.validation import validate_message
result = validate_message(
parsed_message,
public_key_hex="device-public-key-hex",
)
7-Step Validationâ
Every incoming message goes through these checks:
- Version â Is it HxTP/3.1?
- Timestamp â Was it sent recently?
- Payload Size â Is it within limits?
- Nonce â Is it unique? (replay protection)
- Payload Hash â Does the content match its fingerprint?
- Sequence â Are messages in order?
- Signature â Is the Ed25519 signature valid?
If any check fails, the message is rejected immediately.