thingzi-logic-timers
Version:
Easy to use time based nodes with clean design
322 lines (298 loc) • 14.4 kB
HTML
<script type="text/javascript">
RED.nodes.registerType('thingzi-time-check', {
category: 'function',
color: '#9ccff5',
defaults: {
name: {value: ''},
lat: {value: '', validate: function(v){
return latLonValidator(this,v) ;
}},
lon: {value: '', validate: function(v){
return latLonValidator(this,v) ;
}},
// ON config params
ontype: {value: 'tod'},
ontimesun: {value: 'dusk'},
ontimetod: {value: null},
ontimetodtype: {value: 'str'},
onoffset: {value: null, validate: function(v){
return (v >= -180 && v <= 180);
}},
onrandomoffset: {value: null},
// OFF config params
offtype: {value: 'tod'},
offtimesun: {value: 'dawn'},
offtimetod: {value: null},
offtimetodtype: {value: 'str'},
offoffset: {value: null, validate: function(v){
return (v >= -180 && v <= 180);
}},
offrandomoffset: {value: null},
// Days of the week
mon: {value: true},
tue: {value: true},
wed: {value: true},
thu: {value: true},
fri: {value: true},
sat: {value: true},
sun: {value: true},
// Pass on unchecked days
passunchecked: {value: false},
},
inputs: 1,
outputs: 2,
outputLabels: ["check passed","check failed"],
icon: "time-check.png",
label: function () {
return this.name ?? "time check";
},
paletteLabel: "time check",
oneditprepare: function () {
var updateGeo = function() {
if ($('#node-input-ontype').val() === 'sun' || $('#node-input-offtype').val() === 'sun') {
$('.thingzi-geo').show();
} else {
$('.thingzi-geo').hide();
}
}
// START
var startType = $('#node-input-ontype');
var startTimeTod = $('#node-input-ontimetod');
var startTimeTodType = $('#node-input-ontimetodtype');
if (!startType.val()) {
startType.val('tod');
}
if (!startTimeTodType.val()) {
startTimeTodType.val('str');
}
startType.on('change', function(data) {
$('.thingzi-starttype').hide();
switch (startType.val()) {
case "sun": $('.thingzi-starttype-sun').show(); break;
case "tod": $('.thingzi-starttype-tod').show(); break;
}
});
startTimeTod.typedInput({
default: 'str',
typeField: startTimeTodType,
types:['str','flow','global']});
startTimeTodType.val(this.ontimetodtype);
// END
var endType = $('#node-input-offtype');
var endTimeTod = $('#node-input-offtimetod');
var endTimeTodType = $('#node-input-offtimetodtype');
if (!endType.val()) {
endType.val('tod');
}
if (!endTimeTodType.val()) {
endTimeTodType.val('str');
}
endType.on('change', function(data) {
$('.thingzi-endtype').hide();
switch (endType.val()) {
case "sun": $('.thingzi-endtype-sun').show(); break;
case "tod": $('.thingzi-endtype-tod').show(); break;
}
});
endTimeTod.typedInput({
default: 'str',
typeField: endTimeTodType,
types:['str','flow','global']});
endTimeTodType.val(this.offtimetodtype);
// Get lat/long from API
if (!$("#node-input-lat").val().trim() && !$("#node-input-lon").val().trim()) {
$.getJSON('thingzi/timer/location', function( data, status, xhr ) {
$("#node-input-lat").val(Number(data.latitude.toFixed(5)));
$("#node-input-lon").val(Number(data.longitude.toFixed(5)));
});
}
// Show/hide Geo fields
updateGeo();
$('.thingzi-geo-check').on('change', function(data) {
updateGeo();
});
}
});
var latLonValidator = function(node, v){
if (node.ontype === 'sun' || node.offtype === 'sun') {
return (node.lat.length > 0 && !isNaN(node.lat) && node.lon.length > 0 && !isNaN(node.lon));
} else {
return true;
}
}
</script>
<script type="text/html" data-template-name="thingzi-time-check">
<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-row">
<label title="days to check, by default not ticked days will fail the check" for="node-input-lat"><i class="fa fa-calendar">
</i> Schedule
</label>
<table style="display: inline-block; position: relative; top: 5px; left: -5px;">
<tr>
<td><input type="checkbox" id="node-input-mon" placeholder="" style="width: 20px; margin: 0">Mon</td>
<td><input type="checkbox" id="node-input-tue" placeholder="" style="width: 20px; margin: 0">Tue</td>
<td><input type="checkbox" id="node-input-wed" placeholder="" style="width: 20px; margin: 0">Wed</td>
<td><input type="checkbox" id="node-input-thu" placeholder="" style="width: 20px; margin: 0">Thu</td>
<td><input type="checkbox" id="node-input-fri" placeholder="" style="width: 20px; margin: 0">Fri</td>
<td><input type="checkbox" id="node-input-sat" placeholder="" style="width: 20px; margin: 0">Sat</td>
<td><input type="checkbox" id="node-input-sun" placeholder="" style="width: 20px; margin: 0">Sun</td>
</tr>
</table>
</div>
<div class="form-row">
<label title="if ticked, when a day is unchecked the test will always pass" style="margin-left: 100px; width: 70%">
<input type="checkbox" id="node-input-passunchecked" style="width: 20px; margin: 0">
<span>Pass test on unchecked days</span>
</label>
</div>
<div>
<hr>
<h4>Start</h4>
<div class="form-row">
<label for="node-input-ontype">Type</label>
<select id="node-input-ontype" class="thingzi-geo-check">
<option value="tod">Time of Day</option>
<option value="sun">Sun Event</option>
</select>
</div>
<div class="form-row thingzi-starttype thingzi-starttype-sun">
<label for="node-input-ontimesun">Sun Event</label>
<select id="node-input-ontimesun">
<option value="solarNoon">Solar Noon</option>
<option value="goldenHourEnd">Golden Hour End</option>
<option value="goldenHour">Golden Hour</option>
<option value="sunriseEnd">Sunrise End</option>
<option value="sunsetStart">Sunset Start</option>
<option value="sunrise">Sunrise</option>
<option value="sunset">Sunset</option>
<option value="dawn">Dawn</option>
<option value="dusk">Dusk</option>
<option value="nauticalDawn">Nautical Dawn</option>
<option value="nauticalDusk">Nautical Dusk</option>
<option value="nightEnd">Night End</option>
<option value="night">Night</option>
<option value="nadir">Nadir</option>
</select>
</div>
<div class="form-row thingzi-starttype thingzi-starttype-tod">
<label title="Simple time string e.g. HH::mm. Can also value from flow or global context" for="node-input-ontimetod">
Time (HH:mm)
</label>
<input type="text" id="node-input-ontimetod" style="width: 70%"/>
<input type="hidden" id="node-input-ontimetodtype">
</div>
<div class="form-row thingzi-starttype thingzi-starttype-sun thingzi-starttype-tod">
<label for="node-input-onoffset">Offset (mins)</label>
<input type="number" id="node-input-onoffset" placeholder="0">
</div>
<div class="form-row thingzi-starttype thingzi-starttype-sun thingzi-starttype-tod">
<label style="margin-left: 100px; width: 70%">
<input type="checkbox" id="node-input-onrandomoffset" placeholder="" style="width: 20px; margin: 0">
Randomise time within offset
</label>
</div>
</div>
<div>
<hr>
<h4>End</h4>
<div class="form-row">
<label for="node-input-offtype">Type</label>
<select id="node-input-offtype" class="thingzi-geo-check">
<option value="tod">Time of Day</option>
<option value="sun">Sun Event</option>
</select>
</div>
<div class="form-row thingzi-endtype thingzi-endtype-sun">
<label for="node-input-offtimesun">Sun Event</label>
<select id="node-input-offtimesun">
<option value="solarNoon">Solar Noon</option>
<option value="goldenHourEnd">Golden Hour End</option>
<option value="goldenHour">Golden Hour</option>
<option value="sunriseEnd">Sunrise End</option>
<option value="sunsetStart">Sunset Start</option>
<option value="sunrise">Sunrise</option>
<option value="sunset">Sunset</option>
<option value="dawn">Dawn</option>
<option value="dusk">Dusk</option>
<option value="nauticalDawn">Nautical Dawn</option>
<option value="nauticalDusk">Nautical Dusk</option>
<option value="nightEnd">Night End</option>
<option value="night">Night</option>
<option value="nadir">Nadir</option>
</select>
</div>
<div class="form-row thingzi-endtype thingzi-endtype-tod">
<label title="Simple time string e.g. HH::mm. Can also value from flow or global context" for="node-input-offtimetod">
Time (24hr)
</label>
<input type="text" id="node-input-offtimetod" style="width: 70%"/>
<input type="hidden" id="node-input-offtimetodtype">
</div>
<div class="form-row thingzi-endtype thingzi-endtype-sun thingzi-endtype-tod">
<label for="node-input-offoffset">Offset (mins)</label>
<input type="number" id="node-input-offoffset" placeholder="0">
</div>
<div class="form-row thingzi-endtype thingzi-endtype-sun thingzi-endtype-tod">
<label style="margin-left: 100px; width: 70%">
<input type="checkbox" id="node-input-offrandomoffset" placeholder="" style="width: 20px; margin: 0">
Randomise time within offset
</label>
</div>
</div>
<div class="thingzi-geo">
<hr>
<h4>Sun Events</h4>
<div class="form-row">
<label for="node-input-lat"><i class="fa fa-globe"></i> Latitude</label>
<input type="text" id="node-input-lat" placeholder="51.025">
</div>
<div class="form-row">
<label for="node-input-lon"><i class="fa fa-globe"></i> Longitude</label>
<input type="text" id="node-input-lon" placeholder="-1.4">
</div>
</div>
</script>
<script type="text/html" data-help-name="thingzi-time-check">
<p>Test if the current or supplied time is within the given range.</p>
<p>
If the time is within the range, the message is forwarded to the next node via the primary output.
if not then the message is sent via the secondary output. The time to check can also be overridden
by supplying a timestamp via the 'time' topic or a simple HH;mm string via the 'nowtime' topic.
</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt class="optional">time (optional) <span class="property-type">timestamp</span></dt>
<dd> A timestamp to check against instead of the current time, if not set the current time now will be used.</dd>
<dt class="optional">nowtime (optional) <span class="property-type">string</span></dt>
<dd> Simple time string to check against instead of the current time e.g. HH:mm.</dd>
<dt class="optional">starttime (optional) <span class="property-type">string</span></dt>
<dd> Simple time string to use instead of the start time e.g. HH:mm. This forces "time of day" mode for the start time</dd>
<dt class="optional">endtime (optional) <span class="property-type">string</span></dt>
<dd> Simple time string to use instead of the off time e.g. HH:mm. This forces "time of day" mode for the end time</dd>
</dl>
<h3>Outputs</h3>
<ol class="node-ports">
<li>Check Passed
<dl class="message-properties">
<dt>msg object</dt>
<dd> Entire message that was sent to input (if time check passed).</dd>
</dl>
</li>
<li>Check Failed
<dl class="message-properties">
<dt>msg object</dt>
<dd> Entire message that was sent to input (if time check failed).</dd>
</dl>
</li>
</ol>
<h3>Details</h3>
<p>Time check ranges can be fixed times or sun events, which are useful for knowing
when to trigger lights without dedicated sensors. When using sun events the node will
try to use your lat/long position using the IP address of your ISP which is usually
close enough. You can override this if you wish.</p>
<p>Times entered as text must be in 24hr format <code>HH:mm</code> (or military time in US). e.g. 18:45 or 09:50.
Note that seconds are also supported e.g. 11:30:45</p>
</script>