Skip to content

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

MethodPathPurposeNotes
GET/projects/{project_id}/devices/{device_pk}/factors/List factors for a deviceCached; ordered by unit, address, data_index. See List Factors.
GET/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/Retrieve a single factorIncludes derived metadata (the_type_detail, etc.). See Retrieve Factor.
POST/projects/{project_id}/devices/{device_pk}/factors/Create factorValidates uniqueness of (unit, address, data_index). See Create Factor.
PATCH/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/Update factorPartial updates allowed. See Update Factor.
DELETE/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/Remove factorDeletes factor and refreshes caches. See Delete Factor.
POST`/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/onoffforward
GET/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/current-data/Real-time snapshotUses the low-latency cache. See Real-time Snapshot.
POST/projects/{project_id}/devices/{device_pk}/factors/{factor_pk}/set-threshold/Configure min/max thresholdsGenerates 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 payloads
  • modbus_type: One of holding, input, coil, discrete
  • data_type: int16, uint16, int32, float, etc.
  • data_endian: Byte order (ABCD, DCBA, etc.)
  • data_factor / data_delta: Optional scaling/offset
  • the_type: Logical device type (temp, humi, switch, etc.)
  • the_type_detail: Metadata (name/unit/icon) resolved from DeviceTypeConfig
  • agri_id: Full identifier device_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"
}
FieldTypeRequiredNotes
unitintegerYesModbus slave ID
addressintegerYesRegister address
data_indexintegerYesOffset for multi-register reads
the_typeenumYesSensor/control type; see Base Data
modbus_typeenumYesholding, input, coil, discrete
data_typeenumYesint16, uint16, int32, float, etc.
data_endianenumYesByte order (ABCD, DCBA, BADC, CDAB)
data_factorfloatNoMultiply raw value
data_deltafloatNoAdditive delta
enabledboolNoDefaults to true
infostringNoFree-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

StatusCodeDescription
400INVALID_FACTOR_DEFINITIONDuplicate (unit,address,data_index) or unsupported data type
400DEVICE_NOT_EDITABLEBase device firmware forbids custom factors
401UNAUTHORIZEDMissing or invalid token
403FORBIDDENCaller lacks required role
404FACTOR_NOT_FOUNDFactor PK/agri_id not in current organization
422INVALID_THRESHOLDmin_value/max_value payload invalid
500COMMAND_FAILEDError while creating the control command or evaluation rules

Operational Notes

  1. Hardware Support: Non-programmable devices expose read-only templates; create/update/delete will return DEVICE_NOT_EDITABLE.
  2. Command Tokens: Store the token value returned by control endpoints to correlate with device acknowledgements emitted elsewhere in the system.
  3. Cache vs. Historical Store: current-data relies on a low-latency cache, while historical APIs read from long-term storage with pagination. Expect slight divergence between the two sources.
  4. agri_id Format: agri_id = <device_agri_id>-<unit>-<address><data_index>; leading zeros in address/data_index are significant. Use the Field Reference to parse IDs consistently.
  5. Cache Refresh: Factor CRUD operations automatically refresh cached list/detail responses. Control endpoints do not alter configuration and thus do not flush caches.