Skip to content

Device Points

Overview

Device points define how a device reads or writes physical signals. Each point maps to a Modbus register, stores optional engineering conversion parameters, and can be controlled (ON/OFF/Forward/Reverse) when the underlying hardware supports it.

  • Base Path: /api/v2/projects/{project_id}/devices/{device_id}/points/
  • Caching: Point list/detail endpoints cache responses for 5 minutes and automatically refresh whenever a point is added, updated, or removed.

Endpoint Summary

MethodPathPurposeNotes
GET/projects/{project_id}/devices/{device_id}/points/List points for a deviceCached; ordered by slave_id, address, data_index
GET/projects/{project_id}/devices/{device_id}/points/{id}/Retrieve a single pointIncludes derived metadata (the_type_detail, etc.)
POST/projects/{project_id}/devices/{device_id}/points/Create a pointValidates uniqueness of (slave_id, address, data_index)
PATCH/projects/{project_id}/devices/{device_id}/points/{id}/Update a pointPartial updates allowed
DELETE/projects/{project_id}/devices/{device_id}/points/{id}/Delete a pointCache is refreshed automatically
POST/projects/{project_id}/devices/{device_id}/points/{id}/on/Turn onSends ON command to device, returns command token
POST/projects/{project_id}/devices/{device_id}/points/{id}/off/Turn offSends OFF command to device, returns command token
POST/projects/{project_id}/devices/{device_id}/points/{id}/forward/Forward rotationSends FORWARD command, returns command token
POST/projects/{project_id}/devices/{device_id}/points/{id}/antiport/Reverse rotationSends ANTIPORT command, returns command token
POST/projects/{project_id}/devices/{device_id}/points/{id}/stop/StopSends STOP command, returns command token
POST/projects/{project_id}/devices/{device_id}/points/{id}/set-content/Set display contentFor LED/digit display devices, returns command token
POST/projects/{project_id}/devices/{device_id}/points/{id}/set-alarm-level/Set alarm levelLevel range 0–5, returns command token
GET/projects/{project_id}/devices/{device_id}/points/{id}/current-data/Real-time snapshotReads latest value from low-latency cache
POST/projects/{project_id}/devices/{device_id}/points/{id}/set-threshold/Configure thresholdSets min_value/max_value; triggers alert when exceeded
GET/projects/{project_id}/devices/{device_id}/points/threshold-points/List threshold pointsReturns only points with at least one threshold configured
GET/projects/{project_id}/devices/{device_id}/points/options/Get configuration optionsReturns Modbus types, data types, and point types
POST/projects/{project_id}/devices/{device_id}/points/{id}/duplicate/Duplicate a pointCreates a sibling point with auto-incremented data_index
GET/api/v2/data/{point_agri_id}/Historical dataQuery historical data by point agri_id

Point Model

Each point exposes the following fields:

FieldTypeDescription
idintegerPoint primary key
agri_idstringFull identifier: {device_agri_id}-{slave_id}-{address}{data_index}
device_idintegerParent device ID
namestringPoint name
slave_idintegerModbus slave ID
addressintegerRegister address
data_indexintegerOffset for multi-register reads (0–9)
the_typeintegerPoint type ID
the_type_detailobjectPoint type metadata (name, unit, icon)
modbus_typestringOne of holding, input, coil, discrete
data_typestringint16, uint16, int32, float, etc.
data_endianstringByte order: ABCD, DCBA, BADC, CDAB
data_scalefloatScale factor. Final value = raw × data_scale + data_delta
data_deltafloatAdditive offset. Final value = raw × data_scale + data_delta
min_valuefloatAlert lower threshold (optional)
max_valuefloatAlert upper threshold (optional)
enabledbooleanWhether the point is active
infostringFree-form note (optional)

List Points

http
GET /api/v2/projects/{project_id}/devices/{device_id}/points/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Response example:

json
[
  {
    "id": 12,
    "agri_id": "d-1000-abcd-1-00",
    "device_id": 5,
    "name": "Inlet Temperature",
    "slave_id": 1,
    "address": 0,
    "data_index": 0,
    "the_type": 1,
    "the_type_detail": {
      "the_type": 1,
      "name": "Temperature",
      "unit": "℃",
      "icon_url": "https://cloud.yengear.com/media/icon/temp.png",
      "is_shared": true
    },
    "modbus_type": "holding",
    "data_type": "int16",
    "data_endian": "ABCD",
    "data_scale": 0.1,
    "data_delta": 0.0,
    "min_value": null,
    "max_value": null,
    "enabled": true,
    "info": null
  }
]

Retrieve Point

http
GET /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Returns the same schema as the list entry, including min_value/max_value if configured.

Create Point

http
POST /api/v2/projects/{project_id}/devices/{device_id}/points/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>
Content-Type: application/json

{
  "name": "Inlet Temperature",
  "slave_id": 1,
  "address": 0,
  "data_index": 0,
  "the_type": 1,
  "modbus_type": "holding",
  "data_type": "int16",
  "data_endian": "ABCD",
  "data_scale": 0.1,
  "info": "Inlet temperature sensor"
}

Request Fields

FieldTypeRequiredNotes
slave_idintegerYesModbus slave ID
addressintegerYesRegister address
data_indexintegerYesOffset for multi-register reads
the_typeintegerYesPoint type ID
modbus_typestringYesholding, input, coil, discrete
data_typestringYesint16, uint16, int32, float, etc.
data_endianstringYesByte order (ABCD, DCBA, BADC, CDAB)
namestringNoPoint name
data_scalefloatNoScale factor, default 1
data_deltafloatNoAdditive offset, default 0
enabledbooleanNoDefaults to true
infostringNoFree-form note

