123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- <script type="text/x-red" data-template-name="ramp-thermostat">
- <div class="form-row">
- <label for="node-input-profile"><i class="fa fa-line-chart"></i> Profile</label>
- <input type="text" id="node-input-profile">
- </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"> (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"> (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">
- </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 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>
- <script type="text/x-red" data-help-name="ramp-thermostat">
- <p>A node that emulates a thermostat.</p>
- <p>The ramp-thermostat controls an actuator depending on the current input temperature and the target temperature.</p>
-
- <h3>Inputs</h3>
- <dl class="message-properties">
- <dt>payload
- <span class="property-type">number</span>
- </dt>
- <dd> current temperature</dd>
- <dt class="optional">topic <span class="property-type">string</span></dt>
- <dd> setCurrent (or undefined)</dd>
- </dl>
- <dl class="message-properties">
- <dt>payload
- <span class="property-type">number</span>
- </dt>
- <dd> target temperature</dd>
- <dt class="optional">topic <span class="property-type">string</span></dt>
- <dd> setTarget</dd>
- </dl>
- <dl class="message-properties">
- <dt>payload
- <span class="property-type">string</span>
- </dt>
- <dd> profile name</dd>
- <dt class="optional">topic <span class="property-type">string</span></dt>
- <dd> setProfile</dd>
- </dl>
- <dl class="message-properties">
- <dt>payload
- <span class="property-type">object</span>
- </dt>
- <dd> JSON e.g. {"name":"myGreatProfile","points":{"00:00":16.0,"08:00":20.0,
- "20:00":20.0,"24:00":16.0}}</dd>
- <dt class="optional">topic <span class="property-type">string</span></dt>
- <dd> setProfile</dd>
- </dl>
- <h3>Outputs</h3>
- <ol class="node-ports">
- <li>State
- <dl class="message-properties">
- <dt>payload <span class="property-type">boolean</span></dt>
- <dd>the state of the thermostat.</dd>
- </dl>
- </li>
- <li>Current Temperature
- <dl class="message-properties">
- <dt>payload <span class="property-type">number</span></dt>
- <dd>the current temperature.</dd>
- </dl>
- </li>
- <li>Target Temperature
- <dl class="message-properties">
- <dt>payload <span class="property-type">number</span></dt>
- <dd>the actual target temperature.</dd>
- </dl>
- </li>
- </ol>
-
- <h3>Details</h3>
- <p>The target temperature is defined by a profile that
- 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">
- RED.nodes.registerType('ramp-thermostat',{
- category: 'smart home',
- color: '#E9967A',
- defaults: {
- name: {value:""},
- profile: {value:"",type:"profile"},
- hysteresisplus: {value:0, validate:RED.validators.number()},
- hysteresisminus: {value:0, validate:RED.validators.number()},
- ramplimit: {value:"", validate:RED.validators.regex(/^\d*$/)}
- },
- inputs:1,
- outputs:3,
- outputLabels: ["state","current temperature","target temperature"],
- icon: "trigger.png",
- label: function() {
- return this.name||"ramp-thermostat";
- },
- paletteLabel: 'thermostat'
- });
- </script>
- <script type="text/x-red" data-template-name="profile">
- <div class="form-row">
- <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
- <input type="text" id="node-config-input-name">
- </div>
-
- <div>
- <label style="float:left; margin-bottom:10px"><i class="fa fa-dot-circle-o"></i> Points:</label>
- <label style="float:left;margin-left:45px;"> Time (hh:mm)   Temp (°)</label>
- </div>
- <div class="form-row">
- <label for="node-config-input-time1"><i class="fa fa-dot-circle-o"></i> #1</label>
- <input class="input-append-left" type="text" id="node-config-input-time1" style="width:50px">
- <input type="text" id="node-config-input-temp1" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time2"><i class="fa fa-dot-circle-o"></i> #2</label>
- <input class="input-append-left" type="text" id="node-config-input-time2" style="width:50px">
- <input type="text" id="node-config-input-temp2" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time3"><i class="fa fa-dot-circle-o"></i> #3</label>
- <input class="input-append-left" type="text" id="node-config-input-time3" style="width:50px">
- <input type="text" id="node-config-input-temp3" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time4"><i class="fa fa-dot-circle-o"></i> #4</label>
- <input class="input-append-left" type="text" id="node-config-input-time4" style="width:50px">
- <input type="text" id="node-config-input-temp4" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time5"><i class="fa fa-dot-circle-o"></i> #5</label>
- <input class="input-append-left" type="text" id="node-config-input-time5" style="width:50px">
- <input type="text" id="node-config-input-temp5" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time6"><i class="fa fa-dot-circle-o"></i> #6</label>
- <input class="input-append-left" type="text" id="node-config-input-time6" style="width:50px">
- <input type="text" id="node-config-input-temp6" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time7"><i class="fa fa-dot-circle-o"></i> #7</label>
- <input class="input-append-left" type="text" id="node-config-input-time7" style="width:50px">
- <input type="text" id="node-config-input-temp7" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time8"><i class="fa fa-dot-circle-o"></i> #8</label>
- <input class="input-append-left" type="text" id="node-config-input-time8" style="width:50px">
- <input type="text" id="node-config-input-temp8" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time9"><i class="fa fa-dot-circle-o"></i> #9</label>
- <input class="input-append-left" type="text" id="node-config-input-time9" style="width:50px">
- <input type="text" id="node-config-input-temp9" style="margin-left:45px; width:50px">
- </div>
- <div class="form-row">
- <label for="node-config-input-time10"><i class="fa fa-dot-circle-o"></i> #10</label>
- <input class="input-append-left" type="text" id="node-config-input-time10" style="width:50px">
- <input type="text" id="node-config-input-temp10" style="margin-left:45px; width:50px">
- </div>
- <div class="form-tips"><span>A Profile has at least 2 Points and should typically start at 00:00 and end at 24:00.</span>
- </div>
- </script>
- <script type="text/javascript">
- var time_re = /(^$)|(^(?:[01]\d|2[0-4]):[0-5]\d$)/;
- var temp_re = /^[+-]?\d*\.?\d+$|^$/;
- RED.nodes.registerType('profile',{
- category: 'config',
- defaults: {
- name: {value:'',required:true},
- time1: {value:'', validate:RED.validators.regex(time_re)},
- temp1: {value:'', validate:RED.validators.regex(temp_re)},
- time2: {value:'', validate:RED.validators.regex(time_re)},
- temp2: {value:'', validate:RED.validators.regex(temp_re)},
- time3: {value:'', validate:RED.validators.regex(time_re)},
- temp3: {value:'', validate:RED.validators.regex(temp_re)},
- time4: {value:'', validate:RED.validators.regex(time_re)},
- temp4: {value:'', validate:RED.validators.regex(temp_re)},
- time5: {value:'', validate:RED.validators.regex(time_re)},
- temp5: {value:'', validate:RED.validators.regex(temp_re)},
- time6: {value:'', validate:RED.validators.regex(time_re)},
- temp6: {value:'', validate:RED.validators.regex(temp_re)},
- time7: {value:'', validate:RED.validators.regex(time_re)},
- temp7: {value:'', validate:RED.validators.regex(temp_re)},
- time8: {value:'', validate:RED.validators.regex(time_re)},
- temp8: {value:'', validate:RED.validators.regex(temp_re)},
- time9: {value:'', validate:RED.validators.regex(time_re)},
- temp9: {value:'', validate:RED.validators.regex(temp_re)},
- time10: {value:'', validate:RED.validators.regex(time_re)},
- temp10: {value:'', validate:RED.validators.regex(temp_re)},
- },
- label: function() {
- return this.name;
- }
- });
- </script>
|