node-red-contrib-sunevents
Version:
A node for node-red that generates events based on the position of the Sun at the appropriate time of day
232 lines (197 loc) • 11.9 kB
HTML
<!--
Copyright 2013-2023 Freak Enterprises
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Description:
A node for node-red that generates events based on the location of the Sun
at the appropriate time of day.
-->
<script type="text/x-red" data-template-name="sun events">
<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-topic"><i class="fa fa-tasks"></i> Topic</label>
<input type="text" id="node-input-topic" placeholder="Topic">
</div>
<div class="form-row">
<label><i class="fa fa-cog"></i> Options</label>
<!--
<input type="checkbox" id="node-input-verbose" placeholder="once" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-verbose" style="width: 70%;">Log messages to debug window?</label>
-->
</div>
<div class="form-row">
<label> </label>
<input type="checkbox" id="node-input-testmode" placeholder="once" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-testmode" style="width: 70%;">Make hours seem like minutes? (test mode)</label>
</div>
<hr>
<div class="form-row">
<p><i class="fa fa-warning"></i> Latitude & Longitude</p>
<p>Please note: since v3.0 the preferred way of providing values for latitude and longitude is
via properties in the <i>msg.payload</i>. These parameters below are provided for backwards
compatibility and to help make the upgrade to v3 easier. Parameters passed via
<i>msg.payload</i> take precedence over the values below. You <b>must</b> still inject a payload
at regular intervals to trigger event calculations (a dummy payload will work fine). Please
see the documentation for more details.
</div>
<div class="form-row">
<label for="node-input-latitude"><i class="fa fa-globe"></i> Latitude</label>
<input type="text" id="node-input-latitude" placeholder="50.5">
</div>
<div class="form-row">
<label for="node-input-longitude"><i class="fa fa-globe"></i> Longitude</label>
<input type="text" id="node-input-longitude" placeholder="-0.1">
</div>
</script>
<!-- Next, some simple help text is provided for the node. -->
<script type="text/x-red" data-help-name="sun events">
<p><i>node-red-contrib-sunevents v3.1</i></p>
<p>
A node that emits events based on the location of the Sun at the appropriate time of day. This node can be used
to make something happen at particular period of the day, for example switching on your lights at home at dusk
every day or taking a photo a the darkest time of night ("nadir").
</p>
<p>
On receiving a `msg.payload` containing latitude and longitude coordinates (in decimal), this node waits and then
outputs a series of Sun event objects at the appropriate time for each. A secondary "missed events" output provides
an array of the Sun events that have passed before this node was triggered with an input (See Missed Events for
more details).
</p>
<p>
Calculations are performed using the excellent <a href="https://github.com/mourner/suncalc">SunCalc module</a> and
the resulting Sun events are output from this node at the appropriate time for each:
</p>
<ul>
<li>sunrise: sunrise (top edge of the Sun appears on the horizon)</li>
<li>sunriseEnd: sunrise ends (bottom edge of the Sun touches the horizon)</li>
<li>goldenHourEnd: morning golden hour (soft light, best time for photography) ends</li>
<li>solarNoon: solar noon (Sun is in the highest position)</li>
<li>goldenHour: evening golden hour starts</li>
<li>sunsetStart: sunset starts (bottom edge of the Sun touches the horizon)</li>
<li>sunset: sunset (Sun disappears below the horizon, evening civil twilight starts)</li>
<li>dusk: dusk (evening nautical twilight starts)</li>
<li>nauticalDusk: nautical dusk (evening astronomical twilight starts)</li>
<li>night: night starts (dark enough for astronomical observations)</li>
<li>nightEnd: night ends (morning astronomical twilight starts)</li>
<li>nauticalDawn: nautical dawn (morning nautical twilight starts)</li>
<li>dawn: dawn (morning nautical twilight ends, morning civil twilight starts)</li>
<li>nadir: nadir (darkest moment of the night, Sun is in the lowest position)</li>
</ul>
<p>If you find this node useful and you want to say thanks, feel free to buy me a coffee using the link below.</p>
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=R4Y63PPPD4CGG&source=url">
<img src="https://raw.githubusercontent.com/freakent/node-red-contrib-sunevents/main/docs/thankyou.jpg" title="Say Thanks"/>
</a>
<h2>Upgrading from v2.x</h2>
<p>
Version v3.0 and later of this node works a little differently to previous versions and will
require a change to your flow if you are upgrading from an earlier version.
</p>
<p>The latitude and longitude you defined in the node's
configuration can be used to calculate Sun events if no latitude and longitude coordinates
are passed in the <i>msg.payload</i>. You <b>must</b> still inject a payload at regular
intervals to recalculate the next 24 hour's events, but this payload can be any value.
</p>
<h2>Usage</h2>
<p>Each time this node receives a new `msg.payload` to it's input, it calculates a minimum of 24 hours worth of
Sun events (depending on what time of day it is invoked). To have the node output events reliably every day, you should
inject a latitude and longitude payload into the node at least once every 24 hours. The easiest way to do this is with the node-red Inject node.</p>
<h3>Input</h3>
<p>This node requires a latitude and longitude in decimal form to be passed to it in the msg.payload, either :</p>
<pre>
msg.payload.latitude = 18.7382273
msg.payload.longitude = -64.3201179
</pre>
or
<pre>
msg.payload.lat = 51.501364
msg.payload.lng = -0.1440787
</pre>
<p>Calculations are performed using the Latitude and Longitude that are passed in via the payload. If you have a
frequently changing GPS position it will update the Sun event calculations every time it receives a new latitude
and longitude in the payload.</p>
<h3>Outputs</h3>
<h5>Output 1 - Upcoming Sun Events</h5>
<p>
This node waits for the appropriate time and then outputs the appropriate sun event. The Sun event name is output in `msg.payload.sunevent`,
preserving any other payload values set earlier in the flow. It also outputs the event name
and date & time of the event in `msg.sunevent` object if you need a more complete set of Sun event data. The `msg.topic` can also be set in the
node's configuration.
</p>
<h5>Output 2 - Missed Sun Events</h5>
<p>
An array of Sun events that have occured before this node was invoked. The array is ordered so that the most recent missed
event is at the start of the array (position 0). Which missed event is the most recent is entirely dependant on the time
at which the node is invoked. Each array element is an object containing the event name (event_name) and the date & time (datetime)
at which the event occurred.
</p>
<h3>Config</h3>
<dl>
<dt> <i>Name</i>: </dt> <dd>Override the default name of this node in the flow </dd>
<dt> <i>Topic</i>: </dt> <dd>Set the topic used in the flow from this point onwards </dd>
<dt>Options: </dt>
<dd>
<dl>
<dt><i>Make Hours seem like minutes (test mode)</i>:</dt>
<dd>
Reduces the time you have to wait for an event to fire, 1 hour becomes 1 minute. Obviously the Sun events won't
fire at their correct times but if you are testing your flow it means you won't have to wait for hours to see that things are working.
</dd>
<!-- <dt><i>Verbose</i>:</dt>
<dd>
Output additional logging messages to debug console.
</dd>
--->
</dl>
</dd>
</dl>
<h2>Example Flow</h2>
<p>Unlike previous versions of this node, this node <b>does not</b> perform it's own daily scheduling. In keeping with
the <a href="https://nodered.org/docs/creating-nodes/#general-guidance">general guidance</a> for node-red nodes,
you must now use some other node to invoke the sun-events node at a time and
frequency appropriate for your use case. The Inject node supplied with node-red is a good candidate for this and
is demonstrated in the supplied example flow. Please note, I show the use of 2 inject nodes, one to invoke the flow
on deployment and the other to invoke the flow at a fixed time each day.</p>
<p>There are two example flows provided, one for a fixed GPS positioned injected daily and one for a stream of GPS coordinates that continually updates with your position.
There is an example flow you can import supplied with this node.</p>
<p>Example 1: Fixed GPS position (<a href="https://raw.githubusercontent.com/freakent/node-red-contrib-sunevents/main/examples/sun-events-example-flows.json" target="_blank">Download</a>)
<img src="https://raw.githubusercontent.com/freakent/node-red-contrib-sunevents/main/docs/flow-diagram-1.png">
<p>Example 2: Stream of GPS positions (<a href="https://raw.githubusercontent.com/freakent/node-red-contrib-sunevents/main/examples/sun-events-gps-stream-example-flows.json" target="_blank">Download</a>)
<img src="https://raw.githubusercontent.com/freakent/node-red-contrib-sunevents/main/docs/flow-diagram-2.png">
</script>
<!-- Finally, the node type is registered along with all of its properties -->
<!-- The example below shows a small subset of the properties that can be set-->
<script type="text/javascript">
RED.nodes.registerType('sun events',{
category: 'input', // the palette category
defaults: { // defines the editable properties of the node
testmode: {value:"N"},
verbose: {value:"N"},
topic: {value:""},
name: {value:""}
},
credentials: {
latitude: {type: "text"},
longitude: {type: "text"}
},
color:"#FFCC66",
inputs:1, // set the number of inputs - only 0 or 1
outputs:2, // set the number of outputs - 0 to n
icon: "white_golden_sun.png", //"white-globe.png", // set the icon (held in public/icons)
label: function() { // sets the default label contents
return this.name||"sun events";
},
labelStyle: function() { // sets the class to apply to the label
return this.name ? "" : "node_label_italic";
}
});
</script>