DLMS JavaScript API

Connector functions DLMS JS API guide

In this javascript code, it is possible to use some defined functions to execute DLMS petitions in the connector function. We will explain them below.

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
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.

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 respresents 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:

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

Here is a payload example:

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:

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

connect();

Opens DLMS connection (default via TCP transport).

Kind: global function

The connection parameters need to be set before calling connect:

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 connecto to.
port number 4059 Port of the device you want to connecto to.
connectionType string ("TCP", "UDP") "TCP" Protocol of the device you want to connecto 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 be acorded with the securitySuite used
blockCipherKey byte[] as hexadecimal string null Key used for message encryption. The length of the key in bytes must be acorded with the securitySuite used

addAttr(classId, obisCode, attrId, type, value)

addAttr() is used both for get() and set() methods.

Param Type Mandatory Description
classId Array The class ID of the object to access
obisCode string The name of the object to access
attrId string The attribute index of the object
type string only on set() The data type of the value to set
value string only on set() The data value to set
// 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.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, this function call is implemented for the next use case
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

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 (-21474836482147483647) 0
double-long-unsigned number Unsigned32 (04294967295 0
octet-string Array of number string An ordered sequence of octets (8 bit bytes). May contain a dateTime value, see getDateTime() and getDate() [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 (099) 0
integer number Integer8 (-128127) 0
long number Integer16 (-3276832767) 0
unsigned number Unsigned8 (0255) 0
long-unsigned number Unsigned16 (065535) 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 (-90071992547409919007199254740991) 1 0
long64-unsigned number Unsigned64 (09007199254740991) 1 0
enum number The elements of the enumeration type are defined in the Attribute description or Method description section of a COSEM IC specification (0255) 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}
Warning

JavaScript does not support the whole range of DLMS numbers, see footnotes.

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
Info

For more information see DLMS Blue Book - Date and time formats (section 4.1.6.1 in Blue Book 12)

To transform this object to a Date see getDate(). 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().

get(descriptive) ⇒ Array

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.

Param Type Mandatory Default Description
descriptive boolean true Descriptive mode returns complex data as Array of object containing type and value for each object, non descritive mode flattens the returned array

Example for descriptive get:

// 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 descritive get

// 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"]]}
Non descriptive get

Complex values returned in a non-descriptive get cannot be passed as value in a set.

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

set(descriptive) ⇒ Array

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.

Param Type Mandatory Default Description
descriptive boolean 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.
Info

Normally, a set request should always return a null-data as type and null as value.

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).

// 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.

addMethod(classId, obisCode, methodId, type, value)

addMethod() is used for method() function.

Param Type Mandatory Description
classId Array The class ID of the object to access
obisCode string The name of the object to access
methodId string 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

method(descriptive) ⇒ Array

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.

Param Type Mandatory Default Description
descriptive boolean true Descriptive mode returns complex data as Array of object containing type and value for each object, non descritive mode flattens the returned array
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.

// 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

disconnect()

Close the DLMS connection.

Kind: global function

getCompactData(typeDescription, value, descriptive, italianMode) ⇒ Object

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

Kind: global function
Returns: Object (descriptive mode) or any type described as default type of a DLMS data type - Value of applying the typeDescription to the given value.

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

Here is a description example:

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"}
	]
}
Info
  • Simple data types just need to define the type as seen in 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.

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

var data = dlms.getCompactData(typeDescription, payload);
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]}]}
data = dlms.getCompactData(typeDescription, payload, false);
log(data) // Expected output: [1,2,[3],[4],[5,6],[83, 112, 97, 114, 101, 32, 79, 98, 106, 101, 99, 116]]

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 it’s value) The best-effort Date possible
// 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

getDateTime(value) -> Object

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 it’s value) Value containing a dateTime compatible value
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}

undefinedDateTime() -> Object

Get dateTime object with all it’s fields set to not specified.

You can also use unspecifiedDateTime().

Kind: global function Returns: Object

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