Skip to content

Commit 2c73615

Browse files
Update python library readme (#1229)
1 parent 052897b commit 2c73615

File tree

1 file changed

+192
-2
lines changed

1 file changed

+192
-2
lines changed

clientlib/python/README.md

Lines changed: 192 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# A Python Library for UDMI
22

33
This project is a high-level, extensible Python library designed to simplify the
4-
development of applications for the **Universal Device Management Interface (
5-
UDMI)**. It provides a clean, Pythonic abstraction over the core UDMI
4+
development of applications for the **Universal Device Management Interface (UDMI)**.
5+
It provides a clean, Pythonic abstraction over the core UDMI
66
specification, lowering the barrier to entry for developers and device
77
manufacturers seeking to create UDMI-compliant IoT solutions.
88

@@ -35,3 +35,193 @@ ${UDMI_ROOT}/clientlib/python/bin/build
3535
You can find a few samples demonstrating how to connect a device using different
3636
authentication methods as well as other features of the library in
3737
`$UDMI/ROOT/clientlib/python/samples`.
38+
39+
---
40+
41+
## Comprehensive Feature List
42+
43+
## 1\. Smart Connectivity & Authentication
44+
45+
**Status:** Available
46+
47+
* **Unified Device Factory:** A single entry point (`create_device`) that instantiates the client, dispatcher, and necessary managers based on the provided configuration.
48+
* **Auto-Auth Detection:** Logic to automatically select between Mutual TLS (mTLS), No Auth (Anonymous mode), Basic Auth (Username/Password), or RS256 JWT authentication without explicit code changes.
49+
* **JIT Credential Generation:** A built-in `CredentialManager` detects missing keys and generates RSA/ECC key pairs and self-signed certificates on the fly ("Zero-Config" mTLS/JWT).
50+
* **Connection Robustness:** Automatic reconnection handling using `paho-mqtt` with configurable exponential backoff parameters to survive network instability.
51+
52+
**Sample Usage: [`simple_connect.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/connectivity/simple_connect.py)**
53+
54+
55+
```py
56+
from udmi.core.factory import create_device
57+
from udmi.schema import EndpointConfiguration
58+
59+
# The library automatically detects auth type (or lack there) of from this
60+
# config object
61+
config = EndpointConfiguration.from_dict({
62+
"client_id": "projects/my-project/locations/us-central1/registries/reg/devices/AHU-1",
63+
"hostname": "mqtt.bos.goog",
64+
"port": 8883,
65+
"auth_provider": {"jwt": {"audience": "my-project"}}
66+
})
67+
68+
# Automatic wiring of client, dispatcher, and managers.
69+
# If 'rsa_private.pem' is missing, the factory generates it automatically.
70+
device = create_device(config, key_file="rsa_private.pem")
71+
device.run()
72+
```
73+
74+
## 2\. Device State Management
75+
76+
**Status:** Available
77+
78+
* **Automated Config Loop:** Automatically handles incoming `config` messages, updates the `system.last_config` timestamp, and publishes the acknowledged `state`.
79+
* **Static State Injection:** The `SystemManager` accepts a typed `SystemState` object during initialization, allowing manufacturers to inject static identity fields (Serial Number, Firmware Version, Model) without complex subclassing.
80+
* **Config Sync Latch:** Logic ensures the device does not publish its initial state until a valid Config message is received or a timeout expires, preventing state thrashing on startup.
81+
* **Atomic Persistence:** Critical state data (such as `restart_count` and active endpoint configurations) is saved atomically to disk to prevent data corruption and ensure continuity after power loss.
82+
83+
**Sample Usage: [`state_injection.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/system/state_injection.py)**
84+
85+
```py
86+
from udmi.core.managers import SystemManager
87+
from udmi.schema import SystemState, StateSystemHardware
88+
89+
# Define static device identity once
90+
static_info = SystemState(
91+
hardware=StateSystemHardware(make="Delta", model="Red5"),
92+
serial_no="SN-12345",
93+
software={"firmware": "v2.0"}
94+
)
95+
96+
# Inject into the manager using the factory; the library handles the rest
97+
device = create_device(system_state=static_info,
98+
persistence_path=/path/to/persistence.json)
99+
100+
```
101+
102+
##
103+
104+
## 3\. Telemetry & Observability
105+
106+
**Status:** Available
107+
108+
* **Pointset Management:** A dedicated `PointsetManager` handles the `pointset` configuration block, manages sensor values, and runs a background loop to publish `PointsetEvents` at the configured sample rate.
109+
* **Unified Logging:** A `UDMIMqttLogHandler` integrates with Python's standard `logging` module. It captures application logs (INFO, WARN, ERROR), formats them as UDMI `SystemEvents`, and publishes them to the cloud for remote diagnostics.
110+
* **System Metrics:** The `SystemManager` automatically collects and reports system health metrics (e.g., RAM usage) in the `system` event stream.
111+
112+
**Sample Usage:**
113+
[**`telemetry_basic.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/pointset/telemetry_basic.py)**
114+
115+
```py
116+
# Update the PointsetManager (Internal Cache)
117+
pointset_manager.set_point_value("supply_temp", 22.5)
118+
119+
# The background thread automatically publishes this at the configured 'sample_rate_sec'.
120+
```
121+
122+
[**`logging_integration.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/events/logging_integration.py)**
123+
124+
```py
125+
import logging
126+
from udmi.core.logging.mqtt_handler import UDMIMqttLogHandler
127+
128+
# Attach UDMI handler to standard Python logger
129+
mqtt_handler = UDMIMqttLogHandler(system_manager)
130+
logger = logging.getLogger("my_app")
131+
logger.addHandler(mqtt_handler)
132+
133+
# This log appears in the cloud dashboard automatically as a SystemEvent
134+
logger.warning("High CPU usage detected!")
135+
```
136+
137+
##
138+
139+
## 4\. Pointset Control (Writeback & Provisioning)
140+
141+
**Status:** Available
142+
143+
* **Writeback (Actuation):** Handles `set_value` commands from the cloud (e.g., changing a setpoint). The library parses the command and triggers a registered user callback to execute the hardware change.
144+
* **Dynamic Provisioning:** Seamlessly merges points defined in the initial firmware model with new points provisioned dynamically via the Cloud Configuration.
145+
* **Polling Support:** Supports a "pull" model via set\_poll\_callback for just-in-time data retrieval.
146+
147+
**Sample Usage:**
148+
[**`point_writeback.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/pointset/point_writeback.py)**,
149+
150+
```py
151+
def on_writeback(point_name: str, value: Any):
152+
print(f"Actuating {point_name} to {value}...")
153+
# Hardware logic here...
154+
155+
# Register the handler
156+
pointset_manager.set_writeback_handler(on_writeback)
157+
```
158+
159+
[**`pointset_dynamic_configuration.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/pointset/pointset_dynamic_provisioning.py)**,
160+
161+
[**`telemetry_poll_callback.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/pointset/telemetry_poll_callback.py)**
162+
163+
```py
164+
pointset_manager.set_poll_callback(my_sensor_poll)
165+
```
166+
167+
##
168+
169+
## 5\. Over-The-Air (OTA) Updates
170+
171+
**Status:** Available
172+
173+
* **Generic Blob Fetching:** Utilities to fetch data from HTTP(S) URLs or inline Data URIs (`data:base64...`).
174+
* **Automatic Verification:** The library enforces **SHA256 hash verification** on all downloaded blobs before passing them to the application logic.
175+
* **Two-Stage Workflow:** Supports a "Process" \-\> "State Flush" \-\> "Post-Process" pipeline to safely handle self-updates and restarts without leaving the cloud in an unknown state.
176+
177+
**Sample Usage: [`ota_update_workflow.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/system/ota_update_workflow.py)**
178+
179+
```py
180+
sys_manager.register_blob_handler(
181+
"ota_module_loader",
182+
process=process_firmware, # Writes file to disk
183+
post_process=restart_device # Restarts the app
184+
)
185+
```
186+
187+
##
188+
189+
## 6\. Gateway, Proxy & Discovery
190+
191+
**Status:** Available
192+
193+
* **Proxy Lifecycle:** Handles attach and detach messages for sub-devices.
194+
* **Routed Configuration:** Config messages and Commands targeted at specific proxy IDs are automatically routed to registered handlers.
195+
* **Discovery Manager:** Implementation of the discovery block to support active scanning using registered `FamilyProvider` drivers and reporting `DiscoveryEvents`.
196+
197+
**Sample Usage:**
198+
[**`gateway_proxy.py`**](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/gateway/gateway_proxy.py),**
199+
[**`discovery_scan.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/gateway/discovery_scan.py)**
200+
201+
```py
202+
# Triggered by cloud 'discovery' command
203+
class MyBacnetProvider(FamilyProvider):
204+
def start_scan(self, config, publish):
205+
# Scan network...
206+
publish(device_id, DiscoveryEvents(...))
207+
```
208+
209+
##
210+
211+
## 7\. Others: Reliability, Localnet & Lifecycle Management
212+
213+
**Status:** Available
214+
215+
* **State Throttling:** "Dirty bit" logic triggers state updates immediately upon change, subject to a minimum time interval (STATE\_THROTTLE\_SEC) to prevent broker spamming.
216+
* **Endpoint Redirection:**
217+
* **Sample usage: [`endpoint_redirection.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/advanced/endpoint_redirection.py)**
218+
* **Key Rotation:** The `SystemManager` handles the `rotate_key` command and also has a public API `rotate_key`, triggering the `CredentialManager` to generate new keys, backup old ones, and invoke a callback for cloud registration.
219+
* **Sample usage: [`key_rotation.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/advanced/key_rotation.py)**
220+
* **Localnet Manager:** Handles the localnet configuration block to validate address families (e.g., mapping generic device IDs to physical BACnet addresses) using registered providers.
221+
* **Sample usage: [`localnet_routing.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/localnet/localnet_routing.py)**
222+
* **Lifecycle Commands:** Maps UDMI commands (reboot, shutdown) to registered callbacks or specific process exit codes.
223+
* **Sample usage: [`lifecycle_commands.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/system/lifecycle_commands.py)**
224+
* **Custom Persistence Backend:**
225+
* **Sample usage: [`custom_persistence_backend.py`](https://github.com/faucetsdn/udmi/tree/master/clientlib/python/samples/advanced/custom_persistence_backend.py)**
226+
227+
##

0 commit comments

Comments
 (0)