Browse Source

Merge remote-tracking branch 'drweaver/master'

# Conflicts:
#	package.json
Gareth O'Brien 6 years ago
parent
commit
7d6487f57f
5 changed files with 129 additions and 26 deletions
  1. 7 0
      README.md
  2. 19 18
      package.json
  3. 46 0
      package.json.orig
  4. 30 5
      ramp-thermostat/ramp-thermostat.html
  5. 27 3
      ramp-thermostat/ramp-thermostat.js

+ 7 - 0
README.md

@@ -23,6 +23,13 @@ A profile has at least 2 points and should typically start at 00:00 and end at 2
 
 The hysteresis is used to prevent osciliation. The `[+]` value is added to the target and the `[-]` (absolute) value is subtracted from the target. Within this neutral zone no action accurs.
 
+The ramp limit defines the maximum time prior to a point to apply the 
+gradient for calculating the thermostat value. Prior to this time, the thermostat will
+stay constant, thus avoiding need to add extra points. <br/>
+For example, 2 points `06:00 [10 degrees] - 14:00 [21 degrees]` with no ramp limit will gradually increase thermostate over the 8 hour period. Setting the ramp
+limit to 60 minutes will keep the thermostat at 10 degrees until `13:00` and then will increase only over the last
+hour. Set to `1440` or leave empty to disable this feature.
+
 ## Usage
 
 This node expects a `numeric` msg.payload containing the current temperature (number). The msg.topic should be set to `setCurrent`. It will calculate the target temperature depending on msg.payload at the current time and output 3 values:

+ 19 - 18
package.json

