# DLMS JavaScript API

## Connector functions DLMS JS API guide

This JavaScript code provides predefined functions to execute DLMS requests from the connector function. They are explained below.

{{% notice style="tip" %}}
For Smart Gas devices, there is a specialized extension of this API called [DLMS Gas API](/api/device_integration/connector_functions/protocol_apis/dlms_gas/) which simplifies many common operations.
{{% /notice %}}


Types of south criteria for your DLMS connector function:

| Description                                                                                                                                                      | Format                          | Example                       |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ----------------------------- |
| Identification via **_OBIS code_** for notifications that contain a description element                                                                          | `dlms://obis/<obis-code>`       | `dlms://obis/0.0.66.0.48.255` |
| Identification via **_template ID_** for notifications containing only 1 or more octet-string values and taking first byte of each `octet-string` as template ID | `dlms://template/<template-id>` | `dlms://template/48`          |

{{% notice style="warning" %}}
The OBIS Code needs to be specified using only dots as separator, don't use the complex form `0-0:66.0.48.255` or the Connector Function will not be called.
{{% /notice %}}

### Input parameters in Collection Connector Function

The main script will have access to three main vars:

- entity: json with flattened operation target device entity representation.
- gateway: json with flattened gateway entity representation. It can be null.
- payload: json that represents the DLMS message received from the device.
- contextParams: json object with execution context information. It can have some of this params:
  - apiKey: device or user apikey.
  - remoteIp: remote host where DLMS message is invoked.
  - obisCode: OBIS code of the message arrived.
  - templateId: Template identifier of the message arrived.

ContextParams for COLLECTION Connector function for DLMS connection:

```json
{
  "apiKey": "97c9ceae-c4ee-49ea-ad50-e499bb55ac63",
  "obisCode": "0.1.2.3.3.5",
}
```

Here is a payload example:

```javascript
payload = [
	{
	    "obisCode": "0.0.49.0.75.254",
	    "attrId": 2,
	    "classId": 1,
	    "type": "octet-string",
	    "value": [2, 3, 215, 0]
	},
	{
	    "obisCode": "0.0.49.0.77.254",
	    "attrId": 4,
	    "classId": 1,
	    "type": "unsigned",
	    "value": 1
	}
]
```

### JS DLMS API

For REQUEST Connector Functions we will use the functions described below. You have an object, named `dlms`, with all the functions described. You must use `dlms.<function>`.

If you want to collect data after executing any of these function you can call *collectCF* and you can set various obis code in the URL provided as you can see in the next example:

```javascript
collectCF(result.data, "dlms://obis/0.1.2.3.4.5");
```

#### dlms.connect()

Opens DLMS connection (default via TCP transport).

**Kind**: global function  

The connection parameters need to be set before calling `connect`:

```javascript
dlms.ip = "127.0.0.1"
dlms.connect()
```

| Config name                    | Type                                                                                                        | Default value | Description                                                                                                                                      |
|--------------------------------|-------------------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `ip`                           | `string`                                                                                                    | `null`        | IP address of the device you want to connect to.                                                                                                |
| `port`                         | `number`                                                                                                    | `4059`        | Port of the device you want to connect to.                                                                                                      |
| `connectionType`               | `string` (`"TCP"`, `"UDP"`)                                                                                 | `"TCP"`       | Protocol of the device you want to connect to.                                                                                                  |
| `cwport`                       | `number`                                                                                                    | `16`          | Client WPort.                                                                                                                                    |
| `swport`                       | `number`                                                                                                    | `1`           | Server WPort.                                                                                                                                    |
| `refMethod`                    | `string` (`"LN"`, `"SN"`)                                                                                   | `"LN"`        | Server WPort.                                                                                                                                    |
| `securityLevel`                | `string` (`"MANUFACTURER"`, `"HIGH"`, `"LOW"`, `"SHA1`, `"SHA256"`, `"MD5"`, `"GMAC"`, `"ECDSA"`, `"NONE"`) | `"NONE"`      | Authentication mechanism to use in the connection.                                                                                               |
| `password`                     | `string`                                                                                                    | `null`        | Password to use with the authentication mechanism.                                                                                               |
| `timeout`                      | `number`                                                                                                    | `5000`        | Timeout of the connection.                                                                                                                       |
| `security`                     | `string` (`NONE`, `AUTHENTICATION`, `ENCRYPTION`, `AUTHENTICATION_ENCRYPTION`)                              | `null`        | Security used in every message. `null` value will be treated as `NONE`                                                                           |
| `securitySuite`                | `string` (`SUITE_0`, `SUITE_1`, `SUITE_2`)                                                                  | `null`        | Authentication, encryption and key wrapping algorithm. `null` value will be treated as `SUITE_0`                                                 |
| `authenticationKey`            | `byte[] as hexadecimal string`                                                                              | `null`        | Key used for message authentication. The length of the key in bytes must match the securitySuite used                                  |
| `blockCipherKey`               | `byte[] as hexadecimal string`                                                                              | `null`        | Key used for message encryption. The length of the key in bytes must match the securitySuite used                                      |
| `hesSystemTitle`               | `byte[] as hexadecimal string`                                                                              | `null`        | Overrides default System Title to be sent in requests to client                                                                                  |
| `ignoreSystemTitleInCiphering` | `boolean`                                                                                                   | `false`       | Whether the optional `hesSystemTitle` should be ignored (not sent) when sending ciphered messages                                                |
| `forceGetWithoutList`          | `boolean`                                                                                                   | `false`       | Whether to force `get()` by default to request elements one by one instead of using a list when `MULTIPLE_REFERENCES` conformance is enabled     |
| `forceSetWithoutList`          | `boolean`                                                                                                   | `false`       | Whether to force `set()` by default to request elements one by one instead of using a list when `MULTIPLE_REFERENCES` conformance is enabled     |
| `conformance`                  | `string[]` (`"MULTIPLE_REFERENCES"`, `"GENERAL_PROTECTION"`)                                                | `[]`          | Communication conformance values. For example, 'MULTIPLE_REFERENCES' specifies it is possible to send to device  multiple obis in unique request |

