# JavaScript API

## Timeseries functions JS API guide

This guide describes how to write Custom Timeseries Functions and the contents of the JS API.

The API contains both the implementation of some predefined timeseries functions and some useful functions that can be used when writing Custom Aggregation Functions.


## Writing Custom Aggregation Function

### Input parameters

All functions will have three **implicit** input parameters that must be used for value calculation. 

* `receivedValues`: Array of Json of collected values. Each value will have two fields:
  * `value`: collected value. `value` type depends on Column's datastream type (please note that any datetime value will be formatted as an ISO string).
  * `at`: datetime of collected value. This value will be defined in ISO string. 
* `currentValue`: Columns current aggregated value. The type depends on aggregation function behavior.
* `extra`: Json with useful data for aggregated value updating. In some cases, when aggregated value must be updated, some previous auxiliary data must be used to calculate new values. The fields and their format will be defined taking into account the requirements of the function. For example, if an average data must be updated, previously received *number of elements* and their *sum* are necessary to calculate correctly new average value.

`receivedValues` example:
```javascript
"receivedValues":[
    {
        "value": 3,
        "at": "2023-03-01T00:30:00.000Z"
    },{
        "value": 5,
        "at": "2023-03-01T01:30:00.000Z"
    },{
        "value": 6,
        "at": "2023-03-01T02:30:00.000Z"
    },{
        "value": 8,
        "at": "2023-03-01T02:30:00.000Z"
    }
];
```

`currentValue` example:
```javascript
"currentValue": 4;
```

`extra` example:
```javascript
"extra": {
  "sum": 8,
  "count": 2  
};
```


### Timeserie function result
Defined function **must** return a result with specific format. It will be a json with two parameters:
* `value`: New calculated value.
* `extra`: A JSON with auxiliary data updated. The content of this JSON will be the same of the `extra` input parameter.

Result example:
```javascript
return {
    "executionResult": "OK",
    "value": 5,
    "extra": {
      "sum": 30,
      "count": 5  
    }
};
```

There is an auxiliary function that takes value and extra fields as parameters and returns the json with correct format. For further description of this function check documentation.

Result example using auxiliary function:
```javascript
return result.ok(5, {"sum":30}, {"count":6});
```

If some timeserie function execution throws an exception it will be internally caught. In this case result object will be like this:
```javascript
return {
    "executionResult": "Some javascript execution error message"
}
```

This behavior can be forced using `result.error` function with an Error object or an string message. For example:
```javascript

return result.error(new Error("Custom error message"));
// or
return result.error("Custom error message");
```


### Function implementation example
Taking described Input parameters and the Result to be returned into account, AVG Aggregation Function implementation example is shown here:
```javascript
var newCount = receivedValues.length;
var newSum = 0;
for(var recVal in receivedValues){
    newSum = newSum + receivedValues[recVal].value;
}
if (extra) {
    if(data.exists(extra.count)) newCount = newCount + extra.count;
    if(data.exists(extra.sum)) newSum = newSum + extra.sum;
}
var newValue = newSum / newCount;
return result.ok(newValue, {"sum":newSum}, {"count":newCount});
```

## JS API

#### data.exists(value)

Aux method to check if some value has value. If value is `undefined` or `null` it will return false.

**Kind**: global function  
**Returns**: Boolean - Json with result.  

| Param                    | Type                | Description                                  |
| ------------------------ | ------------------- | -------------------------------------------- |
| value                    | any    | value to be checked.                         |

Example of use:

```javascript
if(data.exists(receivedValues[recVal].value)){
    newSum = newSum + receivedValues[recVal].value;
}
```

#### data.undefined2null(value)

Aux method to replace all undefined fields with null values. Internally used to avoid issues when processing execution result. 

**Kind**: global function  
**Returns**: Any - Json with result.  

| Param                    | Type                | Description                                  |
| ------------------------ | ------------------- | -------------------------------------------- |
| value                    | any    | value to be checked and transformed.         |

Example of use:

```javascript
var newValue = data.undefined2null(undefined);

console.log(newValue) // null
```

#### result.ok(value, ...extraParams)

Used to build aggregation function result object

**Kind**: global function  
**Returns**: Object - Json with result.  

| Param                    | Type                | Description                                                    |
| ------------------------ | ------------------- | -------------------------------------------------------------- |
| value                    | any    | value to be used to update column data.                        |
| extraParams              | any    | List of parameters to be used to compound `extra` json. Each parameter must be a Json with unique parameter and value. |

Example of use:

```javascript
var newValue = result.ok(5, {"sum":30}, {"count":6});
```

#### result.error(error)

Internally used to build aggregation function result object when some execution exception is caught.

**Kind**: global function  
**Returns**: Object - Json with result.  

| Param                    | Type                | Description                                         |
| ------------------------ | ------------------- | -----------------------------------                 |
| error                    | any    | Caught error. It can be Error type or String type   |

Example of use:

```javascript
var newValue = result.error(new Error("Custom error message"));
```

#### aggFunct.AVG(receivedValues, currentValue, extra)

The engine will calculate the arithmetic average of all received values in the configured time bucket. Only available in numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.AVG(receivedValues, currentValue, extra);
```

#### aggFunct.COUNT(receivedValues, currentValue, extra)

The engine will store the count of total number values received per time bucket.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.COUNT(receivedValues, currentValue, extra);
```

#### aggFunct.FIRST(receivedValues, currentValue, extra)

