Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Node.js P1-Reader

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter. Data is parsed according to the official DSMR4.0 specification by Netbeheer Nederland, which is currently used by most popular Kaifa and Landis+Gyr Smart Meters.

How to use

The serial connection is automatically opened on initiating the P1-Reader. Use the reading event to start receiving data, which should come in every 10 seconds.

var P1Reader = require('p1-reader');
var p1Reader = new P1Reader();
p1Reader.on('reading', function(data) {
console.log('Currently consuming: ' + data.electricity.received.actual.reading + data.electricity.received.actual.unit);
});
p1Reader.on('error', function(err) {
console.log('Error while reading: ' + err);
});

Events

The module emits the following events:

  • connected : When a connection with the Smart Meter was successfully setup
  • reading : When a reading is received via the serial connection (should be on a 10 second interval)
  • reading-raw : Same as the reading event but instead returning the raw data as a string
  • error : When the serial connection emits an error
  • close : When the serial connection closes for some reason

Reading structure

The reading event returns the following data structure:

{
"meterType": "ISk5\2MT382-1000",
"version": "42",
"timestamp": "2010-12-09T10:30:20.000Z",
"equipmentId": "4B384547303034303436333935353037",
"textMessage": {
"codes": "3031203631203831",
"message": "0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?"
},
"electricity": {
"received": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 1.193,
"unit": "kW"
}
},
"delivered": {
"tariff1": {
"reading": 123456.789,
"unit": "kWh"
},
"tariff2": {
"reading": 123456.789,
"unit": "kWh"
},
"actual": {
"reading": 0,
"unit": "kW"
}
},
"tariffIndicator": 2,
"threshold": {
"value": 16.1,
"unit": "kW"
},
"switchPosition": "1",
"numberOfPowerFailures": 4,
"numberOfLongPowerFailures": 2,
"longPowerFailureLog": {
"count": 2,
"log": [
{
"startOfFailure": "2010-12-08T14:20:15.000Z",
"endOfFailure": "2010-12-08T14:24:15.000Z",
"duration": 240,
"unit": "s"
},
{
"startOfFailure": "2010-12-08T14:05:03.000Z",
"endOfFailure": "2010-12-08T14:10:04.000Z",
"duration": 301,
"unit": "s"
}
]
},
"voltageSags": {
"L1": 2,
"L2": 1,
"L3": 0
},
"voltageSwell": {
"L1": 0,
"L2": 3,
"L3": 0
},
"instantaneous": {
"current": {
"L1": {
"reading": 1,
"unit": "A"
},
"L2": {
"reading": 2,
"unit": "A"
},
"L3": {
"reading": 3,
"unit": "A"
}
},
"power": {
"positive": {
"L1": {
"reading": 1.111,
"unit": "kW"
},
"L2": {
"reading": 2.222,
"unit": "kW"
},
"L3": {
"reading": 3.333,
"unit": "kW"
}
},
"negative": {
"L1": {
"reading": 4.444,
"unit": "kW"
},
"L2": {
"reading": 5.555,
"unit": "kW"
},
"L3": {
"reading": 6.666,
"unit": "kW"
}
}
}
}
},
"gas": {
"deviceType": "003",
"equipmentId": "3232323241424344313233343536373839",
"timestamp": "2010-12-09T10:00:00.000Z",
"reading": 12785.123,
"unit": "m3",
"valvePosition": "1"
}
}

Emulator mode

Since your development machine is usually not connected to the serial port directly the emulator mode can be enabled. When enabled the module will not connect to a serial port but instead will use a mocked version that will emit messages according to the DSMR 4.0 specification.

The emulator will emit a reading event every 10 seconds just like an actual Smart Meter would do with the most important variables (timestamp, electricity.received.tariff1, electricity.received.actual, gas.timestamp and gas.reading) being incremented.

Provide the emulator option parameter to run the module in emulator mode:

var p1Reader = new P1Reader({emulator: true});

The emulator defaults can be overriden by passing an emulatorOverrides object, which can contain the following parameters:

  • electricityOffset : Starting value of electricity on tariff 1 in kWh (default: 0)
  • electricityIncrement : Incremental value (every 10 seconds) of electricity on tariff 1 in kW (default: 0.1)
  • gasOffset : Starting value of gas in m3 (default: 0)
  • gasIncrement : Incremental value (every hour) of gas in m3 (default: 0.1)
  • interval : Interval (in seconds) in which readings are emitted (default: 10)
  • intervalGas Interval (in seconds) in which the gas reading is incremented (default: 3600)

Debug mode

In debug mode all raw and parsed packages are written to 2 separate log files (debug-data-raw.log and debug-data-parsed.log) and stored in the directory from which the module was triggered.

Provide the debug option parameter to run the module in debug mode:

var p1Reader = new P1Reader({debug: true});

Force specific serial port

If for some reason the automatic serial port discovery does not work it is possible to force a certain port with a specific configuration.

Provide a serialPort object as option parameter to set a specific serial port configuration. The object should contain all of the following field:

  • port : Portname of the serial port on which the Smart Meter is connected (e.g. '/dev/tty-usbserial1')
  • baudRate : Baud rate of the serial port (e.g. '9600' or '115200')
  • parity : Parity of the serial port (e.g. 'none' or 'even')
  • dataBits : Number of data bits used for the serial port (e.g. '7' or '8')
  • stopBits : Number of stop bits used for the serial port (e.g. '1')

Official DSMR documentation

The official DSMR Smart Meter P1 interface documentation from Netbeheer Nederland can be found here: http://www.netbeheernederland.nl/publicaties/publicatie/?documentregistrationid=1745033 This documentation was used as a reference to create and verify this module.

Changelog

1.5.0

  • Serial port auto discovery function now also tries different configurations to allow to automatically connect to any DSMR 4+ Smart Meter
  • Allow forcing both a specific port and configuration (baudrate, parity, databits and stopbits) - Note that the "port" parameter is replaced, which is not backwards compatible
  • Removing the "crash on purpose" when a smart meter could not be found
  • Improving debug logging for better traceability of issues
  • Upgrading "node-serialport" dependency to latest version for improved stability
  • Applying ES6 standards to code

1.4.1

  • Minor bug fix on incorrectly returning the LongPowerFailureLog object

1.4.0

  • Exposing and calculating the datetime of the start of a LongPowerFailure
  • Added the 'reading-raw' event to retrieve the raw data (as a string) that was retrieved from the Smart Meter

1.3.1

  • Added option to control the interval of the emulator mode via an option parameter

1.3.0

  • Added emulator mode for development purposes
  • Extended example with all possible option parameters

1.2.0

  • Upgraded serialport to 4.0.7
  • Serial port is now automatically locked preventing other processes from opening it
  • Added 'connected' event
  • Exposed used serial port name via getSerialPort()

1.1.1

  • Minor bug fix

1.1.0

  • Added option to force a specific port
  • Log more debugging information

1.0.1

  • Updated readme

1.0.0

  • Initial version with full DSMR 4.0 specification implemented

About

Node.js package for reading and parsing data from the P1 port of a Dutch Smart Meter.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages