ramp-thermostat.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <script type="text/x-red" data-template-name="ramp-thermostat">
  2. <div class="form-row">
  3. <label for="node-input-profile"><i class="fa fa-line-chart"></i> Profile</label>
  4. <input type="text" id="node-input-profile">
  5. </div>
  6. <div class="form-row">
  7. <label for="node-input-hysteresisplus"><i class="fa fa-arrows-v"></i> Hysteresis [+]</label>
  8. <input type="text" id="node-input-hysteresisplus" style="width:50px"> (degrees)
  9. </div>
  10. <div class="form-row">
  11. <label for="node-input-hysteresisminus"><i class="fa fa-arrows-v"></i> Hysteresis [-]</label>
  12. <input type="text" id="node-input-hysteresisminus" style="width:50px"> (degrees)
  13. </div>
  14. <div class="form-row">
  15. <label for="node-input-hysteresisleft"><i class="fa fa-arrows-h"></i> Hysteresis</label>
  16. <input type="text" id="node-input-hysteresisleft" style="width:50px"> (mins)
  17. </div>
  18. <div class="form-row">
  19. <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
  20. <input type="text" id="node-input-name" placeholder="Name">
  21. </div>
  22. <div class="form-tips"><span class="fa fa-arrows-v"> Hysteresis is used to prevent osciliation.
  23. The [+] value is added to the target and the [-] (absolute) value is
  24. subtracted from the target. Within this neutral zone no action accurs.<br/>
  25. </span>
  26. </div>
  27. <div class="form-tips">
  28. <span class="fa fa-arrows-h"> Hysteresis defines the maximum time prior to a point to apply the
  29. gradient for calculating the thermostat value. Above this time, the thermostat will
  30. stay constant, thus avoiding need to add extra points.
  31. </span>
  32. </div>
  33. </script>
  34. <script type="text/x-red" data-help-name="ramp-thermostat">
  35. <p>A node that emulates a thermostat.</p>
  36. <p>The ramp-thermostat controls an actuator depending on the current input temperature and the target temperature.</p>
  37. <h3>Inputs</h3>
  38. <dl class="message-properties">
  39. <dt>payload
  40. <span class="property-type">number</span>
  41. </dt>
  42. <dd> current temperature</dd>
  43. <dt class="optional">topic <span class="property-type">string</span></dt>
  44. <dd> setCurrent (or undefined)</dd>
  45. </dl>
  46. <dl class="message-properties">
  47. <dt>payload
  48. <span class="property-type">number</span>
  49. </dt>
  50. <dd> target temperature</dd>
  51. <dt class="optional">topic <span class="property-type">string</span></dt>
  52. <dd> setTarget</dd>
  53. </dl>
  54. <dl class="message-properties">
  55. <dt>payload
  56. <span class="property-type">string</span>
  57. </dt>
  58. <dd> profile name</dd>
  59. <dt class="optional">topic <span class="property-type">string</span></dt>
  60. <dd> setProfile</dd>
  61. </dl>
  62. <dl class="message-properties">
  63. <dt>payload
  64. <span class="property-type">object</span>
  65. </dt>
  66. <dd> JSON e.g. {"name":"myGreatProfile","points":{"00:00":16.0,"08:00":20.0,
  67. "20:00":20.0,"24:00":16.0}}</dd>
  68. <dt class="optional">topic <span class="property-type">string</span></dt>
  69. <dd> setProfile</dd>
  70. </dl>
  71. <h3>Outputs</h3>
  72. <ol class="node-ports">
  73. <li>State
  74. <dl class="message-properties">
  75. <dt>payload <span class="property-type">boolean</span></dt>
  76. <dd>the state of the thermostat.</dd>
  77. </dl>
  78. </li>
  79. <li>Current Temperature
  80. <dl class="message-properties">
  81. <dt>payload <span class="property-type">number</span></dt>
  82. <dd>the current temperature.</dd>
  83. </dl>
  84. </li>
  85. <li>Target Temperature
  86. <dl class="message-properties">
  87. <dt>payload <span class="property-type">number</span></dt>
  88. <dd>the actual target temperature.</dd>
  89. </dl>
  90. </li>
  91. </ol>
  92. <h3>Details</h3>
  93. <p>The target temperature is defined by a profile that
  94. provides the value depending on the current time <code>00:00-24:00</code>.
  95. The profile consists of several points whose connections build a sequence of lines.
  96. The switching moment can be optimized by defining a gradient line like a <code>ramp</code>.</p>
  97. </script>
  98. <script type="text/javascript">
  99. RED.nodes.registerType('ramp-thermostat',{
  100. category: 'smart home',
  101. color: '#E9967A',
  102. defaults: {
  103. name: {value:""},
  104. profile: {value:"",type:"profile"},
  105. hysteresisplus: {value:0, validate:RED.validators.number()},
  106. hysteresisminus: {value:0, validate:RED.validators.number()},
  107. hysteresisleft: {value:60, validate:RED.validators.number()}
  108. },
  109. inputs:1,
  110. outputs:3,
  111. outputLabels: ["state","current temperature","target temperature"],
  112. icon: "trigger.png",
  113. label: function() {
  114. return this.name||"ramp-thermostat";
  115. },
  116. paletteLabel: 'thermostat'
  117. });
  118. </script>
  119. <script type="text/x-red" data-template-name="profile">
  120. <div class="form-row">
  121. <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
  122. <input type="text" id="node-config-input-name">
  123. </div>
  124. <div>
  125. <label style="float:left; margin-bottom:10px"><i class="fa fa-dot-circle-o"></i> Points:</label>
  126. <label style="float:left;margin-left:45px;"> Time (hh:mm)&nbsp;&nbsp&nbsp;Temp (°)</label>
  127. </div>
  128. <div class="form-row">
  129. <label for="node-config-input-time1"><i class="fa fa-dot-circle-o"></i> #1</label>
  130. <input class="input-append-left" type="text" id="node-config-input-time1" style="width:50px">
  131. <input type="text" id="node-config-input-temp1" style="margin-left:45px; width:50px">
  132. </div>
  133. <div class="form-row">
  134. <label for="node-config-input-time2"><i class="fa fa-dot-circle-o"></i> #2</label>
  135. <input class="input-append-left" type="text" id="node-config-input-time2" style="width:50px">
  136. <input type="text" id="node-config-input-temp2" style="margin-left:45px; width:50px">
  137. </div>
  138. <div class="form-row">
  139. <label for="node-config-input-time3"><i class="fa fa-dot-circle-o"></i> #3</label>
  140. <input class="input-append-left" type="text" id="node-config-input-time3" style="width:50px">
  141. <input type="text" id="node-config-input-temp3" style="margin-left:45px; width:50px">
  142. </div>
  143. <div class="form-row">
  144. <label for="node-config-input-time4"><i class="fa fa-dot-circle-o"></i> #4</label>
  145. <input class="input-append-left" type="text" id="node-config-input-time4" style="width:50px">
  146. <input type="text" id="node-config-input-temp4" style="margin-left:45px; width:50px">
  147. </div>
  148. <div class="form-row">
  149. <label for="node-config-input-time5"><i class="fa fa-dot-circle-o"></i> #5</label>
  150. <input class="input-append-left" type="text" id="node-config-input-time5" style="width:50px">
  151. <input type="text" id="node-config-input-temp5" style="margin-left:45px; width:50px">
  152. </div>
  153. <div class="form-row">
  154. <label for="node-config-input-time6"><i class="fa fa-dot-circle-o"></i> #6</label>
  155. <input class="input-append-left" type="text" id="node-config-input-time6" style="width:50px">
  156. <input type="text" id="node-config-input-temp6" style="margin-left:45px; width:50px">
  157. </div>
  158. <div class="form-row">
  159. <label for="node-config-input-time7"><i class="fa fa-dot-circle-o"></i> #7</label>
  160. <input class="input-append-left" type="text" id="node-config-input-time7" style="width:50px">
  161. <input type="text" id="node-config-input-temp7" style="margin-left:45px; width:50px">
  162. </div>
  163. <div class="form-row">
  164. <label for="node-config-input-time8"><i class="fa fa-dot-circle-o"></i> #8</label>
  165. <input class="input-append-left" type="text" id="node-config-input-time8" style="width:50px">
  166. <input type="text" id="node-config-input-temp8" style="margin-left:45px; width:50px">
  167. </div>
  168. <div class="form-row">
  169. <label for="node-config-input-time9"><i class="fa fa-dot-circle-o"></i> #9</label>
  170. <input class="input-append-left" type="text" id="node-config-input-time9" style="width:50px">
  171. <input type="text" id="node-config-input-temp9" style="margin-left:45px; width:50px">
  172. </div>
  173. <div class="form-row">
  174. <label for="node-config-input-time10"><i class="fa fa-dot-circle-o"></i> #10</label>
  175. <input class="input-append-left" type="text" id="node-config-input-time10" style="width:50px">
  176. <input type="text" id="node-config-input-temp10" style="margin-left:45px; width:50px">
  177. </div>
  178. <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>
  179. </div>
  180. </script>
  181. <script type="text/javascript">
  182. var time_re = /(^$)|(^(?:[01]\d|2[0-4]):[0-5]\d$)/;
  183. var temp_re = /^[+-]?\d*\.?\d+$|^$/;
  184. RED.nodes.registerType('profile',{
  185. category: 'config',
  186. defaults: {
  187. name: {value:'',required:true},
  188. time1: {value:'', validate:RED.validators.regex(time_re)},
  189. temp1: {value:'', validate:RED.validators.regex(temp_re)},
  190. time2: {value:'', validate:RED.validators.regex(time_re)},
  191. temp2: {value:'', validate:RED.validators.regex(temp_re)},
  192. time3: {value:'', validate:RED.validators.regex(time_re)},
  193. temp3: {value:'', validate:RED.validators.regex(temp_re)},
  194. time4: {value:'', validate:RED.validators.regex(time_re)},
  195. temp4: {value:'', validate:RED.validators.regex(temp_re)},
  196. time5: {value:'', validate:RED.validators.regex(time_re)},
  197. temp5: {value:'', validate:RED.validators.regex(temp_re)},
  198. time6: {value:'', validate:RED.validators.regex(time_re)},
  199. temp6: {value:'', validate:RED.validators.regex(temp_re)},
  200. time7: {value:'', validate:RED.validators.regex(time_re)},
  201. temp7: {value:'', validate:RED.validators.regex(temp_re)},
  202. time8: {value:'', validate:RED.validators.regex(time_re)},
  203. temp8: {value:'', validate:RED.validators.regex(temp_re)},
  204. time9: {value:'', validate:RED.validators.regex(time_re)},
  205. temp9: {value:'', validate:RED.validators.regex(temp_re)},
  206. time10: {value:'', validate:RED.validators.regex(time_re)},
  207. temp10: {value:'', validate:RED.validators.regex(temp_re)},
  208. },
  209. label: function() {
  210. return this.name;
  211. }
  212. });
  213. </script>