node-red-contrib-energymeterplus 0.1.2 → 0.2.1

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.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- #### **EnergyMeterPlus Node Version 0.1.2**
1
+ #### **EnergyMeterPlus Node Version 0.2.1**
2
2
 
3
3
 
4
4
 
@@ -70,7 +70,7 @@ Input Unit: "W" for Watts (default) or "kW" if your source already provides kilo
70
70
 
71
71
 
72
72
 
73
- Baselines: Initial values for daily, weekly, monthly, and yearly counters. Can also be used to correct baseline values or left blank if not needed.
73
+ Baselines: Initial values for daily, weekly, monthly, and yearly counters. Can also be used to correct baseline values or left blank if not needed. Baseline values are applied once at startup or upon a config change and are cleared from the UI. New values can be entered as needed, and the cycle repeats.
74
74
 
75
75
 
76
76
 
@@ -19,12 +19,29 @@ module.exports = function(RED) {
19
19
 
20
20
  // Load persisted baseline or initialize
21
21
  let baseline = node.context().get("baseline") || {
22
- daily: baselineDaily,
23
- weekly: baselineWeekly,
24
- monthly: baselineMonthly,
25
- yearly: baselineYearly
22
+ daily: 0,
23
+ weekly: 0,
24
+ monthly: 0,
25
+ yearly: 0
26
26
  };
27
27
 
28
+ // Apply baselines if new values entered
29
+ let baselineApplied = node.context().get("baselineApplied") || false;
30
+ if (!baselineApplied || baselineDaily || baselineWeekly || baselineMonthly || baselineYearly) {
31
+ baseline.daily += baselineDaily;
32
+ baseline.weekly += baselineWeekly;
33
+ baseline.monthly += baselineMonthly;
34
+ baseline.yearly += baselineYearly;
35
+
36
+ node.context().set("baselineApplied", true);
37
+
38
+ // Cosmetic blanking: clear config fields so they show empty in UI
39
+ config.baselineDaily = "";
40
+ config.baselineWeekly = "";
41
+ config.baselineMonthly = "";
42
+ config.baselineYearly = "";
43
+ }
44
+
28
45
  // Load last timestamp or initialize
29
46
  let lastCheck = node.context().get("lastCheck") || new Date();
30
47
 
@@ -41,10 +58,45 @@ module.exports = function(RED) {
41
58
  // Rollover logic
42
59
  function checkRollover() {
43
60
  let now = new Date();
44
- if (now.getDate() !== lastCheck.getDate()) baseline.daily = baselineDaily;
45
- if (now.getDay() === 0 && lastCheck.getDay() !== 0) baseline.weekly = baselineWeekly;
46
- if (now.getMonth() !== lastCheck.getMonth()) baseline.monthly = baselineMonthly;
47
- if (now.getFullYear() !== lastCheck.getFullYear()) baseline.yearly = baselineYearly;
61
+
62
+ // Daily rollover (midnight)
63
+ if (now.getDate() !== lastCheck.getDate()) {
64
+ baseline.weekly += baseline.daily; // absorb yesterday
65
+ baseline.daily = 0;
66
+ }
67
+
68
+ // Weekly rollover (Sunday → Monday)
69
+ if (now.getDay() === 1 && lastCheck.getDay() !== 1) {
70
+ baseline.monthly += baseline.weekly; // absorb last week
71
+ baseline.weekly = 0;
72
+ }
73
+
74
+ // Monthly rollover (1st of month)
75
+ if (now.getMonth() !== lastCheck.getMonth()) {
76
+ baseline.yearly += baseline.monthly; // absorb last month
77
+ baseline.monthly = 0;
78
+ }
79
+
80
+ // Yearly rollover (Jan 1)
81
+ if (now.getFullYear() !== lastCheck.getFullYear()) {
82
+ try {
83
+ const archivePath = path.join(path.dirname(filePath), "yearly_archive.json");
84
+ let archive = [];
85
+ if (fs.existsSync(archivePath)) {
86
+ archive = JSON.parse(fs.readFileSync(archivePath));
87
+ }
88
+ archive.push({
89
+ year: lastCheck.getFullYear(),
90
+ total_kWh: baseline.yearly,
91
+ timestamp: new Date().toISOString()
92
+ });
93
+ fs.writeFileSync(archivePath, JSON.stringify(archive, null, 2));
94
+ } catch (err) {
95
+ node.error("Failed to archive yearly total: " + err);
96
+ }
97
+ baseline.yearly = 0;
98
+ }
99
+
48
100
  lastCheck = now;
49
101
  node.context().set("baseline", baseline);
50
102
  node.context().set("lastCheck", lastCheck);
@@ -62,12 +114,7 @@ module.exports = function(RED) {
62
114
 
63
115
  let energyIncrement = power_kW * durationHours;
64
116
 
65
- baseline.daily += energyIncrement;
66
- baseline.weekly += energyIncrement;
67
- baseline.monthly += energyIncrement;
68
- baseline.yearly += energyIncrement;
69
-
70
- node.context().set("baseline", baseline);
117
+ baseline.daily += energyIncrement;
71
118
 
72
119
  function round2(val) { return Number(val.toFixed(2)); }
73
120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-energymeterplus",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
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",