node-echonet-lite
v0.6.0
Published
The node-echonet-lite is a Node.js module which allows you to communicate with home appliances supporting the ECHONET Lite protocol.
Downloads
24
Readme
node-echonet-lite
The node-echonet-lite is a Node.js module which allows you to communicate with home appliances supporting the ECHONET Lite protocol.
This module provides you with functions such as listening, parsing, creating, sending ECHONET Lite packets over LAN/IPv4 on LAN (Wi-Fi or Ehternet) and UDP/IPv6 on Wi-SUN.
The ECHONET Lite is a communications protocol for smart home devices, which is mainly used in Japan. This module is based on the ECHONET Lite specifications which are available at the web site of the ECHONET Consortium:
- English
- Japanese
The node-echonet-lite mainly has functionalities as follows:
- Listens incoming ECHONET Lite packets
- Parses ECHONET Lite packets
- Creates ECHONET Lite packets
- Sends ECHONET Lite packets
The ECHONET Lite specification defines a lot of classes (profiles of devices), the node-echonet-lite currently supports some classes as follows:
- Sensor-related Device Class Group (Class Group code:
0x00
)- Crime prevention sensor class (Class code:
0x02
) - Visitor sensor class (Class code:
0x08
) - Temperature sensor class (Class code:
0x11
) - Humidity sensor class (Class code:
0x12
) - Electric energy sensor class (Class code:
0x22
) - Air pressure sensor class (Class code:
0x2D
)
- Crime prevention sensor class (Class code:
- Air Conditioner-related Device Class Group (Class Group code:
0x01
)- Home air conditioner class (Class code:
0x30
) - Air cleaner class (Class code:
0x35
)
- Home air conditioner class (Class code:
- Housing/Facilities-related Device Class Group (Class Group code:
0x02
)- Electrically operated blind/shade class (Class code:
0x60
) - Electrically operated rain sliding door/shutter class (Class code:
0x63
) - Electric lock class (Class code:
0x6F
) - Instantaneous water heater class (Class code:
0x72
) - Power distribution board metering class (Class code:
0x87
) - Low-voltage smart electric energy meter class (Class code:
0x88
) - General lighting class (Class code:
0x90
)
- Electrically operated blind/shade class (Class code:
- Cooking/Household-related Device Class Group (Class Group code:
0x03
)- Combination microwave oven(Electronic oven) class (Class code:
0xB8
)
- Combination microwave oven(Electronic oven) class (Class code:
- Audiovisual-related Device Class Group (Class Group code:
0x06
)- Display class (Class code:
0x01
)
- Display class (Class code:
- Profile class Group (Class Group Code:
0x0E
)- Node Profile Class (Class code:
0x0F
)
- Node Profile Class (Class code:
Besides the Device Object Super Class is supported as well, which is a base class inherited by all other classes. See the section "Supported EPCs" for details.
The node-echonet-lite parses ECHONET Lite packets related to the classes above correctly, so you don't have to know the spec for the classes above in detail. But the node-echonet-lite is useful for unknown classes as well, because it is an ECHONET Lite handling framework. This module provides a Buffer
objects representing information for each class in an ECHONET Lite packet. Though you have to know the spec for the class, you can handle any type of classes and you don't have to know the underlying network layers.
The node-echonet-lite supports the network layers as follows:
- UDP/IPv4 on LAN (Wi-Fi or Ethernet)
- This protocol stack is used for most of smart home devices, such as home air conditioners.
- UDP/IPv6 on Wi-SUN
- This protocol stack is used as a communication line between a low-voltage smart electric energy meter and a home gateway (a.k.a. "HEMS gateway") in Japan. The communication line is as known as "Route-B".
- [NOTE] This module is unstable for this network protocol stack for now.
The node-echonet-lite supports the Wi-SUN USB dongles as a HEMS gateway for Wi-SUN Route-B as follows:
- BP35C2, ROHM Semiconductor. [English] [Japanese]
- BP35A1, ROHM Semiconductor. [English] [Japanese]
- RL7023 Stick-D/DSS, TESSERA TECHNOLOGY INC. [Japanese]
If you want to communicate with a smart electric energy meter, you have to get either of the Wi-SUN USB dongles above. Note that the Wi-SUN USB dongles are available only in Japan.
Before using the node-echonet-lite module, you have to know the basics of the ECHONET Lite specification. See the section "ECHONET Lite Tutorial" for details.
Dependencies
- Node.js 4.4 +
- serialport
- Required if a Wi-SUN USB dongle is used.
Installation
$ cd ~
$ npm install serialport
$ npm install node-echonet-lite
ECHONET Lite Emulator
The ECHONET Lite devices are mainly available in Japan. If you don't have any ECHONET devices, it is recommended to use the MoekadenRoom which is an ECHONET Lite Emulator. MoekadenRoom emulates 6 types of devices (classes): Home air conditioner class, General lighting class, Electrically operated blind/shade class, Electric lock class, Temperature sensor class, and Low-voltage smart electric energy meter class. The node-echonet-lite supports the classes.
Table of Contents
- ECHONET Lite Tutorial
- Quick Start
- Operating suggestions
- Constructor of the EchonetLite object
- Methods
init(callback)
setLang(lang)
getClassGroupName(group_code)
getClassName(group_code, class_code)
getPropertyName(group_code, class_code, epc)
isSupportedEpc(group_code, class_code, epc)
setSelfEoj(eoj)
startDiscovery([callback])
stopDiscovery()
getPropertyMaps(address, eoj[, callback])
getPropertyValue(address, eoj, epc[, callback])
setPropertyValue(address, eoj, epc, edt[, callback])
send(address, data[, callback])
close([callback])
setTransactionId(id)
- Events
- Objects
- Supported EPCs
- Monitoring ECHONET Lite packets
- How to handle unknown EPCs
- Release Note
- License
ECHONET Lite Tutorial
The ECHONET Lite packet consists of several blocks as follows:
-------------------------------------------------------------------
|EHD1|EHD2|TID|SEOJ|DEOJ|ESV|OPC|EPC1|PDC1|EDT1|...|EPCn|PDCn|EDTn|
-------------------------------------------------------------------
- EHD1: ECHONET Lite message header 1 (1 Byte)
- EHD2: ECHONET Lite message header 2 (1 Byte)
- TID : Transaction ID (2 Bytes)
- SEOJ: Source ECHONET Lite object specification (3 Bytes)
- DEOJ: Destination ECHONET Lite object specification (3 Bytes)
- ESV : ECHONET Lite service (1 Byte)
- OPC : Number of processing properties (1 Byte)
- EPC : ECHONET Lite Property (1 Byte)
- PDC : Property data counter (1 Byte)
- EDT : Property value data (Specified by PDC)
Though you don't need to know all block, using the node-echonet-lite module, you have to know at least EOJ (SEOJ, DEOJ), ESV, EPC, and EDT block. This section describes the summary of them. If you want to know more, see ECHONET Lite Specification, Version 1.12 for details.
EOJ (ECHONET Lite Object)
The EOJ represents an entity of a device which is called "object" in the ECHONET Lite specification. In a ECHONET Lite packet, you can see two EOJ blocks as the SEOJ and the DEOJ. The SEOJ block means the source object, the DEOJ means the destination object. When you receive an ECHONET Lite packet, the SEOJ in the packet represents the remote device, the DEOJ represents you. In the contrary case, the remote device and you switch places. That is, the DEOJ represents you and the SEOJ represents the remote device.
The EOJ consists of three parts: Class group code, Class code, and Instance code.
A pair of a class group code and a Class code represents a type of a device. For example, the pair of the class group code 0x01
and the class code 0x30
means the Home Air Conditioner Class. The pair of the class group code 0x0E
and the class code 0x0F
means the Node Profile Class which is mainly used for the discovery process. Basically all ECHONET Lite devices have the Node Profile Class.
The instance code is basically 0x01
. The node-echonet-lite module provide you with the EOJ including the Instance code as a result of the discovery process. So you don't need to care about instance codes.
An EOJ is expressed as an Array
object in the node-echonet-lite module, such as [0x01, 0x03, 0x01]
. Some method of the node-echonet-lite requires such an Array
object as an argument.
This node-echonet-lite module uses the EOJ [0x05, 0xFF, 0x01]
as itself (i.e. you) by default. This EOJ means the Controller class in the management, control-related device class group, and instance code 1. you can change the self-EOJ using the setSelfEoj()
method anytime.
ESV (ECHONET Lite service)
The ESV represents a kind of a request/response code. It is similar to the HTTP status code. Though a lot of ESV are defined in the ECHONET Lite specification, it is enough to know 6 types of ESV as follows. If you know the 6 types of ESV, you could accomplish most of what you want to do:
ESV symbol | desctiption
:----------|:-----------
Get
| If you want to get something from the remote device, this ESV is used.
SetC
| If you want to set something to the remote device, this ESV is used.
Get_Res
| If the remote device accepts the Get
request and meets the request, the remote device will use this ESV in the response packet.
Set_Res
| If the remote device accepts the SetC
request and meets the requests, the remote device will use this ESV in the response packet.
Get_SNA
| If the remote device can not accept the Get
request or can not meet the request, the remote device will use this ESV in the response packet.
SetC_SNA
| If the remote device can not accept the SetC
request or can not meet the request, the remote device will use this ESV in the response packet.
Actually, the ESV is an code consisting of 1 byte unsigned integer. But you don't need to know the codes specified in the ECHONET Lite specification because this module communicates with you using only the symbols above (Get
, SetC
, etc.).
EPC (ECHONET Property Code)
The EPC represents a property code. Each device object (EOJ) has a lot of properties (EPCs) such as operation status (0x80
), manufacturer code (0x8A
), room temperature (0xBB
), etc. However an EPC is meaningless by itself. An EPC has a meaning with a class group code and a class code. Note that two same EPCs with a different class group code or class code don't necessarily have the same meaning.
In this section, a set of the three codes described above is expressed like 03-01-80
for the purpose of explanation.
For example, 03-01-80
means the operation status of the Home Air Conditioner Class. 0E-0F-80
means the operation status of the Node Profile class as well. Though both of the two mean the operation status, the meanings are slightly different. 03-01-80
represents an intuitive operation to you. If you turn on your air conditioner, the status will be ON
. If you turn off your air conditioner, the status will be OFF
. But 0E-0F-80
is basically always ON
, because it means the operation status of the network adapter equipped in your air conditioner.
EDT (Property value data)
The EDT represents the data corresponding to the EPC. The data structure depends on the corresponding EPC (in addition to the class group code and the class code), which is specified in the APPENDIX of the ECHONET Lite specification. When you request a certain information to the remote device, the EDT in the response packet is just what you want.
The node-echonet-lite module supports some types of EDT for EPCs which are called "supported EPC" in this document. Note that the remote device does not necessarily support the EPC event if this module supports it.
If the EPC is supported by this module (i.e. a supported EPC), you don't need to know the data structure of the EDT. The node-echonet-lite module parses the EDT of the supported EPC and provides you with the result as the EDT
object, you can access information which you want easily. See the section "Supported EPCs" for details.
Even if the EPC is not supported by this module, you can obtain the Buffer object representing the EDT. Though you need to know the data structure of the EDT, you can parse any EDT by yourself. See the section How to handle unknown EPCs for details.
Quick Start
This section shows how to discover a specific type of device, how to get a value of a specific property of the device, and how to set a value to the property of the device.
Home Air Conditioner
The sample code below discovers a home air conditioner, then gets the current operation status (ON or OFF), finally turns on or off the home air conditioner.
// Load the node-echonet-lite module
var EchonetLite = require('node-echonet-lite');
// Create an EchonetLite object
// The type of network layer must be passed.
var el = new EchonetLite({'type': 'lan'});
// Initialize the EchonetLite object
el.init((err) => {
if(err) { // An error was occurred
showErrorExit(err);
} else { // Start to discover devices
discoverDevices();
}
});
// Start to discover devices
function discoverDevices() {
// Start to discover Echonet Lite devices
el.startDiscovery((err, res) => {
// Error handling
if(err) {
showErrorExit(err);
}
// Determine the type of the found device
var device = res['device'];
var address = device['address'];
var eoj = device['eoj'][0];
var group_code = eoj[0]; // Class group code
var class_code = eoj[1]; // Class code
if(group_code === 0x01 && class_code === 0x30) {
// Stop to discovery process
el.stopDiscovery();
// This means that the found device belongs to the home air conditioner class
console.log('Found an air conditioner (' + address + ').');
// Get the operation status
getOperationStatus(address, eoj);
}
});
}
// Get the operation status
function getOperationStatus(address, eoj) {
var epc = 0x80; // An property code which means the operation status
el.getPropertyValue(address, eoj, epc, (err, res) => {
// this value is true if the air conditione is on
var status = res['message']['data']['status'];
var desc = (status ? 'on' : 'off');
console.log('The air conditioner is ' + desc + '.');
// Toggle the status of the operation status
changePowerStatus(address, eoj, epc, !status);
});
}
// Change the status of the operation status
function changePowerStatus(address, eoj, epc, status) {
var edt = { 'status': status };
el.setPropertyValue(address, eoj, epc, edt, (err, res) => {
var desc = (status ? 'on' : 'off');
console.log('The air conditionaer was turned ' + desc + '.');
el.close(() => {
console.log('Closed.');
// This script terminates here.
});
});
}
// Print an error then terminate the process of this script
function showErrorExit(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
}
This sample code will output the result like this:
Found an air conditioner (192.168.10.15).
The air conditioner is off.
The air conditionaer was turned on.
Smart Electric Energy Meter
// Load the node-echonet-lite module
var EchonetLite = require('node-echonet-lite');
// Create an EchonetLite object for Wi-SUN Route-B
var el = new EchonetLite({
'type' : 'wisunb',
'adapter': 'bp35c2',
'path' : 'COM6',
'id' : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
'pass' : 'XXXXXXXXXXXX'
});
// Initialize the EchonetLite object
el.init((err) => {
if(err) { // An error was occurred
showErrorExit(err);
} else { // Start to discover devices
discoverDevices();
}
});
// Start to discover devices
function discoverDevices() {
// Start to discover a smart electric energy meter
// on Wi-SUN B-route using a Wi-SUN USB dongle
el.startDiscovery((err, res) => {
// Error handling
if(err) {
showErrorExit(err);
}
// Determine the type of the found device
var device = res['device'];
var address = device['address'];
var eoj = device['eoj'][0];
var group_code = eoj[0]; // Class group code
var class_code = eoj[1]; // Class code
if(group_code === 0x02 && class_code === 0x88) {
// Stop to discovery process
el.stopDiscovery();
// This means that the found device belongs to
// the low voltage smart electric energy meter class
console.log('Found a smart electric energy meter (' + address + ').');
// Get the Measured instantaneous electric energy
getMeasuredValue(address, eoj);
}
});
}
// Get the measured values
function getMeasuredValue(address, eoj) {
var epc = 0xE7; // An property code which means "Measured instantaneous electric energy"
el.getPropertyValue(address, eoj, epc, (err, res) => {
var energy = res['message']['data']['energy'];
console.log('Measured instantaneous electric energy is ' + energy + ' W.');
el.close(() => {
console.log('Closed.');
process.exit();
});
});
}
// Print an error then terminate the process of this script
function showErrorExit(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
}
This sample code will output the result like this:
Found a smart electric energy meter (XXX0:0000:0000:0000:0XXX:XXXX:XXXX:XXXX).
Measured instantaneous electric energy is 402 W.
Closed.
Operating suggestions
If you want to send multiple requests, never send them simultaneously. Be sure to send a request after the response for the previous request came. You should know the remote device is not a high-performance computer such as a personal computer or a smart phone. It is a poor-performance embedded device. Never put unnecessary pressure on such devices in order to avoid unexpected problems.
Never do this:
// [CAUTION] NEVER DO THIS
[0xE0, 0xE1, 0xE2].forEach((epc) => {
el.getPropertyValue(address, eoj, epc, (err, res) => {
console.dir(res['message']['data']);
});
});
Do this instead:
var epc_list = [0xBA, 0xBB, 0xBE];
(function request() {
var epc = epc_list.shift();
if(epc) {
el.getPropertyValue(address, eoj, epc, (err, res) => {
console.dir(res['message']['data']);
request();
});
} else {
el.close();
}
})();
Especially, You should be more careful to Wi-SUN devices because not only Wi-SUN-related devices perform really poorly but also the bit-rate of Wi-SUN is really poorer than Wi-Fi or Ethernet. If you send another request, it is strongly encouraged to wait at least in 1 second after the response for the previous request came using the setTimeout()
method implemented in Node.js.
var epc_list = [0xBA, 0xBB, 0xBE];
(function request() {
var epc = epc_list.shift();
if(epc) {
el.getPropertyValue(address, eoj, epc, (err, res) => {
console.dir(res['message']['data']);
// HERE IS IMPORTANT!!!
setTimeout(request, 1000);
});
} else {
el.close();
}
})();
How long you should wait, it depends on conditions. You might have to wait longer.
The suggestion described here is applied to the all methods sending a packet as well: getPropertyMaps()
, getPropertyValue()
, setPropertyValue()
, and send()
.
Constructor of the EchonetLite object
In order to use the node-echonet-lite, you have to load the node-echonet-lite module as follows:
var EchonetLite = require('node-echonet-lite');
You can get an EchonetLite
constructor using the code above. Then you have to create an EchonetLite
object as an instance of the EchonetLite
constructor as follows:
var el = new EchonetLite({'type': 'lan'});
The EchonetLite
constructor takes an argument. It must be a hash object having the properties as follows:
Property | Type | Required | Description
:--------|:-------|:---------|:-----------
type
| String | required | The type of the network layer (protocol stack). The value must be either lan
or wisunb
. The value lan
means UDP/IPv4 on LAN (Wi-Fi or Ethernet). The value wisunb
means UDP/IPv6 on Wi-SUN.
lang
| String | optional | The language code. The value must be either en
(English) or ja
(Japanese). This module can report analysis results of incoming ECHONET Lite packets using the specified language. The default value is en
If you set lan
to type
property, the additional properties are required as follows:
Property | Type | Required | Description
:------------|:--------|:---------|:-----------
netif
| String | optional | Specify the multicast interface as an IPv4 address.
membership
| Boolean | optional | Joining the multicast group or not. The default value is true
.
If the netif
is not specified, all available network interfaces will be joined to a multicast group. If you want to use one network interface, set the netif
parameter to the IPv4 address representing the network interface you want to use.
The membership
indicates whether joining the multicast group (true
) or not (false
). Note that the notify
event would not work if this parameter is set to false
. Basically, it is strongly recommended not to specify this parameter unless you encounter an error related to multicast.
The membership
was introduced for Windows WSL (Windows Subsystem for Linux). As far as I know, some node.js methods related to udp multicast throws an exception. For now, no complete solution for WSL is found.
If you set wisunb
to type
property, the additional properties are required as follows:
Property | Type | Required | Description
:--------|:-------|:---------|:-----------
adapter
| String | required | The product name of Wi-SUN USB dongle. The value must be either bp35a1
or rl7023
.
path
| String | required | The path of the serial port which the Wi-SUN USB dongle is inserted. If you use Windows OS, it should be like COM3
. If you use Linux, it should be like /dev/tty-usbserial1
.
baud
| Number | optional | The baud rate of the Wi-SUN USB dongle. The default value is 115200. If your Wi-SUN USB dongle supports the default baud rate, you don't need to specify this property.
id
| String | required | The Route-B ID.
pass
| String | required | The Route-B Password.
The sample code below shows how to create an EchonetLite
object for the network layer "UDP/IPv6 on Wi-SUN".
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({
'lang' : 'ja',
'type' : 'wisunb',
'adapter': 'bp35a1',
'path' : 'COM8',
'id' : '0123456789ABCDEF0123456789ABCDEF',
'pass' : 'ABCDEFGHIJKL',
'baud' : 115200
});
Technically, you can create multiple EchonetLite
objects with the same type of network layer. However, that don't work well. Never do that.
// [CAUTION] NEVER DO THIS. THIS NEVER WORKS.
var el1 = new EchonetLite({'type': 'lan'});
var el2 = new EchonetLite({'type': 'lan'});
The code below also don't work.
// [CAUTION] NEVER DO THIS. THIS NEVER WORKS.
var el1 = new EchonetLite({'type': 'wisunb', ...});
var el2 = new EchonetLite({'type': 'wisunb', ...});
You can create two EchonetLite
objects with different type of network layer. The code blow will work well.
// This will work well.
var el1 = new EchonetLite({'type': 'lan'});
var el2 = new EchonetLite({'type': 'wisunb', ...});
Methods
This section describes the methods implemented in the EchonetLite
object.
init(callback)
This method initializes the EchonetLite
object. You have to initialize the EchonetLite
object immediately after you create it.
The initialization is processed asynchronously. Therefore you have to specify a callback function as the 1st argument of this method.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({'type': 'lan'});
// Initialize the EchonetLite object
el.init((err) => {
if(err) { // An error was occurred
// Do something for the error.
} else { // The initialization process completed successfully
// Do something using the EchonetLite object.
// Generally, the discover process is started here.
}
});
setLang(lang)
This method set the language for the packet analysis. Basically you don't need to call this method. If you want to get the results of the packet analysis, you can choose the language from English and Japanese.
If you want to set the language to English explicitly, pass an string en
to this method as the 1st argument. Similarly, if you want to set the language to Japanese, pass an string ja
to this method as the 1st argument.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({'type': 'lan'});
// Set the language to Japanese
var lang = el.setLang('ja');
// Set the language to English
var lang = el.setLang('en');
This method can be called anytime after the EchonetLite
object was created. You don't need to wait for the completion of the initialization process of the EchonetLite
object.
getClassGroupName(group_code)
getClassName(group_code, class_code)
getPropertyName(group_code, class_code, epc)
isSupportedEpc(group_code, class_code, epc)
The getClassGroupName()
method, the getClassName()
method, and the getPropertyName()
method returns the class group name, the class name, and the property name respectively. These names are defined in the ECHONET Lite specification. The node-echonet-lite module knows all names specified in the spec.
The isSupportedEpc()
method returns true
or false
. If the EDT of the set of codes passed to this method is supported to be parsed by the node-echonet-lite module, this method returns true
, otherwise false
.
The sample code below shows how to get the group name, the class name, and property name. Furthermore, it shows how to determine if the EDT of the specified EPC is supported to be parsed by this module.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({'lang': 'en', 'type': 'lan'});
var group_code = 0x02;
var class_code = 0x64;
var epc = 0xD0;
var group_name = el.getClassGroupName(group_code);
var class_name = el.getClassName(group_code, class_code);
var prop_name = el.getPropertyName(group_code, class_code, epc);
var supported = el.isSupportedEpc(group_code, class_code, epc);
console.log('- Group name : ' + group_name);
console.log('- Class name : ' + class_name);
console.log('- Property name : ' + prop_name);
console.log('- Is supported : ' + (supported ? 'Yes' : 'No'));
The sample code above will output the result like this:
- Group name : Housing/facility-related device class group
- Class name : Electrically operated gate class
- Property name : Opening speed setting
- Is supported : No
if you want to see the result in Japanese, specify it to the EchonetLite
constructor like this:
var el = new EchonetLite({'lang': 'ja', 'type': 'lan'});
You can also use the setLang()
method of the EchonetLite
object:
el.setLang('ja');
If the language setting is ja
, the result will be as follows:
- Group name : 住宅・設備関連機器クラスグループ
- Class name : 電動ゲート
- Property name : 開速度設定
- Is supported : No
setSelfEoj(eoj)
This method allows you to set the self-EOJ to arbitrary EOJ. The first argument eoj
must be an Array
object consisting three codes: the class group code, the class code, and the instance code. Each code must be an integer in the range of 0 (0x00
) to 255 (0xFF
).
var el = new EchonetLite({'type': 'lan'});
el.setSelfEoj([0x06, 0x04, 0x01]);
Once you set the self-EOJ, this module uses it for the SEOJ of each ECHONET Lite packet to be sent even when the discovery process is executed. You can use this method at any time after the EchonetLite
object was created.
If you don't call this method, this module uses the default self-EOJ [0x05, 0xFF, 0x01]
as the SEOJ of each ECHONET Lite packet to be sent. This default self-EOJ means the Controller class in the management, control-related device class group, and instance code 1.
startDiscovery([callback])
This method start the discovery process and tries to find ECHONET Lite devices. Whenever a ECHONET Lite device was found, the callback
function specified to the 1st argument will be called. The callback
is optional.
The callback
will be passed two argument. The 1st argument is an Error
object. If no error occurred, it will be null
.
If a device was found successfully, the Response
object will be passed as the 2nd argument. See the section "Response
object" in details.
// Start to discover Echonet Lite devices
el.startDiscovery((err, res) => {
if(err) { // An error was occurred
// Do something for the error.
} else { // An ECHONET Lite device was found.
// Determine the type of the found device
var device = res['device'];
var address = device['address'];
var eoj = device['eoj'][0];
var group_code = eoj[0]; // Class group code
var class_code = eoj[1]; // Class code
if(group_code === 0x01 && class_code === 0x30) {
// This means that the found device belongs to the home air conditioner class
console.log('Found an air conditioner (' + address + ').');
// Stop to discovery process
el.stopDiscovery();
// Do something to the device
...
}
}
});
If no ECHONET Lite device was found, more than one network adapter might exist on your host computer. When this method is called, the node-echonet-lite sends an UDP multicast packet to 224.0.23.0
in the LAN mode. If more than one network adapter exists on your host computer, the OS on your computer possibly would pass it to an unexpected network adapter. It is recommended to disable such network adapters.
Be sure to call stopDiscovery()
method if the targeted device was found.
stopDiscovery()
This method stop the discovery process. After the startDiscovery()
method was called and the targeted device was found, then be sure to call this method before controlling the targeted devices.
getPropertyMaps(address, eoj[, callback])
This method get the property maps from the specified device. The property maps let you know which EPCs the device supports. Therefore getting the property maps is essential in order to interact with ECHONET Lite devices.
This method takes three arguments. the 1st argument addresss
is the IP address of the targeted device. The addresss
is required. The IP address can be get from the discovery process.
The 2nd argument eoj
is the EOJ of the targeted device. It must be passed as an Array
object. The Array
object can be get from the discovery process.
The 3rd argument callback
is a callback function called when this method completes the process. Two arguments will be passed to the callback
. The 1st argument is an Error
object. If no error occurred, it will be null
. If this method completes the process successfully, the Response
object will be passed as the 2nd argument. The special property data
is added to the the Response
object for this method. The value of the data
property is a hash object having the properties as follows:
Property | Type | Description
:--------|:-------|:-----------
inf
| Array | Status change announcement property map
set
| Array | Set property map
get
| Array | Get property map
Each property map contains the supported EPCs as a number.
el.startDiscovery((err, res) => {
// Determine the type of the found device
var device = res['device'];
var address = device['address'];
var eoj = device['eoj'][0];
var group_code = eoj[0]; // Class group code
var class_code = eoj[1]; // Class code
if(group_code === 0x01 && class_code === 0x30) {
// This means that the found device belongs to the home air conditioner class
console.log('- IP address: ' + address);
console.log('- EOJ: ' + JSON.stringify(eoj));
// Stop to discovery process
el.stopDiscovery();
// Get the property maps
el.getPropertyMaps(address, eoj, (err, res) => {
console.log('- Property Maps:')
console.dir(res['message']['data']);
process.exit();
});
}
});
The sample code above will print the result as follows:
- IP address: 192.168.10.15
- EOJ: [1,48,1]
- Property Maps:
{ inf: [ 128, 129, 136, 143, 160, 176 ],
set: [ 128, 129, 143, 147, 160, 163, 176, 179, 180, 193, 196 ],
get: [ 176, 160, 128, 193, 129, 130, 179, 163, 147, 131, 196, 180, 132, 133, 136, 137, 186, 138, 187, 157, 190, 158, 159, 143 ] }
It is encouraged to check the property maps before interacting with the targeted device.
getPropertyValue(address, eoj, epc[, callback])
This method get the property value of the specified EPC from the specified device.
This method takes four arguments. the 1st argument addresss
is the IP address of the targeted device. This argument is required. The IP address can be get from the discovery process.
The 2nd argument eoj
is the EOJ of the targeted device. This argument is required. It must be passed as an Array
object. The Array
object can be get from the discovery process.
The 3rd argument epc
is the EPC you want to get. This argument is required. You have to know which EPC you want is in advance. you can find the meanings of EPCs in the APPENDIX of the ECHONET Lite specification.
The 4th argument callback
is a callback function called when this method completes the process. This argument is optional. Two arguments will be passed to the callback
. The 1st argument is an Error
object. If no error occurred, it will be null
. If this method completes the process successfully, the Response
object will be passed as the 2nd argument. The special property data
is added to the Response
object for this method. The value of the data
property is a EDT object which is a hash object having some properties depending on the EPC. See the section "EDT object" for details.
The sample code below shows how to use the getPropertyValue()
method. In this code, the measured value of room temperature is got from the home air conditioner.
// Start to discover Echonet Lite devices
el.startDiscovery((err, res) => {
// Determine the type of the found device
var device = res['device'];
var address = device['address'];
var eoj = device['eoj'][0];
var group_code = eoj[0]; // Class group code
var class_code = eoj[1]; // Class code
if(group_code === 0x01 && class_code === 0x30) {
// This means that the found device belongs to the home air conditioner class
console.log('- IP address: ' + address);
console.log('- EOJ: ' + JSON.stringify(eoj));
// Stop to discovery process
el.stopDiscovery();
// Get the property value (Measured value of room temperature)
el.getPropertyValue(address, eoj, 0xBB, (err, res) => {
console.log('- Property value:')
console.dir(res['message']['data']);
process.exit();
});
}
});
The sample code above will print the result as follows:
- IP address: 192.168.10.15
- EOJ: [1,48,1]
- Property value:
{ temperature: 26 }
setPropertyValue(address, eoj, epc, edt[, callback])
This method sets the specified property value (edt
) of the specified EPC (epc
) to the specified device (eoj
in address
).
This method takes five arguments. the 1st argument addresss
is the IP address of the targeted device. This argument is required. The IP address can be get from the discovery process.
The 2nd argument eoj
is the EOJ of the targeted device. This argument is required. It must be passed as an Array
object. The Array
object can be get from the discovery process.
The 3rd argument epc
is the EPC you want to set. This argument is required. You have to know the EPC you want to set in advance. you can find the meanings of EPCs in the APPENDIX of the ECHONET Lite specification.
The 4th argument edt
is the EDT
object which contains some values you want to convey to the targeted device. It is just a hash object. The structure depends on the EPC. See the section "EDT object" for details.
You can specify the 4th argument edt
as a Buffer
object as well. Though you have to create a Buffer
object representing the EDT by yourself, this allows you to send an arbitrary EDT.
The 5th argument callback
is a callback function called when this method completes the process. This argument is optional. Two arguments will be passed to the callback
. The 1st argument is an Error
object. If no error occurred, it will be null
. If this method completes the process successfully, the Response
object will be passed as the 2nd argument.
The sample code below shows how to use the setPropertyValue()
method. The home air conditioner is turned off by this code.
// Start to discover Echonet Lite devices
el.startDiscovery((err, res) => {
// Determine the type of the found device
var device = res['device'];
var address = device['address'];
var eoj = device['eoj'][0];
var group_code = eoj[0]; // Class group code
var class_code = eoj[1]; // Class code
if(group_code === 0x01 && class_code === 0x30) {
// This means that the found device belongs to the home air conditioner class
console.log('- IP address: ' + address);
console.log('- EOJ: ' + JSON.stringify(eoj));
// Stop to discovery process
el.stopDiscovery();
// Create an EDT object
var edt = { 'status': true };
// Turn off the home air conditioner
el.setPropertyValue(address, eoj, 0x80, edt, (err, res) => {
var esv = res['message']['esv'];
if(esv === 'Set_Res') {
console.log('- Result: Success');
} else {
console.log('- Result: Failed');
}
el.close();
});
}
});
You can specify a Buffer
object as the part of EDT as follows:
// Create a Buffer object for the EDT
var edt = new Buffer([0x31]);
// Turn off the home air conditioner
el.setPropertyValue(address, eoj, 0x80, edt, (err, res) => {
// If succeeded, the air conditioner should be turned off.
});
In order to determine the request was accepted by the targeted device, you have to check the value of the ESV in the response packet. You can get the value of the ESV from esv
property in the Message
object in the Response
object passed to the callback function (i.e. res['message']['esv']
). Note that the Error
object passed to the callback function mainly represents an network error. It does not represents the fact that the targeted device didn't accept the request. Even if the targeted device denied the request, the Error
object is null
as long as the targeted device responded.
The sample code above will print the result as follows:
- IP address: 192.168.10.15
- EOJ: [1,48,1]
- Result: Success
send(address, eoj, esv, prop[, callback])
This method sends an arbitrary ECHONET Lite packet to the specified device. It is most primitive method in this module. The getPropertyValue()
and the setPropertyValue()
method can tread only one EPC. But the ECHONET Lite specification allows us to treat multiple EPCs simultaneously in one ECHONET Lite packet. Using this method, you can send a request packet including multiple EPCs.
This method takes five arguments. the 1st argument addresss
is the IP address of the targeted device. This argument is required. The IP address can be get from the discovery process.
The 2nd argument eoj
is the EOJ of the targeted device. This argument is required. It must be passed as an Array
object. The Array
object can be get from the discovery process.
The 3rd argument esv
is the ESV symbol. Note that the value of esv
argument is not a ESV code. It must be specified as a symbol, such as "Get
", "SetC
", etc. "Get
" is used to get a property value from the targeted device. "SetC
" is used to set a property to the targeted device.
The 4th argument prop
is an Array
object consisting of hash objects containing an EPC and an EDT
object. This argument is required. If you want to send EDTs to the targeted device, you have to create EDT
objects by yourself.
[{'epc': 0x80, 'edt': {'status': false}}]
You can set the value of edt
property as an Buffer
object as follows. Though you have to know the byte sequences specified in the ECHONET Lite specification, you can send an arbitrary EDT.
[{'epc': 0x80, 'edt': new Buffer([0x31])}]
If you just want to get the values from the targeted devices, the EDT
object must be null
.
[{'epc': 0xBA, 'edt': null}, {'epc': 0xBB, 'edt': null}]
The 5th argument callback
is a callback function called when this method completes the process. This argument is optional. Two arguments will be passed to the callback
. The 1st argument is an Error
object. If no error occurred, it will be null
. If this method completes the process successfully, the Response
object will be passed as the 2nd argument.
The sample code below shows how to use the send()
method. In this code, three properties are requested to the targeted device simultaneously in one request.
// Start to discover Echonet Lite devices
el.startDiscovery((err, res) => {
// Determine the type of the found device
var device = res['device'];
var address = device['address'];
var eoj = device['eoj'][0];
var group_code = eoj[0]; // Class group code
var class_code = eoj[1]; // Class code
// This means that the found device belongs to the home air conditioner class
if(group_code === 0x01 && class_code === 0x30) {
// Stop to discovery process
el.stopDiscovery();
// Get the property values
var esv = 'Get';
var prop = [
{'epc': 0xBA, 'edt': null}, // Room Humidity
{'epc': 0xBB, 'edt': null}, // Room Temperature
{'epc': 0xBE, 'edt': null} // Outdoor Temperature
];
el.send(address, eoj, esv, prop, (err, res) => {
res['message']['prop'].forEach((p) => {
var epc = p['epc'];
var edt = p['edt'];
if(epc === 0xBA) {
console.log('- Room Humidity : ' + edt['humidity'] + ' %');
} else if(epc === 0xBB) {
console.log('- Room Temperature : ' + edt['temperature'] + ' Celsius');
} else if(epc === 0xBE) {
console.log('- Outdoor Temperature: ' + edt['temperature'] + ' Celsius');
}
});
el.close();
});
}
});
The sample code above will print the result as follows:
- Room Humidity : 60 %
- Room Temperature : 26 Celsius
- Outdoor Temperature: 28 Celsius
close([callback])
This method closes the opening network port and restores the EchonetLite
object to the state immediately after it was newly created. If your task has been completed, it is encouraged to call this method. If you don't call this method, your script will never terminates because the network port is still active.
Once this method is called, the EchonetLite
object does not work anymore as it is. If you want to reuse the object, you have to call the init()
method again.
The process of this method is asynchronous. If you want to do something sequentially after the process of this method completes, you can pass a callback function to this method as the 1st argument.
el.close(() => {
// do something
});
setTransactionId(id)
This method sets the transaction ID (a.k.a. TID). The TID must be an integer in the range of 0
to 65535
.
If the TID is set using this method, it will be used in subsequent request packets. Note that the ID is not automatically incremented. You have to manage TIDs by yourself.
el.setTransactionId(1234);
Basically, you don't have to use this method because a transaction ID is automatically generated and incremented whenever a request packet is created. Only if you need to manage transaction IDs by yourself, use this method.
If null
is passed to this method, the TID will be cleared. That is, TIDs will be automatically generated for subsequent requests.
el.setTransactionId(null);
Events
Whenever an ECHONET Lite packet comes or is sent, several events are fired on the EchonetLite
object. You can listen to events using on()
method on the EchonetLite
object. The event listeners must be set after the initialization process by the init()
method has been completed.
notify
event
The notify
event will be fired whenever any ECHONET Lite packets except the responses for getPropertyValue()
, setPropertyValue()
, getPropertyMaps()
, and send()
methods was received.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({'lang': 'ja', 'type': 'lan'});
el.init((err) => {
if(err) {
console.log('[ERROR] '+ err.toString());
} else {
el.on('notify', (res) => {
console.log('[NOTIFY] From: ' + res['device']['address'] + ' --------------------------');
console.log(JSON.stringify(res['message'], null, ' '));
console.log('');
});
}
});
When a notification packet is received, the code above will show the result as follows:
[NOTIFY] From: 192.168.11.17 --------------------------
{
"tid": 50,
"seoj": [
1,
48,
1
],
"deoj": [
14,
240,
1
],
"esv": "INF",
"prop": [
{
"epc": 128,
"edt": {
"status": false
},
"buffer": {
"type": "Buffer",
"data": [
49
]
}
}
]
}
An Response
object is passed to the callback function as the 1st argument.
data
event
The data
event will be fired whenever any ECHONET Lite packet was received.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({'lang': 'ja', 'type': 'lan'});
el.init((err) => {
if(err) {
console.log('[ERROR] '+ err.toString());
} else {
el.startDiscovery((err, res) => {
el.stopDiscovery();
if(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
} else {
getPropertyMaps(res['device']);
}
});
el.on('data', (res) => {
console.log('[RECEIVE] ---------------------------------------');
console.log(JSON.stringify(res['message'], null, ' '));
console.log('');
});
}
});
An Response
object is passed to the callback function as the 1st argument.
sent
event
The sent
event will be fired whenever any ECHONET Lite packet was sent.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({'lang': 'ja', 'type': 'lan'});
el.init((err) => {
if(err) {
console.log('[ERROR] '+ err.toString());
} else {
el.startDiscovery((err, res) => {
el.stopDiscovery();
if(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
} else {
getPropertyMaps(res['device']);
}
});
el.on('sent', (res) => {
console.log('[SENT] ---------------------------------------');
console.log(JSON.stringify(res['message'], null, ' '));
console.log('');
});
}
});
An Response
object is passed to the callback function as the 1st argument.
data-serial
event
The data-serial
event will be fired whenever any data was received from the Wi-SUN USB dongle. This event is mainly used for debugging.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({
'lang' : 'ja',
'type' : 'wisunb',
'adapter': 'bp35a1',
'path' : 'COM8',
'id' : '0123456789ABCDEF0123456789ABCDEF',
'pass' : 'ABCDEFGHIJKL',
'baud' : 115200
});
el.init((err) => {
if(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
} else {
el.startDiscovery((err, res) => {
el.stopDiscovery();
if(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
} else {
// Do something
}
});
el.on('data-serial', (res) => {
console.log(res['data']);
});
el.on('sent-serial', (res) => {
console.log('> ' + res['data']);
});
}
});
An Response
object is passed to the callback function as the 1st argument. Besides, an extra property is added to the object. The message came from the Wi-SUN USB dongle is set to the data
property in Response
object. Though text data and binary data are mixed in a message between this module and the Wi-SUN USB dongle, the part of binary is converted to hexadecimal representation.
The sample code prints the results as follows:
> SKSENDTO 1 FE80:0000:0000:0000:0000:0000:0000:0000 0E1A 2 000E 1081001A05FF0102880162019E00
EVENT 21 FE80:0000:0000:0000:0000:0000:0000:0000 00
OK
ERXUDP FE80:0000:0000:0000:0000:0000:0000:0000 FE80:0000:0000:0000:0000:0000:0000:0001 0E1A 0E1A 001C64000334809F 1 0012 1081001A02880105FF0172019E040381E5ED
> SKSENDTO 1 FE80:0000:0000:0000:0000:0000:0000:0000 0E1A 2 000E 1081001B05FF0102880162019F00
EVENT 21 FE80:0000:0000:0000:0000:0000:0000:0000 00
OK
sent-serial
event
The send-serial
event will be fired whenever any data was sent to the Wi-SUN USB dongle. This event is mainly used for debugging.
See the previous section for details.
Objects
Response
object
The Response
object represents an ECHONET Lite packet coming from an ECHONET Lite device. It is passed to the callback function for the getPropertyMaps()
method, the getPropertyValue()
method, the setPropertyValue()
method as the 2nd argument. Besides, it is passed to the callback function for an event handler as the 1st argument.
This object consists of the properties as follows:
Property | Type | Description
:-------------|:--------|:-----------
device
| Device
| See the section "Device
object".
message
| Message
| See the section "Message
object".
buffer
| Buffer | This Buffer object represents a whole extent of the ECHONET Lite packet.
hex
| Array | This array represents a whole extent of the telegram. Each element in the array is an hexadecimal representation of each byte.
formatted
| String | This is a formatted text representing the analysis result of the ECHONET Lite packet. See the section "Monitoring ECHONET Lite packets" for details.
lang
| String | The language of the formatted text provided by the formatted
property. This value is either en
(English) or ja
(Japanese).
structure
| Array | This array is used for debugging. You probably don't need this array. If you need to investigate ECHONET Lite packets, the formatted
property would be more useful. If you are interested in this array, you can see the structure using console.dir()
.
Device
object
The Device
object represents the device relevant to the ECHONET Lite packet. If the packet is received one, this object represents the source device of the packet. If the packet is transmitted one, this object represents the destination device of the packet.
This object consists of the properties as follows:
Property | Type | Description
:-------------|:--------|:-----------
address
| String | IP address of the device.
eoj
| Array | A list of EOJ supported by the device. This property is available only in the discovery process.
Message
object
The Message
object represents the summary of the ECHONET Lite packet. This object is the most useful in the Response
object for you.
This object consists of the properties as follows:
Property | Type | Description
:-------------|:--------|:-----------
tid
| Number | The Transaction ID in the ECHONET Lite packet.
seoj
| Array | The SEOJ in the ECHONET Lite packet. The array consists of three numbers: Class Group code, Class code, and Instance code.
deoj
| Array | The DEOJ in the ECHONET Lite packet. The array consists of three numbers: Class Group code, Class code, and Instance code.
esv
| String | The ESV in the ECHONET Lite packet. This value is a symbol. Note that this value is not a ESV code.
prop
| Array | A list of the Prop
object.
data
| Object | This object includes information which this module converted the value of prop
object for you so that you can handle the packet easily. This property exists only in the Response
objects derived from the getPropertyMaps()
method and getPropertyValue()
method. See the descriptions for the methods for details.
Prop
object
The Prop
object represents a set of the EPC and the EDT in the ECHONET Lite packet.
This object consists of the properties as follows:
Property | Type | Description
:-------------|:--------|:-----------
epc
| Number | The EPC.
edt
| EDT
| The EDT
buffer
| Buffer | The Buffer object representing the EDT.
If the EPC is supported by this module, the EDT in the ECHONET Lite packet is parsed so that you can treat it easily, then the EDT
object is set as the value of the edt
property. If the EPC is unknown to this module, the value of the edt
property is null. In both cases, the Prop
object has the buffer
property, the value is a Buffer object representing the part of EDT in the ECHONET Lite packet. You can parse it by yourself even if the EPC is unknown to this module. See the section "How to handle unknown EPCs" for details.
EDT
object
The EDT
object represents the answer for your query from the targeted device. Though this object is just a hash object, the structure depends on the EPC which you requested.
The EDT
object has several properties dedicated for the EPC. For example, if the EPC is 0xBA
for the home air conditioner class (Class Group code: 0x01
, Class code: 0x03
), it means "Measured value of room relative humidity", then the structure of the EDT
object will be as follows:
{ 'humidity': 55 }
If the EPC is 0xE7
for the low-voltage smart electric energy meter class (Class Group code: 0x02
, Class code: 0x88
), it means "Measured instantaneous electric energy", then the structure of the EDT
object will be as follows:
{ 'energy': 794 }
See the section "Supported EPCs" for details.
Supported EPCs
This module supports the Classes specified in the ECHONET Lite specification as follows:
- Super Class Group (Class Group code: N/A)
- Sensor-related Device Class Group (Class Group code:
0x00
) - Air Conditioner-related Device Class Group (Class Group code:
0x01
) - Housing/Facilities-related Device Class Group (Class Group code:
0x02
)- Electrically operated blind/shade class (Class code:
0x60
) - Electrically operated rain sliding door/shutter class (Class code:
0x63
) - Electric lock class (Class code:
0x6F
) - Instantaneous water heater class (Class code:
0x72
) - Power distribution board metering class (Class code:
0x87
) - Low-voltage smart electric energy meter class (Class code:
0x88
) - General lighting class (Class code:
0x90
)
- Electrically operated blind/shade class (Class code:
- Cooking/Household-related Device Class Group (Class Group code:
0x03
) - Audiovisual-related Device Class Group (Class Group code:
0x06
) - Profile class Group (Class Group Code:
0x0E
)
You can find the detailed information about each EDT
object in the document related to the class above.
Monitoring ECHONET Lite packets
In order to debug you scripts, You would monitor ECHONET packets in detail. The node-echonet-lite module provides you with formatted text as a result of packet analysis.
As described above, the formatted
property is implemented in the Response
. Using the value of the formatted
property and the event listening mechanism, you can monitor results of packet analysis in real time.
The sample code below shows how to code a ECHONET packet analyzer. The data
event and the sent
event fired on the EchonetLite
object are listened, then the formatted text derived from the Response
object is output.
var EchonetLite = require('node-echonet-lite');
var el = new EchonetLite({'lang': 'en', 'type': 'lan'});
el.init((err) => {
if(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
} else {
el.startDiscovery((err, res) => {
el.stopDiscovery();
if(err) {
console.log('[ERROR] '+ err.toString());
process.exit();
} else {
// Do something
}
});
el.on('data', (res) => {
console.log(createLine('='));
console.log('[RECV] from ' + res['device']['address']);
console.log(createLine('-'));
console.log(res['formatted']);
console.log('');
});
el.on('sent', (res) => {
console.log(createLine('='));
console.log('[SENT] to ' + res['device']['address']);
console.log(createLine('-'));
console.log(res['formatted']);
console.log('');
});
}
});
function createLine(char) {
var len = process.stdout.columns - 1;
var line = '';
for(var i=0; i<len; i++) {
line += char;
}
return line;
}
The sample code above will output the result like this if the language is set to en
(default):
==================================================================================================
[SENT] to 224.0.23.0
--------------------------------------------------------------------------------------------------
- EHD1 |ECHONET Lite message header 1 |10 |Conventional ECHONET Lite Specification
- EHD2 |ECHONET Lite message header 2 |81 |Format 1 (specified message format)
- TID |Transaction ID |00 01|1
- SEOJ |Source ECHONET Lite object spe..|05 ..|05 FF 01
- SEOJX1 |Source class group code |05 |Management/control-related device class group
- SEOJX2 |Source class code |FF |Controller class
- SEOJX3 |Source instance code |01 |1
- DEOJ |Destination ECHONET Lite objec..|0E ..|0E F0 00
- DEOJX1 |Destination class group code |0E |Profile class group
- DEOJX2 |Destination class code |F0 |Node profile class
- DEOJX3 |Destination instance code |00 |0
- DEOJX3 |Destination instance code |00 |0
- ESV |ECHONET Lite service |62 |Property value read request (Get)
- OPC |Number of processing properties |01 |1
- EPC0 |ECHONET Lite Property |D6 |Self-no