UNPKG

ocpp-js

Version:

Open Charge Point Protocol Implementation in JS

270 lines (231 loc) 8.02 kB
const externalip = require('externalip'); const ip = require('ip'); const IPv6 = require('ip-address').Address6; var Utils = { /** * Log function * @param {String} message to display * @param */ log: function(msg, type) { var d = new Date(), log = Utils.dateToString(d) + " "; if (type != undefined) { if (type == "cs") log += "cs: "; else if (type == "cp") log += "cp: "; else log += "cp#" + type + ": "; } console.log(log + msg); }, getExternalIP: function(callback){ externalip(callback); }, getRemoteAddress: function(address){ if(ip.isV6Format(address)){ var IPv6Address = new IPv6(address); var teredo = IPv6Address.inspectTeredo(); return teredo.client4; }else{ return address; } }, /** * Convert a Date to String * Format: [YY-mm-dd hh:mm:ss] * @param {Date} * @param {String} */ dateToString: function(date) { var year = Utils.addZeroPadding(date.getFullYear()), month = Utils.addZeroPadding(date.getMonth() + 1), day = Utils.addZeroPadding(date.getDate()), hours = Utils.addZeroPadding(date.getHours()), minutes = Utils.addZeroPadding(date.getMinutes()), seconds = Utils.addZeroPadding(date.getSeconds()); return "[" + year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + "]"; }, /** * Add zero-padding if needed * @param {Number} Number of the day/month * @param {String} */ addZeroPadding: function(n) { return n < 10 ? '0' + n : '' + n; }, /** * Generate a random ID * @return String */ makeId: function() { var text = "", possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for (var i = 0; i < 32; i++) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; }, /** * Retrieve OCPP version from string */ retrieveVersion: function(str) { // if array, last occurence if (str instanceof Array) { str = str[str.length - 1]; } var v = []; for (var i in str) { if (str[i] >= 0 && str[i] < 10) { v.push(str[i]); } } return v.join('.'); }, isEmpty: function(obj) { for (var i in obj) { return false; } return true; }, capitaliseFirstLetter: function(string) { return string.charAt(0).toUpperCase() + string.slice(1); }, lowerFirstLetter: function(string) { return string.charAt(0).toLowerCase() + string.slice(1); }, getDateISOFormat: function() { return new Date().toISOString().split('.')[0] + 'Z'; }, validURL: function(str) { var re = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;-]*)/ig; return re.test(str); }, clone: function(obj) { if (null == obj || "object" != typeof obj) return obj; var copy = obj.constructor(); for (var attr in obj) { if (obj.hasOwnProperty(attr)) if (typeof obj[attr] == "object") copy[attr] = Utils.clone(obj[attr]); else copy[attr] = obj[attr]; } return copy; }, // Get network interface IPs, from: // http://stackoverflow.com/questions/3653065/get-local-ip-address-in-node-js getNetworkIPs: function() { var ignoreRE = /^(127\.0\.0\.1|::1|fe80(:1)?::1(%.*)?)$/i; var exec = require('child_process').exec; var cached; var command; var filterRE; switch (process.platform) { case 'win32': //case 'win64': // TODO: test command = 'ipconfig'; filterRE = /\bIPv[46][^:\r\n]+:\s*([^\s]+)/g; break; case 'darwin': command = 'ifconfig'; filterRE = /\binet\s+([^\s]+)/g; // filterRE = /\binet6\s+([^\s]+)/g; // IPv6 break; default: command = 'ifconfig'; filterRE = /\binet\b[^:]+:\s*([^\s]+)/g; // filterRE = /\binet6[^:]+:\s*([^\s]+)/g; // IPv6 break; } return function(callback, bypassCache) { if (cached && !bypassCache) { callback(null, cached); return; } // system call exec(command, function(error, stdout, sterr) { cached = []; var ip; var matches = stdout.match(filterRE) || []; //if (!error) { for (var i = 0; i < matches.length; i++) { ip = matches[i].replace(filterRE, '$1') if (!ignoreRE.test(ip)) { cached.push(ip); } } //} callback(error, cached); }); }; }, logSoap: function(xml, direction) { // @scope: soap server var direction = direction || 'in', prefix = direction == 'in' ? '<<' : '>>', rawContent = xml, content = this.wsdl.xmlToObject(xml), from = null, action = null; // if no content then do nothing if (!content) { if (direction == 'in') Utils.log('<<cp#? Error, message not well-formed:\n' + xml, "cs"); return; } if (content.Header && content.Header.chargeBoxIdentity) { from = content.Header.chargeBoxIdentity; action = content.Header.Action; } // get message content for (var c in content.Body) { content = content.Body[c]; break; }; const Transport = require('../transport'); content = Transport.PRINT_XML ? rawContent : JSON.stringify(content); Utils.log(prefix + 'cp#' + from + ' ' + action + ' ' + content, "cs"); }, generateTransactionId: function(){ return Math.floor(Math.random() * 10); }, toTitleCase: function (str){ return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); }, isPortUsed: function(port, fn) { var net = require('net') var tester = net.createServer().once('error', function (err) { if (err.code != 'EADDRINUSE') return fn(err) fn(null, true); }).once('listening', function() { tester.once('close', function() { fn(null, false) }) .close(); }).listen(port); }, getPort: function(url) { url = url.match(/^(([a-z]+:)?(\/\/)?[^\/]+).*$/)[1] || url; var parts = url.split(':'), port = parseInt(parts[parts.length - 1], 10); if(parts[0] === 'http' && (isNaN(port) || parts.length < 3)) { return 80; } if(parts[0] === 'https' && (isNaN(port) || parts.length < 3)) { return 443; } if(parts.length === 1 || isNaN(port)) return 80; return port; }, getEndpoint: function(uri, ip){ var port = this.getPort(uri); if (ip.substr(0, 7) == "::ffff:") { ip = ip.substr(7) } uri = uri.replace('http://', ''); return ip + ':' + port + uri.substring(uri.indexOf('/'), uri.length); } }; module.exports = Utils;