thingzi-logic-timers
Version:
Easy to use time based nodes with clean design
352 lines (329 loc) • 15.9 kB
HTML
<script type="text/javascript">
RED.nodes.registerType('thingzi-timer', {
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) ;
}},
timerType: {value: 'onoff'},
startupMessage: {value: true},
// ON config params
ontype: {value: 'tod'},
ontimesun: {value: 'dusk'},
ontimetod: {value: null},
onpropertytype: {value: 'msg'},
onproperty: {value: 'payload'},
onvaluetype: {value: 'str'},
onvalue: {value: 'ON'},
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},
offpropertytype: {value: 'msg'},
offproperty: {value: 'payload'},
offvaluetype: {value: 'str'},
offvalue: {value: 'OFF'},
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}
},
inputs: 0,
outputs: 1,
outputLabels: ["time event"],
icon: "timer.png",
label: function () {
return this.name ?? "timer";
},
paletteLabel: "timer",
oneditprepare: function () {
var updateGeo = function() {
if ($('#node-input-ontype').val() === 'sun' || ($('#node-input-timerType').val() === 'onoff' && $('#node-input-offtype').val() === 'sun')) {
$('.thingzi-geo').show();
} else {
$('.thingzi-geo').hide();
}
}
var atLoad = {
"type": $('#node-input-timerType').val(),
"startupMessage": $('#node-input-startupMessage').prop("checked")
};
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)));
});
}
//Timer Type
$('#node-input-timerType').on('change', function(data) {
var atEvent = {
"type": $('#node-input-timerType').val(),
"startupMessage": $('#node-input-startupMessage').prop("checked")
};
switch ($('#node-input-timerType').val()) {
case "onoff":
$('.thingzi-event-trigger').hide();
$('.thingzi-event-switch').show();
$('#node-input-startupMessageText').text('Send previous event on startup');
if (atLoad.type != atEvent.type)
$('#node-input-startupMessage').prop("checked", true);
else
$('#node-input-startupMessage').prop("checked", atLoad.startupMessage);
break;
case "trigger":
$('.thingzi-event-switch').hide();
$('.thingzi-event-trigger').show();
$('#node-input-startupMessageText').text('Send trigger on startup');
if (atLoad.type != atEvent.type) {
$('#node-input-startupMessage').prop("checked", false);
} else {
$('#node-input-startupMessage').prop("checked", atLoad.startupMessage);
}
break;
}
});
// On
$("#node-input-onproperty").typedInput({
default: 'msg',
typeField: $("#node-input-onpropertytype"),
types:['msg','flow','global']});
$("#node-input-onvaluetype").val(this.onvaluetype ?? 'str');
$("#node-input-onvalue").typedInput({
default: 'str',
typeField: $("#node-input-onvaluetype"),
types:['flow','global','str','num','bool','json','date']
});
$('#node-input-ontype').on('change', function(data) {
$('.thingzi-ontype').hide();
switch ($('#node-input-ontype').val()) {
case "sun": $('.thingzi-ontype-sun').show(); break;
case "tod": $('.thingzi-ontype-time').show(); break;
}
});
//Off
$("#node-input-offproperty").typedInput({
default: 'msg',
typeField: $("#node-input-offpropertytype"),
types:['msg','flow','global']});
$("#node-input-offvaluetype").val(this.offvaluetype ?? 'str');
$("#node-input-offvalue").typedInput({
default: 'str',
typeField: $("#node-input-offvaluetype"),
types:['flow','global','str','num','bool','json','date']
});
$('#node-input-offtype').on('change', function(data) {
$('.thingzi-offtype').hide();
switch ($('#node-input-offtype').val()) {
case "sun": $('.thingzi-offtype-sun').show(); break;
case "tod": $('.thingzi-offtype-time').show(); break;
}
});
// 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-timer">
<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 for="node-input-timerType"><i class="fa fa-cog"></i> Type</label>
<select id="node-input-timerType" class="thingzi-geo-check">
<option value="onoff">On/Off</option>
<option value="trigger">Trigger</option>
</select>
</div>
<div class="form-row">
<label 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 style="margin-left: 100px; width: 70%">
<input type="checkbox" id="node-input-startupMessage" style="width: 20px; margin: 0">
<span id="node-input-startupMessageText">Send previous event on startup</span>
</label>
</div>
<div class="thingzi-event thingzi-event-switch thingzi-event-trigger">
<hr>
<h4 class="thingzi-event-switch">On Event</h4>
<h4 class="thingzi-event-trigger">Trigger</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-ontype thingzi-ontype-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-ontype thingzi-ontype-time">
<label for="node-input-ontimetod">Time (24hr)</label>
<input type="text" id="node-input-ontimetod" placeholder="HH:mm">
</div>
<div class="form-row thingzi-ontype thingzi-ontype-sun thingzi-ontype-time">
<label for="node-input-onoffset">Offset (mins)</label>
<input type="number" id="node-input-onoffset" placeholder="0">
</div>
<div class="form-row thingzi-ontype thingzi-ontype-sun thingzi-ontype-time">
<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 class="form-row">
<label for="node-input-onproperty">Send</label>
<input type="text" id="node-input-onproperty" style="width: 70%"/>
<input type="hidden" id="node-input-onpropertytype">
</div>
<div class="form-row">
<label for="node-input-onvalue">Value</label>
<input type="text" id="node-input-onvalue" style="width:70%">
<input type="hidden" id="node-input-onvaluetype">
</div>
</div>
<div class="thingzi-event thingzi-event-switch">
<hr>
<h4>Off Event</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-offtype thingzi-offtype-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-offtype thingzi-offtype-time">
<label for="node-input-offtimetod">Time (24hr)</label>
<input type="text" id="node-input-offtimetod" placeholder="HH:mm">
</div>
<div class="form-row thingzi-offtype thingzi-offtype-sun thingzi-offtype-time">
<label for="node-input-offoffset">Offset (mins)</label>
<input type="number" id="node-input-offoffset" placeholder="0">
</div>
<div class="form-row thingzi-offtype thingzi-offtype-sun thingzi-offtype-time">
<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 class="form-row">
<label for="node-input-offproperty">Send</label>
<input type="text" id="node-input-offproperty" style="width: 70%"/>
<input type="hidden" id="node-input-offpropertytype">
</div>
<div class="form-row">
<label for="node-input-offvalue">Value</label>
<input type="text" id="node-input-offvalue" style="width:70%">
<input type="hidden" id="node-input-offvaluetype">
</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-timer">
<p>Daily on/off timer node for that supports accurate times or sun events.</p>
<p>Supports two modes of operation; trigger or on/off with customised payloads.</p>
<h3>Outputs</h3>
<ol class="node-ports">
<li>Timer event
<dl class="message-properties">
<dt>payload <span class="property-type">string</span></dt>
<dd> User configured timer event. <code>ON</code> or <code>OFF</code> by default.</dd>
</dl>
</li>
</ol>
<h3>Details</h3>
<p>Configure the timer as required, once deployed the next event time will be
shown in the status.</p>
<p>Events can be fixed times or sun events, which are useful for knowing
when to trigger lights without dedicated sensors. By default the node will
try to locate 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 must be 24hr in the format <code>HH:mm</code>. e.g. 13:45 or 09:50.
Note that seconds are also supported e.g. 11:30:45</p>
<p>Timer events are accurate to within one second.</p>
</script>