'use strict'; // This program will connect to one Stiebel Eltron ISG for heatpump heating // to get the heat pump metrics. // example configuration in netdata/conf.d/node.d/stiebeleltron.conf.md var url = require("url"); var http = require("http"); var netdata = require("netdata"); netdata.debug("loaded " + __filename + " plugin"); var stiebeleltron = { name: "Stiebel Eltron", enable_autodetect: false, update_every: 10, base_priority: 60000, charts: {}, pages: {}, createBasicDimension: function (id, name, multiplier, divisor) { return { id: id, // the unique id of the dimension name: name, // the name of the dimension algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm multiplier: multiplier, // the multiplier divisor: divisor, // the divisor hidden: false // is hidden (boolean) }; }, processResponse: function (service, html) { if (html === null) return; // add the service service.commit(); var page = stiebeleltron.pages[service.name]; var categories = page.categories; var categoriesCount = categories.length; while (categoriesCount--) { var context = { html: html, service: service, category: categories[categoriesCount], page: page, chartDefinition: null, dimension: null }; stiebeleltron.processCategory(context); } }, processCategory: function (context) { var charts = context.category.charts; var chartCount = charts.length; while (chartCount--) { context.chartDefinition = charts[chartCount]; stiebeleltron.processChart(context); } }, processChart: function (context) { var dimensions = context.chartDefinition.dimensions; var dimensionCount = dimensions.length; context.service.begin(stiebeleltron.getChartFromContext(context)); while (dimensionCount--) { context.dimension = dimensions[dimensionCount]; stiebeleltron.processDimension(context); } context.service.end(); }, processDimension: function (context) { var dimension = context.dimension; var match = new RegExp(dimension.regex).exec(context.html); if (match === null) return; var value = match[1].replace(",", "."); // most values have a single digit by default, which requires the values to be multiplied. can be overridden. if (stiebeleltron.isDefined(dimension.digits)) { value *= Math.pow(10, dimension.digits); } else { value *= 10; } context.service.set(stiebeleltron.getDimensionId(context), value); }, getChartFromContext: function (context) { var chartId = this.getChartId(context); var chart = stiebeleltron.charts[chartId]; if (stiebeleltron.isDefined(chart)) return chart; var chartDefinition = context.chartDefinition; var service = context.service; var dimensions = {}; var dimCount = chartDefinition.dimensions.length; while (dimCount--) { var dim = chartDefinition.dimensions[dimCount]; var multiplier = 1; var divisor = 10; if (stiebeleltron.isDefined(dim.digits)) divisor = Math.pow(10, Math.max(0, dim.digits)); if (stiebeleltron.isDefined(dim.multiplier)) multiplier = dim.multiplier; if (stiebeleltron.isDefined(dim.divisor)) divisor = dim.divisor; context.dimension = dim; var dimId = this.getDimensionId(context); dimensions[dimId] = this.createBasicDimension(dimId, dim.name, multiplier, divisor); } chart = { id: chartId, name: '', title: chartDefinition.title, units: chartDefinition.unit, family: context.category.name, context: 'stiebeleltron.' + context.category.id + '.' + chartDefinition.id, type: chartDefinition.type, priority: stiebeleltron.base_priority + chartDefinition.prio,// the priority relative to others in the same family update_every: service.update_every, // the expected update frequency of the chart dimensions: dimensions }; chart = service.chart(chartId, chart); stiebeleltron.charts[chartId] = chart; return chart; }, // module.serviceExecute() // this function is called only from this module // its purpose is to prepare the request and call // netdata.serviceExecute() serviceExecute: function (name, uri, update_every) { netdata.debug(this.name + ': ' + name + ': url: ' + uri + ', update_every: ' + update_every); var service = netdata.service({ name: name, request: netdata.requestFromURL(uri), update_every: update_every, module: this }); service.execute(this.processResponse); }, configure: function (config) { if (stiebeleltron.isUndefined(config.pages)) return 0; var added = 0; var pageCount = config.pages.length; while (pageCount--) { var page = config.pages[pageCount]; // some validation if (stiebeleltron.isUndefined(page.categories) || page.categories.length < 1) { netdata.error("Your Stiebel Eltron config is invalid. Disabling plugin."); return 0; } if (stiebeleltron.isUndefined(page.update_every)) page.update_every = this.update_every; this.pages[page.name] = page; this.serviceExecute(page.name, page.url, page.update_every); added++; } return added; }, // module.update() // this is called repeatedly to collect data, by calling // netdata.serviceExecute() update: function (service, callback) { service.execute(function (serv, data) { service.module.processResponse(serv, data); callback(); }); }, getChartId: function (context) { return "stiebeleltron_" + context.page.id + "." + context.category.id + "." + context.chartDefinition.id; }, getDimensionId: function (context) { return context.dimension.id; }, isUndefined: function (value) { return typeof value === 'undefined'; }, isDefined: function (value) { return typeof value !== 'undefined'; } }; module.exports = stiebeleltron;