The engine will store only the first received value per time bucket. The collection engine ignores the following values obtained in the same time bucket.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.FIRST(receivedValues, currentValue, extra);
```

#### aggFunct.GEO_AVG(receivedValues, currentValue, extra)

The engine will calculate the geometric average of all received values in the configured time bucket. Only available in numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.GEO_AVG(receivedValues, currentValue, extra);
```

#### aggFunct.LAST(receivedValues, currentValue, extra)

The engine will store only the last received value per time bucket, overwriting the previous ones.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.LAST(receivedValues, currentValue, extra);
```

#### aggFunct.MAX(receivedValues, currentValue, extra)

The engine will save the maximum value of all received values in the configured time bucket. Only available for numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.MAX(receivedValues, currentValue, extra);
```

#### aggFunct.MEDIAN(receivedValues, currentValue, extra)

The engine will calculate the median of all received values in the configured time bucket. Only available in numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |


Example of use:

```javascript
var newValue = aggFunct.MEDIAN(receivedValues, currentValue, extra);
```

#### aggFunct.MIN(receivedValues, currentValue, extra)

The engine will save the minimum value of all received values in the configured time bucket. Only available for numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.MIN(receivedValues, currentValue, extra);
```

#### aggFunct.STD_DEVIATION(receivedValues, currentValue, extra)

The engine will calculate the standard deviation of all received values in the configured time bucket. Only available in numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.STD_DEVIATION(receivedValues, currentValue, extra);
```

#### aggFunct.SUM(receivedValues, currentValue, extra)

The engine will save the sum of all received values in the configured time bucket. Only available for numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.SUM(receivedValues, currentValue, extra);
```

#### aggFunct.VARIANCE(receivedValues, currentValue, extra)

The engine will calculate the variance of all received values in the configured time bucket. Only available in numeric values.

**Kind**: global function  
**Returns**: Object - Json with result.

| Param                    | Type                   | Description                                                               |
| ------------------------ | -------------------    | --------------------------------------------------------------            |
| receivedValues           | Array     | Array of objects with new values to be used for final value calculation.  |
| currentValue             | any       | Column's current value.                                                   |
| extra                    | Object    | JSON with auxiliary parameters for final value calculation.               |

Example of use:

```javascript
var newValue = aggFunct.VARIANCE(receivedValues, currentValue, extra);
```

#### log.trace(...msg)

Creates *TRACE* level logging messages. It concatenates msg parameters to compound message to be logged.

**Kind**: global function  

| Param  | Type             | Description                                                                                                          |
| ------ | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| ...msg | any | The function takes as parameters a list of elements to be concatenated to generate the string message to be printed. |

Example of use:

```javascript
log.trace("This is a trace message");
```

#### log.debug(...msg)

Creates *DEBUG* level logging messages. It concatenates msg parameters to compound message to be logged.

**Kind**: global function  

| Param  | Type             | Description                                                                                                          |
| ------ | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| ...msg | any | The function takes as parameters a list of elements to be concatenated to generate the string message to be printed. |

Example of use:

```javascript
log.debug("This is a debug message");
```

#### log.info(...msg)

Creates *INFO* level logging messages. It concatenates msg parameters to compound message to be logged.

**Kind**: global function  

| Param  | Type             | Description                                                                                                          |
| ------ | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| ...msg | any | The function takes as parameters a list of elements to be concatenated to generate the string message to be printed. |

Example of use:

```javascript
log.info("This is an info message");
```

#### log.warn(...msg)

Creates *WARN* level logging messages. It concatenates msg parameters to compound message to be logged.

**Kind**: global function  

| Param  | Type             | Description                                                                                                          |
| ------ | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| ...msg | any | The function takes as parameters a list of elements to be concatenated to generate the string message to be printed. |

Example of use:

```javascript
log.warn("This is a warn message");
```

#### log.error(...msg)

Creates *ERROR* level logging messages. It concatenates msg parameters to compound message to be logged.

**Kind**: global function  

| Param  | Type             | Description                                                                                                          |
| ------ | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| ...msg | any | The function takes as parameters a list of elements to be concatenated to generate the string message to be printed. |

Example of use:

```javascript
log.error("This is an error message");
```

#### date.fromString(stringDate)

Create Date object from ISO string.

**Kind**: global function  

| Param      | Type                | Description       |
| ------     | ----------------    | ----------------- |
| stringDate | string | Iso string date   |

Example of use:

```javascript
var parsedDate = date.fromString("2022-01-01T00:00:00.000Z");
```

#### date.toString(date)

Returns iso string representation of Date object. 

**Kind**: global function  

| Param      | Type                | Description   |
| ------     | ----------------    | ------------- |
| date       | Date   | Date object   |

Example of use:

```javascript
var isoDate = date.toString(new Date());
```

#### date.compare(date1, date2)

Compares two dates. These dates can be passed as strings in ISO format or as Date objects. The result is:
 - 0: when both are equal.
 - negative: when date1 is lower than date2   
 - positive: when date1 is higher than date2    

**Kind**: global function  

| Param      | Type                | Description   |
| ------     | ----------------    | ------------- |
| date1      | Date   | Date object   |
| date2      | Date   | Date object   |

Example of use:

```javascript
var date1 = date.fromString("2022-01-01T00:00:00.000Z");
var date2 = date.fromString("2022-01-02T00:00:00.000Z");
var result = date.compare(date1, date2);
```
