diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-04-14 18:12:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-04-14 18:12:10 +0000 |
commit | b5321aff06d6ea8d730d62aec2ffd8e9271c1ffc (patch) | |
tree | 36c41e35994786456154f9d3bf88c324763aeea4 /collectors/node.d.plugin/fronius | |
parent | Adding upstream version 1.33.1. (diff) | |
download | netdata-b5321aff06d6ea8d730d62aec2ffd8e9271c1ffc.tar.xz netdata-b5321aff06d6ea8d730d62aec2ffd8e9271c1ffc.zip |
Adding upstream version 1.34.0.upstream/1.34.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'collectors/node.d.plugin/fronius')
-rw-r--r-- | collectors/node.d.plugin/fronius/Makefile.inc | 13 | ||||
-rw-r--r-- | collectors/node.d.plugin/fronius/README.md | 135 | ||||
-rw-r--r-- | collectors/node.d.plugin/fronius/fronius.node.js | 400 |
3 files changed, 0 insertions, 548 deletions
diff --git a/collectors/node.d.plugin/fronius/Makefile.inc b/collectors/node.d.plugin/fronius/Makefile.inc deleted file mode 100644 index da0743a88..000000000 --- a/collectors/node.d.plugin/fronius/Makefile.inc +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# THIS IS NOT A COMPLETE Makefile -# IT IS INCLUDED BY ITS PARENT'S Makefile.am -# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT - -# install these files -dist_node_DATA += fronius/fronius.node.js -# dist_nodeconfig_DATA += fronius/fronius.conf - -# do not install these files, but include them in the distribution -dist_noinst_DATA += fronius/README.md fronius/Makefile.inc - diff --git a/collectors/node.d.plugin/fronius/README.md b/collectors/node.d.plugin/fronius/README.md deleted file mode 100644 index 746737d0b..000000000 --- a/collectors/node.d.plugin/fronius/README.md +++ /dev/null @@ -1,135 +0,0 @@ -<!-- -title: "Fronius Symo monitoring with Netdata" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/fronius/README.md -sidebar_label: "Fronius Symo" ---> - -# Fronius Symo monitoring with Netdata - -Collects metrics from the configured solar power installation from Fronius Symo. - -**Requirements** - -- Configuration file `fronius.conf` in the node.d Netdata config dir (default: `/etc/netdata/node.d/fronius.conf`) -- Fronius Symo with network access (http) - -It produces per server: - -1. **Power** - -- Current power input from the grid (positive values), output to the grid (negative values), in W -- Current power input from the solar panels, in W -- Current power stored in the accumulator (if present), in W (in theory, untested) - -2. **Consumption** - -- Local consumption in W - -3. **Autonomy** - -- Relative autonomy in %. 100 % autonomy means that the solar panels are delivering more power than it is needed by local consumption. -- Relative self consumption in %. The lower the better - -4. **Energy** - -- The energy produced during the current day, in kWh -- The energy produced during the current year, in kWh - -5. **Inverter** - -- The current power output from the connected inverters, in W, one dimension per inverter. At least one is always present. - -## configuration - -Sample: - -```json -{ - "enable_autodetect": false, - "update_every": 5, - "servers": [ - { - "name": "Symo", - "hostname": "symo.ip.or.dns", - "update_every": 5, - "api_path": "/solar_api/v1/GetPowerFlowRealtimeData.fcgi" - } - ] -} -``` - -If no configuration is given, the module will be disabled. Each `update_every` is optional, the default is `5`. - ---- - -[Fronius Symo 8.2](https://www.fronius.com/en/photovoltaics/products/all-products/inverters/fronius-symo/fronius-symo-8-2-3-m) - -The plugin has been tested with a single inverter, namely Fronius Symo 8.2-3-M: - -- Datalogger version: 240.162630 -- Software version: 3.7.4-6 -- Hardware version: 2.4D - -Other products and versions may work, but without any guarantees. - -Example Netdata configuration for node.d/fronius.conf. Copy this section to fronius.conf and change name/ip. -The module supports any number of servers. Sometimes there is a lag when collecting every 3 seconds, so 5 should be okay too. You can modify this per server. - -```json -{ - "enable_autodetect": false, - "update_every": 5, - "servers": [ - { - "name": "solar", - "hostname": "symo.ip.or.dns", - "update_every": 5, - "api_path": "/solar_api/v1/GetPowerFlowRealtimeData.fcgi" - } - ] -} -``` - -The output of /solar_api/v1/GetPowerFlowRealtimeData.fcgi looks like this: - -```json -{ - "Head" : { - "RequestArguments" : {}, - "Status" : { - "Code" : 0, - "Reason" : "", - "UserMessage" : "" - }, - "Timestamp" : "2017-07-05T12:35:12+02:00" - }, - "Body" : { - "Data" : { - "Site" : { - "Mode" : "meter", - "P_Grid" : -6834.549847, - "P_Load" : -1271.450153, - "P_Akku" : null, - "P_PV" : 8106, - "rel_SelfConsumption" : 15.685297, - "rel_Autonomy" : 100, - "E_Day" : 35020, - "E_Year" : 5826076, - "E_Total" : 14788870, - "Meter_Location" : "grid" - }, - "Inverters" : { - "1" : { - "DT" : 123, - "P" : 8106, - "E_Day" : 35020, - "E_Year" : 5826076, - "E_Total" : 14788870 - } - } - } - } -} -``` - -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fnode.d.plugin%2Ffronius%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/node.d.plugin/fronius/fronius.node.js b/collectors/node.d.plugin/fronius/fronius.node.js deleted file mode 100644 index 436f3a325..000000000 --- a/collectors/node.d.plugin/fronius/fronius.node.js +++ /dev/null @@ -1,400 +0,0 @@ -"use strict"; -// SPDX-License-Identifier: GPL-3.0-or-later - -// This program will connect to one or more Fronius Symo Inverters. -// to get the Solar Power Generated (current, today). - -// example configuration in netdata/conf.d/node.d/fronius.conf.md - -require("url"); -require("http"); -var netdata = require("netdata"); - -netdata.debug("loaded " + __filename + " plugin"); - -var fronius = { - name: "Fronius", - enable_autodetect: false, - update_every: 5, - base_priority: 60000, - charts: {}, - - powerGridId: "p_grid", - powerPvId: "p_pv", - powerAccuId: "p_akku", // not my typo! Using the ID from the AP - consumptionLoadId: "p_load", - autonomyId: "rel_autonomy", - consumptionSelfId: "rel_selfconsumption", - solarConsumptionId: "solar_consumption", - energyTodayId: "e_day", - energyYearId: "e_year", - - createBasicDimension: function (id, name, 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: 1, // the multiplier - divisor: divisor, // the divisor - hidden: false // is hidden (boolean) - }; - }, - - // Gets the site power chart. Will be created if not existing. - getSitePowerChart: function (service, suffix) { - var id = this.getChartId(service, suffix); - var chart = fronius.charts[id]; - if (fronius.isDefined(chart)) return chart; - - var dim = {}; - dim[fronius.powerGridId] = this.createBasicDimension(fronius.powerGridId, "grid", 1); - dim[fronius.powerPvId] = this.createBasicDimension(fronius.powerPvId, "photovoltaics", 1); - dim[fronius.powerAccuId] = this.createBasicDimension(fronius.powerAccuId, "accumulator", 1); - - chart = { - id: id, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Site Power", // the title of the chart - units: "W", // the units of the chart dimensions - family: "power", // the family of the chart - context: "fronius.power", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 1, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(id, chart); - fronius.charts[id] = chart; - - return chart; - }, - - // Gets the site consumption chart. Will be created if not existing. - getSiteConsumptionChart: function (service, suffix) { - var id = this.getChartId(service, suffix); - var chart = fronius.charts[id]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.consumptionLoadId] = this.createBasicDimension(fronius.consumptionLoadId, "load", 1); - - chart = { - id: id, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Load", // the title of the chart - units: "W", // the units of the chart dimensions - family: "consumption", // the family of the chart - context: "fronius.consumption", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 2, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(id, chart); - fronius.charts[id] = chart; - - return chart; - }, - - // Gets the site consumption chart. Will be created if not existing. - getSiteAutonomyChart: function (service, suffix) { - var id = this.getChartId(service, suffix); - var chart = fronius.charts[id]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.autonomyId] = this.createBasicDimension(fronius.autonomyId, "autonomy", 1); - dim[fronius.consumptionSelfId] = this.createBasicDimension(fronius.consumptionSelfId, "self_consumption", 1); - dim[fronius.solarConsumptionId] = this.createBasicDimension(fronius.solarConsumptionId, "solar_consumption", 1); - - chart = { - id: id, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Autonomy", // the title of the chart - units: "%", // the units of the chart dimensions - family: "autonomy", // the family of the chart - context: "fronius.autonomy", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 3, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(id, chart); - fronius.charts[id] = chart; - - return chart; - }, - - // Gets the site energy chart for today. Will be created if not existing. - getSiteEnergyTodayChart: function (service, suffix) { - var chartId = this.getChartId(service, suffix); - var chart = fronius.charts[chartId]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.energyTodayId] = this.createBasicDimension(fronius.energyTodayId, "today", 1000); - chart = { - id: chartId, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Energy production for today",// the title of the chart - units: "kWh", // the units of the chart dimensions - family: "energy", // the family of the chart - context: "fronius.energy.today", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 4, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(chartId, chart); - fronius.charts[chartId] = chart; - - return chart; - }, - - // Gets the site energy chart for today. Will be created if not existing. - getSiteEnergyYearChart: function (service, suffix) { - var chartId = this.getChartId(service, suffix); - var chart = fronius.charts[chartId]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.energyYearId] = this.createBasicDimension(fronius.energyYearId, "year", 1000); - chart = { - id: chartId, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Energy production for this year",// the title of the chart - units: "kWh", // the units of the chart dimensions - family: "energy", // the family of the chart - context: "fronius.energy.year", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 5, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(chartId, chart); - fronius.charts[chartId] = chart; - - return chart; - }, - - // Gets the inverter power chart. Will be created if not existing. - // Needs the array of inverters in order to create a chart with all inverters as dimensions - getInverterPowerChart: function (service, suffix, inverters) { - var chartId = this.getChartId(service, suffix); - var chart = fronius.charts[chartId]; - if (fronius.isDefined(chart)) return chart; - - var dim = {}; - for (var key in inverters) { - if (inverters.hasOwnProperty(key)) { - var name = key; - if (!isNaN(key)) name = "inverter_" + key; - dim[key] = this.createBasicDimension("inverter_" + key, name, 1); - } - } - - chart = { - id: chartId, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Inverter Output",// the title of the chart - units: "W", // the units of the chart dimensions - family: "inverters", // the family of the chart - context: "fronius.inverter.output", // the context of the chart - type: netdata.chartTypes.stacked, // the type of the chart - priority: fronius.base_priority + 6, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(chartId, chart); - fronius.charts[chartId] = chart; - - return chart; - }, - - processResponse: function (service, content) { - var json = fronius.convertToJson(content); - if (json === null) return; - - // add the service - service.commit(); - - var chartDefinitions = fronius.parseCharts(service, json); - var chartCount = chartDefinitions.length; - while (chartCount--) { - var chartObj = chartDefinitions[chartCount]; - service.begin(chartObj.chart); - var dimCount = chartObj.dimensions.length; - while (dimCount--) { - var dim = chartObj.dimensions[dimCount]; - service.set(dim.name, dim.value); - } - service.end(); - } - }, - - parseCharts: function (service, json) { - var site = json.Body.Data.Site; - return [ - this.parsePowerChart(service, site), - this.parseConsumptionChart(service, site), - this.parseAutonomyChart(service, site), - this.parseEnergyTodayChart(service, site), - this.parseEnergyYearChart(service, site), - this.parseInverterChart(service, json.Body.Data.Inverters) - ]; - }, - - parsePowerChart: function (service, site) { - return this.getChart(this.getSitePowerChart(service, "power"), - [ - this.getDimension(this.powerGridId, Math.round(site.P_Grid)), - this.getDimension(this.powerPvId, Math.round(Math.max(site.P_PV, 0))), - this.getDimension(this.powerAccuId, Math.round(site.P_Akku)) - ] - ); - }, - - parseConsumptionChart: function (service, site) { - return this.getChart(this.getSiteConsumptionChart(service, "consumption"), - [this.getDimension(this.consumptionLoadId, Math.round(Math.abs(site.P_Load)))] - ); - }, - - parseAutonomyChart: function (service, site) { - var selfConsumption = site.rel_SelfConsumption; - var solarConsumption = 0; - var load = Math.abs(site.P_Load); - var power = Math.max(site.P_PV, 0); - if (power <= 0) solarConsumption = 0; - else if (load >= power) solarConsumption = 100; - else solarConsumption = 100 / power * load; - return this.getChart(this.getSiteAutonomyChart(service, "autonomy"), - [ - this.getDimension(this.autonomyId, Math.round(site.rel_Autonomy)), - this.getDimension(this.consumptionSelfId, Math.round(selfConsumption === null ? 100 : selfConsumption)), - this.getDimension(this.solarConsumptionId, Math.round(solarConsumption)) - ] - ); - }, - - parseEnergyTodayChart: function (service, site) { - return this.getChart(this.getSiteEnergyTodayChart(service, "energy.today"), - [this.getDimension(this.energyTodayId, Math.round(Math.max(site.E_Day, 0)))] - ); - }, - - parseEnergyYearChart: function (service, site) { - return this.getChart(this.getSiteEnergyYearChart(service, "energy.year"), - [this.getDimension(this.energyYearId, Math.round(Math.max(site.E_Year, 0)))] - ); - }, - - parseInverterChart: function (service, inverters) { - var dimensions = []; - for (var key in inverters) { - if (inverters.hasOwnProperty(key)) { - dimensions.push(this.getDimension(key, Math.round(inverters[key].P))); - } - } - return this.getChart(this.getInverterPowerChart(service, "inverters.output", inverters), dimensions); - }, - - getDimension: function (name, value) { - return { - name: name, - value: value - }; - }, - - getChart: function (chart, dimensions) { - return { - chart: chart, - dimensions: dimensions - }; - }, - - getChartId: function (service, suffix) { - return "fronius_" + service.name + "." + suffix; - }, - - convertToJson: function (httpBody) { - if (httpBody === null) return null; - var json = httpBody; - // can't parse if it's already a json object, - // the check enables easier testing if the httpBody is already valid JSON. - if (typeof httpBody !== "object") { - try { - json = JSON.parse(httpBody); - } catch (error) { - netdata.error("fronius: Got a response, but it is not valid JSON. Ignoring. Error: " + error.message); - return null; - } - } - return this.isResponseValid(json) ? json : null; - }, - - // some basic validation - isResponseValid: function (json) { - if (this.isUndefined(json.Body)) return false; - if (this.isUndefined(json.Body.Data)) return false; - if (this.isUndefined(json.Body.Data.Site)) return false; - return this.isDefined(json.Body.Data.Inverters); - }, - - // 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("http://" + uri), - update_every: update_every, - module: this - }); - service.execute(this.processResponse); - }, - - - configure: function (config) { - if (fronius.isUndefined(config.servers)) return 0; - var added = 0; - var len = config.servers.length; - while (len--) { - var server = config.servers[len]; - if (fronius.isUndefined(server.update_every)) server.update_every = this.update_every; - if (fronius.areUndefined([server.name, server.hostname, server.api_path])) continue; - - var url = server.hostname + server.api_path; - this.serviceExecute(server.name, url, server.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(); - }); - }, - - isUndefined: function (value) { - return typeof value === "undefined"; - }, - - areUndefined: function (valueArray) { - var i = 0; - for (i; i < valueArray.length; i++) { - if (this.isUndefined(valueArray[i])) return true; - } - return false; - }, - - isDefined: function (value) { - return typeof value !== "undefined"; - } -}; - -module.exports = fronius; |