node-red-contrib-energymeterplus 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,14 +4,14 @@
4
4
  color: '#f3a108fe', <!-- Dutch Orange -->
5
5
  defaults: {
6
6
  name: {value:""},
7
- baselineDaily: {value:0},
8
- baselineWeekly: {value:0},
9
- baselineMonthly: {value:0},
10
- baselineYearly: {value:0},
11
- unitCost: {value:0.15},
12
- currency: {value:"USD"}, // NEW field
13
- filePath: {value:"/config/node_red/solargen_data.json"},
14
- inputUnit: {value:"kW"}
7
+ baselineDaily: {value:0, required:false},
8
+ baselineWeekly: {value:0, required:false},
9
+ baselineMonthly: {value:0, required:false},
10
+ baselineYearly: {value:0, required:false},
11
+ unitCost: {value:0.15, required:true},
12
+ currency: {value:"USD", required:true}, // NEW field
13
+ filePath: {value:"/config/node_red/solargen_data.json", required:false},
14
+ inputUnit: {value:"kW", required:true}
15
15
  },
16
16
  inputs:1,
17
17
  outputs:1,
@@ -19,12 +19,23 @@
19
19
  label: function() {
20
20
  return this.name || "energyMeterPlus";
21
21
  },
22
+ oneditprepare: function() {
23
+ // Nothing special here yet
24
+ },
22
25
  oneditsave: function() {
23
- // Cosmetic blanking: clear baseline fields in the editor UI after deploy
24
- $("#node-input-baselineDaily").val("");
25
- $("#node-input-baselineWeekly").val("");
26
- $("#node-input-baselineMonthly").val("");
27
- $("#node-input-baselineYearly").val("");
26
+ // When user clicks Done, send a one-time baseline message
27
+ var baselineMsg = {
28
+ topic: "applyBaseline",
29
+ nodeId: this.id, // include the nodeId!
30
+ payload: {
31
+ daily: Number($("#node-input-baselineDaily").val()) || 0,
32
+ weekly: Number($("#node-input-baselineWeekly").val()) || 0,
33
+ monthly: Number($("#node-input-baselineMonthly").val()) || 0,
34
+ yearly: Number($("#node-input-baselineYearly").val()) || 0
35
+ }
36
+ };
37
+ // Push message into runtime instantly
38
+ RED.comms.send("energyMeterPlus/applyBaseline", baselineMsg);
28
39
  }
29
40
  });
30
41
  </script>
@@ -2,6 +2,25 @@ const fs = require("fs");
2
2
  const path = require("path");
3
3
 