{{% notice style="warning" %}}

In case of `security` parameter is not `NONE`, next default values will be set:
- `blockCipherKey`: `000102030405060708090A0B0C0D0E0F`
- `authenticationKey`: `D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF`

{{% /notice %}}

### Add attributes

`addAttr()` is used both for `get()` and `set()` methods and has multiple signatures:

#### dlms.addAttr(classId, obisCode, attrId)

Applicable for normal gets.

| Param      | Type                | Description                          |
| ---------- | ------------------- | ------------------------------------ |
| `classId`  | `Array`             | The class ID of the object to access |
| `obisCode` | `string`            | The name of the object to access     |
| `attrId`   | `number`            | The attribute index of the object    |

```javascript
// After connection has been established
dlms.addAttr(1, "1.2.3.4.5.6", 2)
var getResult = dlms.get() // More details on get() next
```

#### dlms.addAttr(classId, obisCode, attrId, type, value)

Applicable for normal sets.

| Param      | Type                | Description                          |
| ---------- | ------------------- | ------------------------------------ |
| `classId`  | `Array`             | The class ID of the object to access |
| `obisCode` | `string`            | The name of the object to access     |
| `attrId`   | `number`            | The attribute index of the object    |
| `type`     | `string`            | The data type of the value to set    |
| `value`    | see data types      | The data value to set                |

```javascript
// After connection has been established
dlms.addAttr(1, "1.2.3.4.5.6", 2, "unsigned", 254)
var setResult = dlms.set() // More details on set next
```

#### dlms.addAttr(classId, obisCode, attrId, data)

Applicable for normal sets.

| Param      | Type                               | Description                              |
| ---------- | ---------------------------------- | ---------------------------------------- |
| `classId`  | `Array`                            | The class ID of the object to access     |
| `obisCode` | `string`                           | The name of the object to access         |
| `attrId`   | `number`                           | The attribute index of the object        |
| `data`     | `object` (with `type` and `value`) | The data with both type and value to set |

where:

| `data` attribute | Type           | Description                       |
| ---------------- | -------------- | --------------------------------- |
| `type`           | `string`       | The data type of the value to set |
| `value`          | see data types | The data value to set             |

This is an alternate way of using `addAttr(classId, obisCode, attrId, type, value)` with the data parameters in an object.

```javascript
// After connection has been established
//dlms.addAttr(1, "1.2.3.4.5.6", 2, "unsigned", 254)
dlms.addAttr(1, "1.2.3.4.5.6", 2, {"type": "unsigned", "value": 254}) // This is similar to the previous addAttr (commented)
var setResult = dlms.set() // More details on set next
```

It's helpful when used in combination with `get()`.

```javascript
// After connection has been established
dlms.addAttr(1, "1.2.3.4.5.6", 2)
var getResult = dlms.get() // More details on get next
dlms.addAttr(1, "1.2.3.4.5.255", 2, getResult[0]) // Set on object 1.2.3.4.5.255 the value (and data type) retrieved from object 1.2.3.4.5.6
var setResult = dlms.set() // More details on set next
```

#### dlms.addAttr(classId, obisCode, attrId, selectiveAccess)

Applicable for gets with selective access.

| Param             | Type                                                    | Description                          |
| ----------------- | ------------------------------------------------------- | ------------------------------------ |
| `classId`         | `Array`                                                 | The class ID of the object to access |
| `obisCode`        | `string`                                                | The name of the object to access     |
| `attrId`          | `number`                                                | The attribute index of the object    |
| `selectiveAccess` | `object` (with `accessSelector` and `accessParameters`) | The selective access descriptor      |

where:

| `selectiveAccess` attribute | Type                             | Description           |
| -------------------------- | -------------------------------- | --------------------- |
| `accessSelector`           | `number`                         | The access selector   |
| `accessParameters`         | `object` with `type` and `value` | The access parameters |

and

| `accessParameters` attribute | Type           | Description                             |
| ---------------------------- | -------------- | --------------------------------------- |
| `type`                       | `string`       | The data type of access parameters      |
| `value`                      | see data types | The data value of the access parameters |

