Tuning the documentation of calculated field function
This commit is contained in:
parent
fd0e7a543e
commit
07d81e58b1
@ -1,151 +1,164 @@
|
|||||||
#### Calculated field TBEL script function
|
## Calculated Field TBEL Script Function
|
||||||
|
|
||||||
The **calculate()** function is a user-defined script that allows you to perform custom calculations using [TBEL{:target="_blank"}](${siteBaseUrl}/docs${docPlatformPrefix}/user-guide/tbel/) on telemetry and attribute data.
|
The **calculate()** function is a user-defined script that enables custom calculations using [TBEL](\${siteBaseUrl}/docs\${docPlatformPrefix}/user-guide/tbel/) on telemetry and attribute data.
|
||||||
It receives arguments configured in the calculated field setup and an additional `ctx` object, which provides access to all arguments.
|
It receives arguments configured in the calculated field setup, along with an additional `ctx` object that provides access to all arguments.
|
||||||
|
|
||||||
##### Function signature
|
|
||||||
|
### Function Signature
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function calculate(ctx, arg1, arg2, ...): object | object[]
|
function calculate(ctx, arg1, arg2, ...): object | object[]
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Argument representation in the script
|
### Supported Arguments
|
||||||
|
|
||||||
Before describing how arguments are passed to the function, let's define how different argument types are **represented** inside the script.
|
There are three types of arguments supported in the calculated field configuration:
|
||||||
|
|
||||||
There are two types of arguments that can be used in the function:
|
#### Attribute and Latest Telemetry Arguments
|
||||||
|
|
||||||
* single value arguments - represent the latest telemetry data or attribute.
|
These arguments are single values and may be of type: boolean, int64 (long), double, string, or JSON.
|
||||||
```json
|
|
||||||
{
|
Attribute and Latest telemetry are single value arguments that may be one of: boolean, int64 (long), double, string and JSON.
|
||||||
"altitude": {
|
|
||||||
|
**Example: Convert Temperature from Fahrenheit to Celsius**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var temperatureC = (temperatureF - 32) / 1.8;
|
||||||
|
return {
|
||||||
|
"temperatureC": toFixed(temperatureC, 2)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, using `ctx` to access the argument as an object:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"temperatureF": {
|
||||||
"ts": 1740644636669,
|
"ts": 1740644636669,
|
||||||
"value": 1034
|
"value": 36.6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* when accessed via `ctx.args`, they remain objects:
|
You may notice that the object includes both the `value` of an argument and its timestamp as `ts`.
|
||||||
|
Let's modify the function that converts Fahrenheit to Celsius to also return the timestamp information:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var altitudeTimestamp = ctx.args.altitude.ts;
|
var temperatureC = (temperatureF - 32) / 1.8;
|
||||||
var altitudeValue = ctx.args.altitude.value;
|
return {
|
||||||
```
|
"ts": ctx.args.temperatureF.ts,
|
||||||
|
"values": { "temperatureC": toFixed(temperatureC, 2) }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
* when accessed as a **function parameter**, only the value is passed:
|
#### Time Series Rolling Arguments
|
||||||
|
|
||||||
```javascript
|
These contain time series data within a defined time window. Example format:
|
||||||
function calculate(ctx, altitude/*(single value argument)*/, temperature/*(time series rolling argument)*/) {
|
|
||||||
// altitude = 1035
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* time series rolling arguments - contain historical data within a defined time window.
|
```json
|
||||||
```json
|
{
|
||||||
{
|
|
||||||
"temperature": {
|
"temperature": {
|
||||||
"timeWindow": {
|
"timeWindow": {
|
||||||
"startTs": 1740643762896,
|
"startTs": 1740643762896,
|
||||||
"endTs": 1740644662896
|
"endTs": 1740644662896
|
||||||
},
|
},
|
||||||
"values": [
|
"values": [
|
||||||
{ "ts": 1740644355935, "value": 72.32 },
|
{ "ts": 1740644350000, "value": 72.32 },
|
||||||
{ "ts": 1740644365935, "value": 72.86 },
|
{ "ts": 1740644360000, "value": 72.86 },
|
||||||
{ "ts": 1740644375935, "value": 73.58 },
|
{ "ts": 1740644370000, "value": 73.58 },
|
||||||
{ "ts": 1740644385935, "value": "NaN" }
|
{ "ts": 1740644380000, "value": "NaN" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The values are always converted to type `double`, and `NaN` is used when conversion fails. One may use `isNaN(double): boolean` function to check that the value is a valid number.
|
||||||
|
|
||||||
|
**Example: Accessing time series rolling argument data**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var startOfInterval = temperature.timeWindow.startTs;
|
||||||
|
var endOfInterval = temperature.timeWindow.endTs;
|
||||||
|
var firstItem = temperature.values[0];
|
||||||
|
var firstItemTs = firstItem.ts;
|
||||||
|
var firstItemValue = firstItem.value;
|
||||||
|
var sum = 0.0;
|
||||||
|
// iterate through all values and calculate the sum using foreach:
|
||||||
|
foreach(t: temperature) {
|
||||||
|
if(!isNaN(t.value)) { // check that the value is a valid number;
|
||||||
|
sum += t.value;
|
||||||
}
|
}
|
||||||
```
|
}
|
||||||
|
// iterate through all values and calculate the sum using for loop:
|
||||||
|
sum = 0.0;
|
||||||
|
for(var i = 0; i < temperature.values.size; i++) {
|
||||||
|
sum += temperature.values[i].value;
|
||||||
|
}
|
||||||
|
// use built-in function to calculate the sum
|
||||||
|
sum = t.sum();
|
||||||
|
```
|
||||||
|
|
||||||
* when accessed via `ctx.args`, they remain rolling argument objects:
|
##### Built-in Methods for Rolling Arguments
|
||||||
|
|
||||||
```javascript
|
Time series rolling arguments support built-in functions for calculations. These functions accept an optional `ignoreNaN` boolean parameter.
|
||||||
var startOfInterval = temperature.timeWindow.startTs;
|
|
||||||
var firstTimestamp = temperature.values[0].ts;
|
|
||||||
var firstValue = temperature.values[0].value;
|
|
||||||
```
|
|
||||||
|
|
||||||
* when accessed as a **function parameter**, they are passed as rolling arguments, retaining their structure:
|
| Method | Default Behavior (`ignoreNaN = true`) | Alternative (`ignoreNaN = false`) |
|
||||||
|
|------------|-----------------------------------------------------|---------------------------------------------|
|
||||||
|
| `max()` | Returns the highest value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
||||||
|
| `min()` | Returns the lowest value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
||||||
|
| `mean()` | Computes the average value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
||||||
|
| `std()` | Calculates the standard deviation, ignoring NaN. | Returns NaN if any NaN values exist. |
|
||||||
|
| `median()` | Returns the median value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
||||||
|
| `count()` | Counts values, ignoring NaN values. | Counts all values, including NaN. |
|
||||||
|
| `last()` | Returns the most recent value, skipping NaN values. | Returns the last value, even if it is NaN. |
|
||||||
|
| `first()` | Returns the oldest value, skipping NaN values. | Returns the first value, even if it is NaN. |
|
||||||
|
| `sum()` | Computes the total sum, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
||||||
|
|
||||||
```javascript
|
|
||||||
function calculate(ctx, altitude/*(single value argument)*/, temperature/*(time series rolling argument)*/) {
|
|
||||||
var avgTemp = temperature.mean(); // Use rolling argument functions
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Built-in methods for rolling arguments**
|
Usage example:
|
||||||
|
|
||||||
Time series rolling arguments provide built-in functions for calculations.
|
```javascript
|
||||||
These functions accept an optional `ignoreNaN` boolean parameter, which controls how NaN values are handled.
|
var avgTemp = temperature.mean(); // Returns 72.92
|
||||||
Each function has two function signatures:
|
var tempMax = temperature.max(); // Returns 73.58
|
||||||
|
var valueCount = temperature.count(); // Returns 3
|
||||||
|
|
||||||
* **Without parameters:** `method()` → called **without parameters** and defaults to `ignoreNaN = true`, meaning NaN values are ignored.
|
var avgTempNaN = temperature.mean(false); // Returns NaN
|
||||||
* **With an explicit parameter:** `method(boolean ignoreNaN)` → called with a boolean `ignoreNaN` parameter:
|
var tempMaxNaN = temperature.max(false); // Returns NaN
|
||||||
* `true` → ignores NaN values (default behavior).
|
var valueCountNaN = temperature.count(false); // Returns 4
|
||||||
* `false` → includes NaN values in calculations.
|
```
|
||||||
|
|
||||||
| Method | Default Behavior (`ignoreNaN = true`) | Alternative (`ignoreNaN = false`) |
|
This function calculates air density using `altitude` (single value) and `temperature` (time series rolling argument).
|
||||||
|------------|--------------------------------------------------|---------------------------------------------|
|
|
||||||
| `max()` | Returns the highest value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
|
||||||
| `min()` | Returns the lowest value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
|
||||||
| `mean()` | Computes the average value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
|
||||||
| `std()` | Calculates the standard deviation, ignoring NaN. | Returns NaN if any NaN values exist. |
|
|
||||||
| `median()` | Returns the median value, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
|
||||||
| `count()` | Counts only valid (non-NaN) values. | Counts all values, including NaN. |
|
|
||||||
| `last()` | Returns the most recent non-NaN value. | Returns the last value, even if it is NaN. |
|
|
||||||
| `first()` | Returns the oldest non-NaN value. | Returns the first value, even if it is NaN. |
|
|
||||||
| `sum()` | Computes the total sum, ignoring NaN values. | Returns NaN if any NaN values exist. |
|
|
||||||
|
|
||||||
The following calculations are executed over the provided above arguments:
|
```javascript
|
||||||
|
function calculate(ctx, altitude, temperature) {
|
||||||
|
var avgTemperature = temperature.mean(); // Get average temperature
|
||||||
|
var temperatureK = (avgTemperature - 32) * (5 / 9) + 273.15; // Convert Fahrenheit to Kelvin
|
||||||
|
|
||||||
**Usage: default (`ignoreNaN = true`)**
|
// Estimate air pressure based on altitude
|
||||||
|
var pressure = 101325 * Math.pow((1 - 2.25577e-5 * altitude), 5.25588);
|
||||||
|
|
||||||
```javascript
|
// Air density formula
|
||||||
var avgTemp = temperature.mean();
|
var airDensity = pressure / (287.05 * temperatureK);
|
||||||
var tempMax = temperature.max();
|
|
||||||
var valueCount = temperature.count();
|
|
||||||
```
|
|
||||||
|
|
||||||
**Output:**
|
return {
|
||||||
|
"airDensity": airDensity
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
```json
|
##### Merging Time Series Arguments
|
||||||
{
|
|
||||||
"avgTemp": 72.92,
|
|
||||||
"tempMax": 73.58,
|
|
||||||
"valueCount": 3
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Usage: explicit (`ignoreNaN = false`)**
|
Time series rolling arguments can be **merged** to align timestamps across multiple datasets.
|
||||||
|
|
||||||
```javascript
|
| Method | Description | Parameters | Returns |
|
||||||
var avgTemp = temperature.mean(false); // Returns NaN if any NaN values exist
|
|:-----------------------------|:--------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------|
|
||||||
var tempMax = temperature.max(false); // Returns NaN if any NaN values exist
|
| `merge(other, settings)` | Merges with another rolling argument. Aligns timestamps and filling missing values with the previous available value. | <ul><li>`other` (another rolling argument)</li><li>`settings` (optional) - configuration object, supports:<ul><br/><li>`ignoreNaN` (boolean, default true) - controls whether NaN values should be ignored.</li><li>`timeWindow` (object, default {}) - defines a custom time window for filtering merged values.</li></ul></li></ul>| Merged object with timeWindow and aligned values. |
|
||||||
var valueCount = temperature.count(false); // Counts all values, including NaN
|
| `mergeAll(others, settings)` | Merges with multiple rolling arguments. Aligns timestamps and filling missing values with the previous available value. | <ul><li>`others` (array of rolling arguments)</li><li>`settings` (optional) - configuration object, supports:<ul><br/><li>`ignoreNaN` (boolean, default true) - controls whether NaN values should be ignored.</li><li>`timeWindow` (object, default {}) - defines a custom time window for filtering merged values.</li></ul></li></ul>| Merged object with timeWindow and aligned values.|
|
||||||
```
|
|
||||||
|
|
||||||
**Output:**
|
Assuming the following arguments and their values:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"avgTemp": "NaN",
|
|
||||||
"tempMax": "NaN",
|
|
||||||
"valueCount": 4
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Time series rolling arguments can be **merged** to align timestamps across multiple datasets.
|
|
||||||
|
|
||||||
| Method | Description | Parameters | Returns |
|
|
||||||
|:-----------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------|
|
|
||||||
| `merge(other, settings)` | Merges the current rolling argument with another rolling argument by aligning timestamps and filling missing values with the previous available value. | <ul><li>`other` (another rolling argument)</li><li>`settings` (optional) - configuration object, supports:<ul><br/><li>`ignoreNaN` (boolean, default true) - controls whether NaN values should be ignored.</li><li>`timeWindow` (object, default {}) - defines a custom time window for filtering merged values.</li></ul></li></ul>| Merged object with timeWindow and aligned values. |
|
|
||||||
| `mergeAll(others, settings)` | Merges the current rolling argument with multiple rolling arguments by aligning timestamps and filling missing values with the previous available value. | <ul><li>`others` (array of rolling arguments)</li><li>`settings` (optional) - configuration object, supports:<ul><br/><li>`ignoreNaN` (boolean, default true) - controls whether NaN values should be ignored.</li><li>`timeWindow` (object, default {}) - defines a custom time window for filtering merged values.</li></ul></li></ul>| Merged object with timeWindow and aligned values.|
|
|
||||||
|
|
||||||
**Example arguments:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"humidity": {
|
"humidity": {
|
||||||
"timeWindow": {
|
"timeWindow": {
|
||||||
"startTs": 1741356332086,
|
"startTs": 1741356332086,
|
||||||
@ -188,19 +201,19 @@ There are two types of arguments that can be used in the function:
|
|||||||
"value": 77
|
"value": 77
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var mergedData = temperature.merge(humidity, { ignoreNaN: false });
|
var mergedData = temperature.merge(humidity, { ignoreNaN: false });
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output:**
|
**Output:**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mergedData": {
|
"mergedData": {
|
||||||
"timeWindow": {
|
"timeWindow": {
|
||||||
"startTs": 1741356332086,
|
"startTs": 1741356332086,
|
||||||
@ -220,19 +233,19 @@ There are two types of arguments that can be used in the function:
|
|||||||
"values": [77.0, 46.0]
|
"values": [77.0, 46.0]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var mergedData = temperature.mergeAll([humidity, pressure], { ignoreNaN: true });
|
var mergedData = temperature.mergeAll([humidity, pressure], { ignoreNaN: true });
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output:**
|
**Output:**
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mergedData": {
|
"mergedData": {
|
||||||
"timeWindow": {
|
"timeWindow": {
|
||||||
"startTs": 1741356332086,
|
"startTs": 1741356332086,
|
||||||
@ -252,84 +265,136 @@ There are two types of arguments that can be used in the function:
|
|||||||
"values": [77.0, 46.0, 1025.0]
|
"values": [77.0, 46.0, 1025.0]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Function arguments
|
|
||||||
|
|
||||||
* `ctx` - context object that contains all provided arguments, in the representations described above.
|
|
||||||
|
|
||||||
Accessing arguments via `ctx`:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var altitude = ctx.args.altitude; // single value argument
|
|
||||||
var temperature = ctx.args.temperature; // time series rolling argument
|
|
||||||
```
|
|
||||||
|
|
||||||
* `arg1, arg2, ...` - user-defined arguments configured in the calculated field setup.
|
|
||||||
|
|
||||||
How they are passed depends on their type:
|
|
||||||
|
|
||||||
* **single value arguments** are passed as raw values **(e.g., 22.5, "ON")**.
|
|
||||||
* **time series rolling arguments** are passed as objects (containing multiple values).
|
|
||||||
|
|
||||||
##### Example: Air Density Calculation
|
|
||||||
|
|
||||||
This function calculates air density using `altitude` (single value argument) and `temperature` (time series rolling argument).
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
function calculate(ctx, altitude, temperature) {
|
|
||||||
var avgTemperature = temperature.mean(); // Get average temperature
|
|
||||||
var temperatureK = (avgTemperature - 32) * (5 / 9) + 273.15; // Convert Fahrenheit to Kelvin
|
|
||||||
|
|
||||||
// Estimate air pressure based on altitude
|
|
||||||
var pressure = 101325 * Math.pow((1 - 2.25577e-5 * altitude), 5.25588);
|
|
||||||
|
|
||||||
// Air density formula
|
|
||||||
var airDensity = pressure / (287.05 * temperatureK);
|
|
||||||
|
|
||||||
return {
|
|
||||||
"airDensity": airDensity
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* `altitude` is a single value, passed as number.
|
**Example: Freezer temperature analysis**
|
||||||
* `temperature` is a rolling argument, retaining its full structure.
|
|
||||||
|
|
||||||
##### Function return format
|
This function merges `temperature` data with the fridge's `defrost` status. It then analyzes the merged data to identify instances where the fridge is not in defrost mode, yet the internal air temperature is too high ( > -5° C).
|
||||||
|
|
||||||
The script should return a JSON object formatted according to the [ThingsBoard Telemetry Upload API](${siteBaseUrl}/docs${docPlatformPrefix}/user-guide/telemetry/#time-series-data-upload-api/).
|
```javascript
|
||||||
The return value must match one of the supported telemetry upload formats.
|
function calculate(ctx, temperature, defrost) {
|
||||||
|
var merged = temperature.merge(defrost);
|
||||||
|
var result = [];
|
||||||
|
|
||||||
The script must return data in a format compatible with ThingsBoard’s APIs.
|
foreach(item: merged) {
|
||||||
The correct return format depends on the calculated field output configuration:
|
if (item.v1 > -5.0 && item.v2 == 0) {
|
||||||
|
result.add({
|
||||||
* if latest telemetry is used for output, the function must return data according to the [Telemetry Upload API](${siteBaseUrl}/docs${docPlatformPrefix}/reference/mqtt-api/#attributes-api/).
|
ts: item.ts,
|
||||||
|
values: {
|
||||||
* without timestamps
|
issue: {
|
||||||
```json
|
temperature: item.v1,
|
||||||
{
|
defrostState: false
|
||||||
"airDensity": 1.06,
|
|
||||||
"someKey": "value"
|
|
||||||
}
|
}
|
||||||
```
|
}
|
||||||
* with a timestamp:
|
});
|
||||||
```json
|
}
|
||||||
{
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The result is a list of issues that may be used to configure alarm rules:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[{
|
||||||
|
"ts": 1741613833843,
|
||||||
|
"values": {
|
||||||
|
"issue": {
|
||||||
|
"temperature": -3.12,
|
||||||
|
"defrostState": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"ts": 1741613923848,
|
||||||
|
"values": {
|
||||||
|
"issue": {
|
||||||
|
"temperature": -4.16,
|
||||||
|
"defrostState": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Function return format
|
||||||
|
|
||||||
|
The return format depends on the output type configured in the calculated field settings (default: **Time Series**).
|
||||||
|
|
||||||
|
##### Time Series Output
|
||||||
|
|
||||||
|
The function must return a JSON object or array with or without a timestamp.
|
||||||
|
Examples below return 5 data points: airDensity (double), humidity (integer), hvacEnabled (boolean), hvacState (string) and configuration (JSON):
|
||||||
|
|
||||||
|
Without timestamp:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"airDensity": 1.06,
|
||||||
|
"humidity": 70,
|
||||||
|
"hvacEnabled": true,
|
||||||
|
"hvacState": "IDLE",
|
||||||
|
"configuration": {
|
||||||
|
"someNumber": 42,
|
||||||
|
"someArray": [1,2,3],
|
||||||
|
"someNestedObject": {"key": "value"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
With timestamp:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
"ts": 1740644636669,
|
"ts": 1740644636669,
|
||||||
"values": {
|
"values": {
|
||||||
"airDensity": 1.06,
|
"airDensity": 1.06,
|
||||||
"someKey": "value"
|
"humidity": 70,
|
||||||
|
"hvacEnabled": true,
|
||||||
|
"hvacState": "IDLE",
|
||||||
|
"configuration": {
|
||||||
|
"someNumber": 42,
|
||||||
|
"someArray": [1,2,3],
|
||||||
|
"someNestedObject": {"key": "value"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
}
|
||||||
|
```
|
||||||
|
|
||||||
* if attributes are used for output, the function must return data according to the [Attributes API](${siteBaseUrl}/docs${docPlatformPrefix}/user-guide/telemetry/#time-series-data-upload-api/).
|
Array containing multiple timestamps and different values of the `airDensity` :
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
[
|
||||||
{
|
{
|
||||||
"airDensity": 1.06,
|
"ts": 1740644636669,
|
||||||
"someKey": "value"
|
"values": {
|
||||||
|
"airDensity": 1.06
|
||||||
}
|
}
|
||||||
```
|
},
|
||||||
|
{
|
||||||
|
"ts": 1740644636670,
|
||||||
|
"values": {
|
||||||
|
"airDensity": 1.07
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Attribute Output
|
||||||
|
|
||||||
|
The function must return a JSON object **without timestamp** information.
|
||||||
|
Example below return 5 data points: airDensity (double), humidity (integer), hvacEnabled (boolean), hvacState (string) and configuration (JSON):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"airDensity": 1.06,
|
||||||
|
"humidity": 70,
|
||||||
|
"hvacEnabled": true,
|
||||||
|
"hvacState": "IDLE",
|
||||||
|
"configuration": {
|
||||||
|
"someNumber": 42,
|
||||||
|
"someArray": [1,2,3],
|
||||||
|
"someNestedObject": {"key": "value"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user