Appearance
Device Factors
Overview
Device factors define how a device reads or writes physical signals. Each factor maps to a Modbus register, stores optional engineering conversions, and can be controlled (ON/OFF/Forward/Reverse) when the underlying hardware supports it.
- Base Path:
/api/v2/projects/{project_id}/devices/{device_pk}/factors/ - Caching: Factor list/detail endpoints cache responses for 5 minutes and automatically refresh whenever a factor is added, updated, or removed.
Endpoint Summary
| Method | Path | Purpose | Notes |
|---|---|---|---|
| GET | /projects/{project_id}/devices/{device_pk}/factors/ | List factors for a device | Cached; ordered by unit, address, data_index. See List Factors. |
| GET | /projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/ | Retrieve a single factor | Includes derived metadata (the_type_detail, etc.). See Retrieve Factor. |
| POST | /projects/{project_id}/devices/{device_pk}/factors/ | Create factor | Validates uniqueness of (unit, address, data_index). See Create Factor. |
| PATCH | /projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/ | Update factor | Partial updates allowed. See Update Factor. |
| DELETE | /projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/ | Remove factor | Deletes factor and refreshes caches. See Delete Factor. |
| POST | `/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/on | off | forward |
| GET | /projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/current-data/ | Real-time snapshot | Uses the low-latency cache. See Real-time Snapshot. |
| POST | /projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/set-threshold/ | Configure min/max thresholds | Generates rules in rules engine. See Threshold Management. |
| GET | /projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/data/ | Historical data (device context) | Stored in the historical database with 90-day retention. See Historical Data (Device Context). |
| GET | /api/v2/data/{factor_agri_id}/ | Historical data (factor agri ID) | Direct access via the global factor data endpoint. See Historical Data by Factor agri_id. |
Factor Model (see Field Reference for key definitions)
Each factor exposes the following important fields:
unit: Modbus slave ID (int)address: Register address (int)data_index: Offset when reading multi-register payloadsmodbus_type: One ofholding,input,coil,discretedata_type:int16,uint16,int32,float, etc.data_endian: Byte order (ABCD, DCBA, etc.)data_factor/data_delta: Optional scaling/offsetthe_type: Logical device type (temp, humi, switch, etc.)the_type_detail: Metadata (name/unit/icon) resolved fromDeviceTypeConfigagri_id: Full identifierdevice_agri_id-unit-addressindex
List Factors
http
GET /api/v2/projects/{project_id}/devices/{device_pk}/factors/
Authorization: Bearer <token>Response (truncated):
json
[
{
"id": 12,
"unit": 1,
"address": 0,
"data_index": 0,
"the_type": "temp",
"the_type_detail": {
"name": "Temperature",
"unit": "℃",
"icon": "https://cloud.yanjiiot.com/media/icon/temp.png"
},
"modbus_type": "holding",
"data_type": "int16",
"data_endian": "ABCD",
"data_factor": 0.1,
"enabled": true,
"agri_id": "d-1000-abcd-01"
}
]Retrieve Factor
http
GET /api/v2/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/
Authorization: Bearer <token>Returns the same schema as the list entry, including min_value / max_value if defined.
Create Factor
http
POST /api/v2/projects/{project_id}/devices/{device_pk}/factors/
Authorization: Bearer <token>
Content-Type: application/json
{
"unit": 1,
"address": 0,
"data_index": 0,
"the_type": "temp",
"modbus_type": "holding",
"data_type": "int16",
"data_endian": "ABCD",
"data_factor": 0.1,
"info": "Inlet temperature"
}| Field | Type | Required | Notes |
|---|---|---|---|
unit | integer | Yes | Modbus slave ID |
address | integer | Yes | Register address |
data_index | integer | Yes | Offset for multi-register reads |
the_type | enum | Yes | Sensor/control type; see Base Data |
modbus_type | enum | Yes | holding, input, coil, discrete |
data_type | enum | Yes | int16, uint16, int32, float, etc. |
data_endian | enum | Yes | Byte order (ABCD, DCBA, BADC, CDAB) |
data_factor | float | No | Multiply raw value |
data_delta | float | No | Additive delta |
enabled | bool | No | Defaults to true |
info | string | No | Free-form note |
Returns the created factor record. Duplicate (unit,address,data_index) combinations are rejected with 400 BAD_REQUEST.
Update & Delete
http
PATCH /api/v2/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/
Authorization: Bearer <token>
Content-Type: application/json
{
"data_factor": 0.01,
"info": "Scaled to volts"
}Deletion uses DELETE on the same path. Both operations require the device hardware to support editable factors (BaseDevice.property & 0x20).
Copy Factor
http
POST /api/v2/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/copy/
Authorization: Bearer <token>Creates a sibling factor with the same definition, appending _N to the name and auto-incrementing data_index for the same (unit,address) pair.
Control Actions
Switch or actuator factors accept simple POST calls that enqueue control commands:
http
POST /api/v2/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/on/
Authorization: Bearer <token>Available actions: on, off, forward, antiport, stop. Responses share the structure:
json
{
"message": "Operation succeeded",
"token": "cmd_xxx"
}Tokens let clients correlate downstream command status if needed.
Real-time Snapshot
http
GET /api/v2/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/current-data/
Authorization: Bearer <token>Looks up the factor’s agri_id in the in-memory cache. Falling back to an empty payload avoids 404s, enabling dashboards to render optional widgets.
Threshold Management
Set Threshold
http
POST /api/v2/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/set-threshold/
Authorization: Bearer <token>
Content-Type: application/json
{
"min_value": 5.0,
"max_value": 35.0
}Validates the payload, persists min_value/max_value, and calls the rules engine (add_threshold_rule) so alerts trigger when limits are crossed.
List Threshold Factors
http
GET /api/v2/projects/{project_id}/devices/{device_pk}/factors/threshold-factors/
Authorization: Bearer <token>Returns only factors where either threshold is set.
Historical Data (Device Context)
http
GET /api/v2/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/data/?page=1&page_size=50&min_timestamp=1704758400
Authorization: Bearer <token>Response:
json
{
"total": 100,
"data": [
{ "agri_id": "d-1000-abcd-01", "v": 25.6, "t": 1641715200 },
{ "agri_id": "d-1000-abcd-01", "v": 25.1, "t": 1641711600 }
]
}- Data is sorted by timestamp descending.
- Retention: 90 days.
- Responses are cached for 5 minutes.
Historical Data by Factor agri_id
Sometimes integrations only know the factor’s canonical ID (e.g., d-1000-abcd-01). Use the global endpoint:
http
GET /api/v2/data/{factor_agri_id}/?page=1&page_size=50&min_timestamp=1704758400
Authorization: Bearer <token>Behind the scenes, the API validates that the factor’s parent device belongs to the requester’s organization before reading from the historical store. The response follows standard pagination:
json
{
"count": 100,
"next": "?page=2&page_size=50",
"previous": null,
"results": [
{ "agri_id": "d-1000-abcd-01", "v": 24.2, "t": 1641715200 }
]
}Error Codes
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_FACTOR_DEFINITION | Duplicate (unit,address,data_index) or unsupported data type |
| 400 | DEVICE_NOT_EDITABLE | Base device firmware forbids custom factors |
| 401 | UNAUTHORIZED | Missing or invalid token |
| 403 | FORBIDDEN | Caller lacks required role |
| 404 | FACTOR_NOT_FOUND | Factor PK/agri_id not in current organization |
| 422 | INVALID_THRESHOLD | min_value/max_value payload invalid |
| 500 | COMMAND_FAILED | Error while creating the control command or evaluation rules |
Operational Notes
- Hardware Support: Non-programmable devices expose read-only templates; create/update/delete will return
DEVICE_NOT_EDITABLE. - Command Tokens: Store the
tokenvalue returned by control endpoints to correlate with device acknowledgements emitted elsewhere in the system. - Cache vs. Historical Store:
current-datarelies on a low-latency cache, while historical APIs read from long-term storage with pagination. Expect slight divergence between the two sources. - agri_id Format:
agri_id = <device_agri_id>-<unit>-<address><data_index>; leading zeros inaddress/data_indexare significant. Use the Field Reference to parse IDs consistently. - Cache Refresh: Factor CRUD operations automatically refresh cached list/detail responses. Control endpoints do not alter configuration and thus do not flush caches.
