node-red-contrib-energymeterplus 0.3.0 → 0.3.2

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.
Files changed (2) hide show
  1. package/energyMeterPlus.js +37 -50
  2. package/package.json +1 -1
@@ -2,24 +2,6 @@ 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
- const nodeInstance = RED.nodes.getNode(baselineMsg.nodeId);
9
- if (nodeInstance) {
10
- let baseline = nodeInstance.context().get("baseline") || {
11
- daily:0, weekly:0, monthly:0, yearly:0
12
- };
13
- // Additive offsets
14
- baseline.daily += baselineMsg.payload.daily;
15
- baseline.weekly += baselineMsg.payload.weekly;
16
- baseline.monthly += baselineMsg.payload.monthly;
17
- baseline.yearly += baselineMsg.payload.yearly;
18
-
19
- nodeInstance.context().set("baseline", baseline);
20
- }
21
- });
22
-
23
5
  function EnergyMeterPlus(config) {
24
6
  RED.nodes.createNode(this, config);
25
7
  var node = this;
@@ -30,21 +12,23 @@ module.exports = function(RED) {
30
12
  let currencyCode = config.currency || "USD";
31
13
 
32
14
  // Baseline offsets
33
- let baseline = node.context().get("baseline") || { daily:0, weekly:0, monthly:0, yearly:0 };
15
+ let baseline = node.context().get("baseline") || {
16
+ daily: Number(config.baselineDaily) || 0,
17
+ weekly: Number(config.baselineWeekly) || 0,
18
+ monthly: Number(config.baselineMonthly) || 0,
19
+ yearly: Number(config.baselineYearly) || 0
20
+ };
34
21
 
35
22
  // Live increments
36
- let accumulated = node.context().get("accumulated") || { daily:0, weekly:0, monthly:0, yearly:0 };
37
-
38
- // Apply initial baselines from config
39
- baseline.daily += Number(config.baselineDaily) || 0;
40
- baseline.weekly += Number(config.baselineWeekly) || 0;
41
- baseline.monthly += Number(config.baselineMonthly) || 0;
42
- baseline.yearly += Number(config.baselineYearly) || 0;
43
-
44
- node.context().set("baseline", baseline);
45
- node.context().set("accumulated", accumulated);
46
-
47
- let lastCheck = node.context().get("lastCheck") || new Date();
23
+ let accumulated = node.context().get("accumulated") || {
24
+ daily:0, weekly:0, monthly:0, yearly:0
25
+ };
26
+
27
+ // Rehydrate lastCheck from context
28
+ let lastCheck = node.context().get("lastCheck");
29
+ if (!(lastCheck instanceof Date)) {
30
+ lastCheck = new Date(lastCheck || Date.now());
31
+ }
48
32
 
49
33
  function currencySymbol(code) {
50
34
  switch (code) {
@@ -66,46 +50,40 @@ module.exports = function(RED) {
66
50
  if (fs.existsSync(archivePath)) {
67
51
  archive = JSON.parse(fs.readFileSync(archivePath));
68
52
  }
69
- archive.push({ year, total: total, timestamp: new Date().toISOString() });
53
+ archive.push({ year, total, timestamp: new Date().toISOString() });
70
54
  fs.writeFileSync(archivePath, JSON.stringify(archive, null, 2));
71
55
  } catch (err) {
72
56
  node.error("Failed to archive yearly total: " + err);
73
57
  }
74
58
  }
75
59
 
76
- // Rollover logic resets counters
60
+ // Rollover logic
77
61
  function checkRollover() {
78
62
  let now = new Date();
79
63
 
80
- // Daily reset at midnight
81
- if (now.getDate() !== lastCheck.getDate()) {
82
- accumulated.daily = 0;
83
- baseline.daily = 0;
64
+ // Ensure lastCheck is a Date
65
+ if (!(lastCheck instanceof Date)) {
66
+ lastCheck = new Date(lastCheck || Date.now());
84
67
  }
85
68
 
86
- // Weekly reset (Sunday midnight → Monday start)
69
+ if (now.getDate() !== lastCheck.getDate()) {
70
+ accumulated.daily = 0; baseline.daily = 0;
71
+ }
87
72
  if (now.getDay() === 1 && lastCheck.getDay() !== 1) {
88
- accumulated.weekly = 0;
89
- baseline.weekly = 0;
73
+ accumulated.weekly = 0; baseline.weekly = 0;
90
74
  }
91
-
92
- // Monthly reset
93
75
  if (now.getMonth() !== lastCheck.getMonth()) {
94
- accumulated.monthly = 0;
95
- baseline.monthly = 0;
76
+ accumulated.monthly = 0; baseline.monthly = 0;
96
77
  }
97
-
98
- // Yearly reset
99
78
  if (now.getFullYear() !== lastCheck.getFullYear()) {
100
79
  archiveYearly(baseline.yearly + accumulated.yearly, lastCheck.getFullYear());
101
- accumulated.yearly = 0;
102
- baseline.yearly = 0;
80
+ accumulated.yearly = 0; baseline.yearly = 0;
103
81
  }
104
82
 
105
83
  lastCheck = now;
84
+ node.context().set("lastCheck", lastCheck);
106
85
  node.context().set("accumulated", accumulated);
107
86
  node.context().set("baseline", baseline);
108
- node.context().set("lastCheck", lastCheck);
109
87
  }
110
88
  setInterval(checkRollover, 60000);
111
89
 
@@ -114,6 +92,16 @@ module.exports = function(RED) {
114
92
  let now = new Date();
115
93
  let durationHours = (now - lastCheck) / (1000 * 3600);
116
94
 
95
+ // Handle baseline updates
96
+ if (msg.topic === "applyBaseline" && msg.payload) {
97
+ baseline.daily += Number(msg.payload.daily) || 0;
98
+ baseline.weekly += Number(msg.payload.weekly) || 0;
99
+ baseline.monthly += Number(msg.payload.monthly) || 0;
100
+ baseline.yearly += Number(msg.payload.yearly) || 0;
101
+ node.context().set("baseline", baseline);
102
+ }
103
+
104
+ // Handle power input
117
105
  let power = Number(msg.payload);
118
106
  if (!isNaN(power) && durationHours > 0) {
119
107
  let power_kW = (inputUnit === "W") ? power / 1000 : power;
@@ -129,7 +117,6 @@ module.exports = function(RED) {
129
117
  node.context().set("lastCheck", lastCheck);
130
118
  node.context().set("accumulated", accumulated);
131
119
 
132
- // Output = baseline + accumulated
133
120
  msg.payload = {
134
121
  energyDaily: round2(baseline.daily + accumulated.daily),
135
122
  energyWeekly: round2(baseline.weekly + accumulated.weekly),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-energymeterplus",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
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",