summaryrefslogtreecommitdiffstats
path: root/node.d
diff options
context:
space:
mode:
authorCosta Tsaousis <costa@tsaousis.gr>2017-07-25 21:46:35 +0300
committerGitHub <noreply@github.com>2017-07-25 21:46:35 +0300
commit22bac1ff475a00dfd571dfbd0fd5764bc0cbb313 (patch)
treeede4f92d05ce90dabbb319fe80d4d89149ab130d /node.d
parent315417300918ef0c575a7b68a87f422c01914bc2 (diff)
parent8ae4005cee62e4a0d4ab44f5ad2c105e469d3353 (diff)
Merge pull request #2448 from BrainDoctor/stiebeleltron
add plugin for Stiebel Eltron heat pump system
Diffstat (limited to 'node.d')
-rw-r--r--node.d/README.md55
-rw-r--r--node.d/stiebeleltron.node.js196
2 files changed, 251 insertions, 0 deletions
diff --git a/node.d/README.md b/node.d/README.md
index 3c29779054..6818d34de8 100644
--- a/node.d/README.md
+++ b/node.d/README.md
@@ -61,3 +61,58 @@ Sample:
If no configuration is given, the module will be disabled. Each `update_every` is optional, the default is `5`.
---
+
+# stiebel eltron
+
+This module collects metrics from the configured heat pump and hot water installation from Stiebel Eltron ISG web.
+See `netdata/conf.d/node.d/stiebeleltron.conf.md` for more details.
+
+**Requirements**
+ * Configuration file `stiebeleltron.conf` in the node.d netdata config dir (default: `/etc/netdata/node.d/stiebeleltron.conf`)
+ * Stiebel Eltron ISG web with network access (http), without password login
+
+The charts are configurable, however, the provided default configuration collects the following:
+
+1. **General**
+ * Outside temperature in C
+ * Condenser temperature in C
+ * Heating circuit pressure in bar
+ * Flow rate in l/min
+ * Output of water and heat pumps in %
+
+2. **Heating**
+ * Heat circuit 1 temperature in C (set/actual)
+ * Heat circuit 2 temperature in C (set/actual)
+ * Flow temperature in C (set/actual)
+ * Buffer temperature in C (set/actual)
+ * Pre-flow temperature in C
+
+3. **Hot Water**
+ * Hot water temperature in C (set/actual)
+
+4. **Room Temperature**
+ * Heat circuit 1 room temperature in C (set/actual)
+ * Heat circuit 2 room temperature in C (set/actual)
+
+5. **Eletric Reheating**
+ * Dual Mode Reheating temperature in C (hot water/heating)
+
+6. **Process Data**
+ * Remaining compressor rest time in s
+
+7. **Runtime**
+ * Compressor runtime hours (hot water/heating)
+ * Reheating runtime hours (reheating 1/reheating 2)
+
+8. **Energy**
+ * Compressor today in kWh (hot water/heating)
+ * Compressor Total in kWh (hot water/heating)
+
+
+### configuration
+
+The default configuration is provided in [netdata/conf.d/node.d/stiebeleltron.conf.md](https://github.com/firehol/netdata/blob/master/conf.d/node.d/stiebeleltron.conf.md). Just change the `update_every` (if necessary) and hostnames. **You may have to adapt the configuration to suit your needs and setup** (which might be different).
+
+If no configuration is given, the module will be disabled. Each `update_every` is optional, the default is `10`.
+
+---
diff --git a/node.d/stiebeleltron.node.js b/node.d/stiebeleltron.node.js
new file mode 100644
index 0000000000..b0eb0aba79
--- /dev/null
+++ b/node.d/stiebeleltron.node.js
@@ -0,0 +1,196 @@
+'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.page.id + "." + context.category.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;