```javascript
dlms.addAttr(1, "1.2.3.4.5.6", 2, {"accessSelector": 1, "accessParameters": {"type": "unsigned", "value": 254}})
```

{{% notice style="info" %}}
The proper access selector and parameters depend on the manufacturer and object type. Some may implement _by range_ and _by entry_ defined in the _DLMS Blue Book_ - _Parameters for selective access to the buffer attribute_ (section 4.3.6 in _Blue Book 12_).
{{% /notice %}}

```javascript
// Example by range
dlms.addAttr(7, '7.0.99.99.3.255', 2, {
	accessSelector: 1,
	accessParameters: {
		type: 'structure',
		value: [{
			type: 'structure',
			value: [{
				type: 'long-unsigned',
				value: 1
			}, {
				type: 'octet-string',
				value: [0, 0, 1, 1, 0, 255]
			}, {
				type: 'integer',
				value: 2
			}, {
				type: 'long-unsigned',
				value: 0
			}]
		}, {
			type: 'double-long-unsigned',
			value: 1735884000
		}, {
			type: 'double-long-unsigned',
			value: 1736229600
		}, {
			type: 'array',
			value: []
		}]
	}
})
```

#### dlms.addAttr(attribute)

Generic signature applicable for all cases.

| Attribute          | Type                             | Mandatory                             | Description                          |
| ------------------ | -------------------------------- | ------------------------------------- | ------------------------------------ |
| `classId`          | `Array`                          | {{% icon check %}}                    | The class ID of the object to access |
| `obisCode`         | `string`                         | {{% icon check %}}                    | The name of the object to access     |
| `attrId`           | `number`                         | {{% icon check %}}                    | The attribute index of the object    |
| `type`             | `string`                         | only on `set()`                       | The data type of the value to set    |
| `value`            | see data types                   | only on `set()`                       | The data value to set                |
| `accessSelector`   | `number`                         | only on `get()` with selective access | The access selector                  |
| `accessParameters` | `object` with `type` and `value` | only on `get()` with selective access | The access parameters                |

where:

| `accessParameters` attribute | Type           | Description                             |
| ---------------------------- | -------------- | --------------------------------------- |
| `type`                       | `string`       | The data type of access parameters      |
| `value`                      | see data types | The data value of the access parameters |

```javascript
// For normal get
dlms.addAttr({classId: 1, obisCode: "1.2.3.4.5.6", attrId: 2})
// For normal set
dlms.addAttr({classId: 1, obisCode: "1.2.3.4.5.6", attrId: 2, type: "unsigned", value: 254})
// For get with selective access
dlms.addAttr({classId: 1, obisCode: "1.2.3.4.5.6", attrId: 2, accessSelector: 1, accessParameters: {type: "unsigned", value: 254}})
```

##### data types