4
4
  module.exports = function(RED) {
5
+
6
+ // Listener for baseline messages from the editor
7
+ RED.comms.subscribe("energyMeterPlus/applyBaseline", function(baselineMsg) {
8
+ // baselineMsg should include nodeId so we know which instance to update
9
+ const nodeInstance = RED.nodes.getNode(baselineMsg.nodeId);
10
+ if (nodeInstance) {
11
+ let baseline = nodeInstance.context().get("baseline") || {
12
+ daily:0, weekly:0, monthly:0, yearly:0
13
+ };
14
+
15
+ baseline.daily = baselineMsg.payload.daily;
16
+ baseline.weekly = baselineMsg.payload.weekly;
17
+ baseline.monthly = baselineMsg.payload.monthly;
18
+ baseline.yearly = baselineMsg.payload.yearly;
19
+
20
+ nodeInstance.context().set("baseline", baseline);
21
+ }
22
+ });
23
+
5
24
  function EnergyMeterPlus(config) {
6
25
  RED.nodes.createNode(this, config);
7
26
  var node = this;
@@ -11,7 +30,7 @@ module.exports = function(RED) {
11
30
  let inputUnit = config.inputUnit || "W";
12
31
  let currencyCode = config.currency || "USD";
13
32
 
14
- // Counters always start from context or zero
33
+ // Counters start from context or zero
15
34
  let baseline = node.context().get("baseline") || {
16
35
  daily: 0,
17
36
  weekly: 0,
@@ -20,21 +39,22 @@ module.exports = function(RED) {
20
39
  };
21
40
 
22
41
  // Capture baselines once on deploy
23
- let storedBaselines = node.context().get("storedBaselines") || {
42
+ let storedBaselines = {
24
43
  daily: Number(config.baselineDaily) || 0,
25
44
  weekly: Number(config.baselineWeekly) || 0,
26
45
  monthly: Number(config.baselineMonthly) || 0,
27
46
  yearly: Number(config.baselineYearly) || 0
28
47
  };
29
48
 
30
- // Apply each baseline only to its own counter
31
- if (storedBaselines.daily) baseline.daily += storedBaselines.daily;
32
- if (storedBaselines.weekly) baseline.weekly += storedBaselines.weekly;
33
- if (storedBaselines.monthly) baseline.monthly += storedBaselines.monthly;
34
- if (storedBaselines.yearly) baseline.yearly += storedBaselines.yearly;
49
+ // Apply baselines once
50
+ baseline.daily += storedBaselines.daily;
51
+ baseline.weekly += storedBaselines.weekly;
52
+ baseline.monthly += storedBaselines.monthly;
53
+ baseline.yearly += storedBaselines.yearly;
35
54
 
55
+ // Discard baselines from UI after applying
36
56
  node.context().set("baseline", baseline);
37
- node.context().set("storedBaselines", storedBaselines);
57
+ node.context().set("storedBaselines", { daily:0, weekly:0, monthly:0, yearly:0 });
38
58
 
39
59
  // Last timestamp
40
60
  let lastCheck = node.context().get("lastCheck") || new Date();
@@ -70,14 +90,26 @@ module.exports = function(RED) {
70
90
  // Rollover logic
71
91
  function checkRollover() {
72
92
  let now = new Date();
73
- let stored = node.context().get("storedBaselines") || { daily:0, weekly:0, monthly:0, yearly:0 };
74
93
 
75
- if (now.getDate() !== lastCheck.getDate()) baseline.daily = stored.daily;
76
- if (now.getDay() === 1 && lastCheck.getDay() !== 1) baseline.weekly = stored.weekly;
77
- if (now.getMonth() !== lastCheck.getMonth()) baseline.monthly = stored.monthly;
94
+ // Daily rollover
95
+ if (now.getDate() !== lastCheck.getDate()) {
96
+ baseline.daily = 0;
97
+ }
98
+
99
+ // Weekly rollover (Sunday midnight → Monday start)
100
+ if (now.getDay() === 1 && lastCheck.getDay() !== 1) {
101
+ baseline.weekly = 0;
102
+ }
103
+
104
+ // Monthly rollover
105
+ if (now.getMonth() !== lastCheck.getMonth()) {
106
+ baseline.monthly = 0;
107
+ }
108
+
109
+ // Yearly rollover
78
110
  if (now.getFullYear() !== lastCheck.getFullYear()) {
79
111
  archiveYearly(baseline.yearly, lastCheck.getFullYear());
80
- baseline.yearly = stored.yearly;
112
+ baseline.yearly = 0;
81
113
  }
82
114
 
83
115
  lastCheck = now;
@@ -96,6 +128,7 @@ module.exports = function(RED) {
96
128
  let power_kW = (inputUnit === "W") ? power / 1000 : power;
97
129
  let energyIncrement = power_kW * durationHours;
98
130
 
131
+ // Apply increment separately to each counter
99
132
  baseline.daily += energyIncrement;
100
133
  baseline.weekly += energyIncrement;
101
134
  baseline.monthly += energyIncrement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-energymeterplus",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "A custom Node-RED node that integrates power readings into energy totals with persistence and cost calculation.",
5
5
  "author": "Arcfrankye",
6
6
  "license": "MIT",