diff --git a/public/resources/docs/reference/gateway-api/mqtt-js-gateway-attributes-request.js b/public/resources/docs/reference/gateway-api/mqtt-js-gateway-attributes-request.js new file mode 100644 index 0000000000..ff673bc3ed --- /dev/null +++ b/public/resources/docs/reference/gateway-api/mqtt-js-gateway-attributes-request.js @@ -0,0 +1,19 @@ +var mqtt = require('mqtt'); +var client = mqtt.connect('mqtt://localhost', { + username: process.env.TOKEN +}); + +client.on('connect', function () { + console.log('connected'); + client.subscribe('v1/gateway/attributes/response'); + // clientKeys/sharedKeys are comma-separated strings. An empty value returns + // ALL keys in that scope, e.g. sharedKeys: "". Omit a field to exclude a scope. + var request = { id: 1, device: 'Device A', clientKeys: 'fw_version,battery', sharedKeys: 'targetFwVersion' }; + client.publish('v1/gateway/attributes/request', JSON.stringify(request)); +}); + +client.on('message', function (topic, message) { + console.log('response.topic: ' + topic); + console.log('response.body: ' + message.toString()); + client.end(); +}); diff --git a/public/resources/docs/reference/mqtt-api/mqtt-js-attributes-request.js b/public/resources/docs/reference/mqtt-api/mqtt-js-attributes-request.js new file mode 100644 index 0000000000..584f88e91f --- /dev/null +++ b/public/resources/docs/reference/mqtt-api/mqtt-js-attributes-request.js @@ -0,0 +1,20 @@ +var mqtt = require('mqtt'); +var client = mqtt.connect('mqtt://localhost', { + username: process.env.TOKEN +}); +var requestId = 1; + +client.on('connect', function () { + console.log('connected'); + client.subscribe('v1/devices/me/attributes/response/+'); + // Specify keys as comma-separated strings. An empty value returns ALL keys + // in that scope, e.g. sharedKeys: "". Omit a field to exclude that scope. + var request = { clientKeys: 'firmwareVersion,serialNumber', sharedKeys: 'targetTemperature,enabled' }; + client.publish('v1/devices/me/attributes/request/' + requestId, JSON.stringify(request)); +}); + +client.on('message', function (topic, message) { + console.log('response.topic: ' + topic); + console.log('response.body: ' + message.toString()); + client.end(); +}); diff --git a/src/content/_includes/docs/edge/reference/apis-and-sdks/coap-api.mdx b/src/content/_includes/docs/edge/reference/apis-and-sdks/coap-api.mdx index 67ff5dd58e..d9342350ea 100644 --- a/src/content/_includes/docs/edge/reference/apis-and-sdks/coap-api.mdx +++ b/src/content/_includes/docs/edge/reference/apis-and-sdks/coap-api.mdx @@ -29,7 +29,7 @@ Base URL: `coap://{EDGE_HOST}/api/v1/{accessToken}` |-----------|--------|------| | Publish telemetry | POST | `/telemetry` | | Publish client-side attributes | POST | `/attributes` | -| Get attributes | GET | `/attributes?clientKeys=…&sharedKeys=…` | +| Get attributes | GET | `/attributes?clientKeys=…&sharedKeys=…` (or `allClientKeys=true` / `allSharedKeys=true`) | | Subscribe to shared attribute updates | GET + Observe | `/attributes/updates` | | Subscribe to server-side RPC | GET + Observe | `/rpc` | | Respond to server-side RPC | POST | `/rpc/{requestId}` | @@ -82,14 +82,23 @@ coap-client -m post \ -e '{"firmware_version": "1.2.0", "serial": "SN-001"}' ``` -Get client and shared attributes: +Read client-side and/or shared attributes. The response groups results by scope: `{"client": {...}, "shared": {...}}`. Choose which attributes to return with these query parameters: + +| Parameter | Description | +|-----------|-------------| +| `clientKeys` | Comma-separated list of client-side attribute keys to return | +| `sharedKeys` | Comma-separated list of shared attribute keys to return | +| `allClientKeys` | Set to `true` to return all client-side attributes (overrides `clientKeys`) | +| `allSharedKeys` | Set to `true` to return all shared attributes (overrides `sharedKeys`) | + +**Example:** ```bash coap-client -m get \ "coap://$EDGE_HOST/api/v1/$ACCESS_TOKEN/attributes?clientKeys=serial&sharedKeys=firmware_version" ``` -Response example: +**Response:** ```json {"client": {"serial": "SN-001"}, "shared": {"firmware_version": "1.2.0"}} diff --git a/src/content/_includes/docs/edge/reference/apis-and-sdks/gateway-mqtt-api.mdx b/src/content/_includes/docs/edge/reference/apis-and-sdks/gateway-mqtt-api.mdx index 7d39fdc469..2c0dc4f841 100644 --- a/src/content/_includes/docs/edge/reference/apis-and-sdks/gateway-mqtt-api.mdx +++ b/src/content/_includes/docs/edge/reference/apis-and-sdks/gateway-mqtt-api.mdx @@ -153,27 +153,72 @@ mosquitto_pub -h "$EDGE_HOST" -t "v1/gateway/attributes" \ ### Request attribute values -Subscribe to the response topic first, then publish the request. +Subscribe to the response topic first, then publish the request. Because subscribing and publishing must happen in the same MQTT session, this cannot be shown with `mosquitto_pub`/`mosquitto_sub` as two separate commands. Use a script instead. **Subscribe topic:** `v1/gateway/attributes/response` **Publish topic:** `v1/gateway/attributes/request` -**Payload:** +**Request payload:** ```json { "id": 1, "device": "Device A", - "client": ["key1", "key2"], - "shared": ["key3", "key4"] + "clientKeys": "fw_version,battery", + "sharedKeys": "targetFwVersion" } ``` -- **id** — required. Integer request identifier. The response includes the same `id`. +- **id** — required. Integer request identifier. The response echoes the same `id`. - **device** — required. The device name in ThingsBoard. -- **client** — optional. Client-side attribute keys to retrieve. -- **shared** — optional. Shared attribute keys to retrieve. +- **clientKeys** — optional. Comma-separated client-side attribute keys. Set to `""` (empty string) to retrieve all client-side attributes. Omit to exclude client attributes from the response. +- **sharedKeys** — optional. Comma-separated shared attribute keys. Set to `""` (empty string) to retrieve all shared attributes. Omit to exclude shared attributes from the response. + + + +Omitting **both** `clientKeys` and `sharedKeys` (sending only `id` and `device`) returns **all** client and **all** shared attributes in a single scope-separated response. + +**Response payload:** + +```json +{ + "id": 1, + "device": "Device A", + "client": {"fw_version": "1.0", "battery": 87}, + "shared": {"targetFwVersion": "2.0"} +} +``` + +The response is scope-separated: `client` contains client-side attributes, `shared` contains shared attributes. A scope key is omitted from the response if it was not requested. + +**Example (Node.js / mqtt.js):** + +```js +const mqtt = require('mqtt'); +const client = mqtt.connect('mqtt://$EDGE_HOST', { username: '$ACCESS_TOKEN' }); + +client.on('connect', () => { + client.subscribe('v1/gateway/attributes/response', () => { + client.publish( + 'v1/gateway/attributes/request', + JSON.stringify({ + id: 1, + device: 'Device A', + clientKeys: 'fw_version,battery', + sharedKeys: 'targetFwVersion', + }) + ); + }); +}); + +client.on('message', (_topic, message) => { + console.log(message.toString()); + client.end(); +}); +``` ### Subscribe to attribute updates diff --git a/src/content/_includes/docs/edge/reference/apis-and-sdks/http-api.mdx b/src/content/_includes/docs/edge/reference/apis-and-sdks/http-api.mdx index 732a24399e..e2e66a55d0 100644 --- a/src/content/_includes/docs/edge/reference/apis-and-sdks/http-api.mdx +++ b/src/content/_includes/docs/edge/reference/apis-and-sdks/http-api.mdx @@ -30,7 +30,7 @@ Base URL: `http://{EDGE_HOST}:8080/api/v1/{accessToken}` |-----------|--------|------| | Publish telemetry | POST | `/telemetry` | | Publish client-side attributes | POST | `/attributes` | -| Get attributes | GET | `/attributes?clientKeys=…&sharedKeys=…` | +| Get attributes | GET | `/attributes?clientKeys=…&sharedKeys=…` (or `allClientKeys=true` / `allSharedKeys=true`) | | Subscribe to shared attribute updates (long-poll) | GET | `/attributes/updates?timeout={ms}` | | Subscribe to RPC commands (long-poll) | GET | `/rpc?timeout={ms}` | | Respond to server-side RPC | POST | `/rpc/{requestId}` | @@ -64,12 +64,23 @@ curl -v -X POST \ +Read client-side and/or shared attributes. The response groups results by scope: `{"client": {...}, "shared": {...}}`. Choose which attributes to return with these query parameters: + +| Parameter | Description | +|-----------|-------------| +| `clientKeys` | Comma-separated list of client-side attribute keys to return | +| `sharedKeys` | Comma-separated list of shared attribute keys to return | +| `allClientKeys` | Set to `true` to return all client-side attributes (overrides `clientKeys`) | +| `allSharedKeys` | Set to `true` to return all shared attributes (overrides `sharedKeys`) | + +**Example:** + ```bash curl -v \ "http://$EDGE_HOST:8080/api/v1/$ACCESS_TOKEN/attributes?clientKeys=serial&sharedKeys=firmware_version" ``` -Response example: +**Response:** ```json {"client": {"serial": "SN-001"}, "shared": {"firmware_version": "1.2.0"}} diff --git a/src/content/_includes/docs/edge/reference/apis-and-sdks/mqtt-api.mdx b/src/content/_includes/docs/edge/reference/apis-and-sdks/mqtt-api.mdx index d8ed0b9f0d..2ffeaa77e2 100644 --- a/src/content/_includes/docs/edge/reference/apis-and-sdks/mqtt-api.mdx +++ b/src/content/_includes/docs/edge/reference/apis-and-sdks/mqtt-api.mdx @@ -130,6 +130,13 @@ Subscribe to `v1/devices/me/attributes/response/+`, then publish to `v1/devices/ {"clientKeys": "attribute1,attribute2", "sharedKeys": "shared1,shared2"} ``` +| Field | Description | +|-------|-------------| +| `clientKeys` | Comma-separated client-side attribute keys to return; `""` returns all client attributes; omit to exclude the client scope | +| `sharedKeys` | Comma-separated shared attribute keys to return; `""` returns all shared attributes; omit to exclude the shared scope | + +An empty request body (`{}`) returns all client and all shared attributes. + The following example uses MQTT.js because subscribe and publish must happen in the same session: ```js @@ -156,6 +163,32 @@ Response example: {"client": {"attribute1": "value1", "attribute2": true}} ``` +To retrieve all shared attributes, pass an empty string for `sharedKeys`: + +```js +var mqtt = require('mqtt'); +var client = mqtt.connect('mqtt://' + process.env.EDGE_HOST, { + username: process.env.ACCESS_TOKEN +}); + +client.on('connect', function () { + client.subscribe('v1/devices/me/attributes/response/+'); + client.publish('v1/devices/me/attributes/request/1', + JSON.stringify({sharedKeys: ''})); +}); + +client.on('message', function (topic, message) { + console.log('Attributes:', message.toString()); + client.end(); +}); +``` + +Response example: + +```json +{"shared": {"targetTemperature": 24, "enabled": true}} +``` + ### Subscribe to shared attribute updates Subscribe to `v1/devices/me/attributes` to receive shared attribute changes pushed by the server: diff --git a/src/content/_includes/docs/reference/coap-api/attributes.mdx b/src/content/_includes/docs/reference/coap-api/attributes.mdx index 3c47c2ffab..44f5aa1aab 100644 --- a/src/content/_includes/docs/reference/coap-api/attributes.mdx +++ b/src/content/_includes/docs/reference/coap-api/attributes.mdx @@ -30,22 +30,33 @@ Send a `POST` request to upload client-side attributes: ## Request Attribute Values -Send a `GET` request with `clientKeys` and `sharedKeys` query parameters: +Send a `GET` request to the attributes endpoint to read client-side and/or shared attribute values. The response groups results by scope: `{"client": {...}, "shared": {...}}`. -| Credential type | URL | -|-----------------|-----| -| Access Token | | -| X.509 Certificate | | +**Endpoint:** + +| Credential type | Endpoint | +|-----------------|----------| +| Access Token | | +| X.509 Certificate | | + +**Query parameters** — choose which attributes to return: + +| Parameter | Description | +|-----------|-------------| +| `clientKeys` | Comma-separated list of client-side attribute keys to return | +| `sharedKeys` | Comma-separated list of shared attribute keys to return | +| `allClientKeys` | Set to `true` to return all client-side attributes (overrides `clientKeys`) | +| `allSharedKeys` | Set to `true` to return all shared attributes (overrides `sharedKeys`) | -**Access Token:** +**Example** (Access Token): -Response: +**Response:** ```json {"client": {"attribute1": "value1", "attribute2": true}, "shared": {"shared1": "value2", "shared2": false}} @@ -53,10 +64,6 @@ Response: When the device profile payload type is set to Protobuf, the request and response use fixed schemas. See MQTT Attributes for the Protobuf schemas. - - ## Subscribe to Shared Attribute Updates Use the CoAP **Observe** option to receive push notifications when shared attributes change. The connection stays open and ThingsBoard sends a response each time a shared attribute is updated. diff --git a/src/content/_includes/docs/reference/gateway-api/attributes.mdx b/src/content/_includes/docs/reference/gateway-api/attributes.mdx index e4cc24031e..4ca4fab1bd 100644 --- a/src/content/_includes/docs/reference/gateway-api/attributes.mdx +++ b/src/content/_includes/docs/reference/gateway-api/attributes.mdx @@ -1,5 +1,6 @@ import DocLink from '@components/DocLink.astro'; import HostCode from '~/components/HostCode.astro'; +import { Aside } from '@astrojs/starlight/components'; ## Publish Client-Side Attributes @@ -24,24 +25,74 @@ Subscribe to the response topic first, then publish the request. **Publish:** `v1/gateway/attributes/request` +**Request:** + ```json -{ - "id": 1, - "device": "Device A", - "client": ["fw_version", "battery"], - "shared": ["targetFwVersion"] -} +{"id": 1, "device": "Device A", "clientKeys": "fw_version,battery", "sharedKeys": "targetFwVersion"} ``` | Field | Required | Description | |-------|----------|-------------| | `id` | Yes | Integer request identifier — echoed in the response | -| `device` | Yes | Device name | -| `client` | No | Client-side attribute keys to return | -| `shared` | No | Shared attribute keys to return | +| `device` | Yes | Name of a device connected through this gateway | +| `clientKeys` | No | Comma-separated client attribute keys to return; use `""` (empty string) to return all client attributes; omit the field entirely to exclude the client scope | +| `sharedKeys` | No | Comma-separated shared attribute keys to return; use `""` (empty string) to return all shared attributes; omit the field entirely to exclude the shared scope | + + + +Omitting **both** `clientKeys` and `sharedKeys` (sending only `id` and `device`) returns **all** client and **all** shared attributes in a single scope-separated response. + +**Response:** + +```json +{"id": 1, "device": "Device A", "client": {"fw_version": "1.0", "battery": 87}, "shared": {"targetFwVersion": "2.0"}} +``` + +### Example + +The following example is written in JavaScript and is based on [mqtt.js](https://github.com/mqttjs/MQTT.js). A pure command-line example is not available because subscribe and publish must happen in the same MQTT session. + +1. Save the **mqtt-js-gateway-attributes-request.js** file to your PC. + + + + The content of the **mqtt-js-gateway-attributes-request.js** file: + + ```js download='mqtt-js-gateway-attributes-request.js' title="mqtt-js-gateway-attributes-request.js" + var mqtt = require('mqtt'); + var client = mqtt.connect('mqtt://localhost', { + username: process.env.TOKEN + }); + + client.on('connect', function () { + console.log('connected'); + client.subscribe('v1/gateway/attributes/response'); + // clientKeys/sharedKeys are comma-separated strings. An empty value returns + // ALL keys in that scope, e.g. sharedKeys: "". Omit a field to exclude a scope. + var request = { id: 1, device: 'Device A', clientKeys: 'fw_version,battery', sharedKeys: 'targetFwVersion' }; + client.publish('v1/gateway/attributes/request', JSON.stringify(request)); + }); + + client.on('message', function (topic, message) { + console.log('response.topic: ' + topic); + console.log('response.body: ' + message.toString()); + client.end(); + }); + ``` + +2. Now, follow these steps: + + - + ```bash + export TOKEN=$ACCESS_TOKEN + node mqtt-js-gateway-attributes-request.js + ``` ## Subscribe to Shared Attribute Updates diff --git a/src/content/_includes/docs/reference/http-api/attributes.mdx b/src/content/_includes/docs/reference/http-api/attributes.mdx index 33314f0ff4..390870c831 100644 --- a/src/content/_includes/docs/reference/http-api/attributes.mdx +++ b/src/content/_includes/docs/reference/http-api/attributes.mdx @@ -1,6 +1,5 @@ import DocLink from '@components/DocLink.astro'; import HostCode from '~/components/HostCode.astro'; -import { Aside } from '@astrojs/starlight/components'; The HTTP Attributes API lets devices upload client-side attributes, request attribute values, and poll for shared attribute updates. For an explanation of attribute types, see Attributes. @@ -20,27 +19,31 @@ Upload client-side attributes with a `POST` request: ## Request Attribute Values -Request client-side and shared attribute values with a `GET` request: +Send a `GET` request to the attributes endpoint to read client-side and/or shared attribute values. The response groups results by scope: `{"client": {...}, "shared": {...}}`. - +**Endpoint:** -| Query parameter | Description | -|-----------------|-------------| + + +**Query parameters** — choose which attributes to return: + +| Parameter | Description | +|-----------|-------------| | `clientKeys` | Comma-separated list of client-side attribute keys to return | | `sharedKeys` | Comma-separated list of shared attribute keys to return | +| `allClientKeys` | Set to `true` to return all client-side attributes (overrides `clientKeys`) | +| `allSharedKeys` | Set to `true` to return all shared attributes (overrides `sharedKeys`) | + +**Example:** -Response: +**Response:** ```json {"client": {"attribute1": "value1", "attribute2": true}, "shared": {"shared1": "value2", "shared2": false}} ``` - - ## Subscribe to Shared Attribute Updates Poll for shared attribute changes with a long-lived `GET` request: diff --git a/src/content/_includes/docs/reference/mqtt-api/attributes.mdx b/src/content/_includes/docs/reference/mqtt-api/attributes.mdx index 3577f88393..56e4ea76c5 100644 --- a/src/content/_includes/docs/reference/mqtt-api/attributes.mdx +++ b/src/content/_includes/docs/reference/mqtt-api/attributes.mdx @@ -43,6 +43,13 @@ Ask ThingsBoard for the current values of client-side or shared attributes. Usef {"clientKeys": "firmwareVersion,serialNumber", "sharedKeys": "targetTemperature,enabled"} ``` +| Field | Description | +|-------|-------------| +| `clientKeys` | Comma-separated client-side attribute keys to return; `""` returns all client attributes; omit to exclude the client scope | +| `sharedKeys` | Comma-separated shared attribute keys to return; `""` returns all shared attributes; omit to exclude the shared scope | + +An empty request body (`{}`) returns all client and all shared attributes. + **Response:** ```json @@ -52,6 +59,53 @@ Ask ThingsBoard for the current values of client-side or shared attributes. Usef } ``` +**Example** + +The following example is written in JavaScript and is based on [mqtt.js](https://github.com/mqttjs/MQTT.js). Pure command-line examples are not available because subscribe and publish need to happen in the same MQTT session. + +1. Save the **mqtt-js-attributes-request.js** file to your PC. + + + + The content of the **mqtt-js-attributes-request.js** file: + + ```js download='mqtt-js-attributes-request.js' title="mqtt-js-attributes-request.js" + var mqtt = require('mqtt'); + var client = mqtt.connect('mqtt://localhost', { + username: process.env.TOKEN + }); + var requestId = 1; + + client.on('connect', function () { + console.log('connected'); + client.subscribe('v1/devices/me/attributes/response/+'); + // Specify keys as comma-separated strings. An empty value returns ALL keys + // in that scope, e.g. sharedKeys: "". Omit a field to exclude that scope. + var request = { clientKeys: 'firmwareVersion,serialNumber', sharedKeys: 'targetTemperature,enabled' }; + client.publish('v1/devices/me/attributes/request/' + requestId, JSON.stringify(request)); + }); + + client.on('message', function (topic, message) { + console.log('response.topic: ' + topic); + console.log('response.body: ' + message.toString()); + client.end(); + }); + ``` + +2. Now, follow these steps: + + + + ```bash + export TOKEN=$ACCESS_TOKEN + node mqtt-js-attributes-request.js + ``` +