| Name                   | Value type                      | Compatible type in set | Description                                                                                                                                                       | Example                                                                                                                                      |
| ---------------------- | ------------------------------- | ---------------------- | -----------------------------------------------------------------------------------------------------------------------------------------------------             | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `null-data`            | `null`                          |                        |                                                                                                                                                                   | `null`                                                                                                                                       |
| `array`                | `Array` of `object`             |                        | Complex data, all elements must be of the same type                                                                                                               | `[{"type":"unsigned","value":1},{"type":"unsigned","value":2}]`                                                                              |
| `structure`            | `Array` of `object`             |                        | Complex data, different elements possible                                                                                                                         | `[{"type":"unsigned","value":1},{"type":"visible-string","value":"two"}]`                                                                    |
| `boolean`              | `boolean`                       |                        |                                                                                                                                                                   | `true`                                                                                                                                       |
| `bit-string`           | `Array` of `boolean`            | `string`               | An ordered sequence of boolean values. In `set()` an `string` may be used instead of `array` of `boolean` as bit-string representation                            | `[true,false,true]` (`"101"` as string representation in `set()`)                                                                            |
| `double-long`          | `number`                        |                        | Integer32 (`-2147483648`...`2147483647`)                                                                                                                          | `0`                                                                                                                                          |
| `double-long-unsigned` | `number`                        |                        | Unsigned32 (`0`...`4294967295`                                                                                                                                    | `0`                                                                                                                                          |
| `octet-string`         | `Array` of `number`             | `string`               | An ordered sequence of octets (8 bit bytes). May contain a _dateTime_ value, see [getDateTime()](#dlmsgetdatetimevalue) and [getDate()](#dlmsgetdatevalue--date) | `[116,101,115,116]` (or `"test"` in `set()`)                                                                                                 |
| `visible-string`       | `string`                        |                        | An ordered sequence of ASCII characters                                                                                                                           | `"test"`                                                                                                                                     |
| `utf8-string`          | `string`                        |                        | An ordered sequence of characters encoded as UTF-8                                                                                                                | `"test"`                                                                                                                                     |
| `bcd`                  | `number`                        |                        | Binary Coded Decimal (`0`...`99`)                                                                                                                                 | `0`                                                                                                                                          |
| `integer`              | `number`                        |                        | Integer8 (`-128`...`127`)                                                                                                                                         | `0`                                                                                                                                          |
| `long`                 | `number`                        |                        | Integer16 (`-32768`...`32767`)                                                                                                                                    | `0`                                                                                                                                          |
| `unsigned`             | `number`                        |                        | Unsigned8 (`0`...`255`)                                                                                                                                           | `0`                                                                                                                                          |
| `long-unsigned`        | `number`                        |                        | Unsigned16 (`0`...`65535`)                                                                                                                                        | `0`                                                                                                                                          |
| `compact-array`        | `Array` of `object`             |                        | Provides an alternative, compact encoding of complex data, all elements must be of the same type                                                                  | `[{"type":"unsigned","value":1},{"type":"unsigned","value":2}]`                                                                              |
| `long64`               | `number`                        |                        | Integer64 (`-9007199254740991`...`9007199254740991`) [^js-numbers]                                                                                                | `0`                                                                                                                                          |
| `long64-unsigned`      | `number`                        |                        | Unsigned64 (`0`...`9007199254740991`) [^js-numbers]                                                                                                               | `0`                                                                                                                                          |
| `enum`                 | `number`                        |                        | The elements of the enumeration type are defined in the Attribute description or Method description section of a COSEM IC specification (`0`...`255`)             | `0`                                                                                                                                          |
| `float32`              | `number`                        |                        | Floating point number in 4 bytes                                                                                                                                  | `0`                                                                                                                                          |
| `float64`              | `number`                        |                        | Floating point number in 8 bytes                                                                                                                                  | `0`                                                                                                                                          |
| `date-time`            | `object`                        |                        | Object containing all fields in a _dateTime_ object                                                                                                               | `{"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2,"hour":10,"minute":26,"second":55,"hundredthsOfSecond":0,"deviation":-60,"status":0}` |
| `date`                 | `object`                        |                        | Object containing `year`, `month`, `dayOfMonth` and `dayOfWeek` fields in a _dateTime_ object                                                                     | `{"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2}`                                                                                     |
| `time`                 | `object`                        |                        | Object containing `hour`, `minute`, `second` and `hundredthsOfSecond` fields in a _dateTime_ object                                                               | `{"hour":16,"minute":1,"second":2,"hundredthsOfSecond":20}`                                                                                  |

{{% notice style="warning" %}}
JavaScript does not support the whole range of DLMS numbers, see [footnotes](#fn:1).
{{% /notice %}}

[^js-numbers]: See [MAX_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) and [MIN_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER)

###### dateTime objects

A dateTime object is used to specify all possible values for `date-time`, `date` and `time` DLMS types. It may define the following attributes:

| Name                 | Normal values                                 | Additional values                                                                              |
| -------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `year`               | `0..65534`                                    | `65535` means `unspecified`                                                                    |
| `month`              | `1..12` (jan-dec)                             | `253` = daylight savings end, `254` daylight savings begin, `255` not specified                |
| `dayOfMonth`         | `1..31`                                       | `224..252` reserved, `253` 2nd last day of month, `254` last day of month, `255` not specified |
| `dayOfWeek`          | `1..7` (mon-sun)                              | `255` not specified                                                                            |
| `hour`               | `0..23`                                       | `255` not specified                                                                            |
| `minute`             | `0..59`                                       | `255` not specified                                                                            |
| `second`             | `0..59`                                       | `255` not specified                                                                            |
| `hundredthsOfSecond` | `0..99`                                       | `255` not specified                                                                            |
| `deviation`          | `-720..720` (in minutes of local time to UTC) | `32768` not specified                                                                          |
| `status`             | 8 bit flags                                   | `255` not specified                                                                            |

{{% notice style="info" %}}
For more information see _DLMS Blue Book_ - _Date and time formats_ (section 4.1.6.1 in _Blue Book 12_)
{{% /notice %}}

To transform this object to a `Date` see [getDate()](#dlmsgetdatevalue--date). Keep in mind that sets of `date-time`, `date`, `time` and `octet-string` do not accept a `Date` object. To transform it to a _dateTime_ object use [getDateTime()](#dlmsgetdatetimevalue).

#### dlms.get(descriptive, forceWithoutList)

Executes a multi DLMS get attribute request with the previously specified payload (`addAttr(classId, obisCode, attrId)`).

**Kind**: global function  
**Returns**: `Array` - Array of JSONs with responses. Each JSON will have six fields: `result` of the get operation, the requested `classId`, `obisCode` and `attrId`, `type` with the data type of the received value and the `value` received from the device. An optional `error` field may be returned for any error that happened during the get.

| Param              | Type      | Mandatory          | Default | Description                                                                                                                                                                                       |
| ------------------ | --------- | ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  |
| `descriptive`      | `boolean` | {{% icon times %}} | `true`  | Descriptive mode returns complex data as `Array` of `object` containing `type` and `value` for each object, non descriptive mode flattens the returned array                                       |
| `forceWithoutList` | `boolean` | {{% icon times %}} | `false` | Whether to force the get to request elements one by one instead of using a list when `MULTIPLE_REFERENCES` conformance is enabled (if it's not set the global `forceGetWithoutList` will be used) |

Example for descriptive get:

```javascript
// After connection has been established
dlms.addAttr(1, "0.0.0.0.0.0", 2) // Example for null-data
dlms.addAttr(1, "0.0.0.0.0.1", 2) // Example for array
dlms.addAttr(1, "0.0.0.0.0.2", 2) // Example for structure
dlms.addAttr(1, "0.0.0.0.0.3", 2) // Example for boolean
dlms.addAttr(1, "0.0.0.0.0.4", 2) // Example for bit-string
dlms.addAttr(1, "0.0.0.0.0.5", 2) // Example for double-long
// Rest on number examples are omitted because they are similar to double-long
dlms.addAttr(1, "0.0.0.0.0.6", 2) // Example for octet-string
dlms.addAttr(1, "0.0.0.0.0.7", 2) // Example for visible-string
// utf8-string example is omitted because it's similar to visible-string

var result = dlms.get() // Descriptive (true can also be passed)
log(result[0]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.0","attrId":2,"type":"null-data","value":null}]
log(result[1]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.1","attrId":2,"type":"array","value":[{"type":"long-unsigned","value":1},{"type":"long-unsigned","value":2},{"type":"long-unsigned","value":3}]}
log(result[2]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.2","attrId":2,"type":"structure","value":[{"type":"unsigned","value":1},{"type":"long-unsigned","value":2},{"type":"array","value":[{"type":"visible-string","value":"one"},{"type":"visible-string","value":"two"}]}]}
log(result[3]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.3","attrId":2,"type":"boolean","value":true}
log(result[4]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.4","attrId":2,"type":"bit-string","value":[true,false,true]}
log(result[5]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.5","attrId":2,"type":"double-long","value":1}
log(result[6]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.6","attrId":2,"type":"octet-string","value":[116,101,115,116]}
log(result[7]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.7","attrId":2,"type":"visible-string","value":"test"}
```

Example for non descriptive get

```javascript
// After connection has been established
// Simple value types are returned exactly the same as descriptive mode, null-data is included to viasually see this
dlms.addAttr(1, "0.0.0.0.0.0", 2) // Example for null-data
// Simple value types are returned exactly the same as descriptive mode, null-data is included to viasually see this
dlms.addAttr(1, "0.0.0.0.0.1", 2) // Example for array
dlms.addAttr(1, "0.0.0.0.0.2", 2) // Example for structure

var result = dlms.get(false) // Non descriptive
log(result[0]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.0","attrId":2,"type":"null-data","value":null}]
log(result[1]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.1","attrId":2,"type":"array","value":[1,2,3]}
log(result[2]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.2","attrId":2,"type":"structure","value":[1,2,["one","two"]]}
```

{{% notice style="warning" title="Non descriptive get" %}}
Complex values returned in a non-descriptive get cannot be passed as value in a set.
{{% /notice %}}

##### get results

- `success`
- `hardware-fault`
- `temporary-failure`
- `read-write-denied`
- `object-undefined`
- `object-class-inconsistent`
- `object-unavailable`
- `type-unmatched`
- `scope-of-access-violated`
- `data-block-unavailable`
- `long-get-aborted`
- `no-long-get-in-progress`
- `long-set-aborted`
- `no-long-set-in-progress`
- `data-block-number-invalid`
- `other-reason`

#### dlms.set(descriptive)

Executes a multi DLMS set attribute request with the previously specified payload (`addAttr(classId, obisCode, attrId, type, value)`).

**Kind**: global function  
**Returns**: `Array` - Array of JSONs with responses. Each JSON will have six fields: `result` of the set operation, the requested `classId`, `obisCode` and `attrId`, `type` with the data type of the received value and the `value` received from the device. An optional `error` field may be returned for any error that happened during the set.

| Param              | Type      | Mandatory          | Default | Description                                                                                                                                                                                       |
| ------------------ | --------- | ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `descriptive`      | `boolean` | {{% icon times %}} | `true`  | **Does not matter on `set()`**. It's included to have the same signature as `get()` and in case a device returns something in a set.                                                              |
| `forceWithoutList` | `boolean` | {{% icon times %}} | `false` | Whether to force the set to request elements one by one instead of using a list when `MULTIPLE_REFERENCES` conformance is enabled (if it's not set the global `forceSetWithoutList` will be used) |

{{% notice style="info" %}}
Normally, a **set** request should always return a `null-data` as `type` and `null` as `value`.
{{% /notice %}}

{{% notice style="warning" %}}
A **set** request for complex data **must** always specify the `value` in a descriptive manner (as `Array` of `Object` containing both `type` and `value` for each and all elements and sub-elements in case of more nested complex elements).
{{% /notice %}}

```javascript
// After connection has been established
dlms.addAttr(1, "0.0.0.0.0.0", 2, "null-data", null) // Example for null-data
dlms.addAttr(1, "0.0.0.0.0.1", 2, "array", [{"type":"long-unsigned","value":1},{"type":"long-unsigned","value":2},{"type":"long-unsigned","value":3}]) // Example for array
dlms.addAttr(1, "0.0.0.0.0.2", 2, "structure", [{"type":"unsigned","value":1},{"type":"long-unsigned","value":2},{"type":"array","value":[{"type":"visible-string","value":"one"},{"type":"visible-string","value":"two"}]}]) // Example for structure
dlms.addAttr(1, "0.0.0.0.0.3", 2, "boolean", false) // Example for boolean
dlms.addAttr(1, "0.0.0.0.0.4", 2, "bit-string", [true, false, true, false]) // Example for bit-string as boolean array (default type)
dlms.addAttr(1, "0.0.0.0.0.4", 2, "bit-string", "1010") // Example for bit-string as string with the bit-string representation (alternative set value type, a get will always return it as boolean array)
dlms.addAttr(1, "0.0.0.0.0.5", 2, "double-long", 1) // Example for double-long
// Rest on number examples are omitted because they are similar to double-long
dlms.addAttr(1, "0.0.0.0.0.6", 2, "octet-string", [116, 101, 115, 116]) // Example for octet-string as byte array (default type)
dlms.addAttr(1, "0.0.0.0.0.6", 2, "octet-string", "test") // Example for octet-string as string (alternative set value type, a get will always return it as byte array)
dlms.addAttr(1, "0.0.0.0.0.7", 2, "visible-string", "test") // Example for visible-string
// utf8-string example is omitted because it's similar to visible-string

var result = dlms.set() // Descriptive mode does not really matter, because return should always be null-data.
log(result[0]) // Expected output: {"result":"success","classId":1,"obisCode":"0.0.0.0.0.0","attrId":2,"type":"null-data","value":null}]
// All remaining results are similar, including returning null-data.
```

##### set results

They are the same as [get results](#get-results).

#### dlms.addMethod(classId, obisCode, methodId, type, value)

`addMethod()` is used for `method()` function.

| Param      | Type                | Mandatory          | Description                                      |
| ---------- | ------------------- | ------------------ | ------------------------------------------------ |
| `classId`  | `Array`             | {{% icon check %}} | The class ID of the object to access             |
| `obisCode` | `string`            | {{% icon check %}} | The name of the object to access                 |
| `methodId` | `string`            | {{% icon check %}} | The method index in the object                   |
| `type`     | `string`            | when needed        | The data type of the value to pass to the method |
| `value`    | `string`            | when needed        | The data value to pass to the method             |

#### dlms.method(descriptive)

Executes a multi DLMS method (or action) request with the previously specified payload (`addMethod(classId, obisCode, methodId, type, value)`).

**Kind**: global function  
**Returns**: `Array` - Array of JSONs with responses. Each JSON will have six fields: `result` of the method operation, the requested `classId`, `obisCode` and `methodId`, `type` with the data type of the received value and the `value` received from the device. An optional `error` field may be returned for any error that happened during the method (for example an error decoding the optional return parameters).

| Param         | Type      | Mandatory          | Default | Description                          |
| ------------- | --------- | ------------------ | ------- | ------------------------------------ |
| `descriptive` | `boolean` | {{% icon times %}} | `true`  | Descriptive mode returns complex data as `Array` of `object` containing `type` and `value` for each object, non descriptive mode flattens the returned array |

{{% notice style="info" %}}
A **method** request may need and/or return whatever `type` and `value` it's needed. Check Method description section of a COSEM IC specification.
{{% /notice %}}

```javascript
// After connection has been established
dlms.addMethod(7, "1.0.99.1.0.255", 2) // Example for method needing null-data as parameter (default type and value)
dlms.addMethod(7, "1.0.99.1.0.254", 2, "unsigned", 0) // Example for method needing 0 (unsigned) as parameter

var result = dlms.method()
log(result[0]) // Expected output: {"result":"success","classId":1,"obisCode":"1.0.99.1.0.255","methodId":2,"type":"null-data","value":null}]
log(result[1]) // Expected output: {"result":"success","classId":1,"obisCode":"1.0.99.1.0.254","methodId":2,"type":"boolean","value":true}
```

##### action results

- `success`
- `hardware-fault`
- `temporary-failure`
- `read-write-denied`
- `object-undefined`
- `object-class-inconsistent`
- `object-unavailable`
- `type-unmatched`
- `scope-of-access-violated`
- `data-block-unavailable`
- `long-action-aborted`
- `no-long-action-in-progress`
- `other-reason`

#### dlms.initializeNextFrameCounter(currentFrameCounter)

Sets the invocation counter of the ciphering to the next value of the received frame counter. This is used for devices that maintain two separate frame counters (one for transmit and one for receive). Usually the current _Management Frame Counter - On-line_ is received in a _CompactFrame_ notification and that value is the one that needs to be passed to this function for that device.

**Kind**: global function

| Param                 | Type     | Mandatory          | Description                                   |
| --------------------- | -------- | ------------------ | --------------------------------------------- |
| `currentFrameCounter` | `number` | {{% icon check %}} | The current frame counter sent by the device. |

#### dlms.getInvocationCounter()

Returns the current invocation counter of the ciphering.

**Kind**: global function
**Returns**: `number` (integer).

#### dlms.disconnect()

Close the DLMS connection.

**Kind**: global function

#### dlms.getCompactData(typeDescription, value, descriptive, italianMode)

Extract the compact data serialized in a byte array according to the description given.

**Kind**: global function  
**Returns**: `Object` - Object containing `result` and/or `error`. On success, `result` contains the parsed compact data (either in descriptive (with `type` in each value) or non-descriptive (direct values) format depending on the `descriptive` parameter). On error, the `error` will contain the error description and `result` may be `null` or contain a best-effort decoding of the compact data that may be incorrect.

| Param             | Type                                                                                    | Mandatory          | Default | Description                                                                                                                                                 |
| ----------------- | --------------------------------------------------------------------------------------- | ------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `typeDescription` | `Object`                                                                                | {{% icon check %}} |         | Object with the description of the data. The attributes of the object will be different according to the data expected'                                    |
| `value`           | `Array` of `number` (or `Object` containing an `octet-string` `type` with its `value`) | {{% icon check %}} |         | Array of bytes with the compact data (for example the DLMS notification data or element received)                                                           |
| `descriptive`     | `boolean`                                                                               | {{% icon times %}} | `true`  | Descriptive mode returns complex data as `Array` of `object` containing `type` and `value` for each object, non descriptive mode flattens the returned array |
| `italianMode`     | `boolean`                                                                               | {{% icon times %}} | `false` | Determines if the compact data decoding of arrays must be in italian mode or not (`explicitArrayLengthInContent`)                                           |

Here is a description example:

```javascript
var typeDescription = {"type": "structure", "items": [
		{"type": "long-unsigned"},
		{"type": "unsigned"},
		{"type": "array", "length": 1, "subtype": {"type": "long-unsigned"}},
		{"type": "array", "length": 1, "subtype": {"type": "double-long-unsigned"}},
		{"type": "structure", "items": [
			{"type": "unsigned"}, {"type": "long-unsigned"}
		]},
		{"type": "octet-string"}
	]
}
```

{{% notice style="info" %}}
- Simple data types just need to define the `type` as seen in [data types](#data-types).
- `array` type description **must** define a `subtype`, which is a `typeDescription`, and a `length` when not using `italianMode`. `italianMode` (or `explicitArrayLengthInContent`) does not need the length because it's encoded in the received data.
- `structure` type description **must** define an `array` of `items`, which are each a `typeDescription`.
- `compact-array` is not supported inside a compact data.
{{% /notice %}}

Here is an example of the function result in descriptive and non descriptive modes:

```javascript
var {result: data, error} = dlms.getCompactData(typeDescription, payload);
if (error) {
    log("Error: " + error);
} else {
    log(data) // Expected output: {"type":"structure","value":[{"type":"long-unsigned","value":1},{"type":"unsigned","value":2},{"type":"array","value":[{"type":"long-unsigned","value":3}]},{"type":"array","value":[{"type":"double-long-unsigned","value":4}]},{"type":"structure","value":[{"type":"unsigned","value":5},{"type":"long-unsigned","value":6}]},{"type":"octet-string","value":[83,112,97,114,101,32,79,98,106,101,99,116]}]}
}

var {result: data, error} = dlms.getCompactData(typeDescription, payload, false);
if (error) {
    log("Error: " + error);
} else {
    log(data) // Expected output: [1,2,[3],[4],[5,6],[83, 112, 97, 114, 101, 32, 79, 98, 106, 101, 99, 116]]
}
```

#### dlms.getDate(value) ⇒ `Date`

Extract the `Date` of a _dateTime_ object or an `octet-string`. Some _dateTime_ objects or `octet-string` may not contain a complete date and this method will return a date that may not be as accurate as you expect. You should check the _dateTime_ object for unspecified value.

**Kind**: global function
**Returns**: `Date`

| Param             | Type                                                                                                                                 | Mandatory          | Default | Description                     |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | ------- | ------------------------------- |
| `value`           | _dateTime_ object or `Array` of `number` (or `Object` having `type` `date-time`, `date`, `time` or `octet-string` with its `value`) | {{% icon check %}} |         | The best-effort `Date` possible |

```javascript
// compact-data containing all 

var dateTime = data[0]
log(dateTime) // Expected output: {"type":"date-time","value":{"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2,"hour":10,"minute":26,"second":55,"hundredthsOfSecond":0,"deviation":-60,"status":0}}
log(dlms.getDate(dateTime).toISOString()) // Expected output: 2023-11-28T11:26:55.000Z
log(dlms.getDate(dateTime.value).toISOString()) // Expected output: 2023-11-28T11:26:55.000Z

var date = data[1]
log(date) // Expected output: {"type":"date","value":{"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2}}
log(dlms.getDate(date).toISOString()) // Expected output: 2023-11-28T00:00:00.000Z
log(dlms.getDate(date.value).toISOString()) // Expected output: 2023-11-28T00:00:00.000Z

var time = data[2]
log(time) // Expected output: {"type":"date","value":{"hour":16,"minute":1,"second":2,"hundredthsOfSecond":20}}
log(dlms.getDate(time).toISOString()) // Expected output: 0000-01-01T16:01:02.200Z
log(dlms.getDate(time.value).toISOString()) // Expected output: 0000-01-01T16:01:02.200Z

var octet = data[3]
log(octet) // Expected output: {"type":"octet-string","value":[7, 231, 11, 28, 2, 10, 26, 55, 0, -1, -60, 0]}
log(dlms.getDate(octet).toISOString()) // Expected output: 2023-11-28T11:26:55.000Z
log(dlms.getDate(octet.value).toISOString()) // Expected output: 2023-11-28T11:26:55.000Z

var undefinedDateTimeInOctet = data[4]
log(undefinedDateTimeInOctet) // Expected output: {"type":"octet-string","value":[-1, -1, -1, -1, -1, -1, -1, -1, -1, -128, 0, -1]}
log(dlms.getDate(undefinedDateTimeInOctet).toISOString()) // Expected output: 0000-01-01T00:00:00.000Z
log(dlms.getDate(undefinedDateTimeInOctet.value).toISOString()) // Expected output: 0000-01-01T00:00:00.000Z

log(dlms.getDate(dlms.unspecifiedDateTime()).toISOString()) // Expected output: 0000-01-01T00:00:00.000Z
```

#### dlms.getDateTime(value)

Extract the _dateTime_ object of a `Date` or an `octet-string`. The resulting _dateTime_ objects generated from a `Date` will use UTC time specifying a deviation of `0`. If you need something else construct the _dateTime_ object manually.

**Kind**: global function
**Returns**: `Object`

| Param             | Type                                                                                          | Mandatory          | Default | Description                                  |
| ----------------- | --------------------------------------------------------------------------------------------  | ------------------ | ------- | -------------------------------------------- |
| `value`           | `Date` or `Array` of `number` (or `Object` having `type` of `octet-string` with its `value`) | {{% icon check %}} |         | Value containing a dateTime compatible value |


```javascript
log(dlms.getDateTime(new Date('2023-11-28T10:24:00.000Z'))) // Expected output: {"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2,"hour":10,"minute":24,"second":0,"hundredthsOfSecond":0,"deviation":0,"status":0}
log(dlms.getDateTime(new Date('2023-11-28T10:24:00.299Z'))) // Expected output: {"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2,"hour":10,"minute":24,"second":0,"hundredthsOfSecond":29,"deviation":0,"status":0}
log(dlms.getDateTime(new Date('Tue Nov 28 2023 11:24:00 GMT+0100'))) // Expected output: {"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2,"hour":10,"minute":24,"second":0,"hundredthsOfSecond":0,"deviation":0,"status":0}

// compact-data containing all values

var octet = data[0]
log(octet) // Expected output: {"type":"octet-string","value":[7, 231, 11, 28, 2, 10, 26, 55, 0, -1, -60, 0]}
log(dlms.getDateTime(octet)) // Expected output: {"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2,"hour":10,"minute":26,"second":55,"hundredthsOfSecond":0,"deviation":-60,"status":0}
log(dlms.getDateTime(octet)) // Expected output: {"year":2023,"month":11,"dayOfMonth":28,"dayOfWeek":2,"hour":10,"minute":26,"second":55,"hundredthsOfSecond":0,"deviation":-60,"status":0}

var undefinedDateTimeInOctet = data[1]
log(undefinedDateTimeInOctet) // Expected output: {'type': 'octet-string', 'value': [-1, -1, -1, -1, -1, -1, -1, -1, -1, -128, 0, -1]}
log(dlms.getDateTime(undefinedDateTimeInOctet)) // Expected output: {"year":65535,"month":255,"dayOfMonth":255,"dayOfWeek":255,"hour":255,"minute":255,"second":255,"hundredthsOfSecond":255,"deviation":32768,"status":255}
log(dlms.getDateTime(undefinedDateTimeInOctet.value)) // Expected output: {"year":65535,"month":255,"dayOfMonth":255,"dayOfWeek":255,"hour":255,"minute":255,"second":255,"hundredthsOfSecond":255,"deviation":32768,"status":255}
```

#### dlms.undefinedDateTime()

Get _dateTime_ object with all its fields set to not specified.

You can also use `unspecifiedDateTime()`.

**Kind**: global function
**Returns**: `Object`

```javascript
dlms.addAttr(1, '0.0.0.0.0.0', 2, 'octet-string', dlms.undefinedDateTime())
log(dlms.getDate(dlms.undefinedDateTime()).toISOString()) // Expected output: 0000-01-01T00:00:00.000Z
```

#### dlms.unspecifiedDateTime()

Get _dateTime_ object with all its fields set to not specified.

You can also use `undefinedDateTime()`.

**Kind**: global function
**Returns**: `Object`

```javascript
dlms.addAttr(1, '0.0.0.0.0.0', 2, 'octet-string', dlms.unspecifiedDateTime())
log(dlms.getDate(dlms.unspecifiedDateTime()).toISOString()) // Expected output: 0000-01-01T00:00:00.000Z
```