@@ -1,26 +1,27 @@
 {
-    "name"         : "node-red-contrib-ramp-thermostat",
-    "version"      : "0.5.0",
-    "description"  : "A Node-RED node that emulates a thermostat",
-    "dependencies": {
-    },
-    "keywords": [ 
-      "node-red",
-      "thermostat",
-      "profile",
-      "heating control",
-      "tmeperature control",
-      "energy saving",
-      "multtple heating zones",
-      "single room temperature control"
+    "name": "node-red-contrib-ramp-thermostat",
+    "version": "0.5.0",
+    "description": "A Node-RED node that emulates a thermostat",
+    "dependencies": {},
+    "keywords": [
+        "node-red",
+        "thermostat",
+        "profile",
+        "heating control",
+        "tmeperature control",
+        "energy saving",
+        "multtple heating zones",
+        "single room temperature control"
     ],
     "author": "cflurin",
+    "contributors": [
+        "drweaver"
+    ],
     "repository": {
-      "type": "git",
-      "url": "https://github.com/cflurin/node-red-contrib-ramp-thermostat.git"
+        "type": "git",
+        "url": "https://github.com/cflurin/node-red-contrib-ramp-thermostat.git"
     },
-    
-    "node-red"     : {
+    "node-red": {
         "nodes": {
             "ramp-thermostat": "ramp-thermostat/ramp-thermostat.js"
         }

+ 46 - 0
package.json.orig

@@ -0,0 +1,46 @@
+{
+<<<<<<< HEAD
+    "name"         : "node-red-contrib-ramp-thermostat",
+    "version"      : "0.5.0",
+    "description"  : "A Node-RED node that emulates a thermostat",
+    "dependencies": {
+    },
+    "keywords": [ 
+      "node-red",
+      "thermostat",
+      "profile",
+      "heating control",
+      "tmeperature control",
+      "energy saving",
+      "multtple heating zones",
+      "single room temperature control"
+=======
+    "name": "node-red-contrib-ramp-thermostat",
+    "version": "0.5.0",
+    "description": "A Node-RED node that emulates a thermostat",
+    "dependencies": {},
+    "keywords": [
+        "node-red",
+        "thermostat",
+        "profile",
+        "heating control",
+        "tmeperature control",
+        "energy saving",
+        "multtple heating zones",
+        "single room temperature control"
+>>>>>>> drweaver/master
+    ],
+    "author": "cflurin",
+    "contributors": [
+        "drweaver"
+    ],
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/cflurin/node-red-contrib-ramp-thermostat.git"
+    },
+    "node-red": {
+        "nodes": {
+            "ramp-thermostat": "ramp-thermostat/ramp-thermostat.js"
+        }
+    }
+}

+ 30 - 5
ramp-thermostat/ramp-thermostat.html

@@ -5,17 +5,30 @@
     </div>
     <div class="form-row">
         <label for="node-input-hysteresisplus"><i class="fa fa-arrows-v"></i> Hysteresis [+]</label>
-        <input type="text" id="node-input-hysteresisplus" style="width:50px">
+        <input type="text" id="node-input-hysteresisplus" style="width:50px"> (degrees)
     </div>
     <div class="form-row">
         <label for="node-input-hysteresisminus"><i class="fa fa-arrows-v"></i> Hysteresis [-]</label>
-        <input type="text" id="node-input-hysteresisminus" style="width:50px">
+        <input type="text" id="node-input-hysteresisminus" style="width:50px"> (degrees)
     </div>
+    <div class="form-row">
+        <label for="node-input-hysteresisleft"><i class="fa fa-stop-circle"></i> Ramp Limit</label>
+        <input type="text" id="node-input-ramplimit" style="width:50px"> (mins)
+    </div>    
     <div class="form-row">
         <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
-        <input type="text" id="node-input-name" placeholder="Name">
+        <input type="text" id="node-input-name" placeholder="Name"> 
+    </div>
+    <div class="form-tips"><span class="fa fa-arrows-v"> Hysteresis is used to prevent osciliation. 
+        The [+] value is added to the target and the [-] (absolute) value is 
+        subtracted from the target. Within this neutral zone no action accurs.<br/>
+    </span>
     </div>
-    <div class="form-tips"><span>The Hysteresis is used to prevent osciliation. The [+] value is added to the target and the [-] (absolute) value is subtracted from the target. Within this neutral zone no action accurs.</span>
+    <div class="form-tips">
+    <span class="fa fa-stop-circle"> Ramp Limit defines the maximum time prior to a point to apply the 
+        gradient for calculating the thermostat value. Prior to this time, the thermostat will
+        stay constant, thus avoiding need to add extra points.
+    </span>
     </div>
 </script>
 
@@ -100,6 +113,17 @@
     provides the value depending on the current time <code>00:00-24:00</code>.
     The profile consists of several points whose connections build a sequence of lines.
     The switching moment can be optimized by defining a gradient line like a <code>ramp</code>.</p>
+    <p>The hysteresis is used to prevent osciliation. The `[+]` value is added to the target and the `[-]` (absolute) value is subtracted from the target. Within this neutral zone no action accurs.</p>
+    <p>
+    The ramp limit defines the maximum time prior to a point to apply the 
+    gradient for calculating the thermostat value. Prior to this time, the thermostat will
+    stay constant, thus avoiding need to add extra points. <br/>
+    For example, 2 points:<br/><code>06:00: 10 (degrees)</code><br/><code>14:00: 21 (degrees)</code><br/> 
+    with no ramp limit will gradually increase thermostat over the 8 hour period. Setting the ramp
+    limit to 60 minutes will keep the thermostat at 10 degrees until <code>13:00</code> and then will 
+    increase only over the last
+    hour. <br/>Set to <code>1440</code> or leave empty to disable this feature.
+    </p>
 </script>
 
 <script type="text/javascript">
@@ -110,7 +134,8 @@
             name: {value:""},
             profile: {value:"",type:"profile"},
             hysteresisplus: {value:0, validate:RED.validators.number()},
-            hysteresisminus: {value:0, validate:RED.validators.number()}
+            hysteresisminus: {value:0, validate:RED.validators.number()},
+            ramplimit: {value:"", validate:RED.validators.regex(/^\d*$/)}
         },
         inputs:1,
         outputs:3,

+ 27 - 3
ramp-thermostat/ramp-thermostat.js

@@ -28,6 +28,7 @@ module.exports = function(RED) {
     
     this.h_plus = Math.abs(parseFloat(config.hysteresisplus)) || 0;
     this.h_minus = Math.abs(parseFloat(config.hysteresisminus)) || 0;
+    this.ramp_limit = Math.abs(parseInt(config.ramplimit)) || 1440;
     
     // experimental
     //this.profile = globalContext.get(node_name);
@@ -187,15 +188,37 @@ module.exports = function(RED) {
     
     var date = new Date();
     var current_mins = date.getHours()*60 + date.getMinutes();
+
+    // Objects do no guarentee order, lets sort it
+    var points_arr = Object.keys(profile.points)
+                           .map(key=>{return profile.points[key]})
+                           .sort( (a,b)=> { return a.m - b.m });
       
     //console.log("name " + profile.name + " profile.points " + JSON.stringify(profile.points));
-    for (var k in profile.points) {
-      point_mins = parseInt(profile.points[k].m);
+    for( var k=0; k<points_arr.length; k++ ) {
+      point_mins = points_arr[k].m;
       //console.log("mins " + point_mins + " temp " + profile.points[k]);
       
-      point_target = profile.points[k].t;
+      target = point_target = points_arr[k].t;
+
+      if( points_arr.length == 1 ) {
+        // no need to go any further
+        break;
+      }
       
       if (current_mins < point_mins) {
+
+        if( point_mins - current_mins > this.ramp_limit ) {
+          // Not yet in window to start ramping thermostat, stay constant
+          target = pre_target;
+          break;
+        }
+
+        if( point_mins - pre_mins > this.ramp_limit && point_mins - current_mins <= this.ramp_limit ) {
+          // bring the previous point forward to match ramp max
+          pre_mins = point_mins - this.ramp_limit;
+        }
+
         gradient = (point_target - pre_target) / (point_mins - pre_mins);
         target = pre_target + (gradient * (current_mins - pre_mins));
         //this.warn("k=" + k +" gradient " + gradient + " target " + target);          
@@ -207,6 +230,7 @@ module.exports = function(RED) {
     
     if(isNaN(target)) {
       this.warn("target undefined");
+      return {"state":null, "target":0, "status": {fill:"red",shape:"dot",text:"No points in profile"}};
     }
     
     var target_plus = parseFloat((target + this.h_plus).toFixed(1));