0.0.2 • Published 4 years ago

node-enocean-ble v0.0.2

Weekly downloads
4
License
MIT
Repository
github
Last release
4 years ago

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

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:

PropertyTypeRequiredDescription
nobleNobleoptiona 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:

PropertyTypeDescription
addressStringSource Address
securityKeyStringSecurity Key
orderingCodeStringOrdering Code
stepCodeRevisionStringStep Code - Revision
serialStringSerial 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:

PropertyTypeRequiredDescription
cdataObjectRequired
    addressStringRequiredSource address
    securityKeyStringRequiredAES128 security key
    orderingCodeStringRequiredOrdering 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.

PropertyTypeRequiredDescription
filtersObjectOptional
    authBooleanOptionalIf true, unauthenticated telegrams will be ignored. The default value is true.
    replayBooleanOptionalIf 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:

PropertyTypeDescription
addressStringSource address of the device. (e.g., "cb4eb903c96d")
manufacturerStringManufacturer ID. The value is always "03da", which means "EnOcean GmbH". The ID is assigned by Bluetooth SIG.
sequenceIntegerSequence counter. The value is in the range of 0 to 0xFFFFFFFF.
typeStringType of object. It could be "button" (SwitchTelegram), "sensor" (SensorTelegram), or "commissioning" (CommissioningTelegram).
dataObjectThe structure depends on the type of object (the value of type). See the sections below for details.
signatureStringSecurity signature.
authenticatedBooleanIf 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.
replayedBooleanIf 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:

PropertyTypeDescription
dataObjectButton status
    buttonStringButton name which was pressed or released. It could be "A0", "A1", "B0", or "B1".
    pressedStringButton 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:

PropertyTypeDescription
dataObjectSensor status
    temperatureFloatTemperature (degC)
    humidityFloatRelative Humidity (%RH)
    illuminationIntegerIllumination (lx)
    accelerationObjectAcceleration (See the description below for more details)
        statusIntegerStatus code
        descriptionStringMeaning of the status code
        xFloatAcceleration of the x-axis (g)
        yFloatAcceleration of the y-axis (g)
        zFloatAcceleration of the z-axis (g)
    contactBooleanStatus of the Magnet Contact. true means "close", false means "open".
    voltageIntegerVoltage of the backup battery (mV)
    energyIntegerEnergy Level (%)

The mapping of acceleration.status and acceleration.description is as follows:

statusdescription
0Acceleration value out of bound
1Periodic update
2Acceleration wake
3Sensor 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:

PropertyTypeDescription
dataObjectSensor status
    keyStringSecurity key
    addressStringSource 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 NameManufacturerOrdering Code
PTM 215BEnOceanS3221-A215
STM 550B Multisensor ModuleEnOceanS6221-K516
Easyfit Single Rocker Wall Switch for BLE - EWSSBEASYFITE8221-A270
Easyfit Double Rocker Wall Switch for BLE - EWSDBEASYFITE8221-A280
Easyfit Single Rocker Pad for BLE - ESRPBEASYFITESRPB-W-EO
Easyfit Double Rocker Pad for BLE - EDRPBEASYFITEDRPB-W-EO
IoT Multisensor - EMSIBEASYFITE6221-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.