API Reference: Generated Models¶
django_devicehub.models
¶
BaseDevice
¶
Bases: Model
Abstract base for all device models generated by DeviceType.create_models().
Provides identity, status tracking, MQTT authentication, and lifecycle fields. DeviceType-specific StateFields are added as extra columns on the concrete model.
check_mqtt_password(raw_password)
¶
Verify a plaintext password against the stored hash.
generate_credentials()
¶
Generate MQTT credentials and API key.
Returns a dict with plaintext values (shown once, then hashed).
is_heartbeat_overdue(heartbeat_interval=300, multiplier=2.5)
¶
Check if the device has missed its heartbeat window.
send_command(command_name, payload=None, broker_name='default')
¶
Send a command to this device via the configured broker.
BaseMessage
¶
Bases: Model
Abstract base for raw message storage (audit trail / debugging).
BaseReading
¶
Bases: Model
Abstract base for reading models.
Subclasses get one nullable column per Reading field declared on the DeviceType, forming a wide time-series table.
When you call DeviceType.create_models(), three concrete Django models are generated. They inherit from the abstract base models documented here.
BaseDevice¶
Abstract base for all generated device models. Provides device identity, status tracking, MQTT authentication, and lifecycle fields.
Fields¶
| Field | Type | Description |
|---|---|---|
device_id |
CharField(128) |
Unique device identifier. Indexed. |
name |
CharField(255) |
Human-readable name. Blank allowed. |
status |
CharField(20) |
Device status. Choices from DeviceStatus. Default: "offline". Indexed. |
battery_level |
FloatField |
Battery percentage. Nullable. |
last_seen |
DateTimeField |
Last communication timestamp. Nullable. |
firmware_version |
CharField(50) |
Firmware version string. Blank allowed. |
is_active |
BooleanField |
Whether the device is active. Default: True. Indexed. |
mqtt_username |
CharField(128) |
MQTT login username. Unique. Nullable. |
mqtt_password_hash |
CharField(256) |
Hashed MQTT password. |
api_key |
CharField(128) |
API key for REST authentication. Unique. Nullable. |
metadata |
JSONField |
Free-form metadata dict. Default: {}. |
created_at |
DateTimeField |
Auto-set on creation. |
updated_at |
DateTimeField |
Auto-set on save. |
Plus any StateField columns declared on the DeviceType.
Meta¶
abstract = Trueordering = ["-created_at"]
Methods¶
__str__()¶
Returns "{name or device_id} ({status})".
generate_credentials()¶
Generate MQTT credentials and API key.
Returns: dict with plaintext values:
{
"mqtt_username": "myapp-weatherstationdevice-STATION-001",
"mqtt_password": "dG9rZW4t...", # plaintext, shown once
"api_key": "a1b2c3d4...", # 64-char hex
}
Sets mqtt_username, mqtt_password_hash, and api_key on the instance. Call .save() after to persist.
check_mqtt_password(raw_password)¶
Verify a plaintext password against the stored hash.
Parameters:
raw_password(str): The plaintext password to check.
Returns: bool -- True if the password matches.
mark_online()¶
Set status to "online", update last_seen to now, and save.
mark_offline()¶
Set status to "offline" and save.
is_heartbeat_overdue(heartbeat_interval=300, multiplier=2.5)¶
Check if the device has missed its heartbeat window.
Parameters:
heartbeat_interval(int): Expected interval in seconds. Default:300.multiplier(float): How many intervals before considered overdue. Default:2.5.
Returns: bool -- True if last_seen is older than heartbeat_interval * multiplier seconds ago, or if last_seen is None.
send_command(command_name, payload=None, broker_name="default")¶
Send a command to this device via MQTT.
Parameters:
command_name(str): Name of a command declared on the DeviceType.payload(dict | None): Command payload. Validated against the Command's schema.broker_name(str): Which broker to publish through. Default:"default".
Raises:
ValueErrorif the device has no associated DeviceType, or the command name is unknown, or payload validation fails.TypeErrorif a payload value has the wrong type.
Side effects:
- Publishes a JSON message to
{prefix}/{type}/{device_id}/cmd - Fires the
device_command_sentsignal
Related names¶
Generated device models have these reverse relations:
device.readings-- QuerySet of Reading instances (ForeignKeyrelated_name)device.messages-- QuerySet of Message instances (ForeignKeyrelated_name)
DeviceStatus¶
TextChoices enum for device status values.
| Value | Label |
|---|---|
"online" |
Online |
"offline" |
Offline |
"error" |
Error |
"maintenance" |
Maintenance |
"low_battery" |
Low Battery |
"provisioning" |
Provisioning |
BaseReading¶
Abstract base for all generated reading models. Each Reading field declared on the DeviceType becomes a nullable column.
Fields¶
| Field | Type | Description |
|---|---|---|
device |
ForeignKey |
Reference to the device. Related name: "readings". |
timestamp |
DateTimeField |
Data point timestamp. Indexed. |
received_at |
DateTimeField |
Server receive time. Auto-set. |
Plus one nullable column per Reading declared on the DeviceType.
Meta¶
abstract = Trueordering = ["-timestamp"]- Composite index on
(device, timestamp)on generated models
Methods¶
__str__()¶
Returns "Reading at {timestamp}".
ProcessingStatus¶
TextChoices enum for message processing status.
| Value | Label |
|---|---|
"pending" |
Pending |
"processing" |
Processing |
"completed" |
Completed |
"failed" |
Failed |
BaseMessage¶
Abstract base for raw message storage. Every MQTT message received by the MessageRouter is stored as a Message record for audit and debugging.
Fields¶
| Field | Type | Description |
|---|---|---|
device |
ForeignKey |
Reference to the device. Related name: "messages". |
topic |
CharField(512) |
MQTT topic the message was received on. |
payload_json |
JSONField |
Parsed JSON payload. Nullable. |
payload_raw |
BinaryField |
Raw binary payload. Nullable. |
content_type |
CharField(100) |
MQTT 5 content type property. |
correlation_id |
CharField(256) |
MQTT 5 correlation data. |
user_properties |
JSONField |
MQTT 5 user properties dict. Default: {}. |
processing_status |
CharField(20) |
Processing state. Choices from ProcessingStatus. Default: "pending". Indexed. |
processing_error |
TextField |
Error message if processing failed. |
received_at |
DateTimeField |
Server receive time. Auto-set. |
processed_at |
DateTimeField |
When processing completed. Nullable. |
Meta¶
abstract = Trueordering = ["-received_at"]
Methods¶
__str__()¶
Returns "Message on {topic} ({processing_status})".
mark_completed()¶
Set processing_status to "completed" and processed_at to now.
mark_failed(error="")¶
Set processing_status to "failed", store the error message, and set processed_at to now.
Parameters:
error(str): Error description.
Generated Model Naming¶
For a DeviceType named WeatherStation, the generated models are:
| Model | Class name | Default table name |
|---|---|---|
| Device | WeatherStationDevice |
{app_label}_weatherstationdevice |
| Reading | WeatherStationReading |
{app_label}_weatherstationreading |
| Message | WeatherStationMessage |
{app_label}_weatherstationmessage |
The verbose_name is derived from the CamelCase class name: "Weather Station", "Weather Station Reading", "Weather Station Message".
Each generated model has __module__ set to the module that called create_models(), so Django's migration system places it in the correct app.