This library supports Node.js 16.x+.
This library supports the reading and parsing of smartmeter protocols that follow the OBIS number logic to make their data available.
Supported Protocols:
- SmlProtocol: SML (SmartMeterLanguage) as binary format
- D0Protocol: D0 (based on IEC 62056-21:2002/IEC 61107/EN 61107) as ASCII format (binary protocol mode E not supported currently)
- JsonEfrProtocol: OBIS data from EFR Smart Grid Hub (JSON format)
Supported Transports (how to receive the data):
- SerialResponseTransport: receive through serial push data (smartmeter send data without any request on regular intervals). Mostly used for SML
- SerialRequestResponseTransport: D0 protocol in modes A, B, C and D (mode E curently NOT supported!) with Wakeup-, Signon-, pot. ACK- and Data-messages to read out data (programing/write mode not implemented so far)
- HttpRequestTransport: Read data via HTTP by requesting an defined URL
- LocalFileTransport: Read data from a local file
- StdInTransport: Read data from stdin
- TCPTransport: Read data from a tcp socket
var SmartmeterObis = require('smartmeter-obis');
var options = {
'protocol': "D0Protocol",
'transport': "SerialRequestResponseTransport",
'transportSerialPort': "/dev/ir-usb1",
'transportSerialBaudrate': 300,
'protocolD0WakeupCharacters': 40,
'protocolD0DeviceAddress': '',
'requestInterval': 10,
'obisNameLanguage': 'en',
'obisFallbackMedium': 6
};
function displayData(err, obisResult) {
if (err) {
// handle error
// if you want to cancel the processing because of this error call smTransport.stop() before returning
// else processing continues
return;
}
for (var obisId in obisResult) {
console.log(
obisResult[obisId].idToString() + ': ' +
SmartmeterObis.ObisNames.resolveObisName(obisResult[obisId], options.obisNameLanguage).obisName + ' = ' +
obisResult[obisId].valueToString()
);
}
}
var smTransport = SmartmeterObis.init(options, displayData);
smTransport.process();
setTimeout(smTransport.stop, 60000);
The easiest way to use the library is to use the options Object with all data to set the Library configure and initialize by it's own.
Therefor you use the init(options, storeCallback) method and provide an options Object and a callback function. The callback function is called with an error object and the parsed result as soon as a message is received completely and successfully. The callback function will get an Array of "ObisMeasurement" objects on suvccess while each entry contains all data for one datapoint. In error case you get an error object in the first parameter and can control if a new cycle should be started (return true) or if you want to stop processing (return false). The init(options, storeCallback) returns the initialized Transport instance to use to control the dataflow.
Everything else to do is to call the process() method from the returned Transport instance and the whole magic happends in the background. The called method can throw an Error as soon as invalid messages are received. In normal operation the process requests or receives the data in the defined intervals. Call stop() method from Transport instance to do a clean stop.
To debug you can also use the special debug option in the options-array.
The process
Param | Type | Description |
---|---|---|
Basic configuration | ||
[protocol] | string |
required, value SmlProtocol, D0Protocol or JsonEfrProtocol |
[transport] | string |
required, value SerialResponseTransport, SerialRequestResponseTransport, HttpRequestTransport, LocalFileTransport, StdInTransport or TCPTransport |
[requestInterval] | number |
optional, number of seconds to wait for next request or pause serial receiving, value 0 possible to restart directly after finishing one message, Default: is 300 (=5 Minutes) |
Transport specific options | ||
[transportSerialPort] | string |
required for Serial protocols, Serial device name, e.g. "/dev/ttyUSB0" |
[transportSerialBaudrate] | number |
optional, baudrate for initial serial connection, if not defined default values per Transport type are used (9600 for SerialResponseTransprt and 300 for SerialRequestResponseTransport) |
[transportSerialDataBits] | number |
optional, Must be one of: 8, 7, 6, or 5. |
[transportSerialStopBits] | number |
optional, Must be one of: 1 or 2. |
[transportSerialParity] | string |
optional, Must be one of: 'none', 'even', 'mark', 'odd', 'space' |
[transportSerialMaxBufferSize] | number |
optional, default value is 300000 (means after 300000 bytes without a matching message an Error is thrown ) |
[transportSerialMessageTimeout] | number |
ms, optional, default value is 120000 (means after 120000ms without a matching message or new data an Error is thrown ) |
[transportHttpRequestUrl] | string |
required for HttpRequestTransport, Request URL to query data from |
[transportHttpRequestTimeout] | number |
optional for HttpRequestTransport, Timeout in ms, defaut 2000 |
[transportLocalFilePath] | string |
required for LocalFileTransport, File patch to read data from |
[transportStdInMaxBufferSize] | number |
optional, default value is 300000 (means after 300000 bytes without a matching message an Error is thrown ) |
[transportStdInMessageTimeout] | number |
ms, optional, default value is 120000 (means after 120000ms without a matching message or new data an Error is thrown ) |
[transportTcpMaxBufferSize] | number |
optional, default value is 300000 (means after 300000 bytes without a matching message an Error is thrown ) |
[transportTcpMessageTimeout] | number |
ms, optional, default value is 120000 (means after 120000ms without a matching message or new data an Error is thrown ) |
Protocol specific options | ||
[protocolD0WakeupCharacters] | number |
optional for D0Protocol, number of wakeup NULL characters, default 0 |
[protocolD0DeviceAddress] | string |
optional for D0Protocol, device address (max 32 characters) for SignIn-Message, default empty |
[protocolD0SignOnMessage] | string |
optional for D0Protocol, command for SignIn-Message, default "?" to query mandatory fields, other values depending on device. You can provide multiple SignOn messages separated by a comma. The delay between them can be set by parameter anotherQueryDelay |
[protocolD0ModeOverwrite] | string |
optional for D0Protocol, to ignore the mode send by the device set the correct D0 mode here. The mode send by the device in the identification message is ignored |
[protocolD0BaudrateChangeoverOverwrite] | number |
optional for D0Protocol, when the D0 mode needs a baudrate changeover, but the device information from identification message is wrong, overwrite with this value |
[protocolSmlIgnoreInvalidCRC] | boolean |
required for SmlProtocol, if false and CRC checksum is invalid an Error is thrown |
[protocolSmlInputEncoding] | string |
optionalfor SmlProtocol, if set defines the input Encoding of the data. Default is "binary" (as received from a serial connection). Other options are "ascii", "utf-8" or "base64" |
[anotherQueryDelay] | number |
optional for D0Protocol with SerialRequestResponseTransport when multiple SignOnMessages are given. Value is in ms, default 1000 |
OBIS options | ||
[obisFallbackMedium] | number |
optional, if smartmeter do not return complete OBIS IDs (without medium info) this will be used as fallback for name resolving |
Debugging options | ||
[debug] | number |
optional, values: 0 (no logging), 1 (basic logging), 2 (detailed logging), Default: 0 |
[logger] | function |
optional, logging function that accepts one parameter to log a string. Default is "console.log" |
... at least:
- Hager eHz Energy Meter (multiple, e.g. eHZ-IW8E2A5L0EK2P, EHZ363W5, )
- EMH Energy Meter
- EFR SmartGridHub
- Siemens 2WR5 reader from an heat station
- Elster AS1440
- Iskraemeco MT174
- Itron EM214 Typ 720
- Dutch smart-meters (use Serial-Read-only with correct baudrate according to your smart meter if needed and "D0" as protocol)
- DZG DWS7412.1T
- IMPORTANT: There seems to be a Firmware bug and sometimes the current energy consumptions becomes negative! Manual recalculation possible using formular from #75 (comment)
- Landis & Gyr E220, Landis+Gyr E350 EDL21
- potentially you need to configure to send some wake up characters
- Holley DTZ541
- Logarex LK13BE
- ... and many more
Please send me an info on devices where you have used the library successfully and I will add it here.
- finalize tests in ObisNames (german/english) and remove mixtures
- Support for OMS somehow?
- Add testing for TCPTransport
- IMPORTANT: This version requires at least Node.js 16+
- Upgrade dependencies and optimize some pot. crash cases
- IMPORTANT: This version requires at least Node.js 12.17+ (excluding non LTS like 13.x)
- Upgrade dependencies and optimize some pot. crash cases
- add protocolSmlInputEncoding to allow other input encodings for SML messages
- add Typescript typings (credits to pkwagner)
- update OpenSML lib to support Holley DTZ541 wrongly implemented CRC Algorithm
- really read over all network data for tcp socket usage when paused
- prevent potential crash in TCP Transport (Sentry IOBROKER-SMARTMETER-R)
- Read over all network data for tcp socket usage when paused
- fix Sentry crash IOBROKER-SMARTMETER-P
- update OpenSML library to prevent some crash cases
- catch errors when no memory is available anymore and stop processing
- handle stopping of process better
- TCP Transport optimization
- Add TCPTransport support (thanks to @chris1705)
- fix a potential crash
- correctly ignore invalid CRC
- handle stopping of process better
- make sure HTTP based smartmeters are also polled frequently when responses are invalid
- handle stopping of process better
- handle stopping of process better
- handle serial port closes better
- fix some smaller edge cases
- update deps, support nodejs 8.x till 12.x
- update Buffer usage
- Add GitHub Actions for Test and Release
- Small fix
- Add better support for devices with more then 16 values (OpenSML Library upgrade)
- output some logging messages only in debug=2 mode
- add StdInTransport options to also allow to process node "Stdin" streams
- add option to send multiple SignOn messages with D0Protocol and SerialRequestResponseTransport
- also accept "&" in OBIS IDs instead of "*" that is sent by EMH ITZ sometimes
- add some better Error handling for D0 messages and ignore pot. "trash" content before dataflow
- switch to Serialport 6.0.4 to make everything more stable and fix needed things in code for This
- a requestInterval of -1 will end processing after one message in all Transports
- SerialResponseTransport and StdInTransport will process all data which is available before readming new. Buffer needs to be big enough else Buffer-Overruns will be catched
- change callback to new error-first style and replace most thrown errors by a call to the callback method with error object and fix some timing issues
- A serial timeout will no longer trigger an Exception. Instead connection is reset and next cycle is scheduled as configured
- Use newest version of SML Library
- Optimize D0 protocol handling and support dutch DSRM protocol
- Handle special problem cases with soem devices better
- Windows do not support pause and resume on SerialPort
- Further optimizations for D0 protocol and baudrate changover logic
- enhanced D0 protocol support for multiple values
- integrate MessageTimeout also for SerialResponseTransport to avoid unparsed message cases
- maintenance update
- fix potential hanging communication for special SerialRequestResponseTransfer cases
- optimizations for SerialRequestResponseTransport for D0 Protocol
- optimizations on D0 message handling for mode E
- optimizations on D0 message handling
- optimizations
- use own open-sml repository as basis for installation (not ideal but used till acceptance of pull-request)
- add testing for real simulated serialport as manual testscript
- fix debug logging
- optimize memory handling
- support also some letters as measurement-Type (some devices send "F.F")
- allow overwriting of D0 Modus and D0 Baudrate Changeover (because some devices send a wrong identification)
- do not throw error when mode E is detected, but log ... maybe some data are useable
- Optimizations on serial handling for some weired SIGABRT cases
- add optional option "transportSerialMessageTimeout" with default of 60s to make sure the process do not hand forever when missing response from device on bi-directional communication
- finally fix exception on "stop" method
- fix exception on "stop" method
- README fixes
- README fix on options list
- remove unneeded/unused option
- aded changelog to README :-)
- small fix in Serial*Transport classes
- changed codeclimate config to ignore code duplication warnings
- initial development, testing and real-live usage with optimizations
- incorporated first feedback from external users
- initial fully working version is 0.2.0