├── .gitignore ├── mbusParser.js ├── README.md ├── package.json ├── LICENSE ├── aidonParser.js ├── parser.js └── obisParser.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | tests.js -------------------------------------------------------------------------------- /mbusParser.js: -------------------------------------------------------------------------------- 1 | const Parser = require('./parser'); 2 | 3 | function MBusParser(b64string) { 4 | let parsed = new Parser(b64string); 5 | return parsed; 6 | } 7 | MBusParser.prototype = { 8 | constructor: MBusParser, 9 | } 10 | 11 | module.exports = MBusParser; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MBusParser 2 | This package uses Node.js to parse base64 encoded mbus packages. 3 | 4 | ## Disclaimer 5 | This project is only developed as an example and may break at any time. 6 | 7 | ## Use with MBusReader 8 | ```bash 9 | git clone https://github.com/ossno/mbusreader 10 | cd mbusreader 11 | npm install 12 | node mbusreader.js 13 | ``` 14 | 15 | ## Use in your own program 16 | 1. In your project directory 17 | ```bash 18 | npm install https://github.com/ossno/mbusparser --save 19 | ``` 20 | 2. In your node program 21 | ```javascript 22 | const MBusParser = require('./mbusparser'); 23 | let parsed = new MBusParser(base64string); 24 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mbusparser", 3 | "version": "1.0.0", 4 | "description": "This package uses node.js to parse base64 encoded mbus packages", 5 | "main": "mbusParser.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Oss Norge AS", 10 | "license": "MIT", 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/ossno/mbusparser" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/ossno/mbusparser/issues" 17 | }, 18 | "homepage": "https://github.com/ossno/mbusparser#mbusparser", 19 | "dependencies": { 20 | "crc": "^3.8.0", 21 | "int64-buffer": "^0.99.1007" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Oss 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. -------------------------------------------------------------------------------- /aidonParser.js: -------------------------------------------------------------------------------- 1 | var Uint64LE = require("int64-buffer").Uint64LE; 2 | 3 | AidonParser.prototype = { 4 | constructor: AidonParser, 5 | } 6 | 7 | function AidonParser(buffer) { 8 | try { 9 | let meterId = buffer.slice(0, 16).toString(); 10 | let a_plus = parseInt(new Uint64LE(buffer.slice(16, 24))); 11 | let a_minus = parseInt(new Uint64LE(buffer.slice(24, 32))); 12 | let r_plus = parseInt(new Uint64LE(buffer.slice(32, 40))); 13 | let r_minus = parseInt(new Uint64LE(buffer.slice(40, 48))); 14 | let p_plus = buffer.readUInt16LE(48); 15 | let p_minus = buffer.readUInt16LE(52); 16 | let q_plus = buffer.readUInt16LE(56); 17 | let q_minus = buffer.readUInt16LE(60); 18 | let phi1 = buffer.readUInt16LE(64); 19 | let phi2 = buffer.readUInt16LE(66); 20 | let phi3 = buffer.readUInt16LE(68); 21 | let p1 = buffer.readUInt32LE(70); 22 | let p2 = buffer.readUInt32LE(74); 23 | let p3 = buffer.readUInt32LE(78); 24 | let u1 = buffer.readUInt16LE(82); 25 | let u2 = buffer.readUInt16LE(84) 26 | let u3 = buffer.readUInt16LE(86);; 27 | let i1 = buffer.readUInt16LE(88); 28 | let i2 = buffer.readUInt16LE(90); 29 | let i3 = buffer.readUInt16LE(92); 30 | let f = buffer.readUInt16LE(94); 31 | let phases = buffer.readUInt8(96); 32 | 33 | let o = { 34 | meterId: meterId, 35 | a_plus: a_plus, 36 | a_minus: a_minus, 37 | r_plus: r_plus, 38 | r_minus: r_minus, 39 | p_plus: p_plus, 40 | p_minus: p_minus, 41 | q_plus: q_plus, 42 | q_minus: q_minus, 43 | phi1: phi1, 44 | phi2: phi2, 45 | phi3: phi3, 46 | p1: p1, 47 | p2: p2, 48 | p3: p3, 49 | u1: u1, 50 | u2: u2, 51 | u3: u3, 52 | i1: i1, 53 | i2: i2, 54 | i3: i3, 55 | f: f, 56 | phases: phases 57 | } 58 | return {type: "aidon", data: o} 59 | 60 | } catch (err) { 61 | return { 62 | type: "error", data: "Failed to parse aidon data: " + err.message 63 | }; 64 | } 65 | } 66 | 67 | exports.AidonParser = AidonParser; -------------------------------------------------------------------------------- /parser.js: -------------------------------------------------------------------------------- 1 | const { 2 | crc16xmodem 3 | } = require('crc'); 4 | 5 | const { 6 | AidonParser 7 | } = require('./aidonParser'); 8 | const { 9 | ObisHeader, 10 | ObisPackageDateTime, 11 | ObisElementsParser 12 | } = require('./obisParser'); 13 | 14 | function Parser(encodedMBusPackage) { 15 | try { 16 | this._offset = 0; 17 | 18 | this._encodedMBusPackage = encodedMBusPackage 19 | this._mbusPackageBuffer = Buffer.from(this._encodedMBusPackage, 'base64'); 20 | 21 | let frameStart = this._mbusPackageBuffer.readUInt8(0, 1) == 0x7E; 22 | let frameEnd = this._mbusPackageBuffer.readUInt8(this._mbusPackageBuffer.length - 1, this._mbusPackageBuffer.length) == 0x7E; 23 | 24 | let frameFormatType = this._mbusPackageBuffer.readUInt8(1) & 0xF0; 25 | let validFrameFormat = frameFormatType == 0xA0; 26 | let messageSize = ((this._mbusPackageBuffer.readUInt8(1) & 0x0F) << 8) | this._mbusPackageBuffer.readUInt8(2); 27 | 28 | 29 | if (frameStart && frameEnd) { 30 | // Looks like a mbus obis package 31 | 32 | if (validFrameFormat) { 33 | this._messageSize = messageSize; 34 | 35 | // Parse header 36 | this._header = new ObisHeader(this._mbusPackageBuffer) 37 | 38 | if (this._header.isHeaderValidChecksum) { 39 | // Valid header 40 | 41 | // Parse datetime 42 | this._packageDateTime = new ObisPackageDateTime(this._mbusPackageBuffer, this._header.offset); 43 | 44 | // Parse elements 45 | this._elements = new ObisElementsParser(this._mbusPackageBuffer, this._packageDateTime.offset); 46 | 47 | return { 48 | type: "obis", 49 | data: this._elements.elements 50 | }; 51 | } else { 52 | return { 53 | type: "error", 54 | data: "Invalid header checksum" 55 | }; 56 | } 57 | 58 | } else { 59 | return { 60 | type: "error", 61 | data: "Invalid frame format" 62 | }; 63 | } 64 | } else { 65 | // Check for Aidon custom format 66 | 67 | let END = 0xC0; 68 | let ESC = 0xDB; 69 | let ESC_END = 0xDC; 70 | let ESC_ESC = 0xDD; 71 | var newBuffer = Buffer.alloc(0); 72 | 73 | let bytesAdded = 0; 74 | 75 | function updateBuffer(byteToAdd) { 76 | let currentBuffer = Buffer.alloc(1); 77 | currentBuffer[0] = byteToAdd; 78 | newBuffer = Buffer.concat([newBuffer, currentBuffer], bytesAdded + 1); 79 | bytesAdded++; 80 | } 81 | 82 | // SLIP Decode 83 | for (let i = 0; i < this._mbusPackageBuffer.length; i++) { 84 | if (this._mbusPackageBuffer[i] == ESC) { 85 | let nextByte = this._mbusPackageBuffer[i + 1]; 86 | if (nextByte == ESC_END) { 87 | updateBuffer(END); 88 | i++; 89 | } else if (nextByte == ESC_ESC) { 90 | updateBuffer(ESC); 91 | i++; 92 | } else { 93 | updateBuffer(this._mbusPackageBuffer[i]); 94 | } 95 | } else { 96 | updateBuffer(this._mbusPackageBuffer[i]); 97 | } 98 | } 99 | // CRC Check 100 | let messageCRC = Buffer.concat([Buffer.from(newBuffer.slice(98, 99)), Buffer.from(newBuffer.slice(97, 98))]).toString('hex'); 101 | var result = crc16xmodem(newBuffer.slice(0, 97)).toString(16); 102 | 103 | if (messageCRC === result) { 104 | let data = new AidonParser(newBuffer); 105 | return data; 106 | } else { 107 | return { 108 | type: "error", 109 | data: "aidon data failed crc check" 110 | }; 111 | } 112 | 113 | } 114 | } catch (err) { 115 | return {type: "parser", data: "failed to parse" }; 116 | } 117 | } 118 | 119 | Parser.prototype = { 120 | constructor: Parser, 121 | } 122 | 123 | module.exports = Parser; -------------------------------------------------------------------------------- /obisParser.js: -------------------------------------------------------------------------------- 1 | function ObisHeader(mbusPackageBuffer) { 2 | 3 | this._headerOffset = 0; 4 | this._mbusPackageBuffer = mbusPackageBuffer; 5 | 6 | let destinationAddress = this.getAddress(this._mbusPackageBuffer.slice(3, 6)).toString(16); 7 | let sourceAddress = this.getAddress(this._mbusPackageBuffer.slice(3 + this._headerOffset, 6 + this._headerOffset)).toString(16); 8 | let controlField = this._mbusPackageBuffer.slice(4 + this._headerOffset, 5 + this._headerOffset).toString('hex'); 9 | let isHeaderValidChecksum = this._mbusPackageBuffer.readUInt16LE(5 + this._headerOffset) == this.computeChecksum(this._mbusPackageBuffer.slice(1, 5 + this._headerOffset)); 10 | 11 | // Maybe not part of header, but does not fit anywhere else 12 | let destinationLSAP = this._mbusPackageBuffer.slice(7 + this._headerOffset, 7 + this._headerOffset + 1).toString('hex'); 13 | let sourceLSAP = this._mbusPackageBuffer.slice(8 + this._headerOffset, 8 + this._headerOffset + 1).toString('hex'); 14 | let llcQuality = this._mbusPackageBuffer.slice(9 + this._headerOffset, 9 + this._headerOffset + 1).toString('hex'); 15 | 16 | return { 17 | isHeaderValidChecksum: isHeaderValidChecksum, 18 | controlField: controlField, 19 | sourceAddress: sourceAddress, 20 | destinationAddress: destinationAddress, 21 | offset: this._headerOffset + 10 22 | } 23 | } 24 | 25 | ObisHeader.prototype = { 26 | constructor: ObisHeader, 27 | computeChecksum: function (buf) { 28 | var TABLE = [ 29 | 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 30 | 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 31 | 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 32 | 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 33 | 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 34 | 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 35 | 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 36 | 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 37 | 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 38 | 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 39 | 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 40 | 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 41 | 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 42 | 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 43 | 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 44 | 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 45 | 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 46 | 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 47 | 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 48 | 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 49 | 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 50 | 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 51 | 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 52 | 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 53 | 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 54 | 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 55 | 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 56 | 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 57 | 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 58 | 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 59 | 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 60 | 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 61 | ]; 62 | 63 | let fcs = 0xFFFF; 64 | for (let i = 0; i < buf.length; i++) { 65 | let ubyte = buf[i]; 66 | let index = (fcs ^ buf[i]) & 0xff; 67 | fcs = (fcs >> 8) ^ TABLE[index]; 68 | } 69 | fcs ^= 0xffff; 70 | return fcs; 71 | }, 72 | getAddress: function (buf) { 73 | // This functions is not yet complete. Does not handle _headerOffset 74 | let i = 1; 75 | for (; i < 4; i++) { 76 | this._headerOffset = 1; 77 | if ((buf.readUInt8(i - 1) & 0x01) == 0x01) { 78 | break; 79 | } 80 | } 81 | if (i == 1) return buf.readUInt8(0); 82 | if (i == 2) return buf.readUInt16LE(0); 83 | if (i == 3) return buf.readUInt32LE(0); 84 | } 85 | } 86 | 87 | 88 | function ObisPackageDateTime(mbusPackageBuffer, offset) { 89 | 90 | this._mbusPackageBuffer = mbusPackageBuffer; 91 | 92 | let dateTimeLength = this._mbusPackageBuffer.readUInt8(offset); 93 | 94 | var dateTime = this._mbusPackageBuffer.slice(offset + 5, offset + 5 + dateTimeLength); 95 | 96 | if (dateTime.readUInt8(0) == 0x09) { 97 | // String format 98 | let stringLength = dateTime.readUInt8(1); 99 | this.year = dateTime.readUInt16BE(2); 100 | this.month = dateTime.readUInt8(4); 101 | this.date = dateTime.readUInt8(5); 102 | this.hour = dateTime.readUInt8(6); 103 | this.minute = dateTime.readUInt8(7); 104 | this.seconds = dateTime.readUInt8(8); 105 | } 106 | 107 | this.offset = offset + 5 + dateTimeLength; 108 | 109 | return this; 110 | } 111 | 112 | ObisPackageDateTime.prototype = { 113 | constructor: ObisPackageDateTime 114 | } 115 | 116 | 117 | function ObisElementsParser(mbusPackageBuffer, offset) { 118 | this._mbusPackageBuffer = mbusPackageBuffer; 119 | this.offset = offset; 120 | this.elements = []; 121 | let NumberOfElements = this._mbusPackageBuffer.readUInt8(offset); 122 | 123 | this.offset = this.offset + 1; 124 | 125 | for (i = 1; i <= NumberOfElements; i++) { 126 | let item = this.parseElement(); 127 | } 128 | 129 | return this; 130 | } 131 | 132 | ObisElementsParser.prototype = { 133 | constructor: ObisElementsParser, 134 | parseElement: function () { 135 | let obisElement; 136 | let elementType = this._mbusPackageBuffer.readUInt8(this.offset); 137 | let elementSize = this._mbusPackageBuffer.readUInt8(this.offset + 1) 138 | 139 | if (elementType == 0x0A) { 140 | let ListIdentifier = this._mbusPackageBuffer.slice(this.offset + 2, this.offset + 2 + elementSize).toString('ascii'); 141 | this.offset = this.offset + 2 + elementSize; 142 | } 143 | 144 | if (elementType == 0x09) { 145 | obisElement = this.parseObisIdentifier(); 146 | } 147 | 148 | return { 149 | elementType: elementType, 150 | elementSize: elementSize, 151 | obisElement: obisElement 152 | } 153 | }, 154 | 155 | parseObisIdentifier: function () { 156 | this._obisId = 157 | this._mbusPackageBuffer.readUInt8(this.offset + 2) + "." + 158 | this._mbusPackageBuffer.readUInt8(this.offset + 3) + "." + 159 | this._mbusPackageBuffer.readUInt8(this.offset + 4) + "." + 160 | this._mbusPackageBuffer.readUInt8(this.offset + 5) + "." + 161 | this._mbusPackageBuffer.readUInt8(this.offset + 6) + "." + 162 | this._mbusPackageBuffer.readUInt8(this.offset + 7); 163 | 164 | // MeterId 165 | if (this._obisId == "1.1.0.0.5.255") { 166 | this._obisName = "MeterId"; 167 | this._obisValueOffset = 10; 168 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 169 | this._obisSubTypeLength = this._mbusPackageBuffer.readUInt8(this.offset + 9); 170 | this._obisValue = parseInt(this._mbusPackageBuffer.slice(this.offset + 10, this.offset + 10 + this._obisSubTypeLength).toString('ascii')); 171 | } 172 | 173 | // MeterType 174 | if (this._obisId == "1.1.96.1.1.255") { 175 | this._obisName = "MeterType"; 176 | this._obisValueOffset = 10; 177 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 178 | this._obisSubTypeLength = this._mbusPackageBuffer.readUInt8(this.offset + 9); 179 | this._obisValue = this._mbusPackageBuffer.slice(this.offset + 10, this.offset + 10 + this._obisSubTypeLength).toString('ascii'); 180 | } 181 | 182 | // ActivePower+ // P14 183 | if (this._obisId == "1.1.1.7.0.255") { 184 | this._obisName = "ActivePower+"; 185 | this._obisValueOffset = 9; 186 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 187 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 188 | this._obisValue = this._mbusPackageBuffer.readUInt32BE(this.offset + 9); 189 | } 190 | 191 | // ActivePower- // P21 192 | if (this._obisId == "1.1.2.7.0.255") { 193 | this._obisName = "ActivePower-"; 194 | this._obisValueOffset = 9; 195 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 196 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 197 | this._obisValue = this._mbusPackageBuffer.readUInt32BE(this.offset + 9); 198 | } 199 | 200 | // ReactivePower+ 201 | if (this._obisId == "1.1.3.7.0.255") { 202 | this._obisName = "ReactivePower+"; 203 | this._obisValueOffset = 9; 204 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 205 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 206 | this._obisValue = this._mbusPackageBuffer.readUInt32BE(this.offset + 9); 207 | } 208 | 209 | // ReactivePower- 210 | if (this._obisId == "1.1.4.7.0.255") { 211 | this._obisName = "ReactivePower-"; 212 | this._obisValueOffset = 9; 213 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 214 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 215 | this._obisValue = this._mbusPackageBuffer.readUInt32BE(this.offset + 9); 216 | } 217 | 218 | // L1 Current 219 | if (this._obisId == "1.1.31.7.0.255") { 220 | this._obisName = "IL1"; 221 | this._obisValueOffset = 9; 222 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 223 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 224 | this._obisValue = this._mbusPackageBuffer.readUInt32BE(this.offset + 9); 225 | } 226 | 227 | // L2 Current 228 | if (this._obisId == "1.1.51.7.0.255") { 229 | this._obisName = "IL2"; 230 | this._obisValueOffset = 9; 231 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 232 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 233 | this._obisValue = this._mbusPackageBuffer.readUInt32BE(this.offset + 9); 234 | } 235 | 236 | // L3 Current 237 | if (this._obisId == "1.1.71.7.0.255") { 238 | this._obisName = "IL3"; 239 | this._obisValueOffset = 9; 240 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 241 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 242 | this._obisValue = this._mbusPackageBuffer.readUInt32BE(this.offset + 9); 243 | } 244 | 245 | // L1 Voltage 246 | if (this._obisId == "1.1.32.7.0.255") { 247 | this._obisName = "UL1"; 248 | this._obisValueOffset = 9; 249 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 250 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 251 | this._obisValue = this._mbusPackageBuffer.readUInt16BE(this.offset + 9); 252 | } 253 | 254 | // L2 Voltage 255 | if (this._obisId == "1.1.52.7.0.255") { 256 | this._obisName = "UL2"; 257 | this._obisValueOffset = 9; 258 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 259 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 260 | this._obisValue = this._mbusPackageBuffer.readUInt16BE(this.offset + 9); 261 | } 262 | 263 | // L3 Voltage 264 | if (this._obisId == "1.1.72.7.0.255") { 265 | this._obisName = "UL3"; 266 | this._obisValueOffset = 9; 267 | this._obisSubType = this._mbusPackageBuffer.readUInt8(this.offset + 8); 268 | this._obisSubTypeLength = this.getsubTypeLength(this._obisSubType); 269 | this._obisValue = this._mbusPackageBuffer.readUInt16BE(this.offset + 9); 270 | } 271 | 272 | // Set new offset 273 | this.offset = this.offset + this._obisValueOffset + this._obisSubTypeLength 274 | 275 | // Update elements array 276 | this.elements.push({ 277 | _obisId: this._obisId, 278 | _obisName: this._obisName, 279 | _obisValue: this._obisValue 280 | }) 281 | }, 282 | 283 | getsubTypeLength: function (type) { 284 | if (type == 0x06) return 4; 285 | if (type == 0x12) return 2; 286 | } 287 | } 288 | 289 | exports.ObisHeader = ObisHeader; 290 | exports.ObisElementsParser = ObisElementsParser; 291 | exports.ObisPackageDateTime = ObisPackageDateTime; 292 | --------------------------------------------------------------------------------