node-enocean-ble
v0.0.2
Published
The node-enocean-ble monitors and parses telegrams coming from EnOcean BLE devices (rocker wall switch and multisensor). This module supports telegram authentication based on AES128 in CCM (Counter with CBC-MAC) mode and replayed telegram detection.
Downloads
2
Maintainers
Readme
node-enocean-ble
The node-enocean-ble monitors and parses telegrams coming from EnOcean BLE devices (rocker wall switch and multisensor). This module supports telegram authentication based on AES128 in CCM (Counter with CBC-MAC) mode and replayed telegram detection.
Supported OS
The node-enocean-ble supports only Linux-based OSes, such as Raspbian, Ubuntu, and so on. This module does not support Windows and Mac OS for now. (If @abandonware/noble is installed properly, this module might work well on such OSes.)
Dependencies
See the document of the @abandonware/noble for details on installing the @abandonware/noble.
Note that the noble must be run as root on most of Linux environments. See the document of the @abandonware/noble for details.
Installation
Before installing the @abandonware/noble, some linux libraries related Bluetooth as follows must be installed if the OS is Ubuntu/Debian/Raspberry OS.
$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
If you use other OS, follow the instructions described in the document of the @abandonware/noble.
After installing the libraries above, install the @abandonware/noble and the node-enocean-ble (this module) as follows:
$ cd ~
$ npm install @abandonware/noble
$ npm install node-enocean-ble
Table of Contents
- Commissioning
- Quick Start
EnoceanBle
object- Telegram objects
- Supported EnOcean BLE devices
- Release Note
- References
- License
Commissioning
Commissioning is a process that the receiver (in this document, it is the node-enocean-ble) learns the EnOcean BLE devices. For commissioning, you need to obtain commissioning data from your EnOcean BLE device. The commissioning data consists of 3 components:
- Source address
- Security key
- Ordering code
In order to complete commissioning, all components above are required. The EnOcean BLE devices support 3 ways to obtain the commissioning data:
QR code commissioning
A QR code are printed in the back side of each EnOcean BLE device. You can read the QR code using a QR code reader app installed on your smartphone. The commissioning data is as follows:
30SE21500012345+Z38C1D339863D7F8D0000000000000000+30PE8221-A280+2PDC03+S07000001
See the description of the commission()
method for more details.
NFC commissioning
The multisensor products support NFC commissioning. Installing a NFC reader app on your smartphone, you can read the commissioning data touching the device with your smartphone. The commissioning data is as follows:
30SE50010012345+Z2358E2F4682E641A0000000000000000+30PS6221-K516+2PDA05+3C31+16S01000000
See the description of the commission()
method for more details.
Radio-based commissioning
The multisensor products have a LRN button. Pressing the button, a commissioning telegram is sent as a BLE advertising packet. The ndoe-enocean-ble supports such telegram, you can monitor and obtain the commissioning data.
But commissioning telegram contains only the source address and security key. In order to complete commissioning, you need to know the ordering code in advance. The ordering code is printed in the back side of the device.
See the description of the addCommission()
method for more details.
Quick Start
In order to monitor telegrams, load the node-enocean-ble, register your EnOcean BLE devices, set a callback for incoming telegrams, and start to monitor.
// Load the node-enocean-ble and get a `EnoceanBle` constructor object
const EnoceanBle = require('node-enocean-ble');
// Create an `EnoceanBle` object
const enocean = new EnoceanBle();
// Commissioning (Easyfit Double Rocker Wall Switch)
enocean.commission('30SE21500012345+Z38C1D339863D7F8D0000000000000000+30PE8221-A280+2PDC03+S07000001');
// Commissioning (STM 550B Multisensor Module)
enocean.commission('30SE50010012345+Z2358E2F4682E641A0000000000000000+30PS6221-K516+2PDA05+3C31+16S01000000');
// Set a callback for incoming telegrams
enocean.ondata = (telegram) => {
console.log(telegram);
};
// Start to monitor telegrams
enocean.start().then(() => {
// Successfully started to monitor telegrams
}).catch((error) => {
// Failed to start to monitor telegrams
console.error(error);
});
When a telegram is received from the rocker wall switch, the code above will output the parsed telegram data as follows:
{
address: 'e21500012345',
manufacturer: '03da',
sequence: 1435,
type: 'button',
data: { button: 'B0', pressed: true },
signature: '6daea9f1',
authenticated: true,
replayed: false
}
When a telegram is received from the multisensor, the code above will output the parsed telegram data as follows:
{
address: 'e50010012345',
manufacturer: '03da',
sequence: 47577,
type: 'sensor',
data: {
temperature: 27.8,
humidity: 66.5,
illumination: 326,
acceleration: {
status: 3,
description: 'Sensor disabled',
x: 2.86,
y: 3.57,
z: 3.58
},
contact: false,
voltage: 3222
},
signature: '10e650c8',
authenticated: true,
replayed: false
}
See the section "Telegram objects" for the details.
EnoceanBle
object
In order to use the node-enocean-ble, you have to load the node-enocean-ble module as follows:
const EnoceanBle = require('node-enocean-ble');
You can get an EnoceanBle
constructor from the code above. Then you have to create an EnoceanBle
object from the EnoceanBle
constructor as follows:
const enocean = new EnoceanBle();
The EnoceanBle
constructor takes an argument optionally. It must be a hash object containing the properties as follows:
Property | Type | Required | Description
:--------|:-------|:---------|:-----------
noble
| Noble | option | a Noble object of the @abandonware/noble
module
The node-enocean-ble module uses the @abandonware/noble
module in order to interact with BLE devices. If you want to interact other BLE devices using the @abandonware/noble
module, you can create a Noble
object by yourself, then pass it to this module. If you don't specify a Noble
object to the noble
property, this module automatically create a Noble
object internally.
The sample code below shows how to pass a Noble
object to the EnoceanBle
constructor.
// Create a Noble object
const noble = require('@abandonware/noble');
// Create an `EnoceanBle` object
const EnoceanBle = require('../lib/enocean-ble.js');
const enocean = new EnoceanBle({ 'noble': noble });
;
In the code snippet above, the variable enocean
is an EnoceanBle
object. The enocean
object has a lot of methods as described in sections below.
commission(cstring) method
The commission()
method registers an EnOcean BLE device using commissioning data string from QR code or NFC. This method takes a commissioning data.
let cdata = enocean.commission('30SE21500012345+Z38C1D339863D7F8D0000000000000000+30PE8221-A280+2PDC03+S07000001');
This method returns an object representing the commissioning data parsed the commissioning data string:
{
address: 'e21500012345',
securityKey: '38c1d339863d7f8d0000000000000000',
orderingCode: 'E8221-A280',
stepCodeRevision: 'DC-03',
serial: '07000001'
}
The structure of the commissioning data object is as follows:
Property | Type | Description
:------------------|:--------|:--------------------------
address
| String | Source Address
securityKey
| String | Security Key
orderingCode
| String | Ordering Code
stepCodeRevision
| String | Step Code - Revision
serial
| String | Serial Number
If a commissioning data string from NFC is passed to this method, the value of the serial
will be an empty string.
If the address
in the specified commissioning data string has been already registered, the old one will be replaced by the new one.
addCommission(cdata) method
The addCommission()
method registers an EnOcean BLE device manually. This method takes an object containing commissioning data as follows:
Property | Type | Required | Description
:--------------------------------------|:-------|:---------|:------------
cdata
| Object | Required |
address
| String | Required | Source address
securityKey
| String | Required | AES128 security key
orderingCode
| String | Required | Ordering code
The address
and securityKey
must be specified in hexadecimal representation. They are not case-sensitive.
This method is mainly used when you obtain the commissioning data from a commissioning telegram (Radio-based commissioning). The telegram contains the source address and security key, but the ordering code. You can see the ordering code on the back side of the device.
The supported ordering codes are shown in the section "Supported EnOcean BLE devices".
let cdata = enocean.addCommission({
address: 'E21500012345',
securityKey: '38c1d339863d7f8d0000000000000000',
orderingCode: 'E8221-A280'
});
console.log(cdata);
The code above will output the result as follows:
{
address: 'E21500012345',
securityKey: '38c1d339863d7f8d0000000000000000',
orderingCode: 'E8221-A280',
stepCodeRevision: '',
serial: ''
}
Each value of the stepCodeRevision
and the serial
is always an empty string.
deleteCommission(address) method
The deleteCommission()
method deletes a registered commissioning data. The address of the device must be passed to this method. The value of address is not case-sensitive. This method returns the deleted commissioning data object.
let cdata = enocean.deleteCommission('E21500012345');
console.log(cdata);
The code above will output the result as follows:
{
address: 'E21500012345',
securityKey: '38c1d339863d7f8d0000000000000000',
orderingCode: 'E8221-A280',
stepCodeRevision: '',
serial: ''
}
getCommissions() method
The getCommissions()
method gets a list of the registered commissioning data. This method return an Array
object containing the registered commissioning data objects.
let cdata_list = enocean.getCommissions();
console.log(cdata_list);
The code above will output the result as follows:
[
{
address: 'e50010012345',
securityKey: '2358e2f4682e641a0000000000000000',
orderingCode: 'S6221-K516',
stepCodeRevision: '',
serial: ''
},
{
address: 'e21500012345',
securityKey: '38c1d339863d7f8d0000000000000000',
orderingCode: 'E8221-A280',
stepCodeRevision: '',
serial: ''
}
]
start([filters]) method
The start()
method starts to monitor telegrams coming from EnOcean BLE devices. This method returns a Promise
object. This method takes an argument filters
optionally.
Property | Type | Required | Description
:--------------------------------|:--------|:---------|:------------
filters
| Object | Optional |
auth
| Boolean | Optional | If true
, unauthenticated telegrams will be ignored. The default value is true
.
replay
| Boolean | Optional | If true
, replayed telegrams will be ignored. The default value is true
.
The node-enocean-ble supports the telegram authentication based on AES128 in CCM (Counter with CBC-MAC) mode. This mechanism ensures integrity and authenticity of transmitted telegrams. If the auth
is set to true
, unauthenticated telegrams will be ignored.
The EnOcean BLE devices send a telegram 2 or 3 times for purpose of ensuring the reachability. In normal cases, applications which use the node-enocean-ble might not need the replayed telegrams. The replay detection is used for cutting off the redundant telegrams and preventing replay attacks. The node-enocean-ble always checks a sequence counter in each telegram. If the counter in the telegram is less than or equal to the last counter, the telegram will be marks as a replayed telegram. If the replay
is set to true
, the replay detection is enabled and such telegrams will be ignored.
Whenever a telegram is received, the callback function set to the ondata
will be called. When a telegram is received, a hash object representing the telegram will be passed to the callback function.
See the Quick Start section for more details.
stop() method
The stop()
method stops to monitor telegrams coming from EnOcean BLE devices. This method returns a Promise
object.
enocean.stop().then(() => {
// Stopped to monitor successfully
}).catch((error) => {
// Failed to stop to monitor
});
ondata
event handler
If a callback function is set to the ondata
property, the callback function will be called whenever an telegram is received from a EnOcean BLE device during the monitoring process is active (from the moment when the start()
method is called, to the moment when the stop()
method is called).
A Telegram object will be passed to the callback function. See the "Telegram objects" section for more details.
Telegram objects
After the start()
method is invoked, the ondata
event handler will be called whenever a telegram comes from the EnOcean BLE devices. A telegram object is passed to the callback. There are 3 object types: SwitchTelegram
, SensorTelegram
, and CommissioningTelegram
object. The basic structure of the object is as follows:
Property | Type | Description
:---------------|:--------|:-----------
address
| String | Source address of the device. (e.g., "cb4eb903c96d"
)
manufacturer
| String | Manufacturer ID. The value is always "03da"
, which means "EnOcean GmbH". The ID is assigned by Bluetooth SIG.
sequence
| Integer | Sequence counter. The value is in the range of 0 to 0xFFFFFFFF.
type
| String | Type of object. It could be "button"
(SwitchTelegram
), "sensor"
(SensorTelegram
), or "commissioning"
(CommissioningTelegram
).
data
| Object | The structure depends on the type of object (the value of type
). See the sections below for details.
signature
| String | Security signature.
authenticated
| Boolean | If the telegram was authenticated (verified) by the telegram authentication process based on AES128 in CCM (Counter with CBC-MAC) mode, the value will be true
. Otherwise, the value will be false
.
replayed
| Boolean | If the sequence counter (the value of sequence
) is less than or equal to the last counter (i.e., the telegram is replayed), the value will be true
. Otherwise, it will be false
.
If the value of the type
is "commissioning"
(CommissioningTelegram
), the signature
and authenticated
do not exist in the object.
SwitchTelegram
object
When a button on a Rocker Wall Switch is pressed or released, a SwichTelegram
object will be passed to the callback. The structure of the data
in the object is as follows:
Property | Type | Description
:---------------|:--------|:-----------
data
| Object | Button status
button
| String | Button name which was pressed or released. It could be "A0"
, "A1"
, "B0"
, or "B1"
.
pressed
| String | Button action. When a button was pressed, the value will be true
. When a button was released, the value will be false
.
{
address: 'e21500012345',
manufacturer: '03da',
sequence: 1453,
type: 'button',
data: { button: 'A0', pressed: true },
signature: '8649a1e6',
authenticated: true,
replayed: false
}
SensorTelegram
object
When a telegram comes from a multisensor, a SensorTelegram
object will be passed to the callback. The structure of the data
in the object is as follows:
Property | Type | Description
:---------------|:--------|:-----------
data
| Object | Sensor status
temperature
| Float | Temperature (degC)
humidity
| Float | Relative Humidity (%RH)
illumination
| Integer | Illumination (lx)
acceleration
| Object | Acceleration (See the description below for more details)
status
| Integer | Status code
description
| String | Meaning of the status code
x
| Float | Acceleration of the x-axis (g)
y
| Float | Acceleration of the y-axis (g)
z
| Float | Acceleration of the z-axis (g)
contact
| Boolean | Status of the Magnet Contact. true
means "close", false
means "open".
voltage
| Integer | Voltage of the backup battery (mV)
energy
| Integer | Energy Level (%)
The mapping of acceleration.status
and acceleration.description
is as follows:
status
| description
:--------|:----------------------------
0
| Acceleration value out of bound
1
| Periodic update
2
| Acceleration wake
3
| Sensor disabled
For now, the acceleration
is experimental. The multisensor products seem to disable the report of acceleration by default. Unfortunately, I don't know how to enable the report of acceleration. Therefore, I'm not sure whether the result is correct or not.
If a backup battery is mounted in the device, the voltage
exists while the energy
does not exit, and vice versa.
- When a backup battery is mounted:
{
address: 'e50010012345',
manufacturer: '03da',
sequence: 47810,
type: 'sensor',
data: {
temperature: 24.9,
humidity: 64.5,
illumination: 250,
acceleration: {
status: 3,
description: 'Sensor disabled',
x: 4.63,
y: -4.15,
z: 4.22
},
contact: false,
voltage: 3222
},
signature: '3828b6b7',
authenticated: true,
replayed: false
}
- When a backup battery is not mounted:
{
address: 'e50010012345',
manufacturer: '03da',
sequence: 47825,
type: 'sensor',
data: {
temperature: 26.4,
humidity: 64,
illumination: 291,
acceleration: {
status: 3,
description: 'Sensor disabled',
x: 4.95,
y: -1.55,
z: 4.22
},
contact: false,
energy: 100
},
signature: '17103bcf',
authenticated: true,
replayed: false
}
CommissioningTelegram
object
When the LRN button on the multisensor is pressed, a CommissioningTelegram
object will be passed to the callback. The structure of the data
in the object is as follows:
Property | Type | Description
:---------------|:--------|:-----------
data
| Object | Sensor status
key
| String | Security key
address
| String | Source address
{
address: 'e50010012345',
manufacturerId: '03da',
sequence: 47803,
type: 'commissioning',
data: { key: '2358e2f4682e641a0000000000000000', address: 'e50010012345' },
replayed: false
}
Supported EnOcean BLE devices
For now, the EnOcean BLE devices which the node-enocean-ble supports are as follows:
Product Name | Manufacturer | Ordering Code :------------|:-------------|:-------------- PTM 215B | EnOcean | S3221-A215 STM 550B Multisensor Module | EnOcean | S6221-K516 Easyfit Single Rocker Wall Switch for BLE - EWSSB | EASYFIT | E8221-A270 Easyfit Double Rocker Wall Switch for BLE - EWSDB | EASYFIT | E8221-A280 Easyfit Single Rocker Pad for BLE - ESRPB | EASYFIT | ESRPB-W-EO Easyfit Double Rocker Pad for BLE - EDRPB | EASYFIT | EDRPB-W-EO IoT Multisensor - EMSIB | EASYFIT | E6221-K516B6221-K516
I actually tested only STM 550B Multisensor Module (S6221-K516) and Easyfit Double Rocker Wall Switch for BLE - EWSDB (E8221-A280). The others should work well with the node-enocean-ble because they use the same EnOcean BLE module as the two. If your device does not work well with the node-enocean-ble, let me know.
Release Note
- v0.0.2 (2020-09-29)
- Added the replay detection in the commissioning telegram
- v0.0.1 (2020-09-29)
- First public release
References
License
The MIT License (MIT)
Copyright (c) 2020 Futomi Hatano
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.