├── icons └── gauge.png ├── .gitignore ├── package.json ├── locales └── en-US │ ├── smartmeter-connection.json │ └── smartmeter.json ├── LICENSE ├── smartmeter-connection.js ├── README.md ├── smartmeter.js ├── smartmeter.html └── smartmeter-connection.html /icons/gauge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolchip/node-red-contrib-smartmeter/HEAD/icons/gauge.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Visual Studio Code 40 | .vscode -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-red-contrib-smartmeter", 3 | "version": "0.6.3", 4 | "description": "Node, that reads and parses values from smartmeter devices", 5 | "main": "smartmeter.js", 6 | "dependencies": { 7 | "serialport": "^9.2.8", 8 | "smartmeter-obis": "^2.3.0" 9 | }, 10 | "keywords": [ 11 | "node-red", 12 | "smartmeter", 13 | "sml", 14 | "d0", 15 | "jsonefr" 16 | ], 17 | "node-red": { 18 | "nodes": { 19 | "smartmeter": "smartmeter.js", 20 | "smartmeter-connection": "smartmeter-connection.js" 21 | } 22 | }, 23 | "author": "Sebastian B.", 24 | "license": "MIT", 25 | "email": "coolchip@gmx.de", 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/coolchip/node-red-contrib-smartmeter" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/coolchip/node-red-contrib-smartmeter/issues" 32 | }, 33 | "homepage": "https://github.com/coolchip/node-red-contrib-smartmeter#readme" 34 | } 35 | -------------------------------------------------------------------------------- /locales/en-US/smartmeter-connection.json: -------------------------------------------------------------------------------- 1 | { 2 | "smartmeter-connection": { 3 | "label": { 4 | "sourcetype": "Source type", 5 | "serialport": "Serial port", 6 | "settings": "Settings", 7 | "baudrate": "Baud rate", 8 | "databits": "Data bits", 9 | "parity": "Parity", 10 | "stopbits": "Stop bits", 11 | "host": "Host", 12 | "port": "Port", 13 | "filepath": "Filename" 14 | }, 15 | "placeholder": { 16 | "serialport": "for example: /dev/ttyUSB0/", 17 | "filepath": "for example: /tmp/data.json" 18 | }, 19 | "sourcetype": { 20 | "serial": "Serial", 21 | "http": "HTTP", 22 | "tcp": "TCP Client", 23 | "file": "File" 24 | }, 25 | "parity": { 26 | "none": "None", 27 | "even": "Even", 28 | "mark": "Mark", 29 | "odd": "Odd", 30 | "space": "Space" 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Sebastian Balling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /smartmeter-connection.js: -------------------------------------------------------------------------------- 1 | module.exports = function (RED) { 2 | 'use strict'; 3 | const serialp = require('serialport'); 4 | 5 | function SmartmeterConnectionNode(n) { 6 | RED.nodes.createNode(this, n); 7 | this.serialport = n.serialport; 8 | this.serialbaud = parseInt(n.serialbaud) || 57600; 9 | this.databits = parseInt(n.databits) || 8; 10 | this.parity = n.parity || 'none'; 11 | this.stopbits = parseInt(n.stopbits) || 1; 12 | this.httphost = n.httphost || 'localhost'; 13 | this.httpport = n.httpport || 80; 14 | this.filepath = n.filepath || ''; 15 | this.tcphost = n.tcphost || 'localhost'; 16 | this.tcpport = n.tcpport || 502; 17 | } 18 | RED.nodes.registerType('smartmeter-connection', SmartmeterConnectionNode); 19 | 20 | RED.httpAdmin.get("/smartmeter-serialports", RED.auth.needsPermission('serial.read'), function(req,res) { 21 | serialp.list().then( 22 | ports => { 23 | const a = ports.map(p => p.path); 24 | res.json(a); 25 | }, 26 | err => { 27 | res.json([RED._(`serialport.list() error: ${err}`)]); 28 | } 29 | ) 30 | }); 31 | } -------------------------------------------------------------------------------- /locales/en-US/smartmeter.json: -------------------------------------------------------------------------------- 1 | { 2 | "smartmeter": { 3 | "label": { 4 | "datasource": "Data source", 5 | "protocol": "Protocol", 6 | "transport": "Transport", 7 | "requestInterval": "Request interval", 8 | "d0WakeupCharacters": "Wake Up Character (D0)", 9 | "d0SignOnMessage": "SignIn-Message (D0)", 10 | "d0BaudrateChangeoverOverwrite": "Force Baudrate (D0)", 11 | "protocolSmlIgnoreInvalidCRC": "Ignore invalid CRC (Sml)", 12 | "debugging": "Debugging (see 'Help' tab)" 13 | }, 14 | "placeholder": { 15 | "requestInterval": "0" 16 | }, 17 | "protocol": { 18 | "smlprotocol": "SmlProtocol", 19 | "d0protocol": "D0Protocol", 20 | "jsonerfprotocol": "JsonEfrProtocol" 21 | }, 22 | "transport": { 23 | "serialresponsetransport": "SerialResponseTransport", 24 | "serialrequesttransport": "SerialRequestResponseTransport", 25 | "httprequesttransport": "HttpRequestTransport", 26 | "localfiletransport": "LocalFileTransport", 27 | "tcptransport": "Read data from a tcp socket" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## node-red-contrib-smartmeter 2 | [![npm version](https://badge.fury.io/js/node-red-contrib-smartmeter.svg)](https://badge.fury.io/js/node-red-contrib-smartmeter) 3 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/coolchip/node-red-contrib-smartmeter) 4 | 5 | #### Node-RED Node, that reads and parses the data from smartmeter devices. Supports for example Hager eHz Energy Meter, EMH Energy Meter, EFR SmartGridHub, Siemens 2WR5, Elster AS1440, Iskraemeco MT174, Itron EM214 Typ 720. 6 | 7 | This work depends on the great smartmeter Module ([smartmeter@github](https://github.com/Apollon77/smartmeter-obis) and [smartmeter@npm](https://www.npmjs.com/package/smartmeter-obis)). 8 | 9 | ### Install 10 | Just run 11 | ``` 12 | npm install node-red-contrib-smartmeter 13 | ``` 14 | 15 | ### How to use 16 | Connect your reader and configure the smartmeter node. 17 | An external trigger is only needed by some smartmeters. 18 | 19 | ### Example 20 | ```text 21 | [{"id":"55761f32.81b66","type":"smartmeter","z":"58f83f17.8d781","name":"","ip":"192.168.0.20","port":"8888","x":460,"y":400,"wires":[["294e49ea.47ce96"]]},{"id":"2be68b81.81e9a4","type":"inject","z":"58f83f17.8d781","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":260,"y":400,"wires":[["55761f32.81b66"]]},{"id":"294e49ea.47ce96","type":"debug","z":"58f83f17.8d781","name":"","active":true,"console":"false","complete":"false","x":670,"y":400,"wires":[]}] 22 | ``` 23 | -------------------------------------------------------------------------------- /smartmeter.js: -------------------------------------------------------------------------------- 1 | module.exports = function (RED) { 2 | 'use strict'; 3 | var smartmeterObis = require('smartmeter-obis'); 4 | 5 | function SmartmeterNode(config) { 6 | RED.nodes.createNode(this, config); 7 | var node = this; 8 | 9 | node.smartmeterDatasource = RED.nodes.getNode(config.datasource); 10 | if (node.smartmeterDatasource) { 11 | var options = { 12 | 'protocol': config.protocol, 13 | 'transport': config.transport, 14 | 'transportSerialPort': node.smartmeterDatasource.serialport, 15 | 'transportSerialBaudrate': node.smartmeterDatasource.serialbaud, 16 | 'transportSerialDataBits': node.smartmeterDatasource.databits, 17 | 'transportSerialStopBits': node.smartmeterDatasource.stopbits, 18 | 'transportSerialParity': node.smartmeterDatasource.parity, 19 | 'requestInterval': config.requestInterval, 20 | 'protocolD0WakeupCharacters': config.d0WakeupCharacters, 21 | 'protocolD0SignOnMessage': config.d0SignOnMessage, 22 | 'protocolD0BaudrateChangeoverOverwrite': config.d0BaudrateChangeoverOverwrite, 23 | 'protocolSmlIgnoreInvalidCRC': config.protocolSmlIgnoreInvalidCRC, 24 | 'transportHttpRequestUrl': `${node.smartmeterDatasource.httphost}:${node.smartmeterDatasource.httpport}`, 25 | 'transportLocalFilePath': node.smartmeterDatasource.filepath, 26 | 'transportTcpHost': node.smartmeterDatasource.tcphost, 27 | 'transportTcpPort': node.smartmeterDatasource.tcpport, 28 | 'obisNameLanguage': 'de', 29 | 'obisFallbackMedium': 6, 30 | 'debug': config.debugging ? 2 : 0, 31 | 'logger': (log) => console.log(log), 32 | }; 33 | 34 | function sendData(err, obisResult) { 35 | if (err) { 36 | return RED.log.error(`smartmeter-obis error: ${err}`); 37 | } 38 | const msg = { 39 | payload: obisResult 40 | }; 41 | node.send(msg); 42 | } 43 | 44 | var smTransport = smartmeterObis.init(options, sendData); 45 | var firstRun = true; 46 | 47 | if (config.requestInterval >= 0 ) { 48 | smTransport.process(); 49 | firstRun = false; 50 | } 51 | 52 | node.on('close', function () { 53 | smTransport.stop(); 54 | }); 55 | 56 | node.on('input', function() { 57 | if (!firstRun && !smTransport.protocol.isProcessComplete()) { 58 | node.warn("Previous process hasn't finished yet"); 59 | return; 60 | } 61 | smTransport.process(); 62 | if (config.requestInterval < 0 ) { 63 | smTransport = smartmeterObis.init(options, sendData); 64 | firstRun = true; 65 | } 66 | }); 67 | } 68 | } 69 | RED.nodes.registerType('smartmeter', SmartmeterNode); 70 | } 71 | -------------------------------------------------------------------------------- /smartmeter.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 59 | 60 | 116 | -------------------------------------------------------------------------------- /smartmeter-connection.html: -------------------------------------------------------------------------------- 1 | 91 | 92 | --------------------------------------------------------------------------------