@cryptotaxi247 / netdata-1 / commits / b25815c0a

Improving the dashboard and replaced inverter energy chart with site energy chart.

BrainDoctor committed Jul 6, 2017 at 15:47 UTC b25815c0a753516f73f7c288418b3a3a391d94b2
2 files changed +108 -73
node.d/fronius.node.js
+79 -73
@@ -19,33 +19,34 @@ var fronius = {
19 charts: {},
20
21 powerGridId: "p_grid",
22 - powerPvId: 'p_pv',
23 - powerAccuId: 'p_akku', // not my typo! Using the ID from the AP
24 - consumptionLoadId: 'p_load',
25 - autonomyId: 'rel_autonomy',
26 - consumptionSelfId: 'rel_selfconsumption',
27 -
28 - createBasicDimension: function (id, name) {
22 + powerPvId: "p_pv",
23 + powerAccuId: "p_akku", // not my typo! Using the ID from the AP
24 + consumptionLoadId: "p_load",
25 + autonomyId: "rel_autonomy",
26 + consumptionSelfId: "rel_selfconsumption",
27 + energyTodayId: "e_day",
28 + energyYearId: "e_year",
29 +
30 + createBasicDimension: function (id, name, divisor) {
31 return {
32 id: id, // the unique id of the dimension
33 name: name, // the name of the dimension
34 algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
35 multiplier: 1, // the multiplier
34 - divisor: 1, // the divisor
36 + divisor: divisor, // the divisor
37 hidden: false // is hidden (boolean)
38 };
39 },
40
41 // Gets the site power chart. Will be created if not existing.
42 getSitePowerChart: function (service, id) {
41 -
43 var chart = fronius.charts[id];
44 if (fronius.isDefined(chart)) return chart;
45
46 var dim = {};
46 - dim[fronius.powerGridId] = this.createBasicDimension(fronius.powerGridId, "Grid");
47 - dim[fronius.powerPvId] = this.createBasicDimension(fronius.powerPvId, "Photovoltaics");
48 - dim[fronius.powerAccuId] = this.createBasicDimension(fronius.powerAccuId, "Accumulator");
47 + dim[fronius.powerGridId] = this.createBasicDimension(fronius.powerGridId, "Grid", 1);
48 + dim[fronius.powerPvId] = this.createBasicDimension(fronius.powerPvId, "Photovoltaics", 1);
49 + dim[fronius.powerAccuId] = this.createBasicDimension(fronius.powerAccuId, "Accumulator", 1);
50
51 chart = {
52 id: id, // the unique id of the chart
@@ -67,11 +68,10 @@ var fronius = {
68
69 // Gets the site consumption chart. Will be created if not existing.
70 getSiteConsumptionChart: function (service, id) {
70 -
71 var chart = fronius.charts[id];
72 if (fronius.isDefined(chart)) return chart;
73 var dim = {};
74 - dim[fronius.consumptionLoadId] = this.createBasicDimension(fronius.consumptionLoadId, "Load");
74 + dim[fronius.consumptionLoadId] = this.createBasicDimension(fronius.consumptionLoadId, "Load", 1);
75
76 chart = {
77 id: id, // the unique id of the chart
@@ -91,14 +91,13 @@ var fronius = {
91 return chart;
92 },
93
94 -
94 // Gets the site consumption chart. Will be created if not existing.
95 getSiteAutonomyChart: function (service, id) {
96 var chart = fronius.charts[id];
97 if (fronius.isDefined(chart)) return chart;
98 var dim = {};
100 - dim[fronius.autonomyId] = this.createBasicDimension(fronius.autonomyId, "Autonomy");
101 - dim[fronius.consumptionSelfId] = this.createBasicDimension(fronius.consumptionSelfId, "Self Consumption");
99 + dim[fronius.autonomyId] = this.createBasicDimension(fronius.autonomyId, "Autonomy", 1);
100 + dim[fronius.consumptionSelfId] = this.createBasicDimension(fronius.consumptionSelfId, "Self Consumption", 1);
101
102 chart = {
103 id: id, // the unique id of the chart
@@ -118,36 +117,45 @@ var fronius = {
117 return chart;
118 },
119
121 - // Gets the inverter power chart. Will be created if not existing.
122 - // Needs the array of inverters in order to create a chart with all inverters as dimensions
123 - getInverterPowerChart: function (service, chartId, inverters) {
124 -
120 + // Gets the site energy chart for today. Will be created if not existing.
121 + getSiteEnergyTodayChart: function (service, chartId) {
122 var chart = fronius.charts[chartId];
123 if (fronius.isDefined(chart)) return chart;
127 -
124 var dim = {};
125 + dim[fronius.energyTodayId] = this.createBasicDimension(fronius.energyTodayId, "Today", 1000);
126 + chart = {
127 + id: chartId, // the unique id of the chart
128 + name: '', // the unique name of the chart
129 + title: service.name + ' Energy production for today', // the title of the chart
130 + units: 'kWh', // the units of the chart dimensions
131 + family: 'Energy', // the family of the chart
132 + context: 'fronius.energy.today', // the context of the chart
133 + type: netdata.chartTypes.area, // the type of the chart
134 + priority: fronius.base_priority + 4, // the priority relative to others in the same family
135 + update_every: service.update_every, // the expected update frequency of the chart
136 + dimensions: dim
137 + };
138 + chart = service.chart(chartId, chart);
139 + fronius.charts[chartId] = chart;
140
130 - var inverterCount = Object.keys(inverters).length;
131 - var inverter = inverters[inverterCount.toString()];
132 - var i = 1;
133 - for (i; i <= inverterCount; i++) {
134 - if (fronius.isUndefined(inverter)) {
135 - netdata.error("Expected an Inverter with a numerical name! " +
136 - "Have a look at your JSON output to verify.");
137 - continue;
138 - }
139 - dim[i.toString()] = this.createBasicDimension("inverter_" + i, "Inverter " + i);
140 - }
141 + return chart;
142 + },
143
144 + // Gets the site energy chart for today. Will be created if not existing.
145 + getSiteEnergyYearChart: function (service, chartId) {
146 + var chart = fronius.charts[chartId];
147 + if (fronius.isDefined(chart)) return chart;
148 + var dim = {};
149 + dim[fronius.energyYearId] = this.createBasicDimension(fronius.energyYearId, "Year", 1000);
150 chart = {
151 id: chartId, // the unique id of the chart
152 name: '', // the unique name of the chart
145 - title: service.name + ' Current Inverter Output', // the title of the chart
146 - units: 'W', // the units of the chart dimensions
147 - family: 'Inverters', // the family of the chart
148 - context: 'fronius.inverter', // the context of the chart
149 - type: netdata.chartTypes.stacked, // the type of the chart
150 - priority: fronius.base_priority + 4, // the priority relative to others in the same family
153 + title: service.name + ' Energy production for this year', // the title of the chart
154 + units: 'kWh', // the units of the chart dimensions
155 + family: 'Energy', // the family of the chart
156 + context: 'fronius.energy.year', // the context of the chart
157 + type: netdata.chartTypes.area, // the type of the chart
158 + priority: fronius.base_priority + 5, // the priority relative to others in the same family
159 update_every: service.update_every, // the expected update frequency of the chart
160 dimensions: dim
161 };
@@ -157,9 +165,9 @@ var fronius = {
165 return chart;
166 },
167
160 - // Gets the inverter energy production chart for today. Will be created if not existing.
168 + // Gets the inverter power chart. Will be created if not existing.
169 // Needs the array of inverters in order to create a chart with all inverters as dimensions
162 - getInverterEnergyTodayChart: function (service, chartId, inverters) {
170 + getInverterPowerChart: function (service, chartId, inverters) {
171
172 var chart = fronius.charts[chartId];
173 if (fronius.isDefined(chart)) return chart;
@@ -175,25 +183,18 @@ var fronius = {
183 "Have a look at your JSON output to verify.");
184 continue;
185 }
178 - dim[i.toString()] = {
179 - id: 'inverter_' + i, // the unique id of the dimension
180 - name: 'Inverter ' + i, // the name of the dimension
181 - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
182 - multiplier: 1, // the multiplier
183 - divisor: 1000, // the divisor
184 - hidden: false // is hidden (boolean)
185 - };
186 + dim[i.toString()] = this.createBasicDimension("inverter_" + i, "Inverter " + i, 1);
187 }
188
189 chart = {
190 id: chartId, // the unique id of the chart
191 name: '', // the unique name of the chart
191 - title: service.name + ' Inverter Energy production for today', // the title of the chart
192 - units: 'kWh', // the units of the chart dimensions
192 + title: service.name + ' Current Inverter Output', // the title of the chart
193 + units: 'W', // the units of the chart dimensions
194 family: 'Inverters', // the family of the chart
194 - context: 'fronius.inverter', // the context of the chart
195 + context: 'fronius.inverter.output', // the context of the chart
196 type: netdata.chartTypes.stacked, // the type of the chart
196 - priority: fronius.base_priority + 5, // the priority relative to others in the same family
197 + priority: fronius.base_priority + 6, // the priority relative to others in the same family
198 update_every: service.update_every, // the expected update frequency of the chart
199 dimensions: dim
200 };
@@ -203,18 +204,13 @@ var fronius = {
204 return chart;
205 },
206
206 -
207 processResponse: function (service, content) {
208 if (content === null) return;
209 var json = JSON.parse(content);
210 - // validating response
211 - if (fronius.isUndefined(json.Body)) return;
212 - if (fronius.isUndefined(json.Body.Data)) return;
213 - if (fronius.isUndefined(json.Body.Data.Site)) return;
214 - if (fronius.isUndefined(json.Body.Data.Inverters)) return;
210 + if (!fronius.isResponseValid(json)) return;
211
212 // add the service
217 - if (service.added !== true) service.commit();
213 + service.commit();
214
215 var site = json.Body.Data.Site;
216
@@ -240,24 +236,37 @@ var fronius = {
236 service.set(fronius.consumptionSelfId, Math.round(site.rel_SelfConsumption));
237 service.end();
238
239 + // Site Energy Today Chart
240 + service.begin(fronius.getSiteEnergyTodayChart(service, 'fronius_' + service.name + '.energy.today'));
241 + service.set(fronius.energyTodayId, Math.round(site.E_Day));
242 + service.end();
243 +
244 + // Site Energy Year Chart
245 + service.begin(fronius.getSiteEnergyYearChart(service, 'fronius_' + service.name + '.energy.year'));
246 + service.set(fronius.energyYearId, Math.round(site.E_Year));
247 + service.end();
248 +
249 // Inverters
250 var inverters = json.Body.Data.Inverters;
245 - var inverterCount = Object.keys(inverters).length;
246 - if (inverterCount <= 0) return;
247 - var i = 1;
248 - for (i; i <= inverterCount; i++) {
249 - var inverter = inverters[i];
251 + var inverterCount = Object.keys(inverters).length + 1;
252 + while (inverterCount--) {
253 + var inverter = inverters[inverterCount];
254 if (fronius.isUndefined(inverter)) continue;
251 - netdata.debug("Setting values");
255 service.begin(fronius.getInverterPowerChart(service, 'fronius_' + service.name + '.inverters.output', inverters));
253 - service.set(i.toString(), Math.round(inverter.P));
254 - service.end();
255 - service.begin(fronius.getInverterEnergyTodayChart(service, 'fronius_' + service.name + '.inverters.today', inverters));
256 - service.set(i.toString(), Math.round(inverter.E_Day));
256 + service.set(inverterCount.toString(), Math.round(inverter.P));
257 service.end();
258 }
259 },
260
261 + // some basic validation
262 + isResponseValid: function (json) {
263 + if (fronius.isUndefined(json.Body)) return false;
264 + if (fronius.isUndefined(json.Body.Data)) return false;
265 + if (fronius.isUndefined(json.Body.Data.Site)) return false;
266 + if (fronius.isUndefined(json.Body.Data.Inverters)) return false;
267 + return true;
268 + },
269 +
270 // module.serviceExecute()
271 // this function is called only from this module
272 // its purpose is to prepare the request and call
@@ -271,7 +280,6 @@ var fronius = {
280 update_every: update_every,
281 module: this
282 });
274 - service.request.method = 'GET';
283 service.execute(this.processResponse);
284 },
285
@@ -308,8 +316,6 @@ var fronius = {
316 isDefined: function (value) {
317 return typeof value !== 'undefined';
318 }
311 -
312 -
319 };
320
321 module.exports = fronius;
web/dashboard_info.js
+29
@@ -285,6 +285,12 @@ netdataDashboard.menu = {
285 info: undefined
286 },
287
288 + 'fronius': {
289 + title: 'Solar Power',
290 + icon: '<i class="fa fa-sun-o" aria-hidden="true"></i>',
291 + info: undefined
292 + },
293 +
294 'snmp': {
295 title: 'SNMP',
296 icon: '<i class="fa fa-random" aria-hidden="true"></i>',
@@ -1324,5 +1330,28 @@ netdataDashboard.context = {
1330 info: 'These tags are optional and describe some error conditions which occured during response delivery (if any). ' +
1331 '<code>ABORTED</code> when the response was not completed due to the connection being aborted (usually by the client). ' +
1332 '<code>TIMEOUT</code>, when the response was not completed due to a connection timeout.'
1333 + },
1334 +
1335 + // ------------------------------------------------------------------------
1336 + // Fronius Solar Power
1337 +
1338 + 'fronius.power': {
1339 + info: 'Positive <code>Grid</code> values mean that power is coming from the grid. Negative values are excess power that is going back into the grid, possibly selling it. ' +
1340 + '<code>Photovoltaics</code> is the power generated from the solar panels. ' +
1341 + '<code>Accumulator</code> is the stored power in the accumulator, if one is present.'
1342 + },
1343 +
1344 + 'fronius.autonomy': {
1345 + commonMin: true,
1346 + commonMax: true,
1347 + valueRange: "[0, 100]",
1348 + info: 'The <code>Autonomy</code> is the percentage of how autonomous the installation is. An autonomy of 100 % means that the installation is producing more energy than it is needed. ' +
1349 + 'The <code>Self consumption</code> indicates the ratio between the current power generated and the current load. When it reaches 100 %, the <code>Autonomy</code> declines, since the solar panels can not produce enough energy and need support from the grid.'
1350 + },
1351 +
1352 + 'fronius.energy.today': {
1353 + commonMin: true,
1354 + commonMax: true,
1355 + valueRange: "[0, null]"
1356 }
1357 };