Returns the created point record. Duplicate (slave_id, address, data_index) combinations are rejected with 400.

Note: The device's BaseDevice.property & 0x20 must be set, otherwise DEVICE_NOT_EDITABLE is returned.

Update Point

http
PATCH /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>
Content-Type: application/json

{
  "data_scale": 0.01,
  "info": "Scaled to volts"
}

Partial updates are supported — only include the fields you want to change.

Delete Point

http
DELETE /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Returns 204 No Content on success.

Duplicate Point

http
POST /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/duplicate/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Creates a sibling point with the same configuration. The name gets _N appended, and data_index is auto-incremented for the same (slave_id, address) pair. Returns 201 with the new point data.

Control Actions

Switch and actuator points accept control commands. Requires operator role or higher.

http
POST /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/on/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>
ActionEndpointDescription
Turn onPOST /on/Send ON command to device
Turn offPOST /off/Send OFF command to device
ForwardPOST /forward/Motor forward rotation
ReversePOST /antiport/Motor reverse rotation
StopPOST /stop/Stop current operation

All control actions return the same response structure:

json
{
  "success": true,
  "message": "Operation succeeded",
  "token": "cmd_xxxxxxxxxxxxxxxx"
}

The token can be used to correlate command execution status.

Set Display Content

For LED and digit display devices:

http
POST /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/set-content/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>
Content-Type: application/json

{
  "content": "Hello"
}
FieldTypeRequiredNotes
contentstringYesText to display on the device

Set Alarm Level

http
POST /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/set-alarm-level/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>
Content-Type: application/json

{
  "level": 2
}
FieldTypeRequiredNotes
levelintegerYesAlarm level, range 0–5

Real-time Snapshot

http
GET /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/current-data/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Reads the point's latest value from the low-latency cache (Cloudflare D1). Returns an empty object if no data is available yet — never returns 404.

Response example:

json
{
  "agri_id": "d-1000-abcd-1-00",
  "value": 24.5,
  "the_type": 1,
  "unit": "℃",
  "updated_at": 1704758400
}

Get Configuration Options

http
GET /api/v2/projects/{project_id}/devices/{device_id}/points/options/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Returns available configuration options for creating points:

json
{
  "modbus_type_choices": [
    {"value": "holding", "label": "Holding Register"},
    {"value": "input", "label": "Input Register"},
    {"value": "coil", "label": "Coil"},
    {"value": "discrete", "label": "Discrete Input"}
  ],
  "data_type_choices": [
    {"value": "int16", "label": "16-bit Integer"},
    {"value": "uint16", "label": "16-bit Unsigned Integer"},
    {"value": "int32", "label": "32-bit Integer"},
    {"value": "float", "label": "Float"}
  ],
  "data_endian_choices": [
    {"value": "ABCD", "label": "Big Endian"},
    {"value": "DCBA", "label": "Little Endian"},
    {"value": "BADC", "label": "Mid-Little Endian"},
    {"value": "CDAB", "label": "Mid-Big Endian"}
  ],
  "point_types": [
    {"the_type": 1, "name": "Temperature", "unit": "℃", "is_shared": true},
    {"the_type": 2, "name": "Humidity", "unit": "%RH", "is_shared": true},
    {"the_type": 200, "name": "Switch", "unit": "", "is_shared": true}
  ]
}

Threshold Management

Set Threshold

http
POST /api/v2/projects/{project_id}/devices/{device_id}/points/{id}/set-threshold/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>
Content-Type: application/json

{
  "min_value": 5.0,
  "max_value": 35.0
}
FieldTypeRequiredNotes
min_valuefloatNoLower alert threshold
max_valuefloatNoUpper alert threshold

Both fields are optional, but if both are provided, min_value must be less than max_value.

List Threshold Points

http
GET /api/v2/projects/{project_id}/devices/{device_id}/points/threshold-points/
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Returns only points where at least one threshold is configured.

Historical Data by agri_id

http
GET /api/v2/data/{point_agri_id}/?page=1&page_size=50&min_timestamp=1704758400
Authorization: Bearer <token>
X-Organization-Slug: <org-slug>

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
page_sizeinteger50Records per page
min_timestampintegerFilter by minimum Unix timestamp (seconds)

The API validates that the point's parent device belongs to the requester's organization before reading from the historical store.

Response example:

json
{
  "count": 100,
  "next": "?page=2&page_size=50",
  "previous": null,
  "results": [
    { "agri_id": "d-1000-abcd-1-00", "v": 24.2, "t": 1704758400 }
  ]
}

Error Codes

StatusCodeDescription
400DUPLICATE_POINT(slave_id, address, data_index) combination already exists
400DEVICE_NOT_EDITABLEDevice does not support custom point configuration
400INVALID_THRESHOLDInvalid min_value/max_value payload
401UNAUTHORIZEDMissing or invalid token
403FORBIDDENCaller lacks required role
404POINT_NOT_FOUNDPoint not found or not in the current organization
500COMMAND_FAILEDFailed to dispatch control command

Operational Notes

  1. Hardware Support: Only devices with BaseDevice.property & 0x20 set support custom point configuration. Create/update/delete on unsupported devices return DEVICE_NOT_EDITABLE.
  2. Command Tokens: Store the token returned by control endpoints to correlate with device acknowledgements.
  3. Real-time vs. Historical: current-data reads from low-latency cache; the historical endpoint reads from persistent storage with pagination. Expect slight divergence between the two sources.
  4. agri_id Format: agri_id = {device_agri_id}-{slave_id}-{address}{data_index}. No leading zeros on address or data_index.
  5. Cache Refresh: Create, update, and delete operations automatically refresh the cached list/detail responses. Control actions do not alter configuration and do not flush caches.