{"id":168,"date":"2014-06-29T13:14:40","date_gmt":"2014-06-29T10:14:40","guid":{"rendered":"http:\/\/www.bashpi.org\/?page_id=168"},"modified":"2020-12-03T17:30:19","modified_gmt":"2020-12-03T15:30:19","slug":"outdoor-lights-switching-on-sunsetsunrise","status":"publish","type":"page","link":"https:\/\/www.bashpi.org\/?page_id=168","title":{"rendered":"Outdoor lights switching"},"content":{"rendered":"<p>This is simple practical example what to do with your Raspberry Pi and CONNECTED relay-board. Its written from RPi perspective so if you have regular PC, you may have to do some things differently.<\/p>\n<p>If you have spare relay on your board, you don&#8217;t have to buy any switches with light sensitive&nbsp;sensor to switch your outdoor lights, house number lights etc. Also in urban environment these regular switches which use <a href=\"http:\/\/en.wikipedia.org\/wiki\/Photoresistor\">photoresistors<\/a> may be triggered incorrectly by streetlights, passing cars or even because sometimes they are mounted too close to the lamp what they are switching. Tuning these&nbsp;sensors to work normally may be painful. Also keep in mind that mounting such sensor\/switch somewhere outside, drilling holes, wiring etc. will need some extra work and money.<\/p>\n<p>So&#8230; what if you could just CALCULATE SUNRISE AND SUNSET TIME in your geographical location and switch lights accordingly? (Or dusk and dawn if you like it better)<\/p>\n<p>It is possible and farely simple if you are not seeking for ultimate precision but there are few requirements:<\/p>\n<ul>\n<li>You have to have BV4627 relayboard up&amp;running with your RPi as instructed in this <a title=\"BV4627 Relay controller and bash, advanced\" href=\"http:\/\/www.bashpi.org\/?p=147\">how-to<\/a> and one free relay.<\/li>\n<li>RPi clock must be correct. So you have to set timezone correctly and have network connection so that ntp daemon can sync the clock. Script is checking is the clock synced so you must have access to some ntp server. If you have just <a href=\"http:\/\/en.wikipedia.org\/wiki\/Real_time_clock\">RTC<\/a>, you must modify the lights_switch.sh script.<\/li>\n<li>You have to get your location&#8217;s geographical coordinates from somewhere f.e. go to <a href=\"http:\/\/maps.google.com\/\">Google maps<\/a>, find your neighbours house, right-click, select &#8220;what&#8217;s here&#8221; and take latitude\/longitude coordinates from there.<\/li>\n<li>You need <a href=\"http:\/\/en.wikipedia.org\/wiki\/PHP\">PHP<\/a> (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Command-line_interface\">CLI &#8211; command line interface<\/a> ) as PHP already has suitable function for calculating sunset &amp; sunrise.<\/li>\n<\/ul>\n<p><strong>1. install php-cli.<\/strong> If you have Raspberry Pi with Raspbian Wheezy, you can install it and all its dependencies using following commands:<\/p>\n<pre><code class=\"language-bash\">sudo apt-get update\nsudo apt-get install php5-cli\n<\/code><\/pre>\n<p><strong>2. User account<\/strong><\/p>\n<p>Lets create system account named <em>lights<\/em>. Command creates also homedir for user <em>lights<\/em>.<\/p>\n<pre><code class=\"language-bash\">sudo useradd -r -m lights\n<\/code><\/pre>\n<p><strong>3. Create scripts, cron job and sudo rules<\/strong><\/p>\n<p>Switch to user lights and create following files. If homedir is different , change the paths.<\/p>\n<p><strong>Script: \/home\/lights\/lights_calculator.php<\/strong><\/p>\n<p>This script calculates what should be lights status in the moment.&nbsp; Run it with parameter &#8220;list&#8221; from commandline to see detailed information about sunrise and sunset. You should change coordinates in the script. Latitude &amp; longitude on planet earth are enough, milky-way address is not needed. PHP functions <a href=\"http:\/\/php.net\/manual\/en\/function.date-sunset.php\">date_sunset<\/a> and <a href=\"http:\/\/www.php.net\/manual\/en\/function.date-sunrise.php\">date_sunrise<\/a> have also third parameter named <em>zenith <\/em>what I really don&#8217;t understand and\/or care. Adjust <em>zenith<\/em> if you get incorrect sunrise\/sunset times (check with &#8220;list&#8221; parameter). For comparison use sunrise&amp;sunset times from some local weather-station. Please also set your timezone in this script so that your offset from GMT could be calculated.<\/p>\n<p>You can also adjust some delays related to switching on and off in the end of the script. For example you can configure in script that during summer months (longer days) lights are switched on a bit later, not on exactly on sunset.<\/p>\n<pre><code class=\"language-php\">#!\/usr\/bin\/php5\n&lt;?php\n\n# this script calculates sunset and sunrise times and echos what should be current lights status \n# php is used to make calculations easier \n# Argo Ellisson 2014, BashPi.org, usage licence: GNU General Public License (GPL) Version 3\n# version 1.0\n\n# USE parameter \"list\" to see detailed output\n\n# Comment in if you want timesync check also here, otherwise its done by parent bash script\n#exec ('\/usr\/sbin\/ntp-wait -n 5 -s 3',$output,$retval);\n#if($retval != 0) exit;\n\n# parameters\n\n$timeformat=\"%Y-%m-%d %H:%M:%S\";\n\n# Set your geographical coordinates\n$latitude=59.396217;\n$longitude=24.765952;\n\n# Set zenith for date_sunrise and date_sunset functions. It should be approx 90 but what it really is I dont know. \n# So either check it out or just change until sunset-sunrise will match something what is confirmed to be correct \n$zenith=90.83333333333;\n\n# Set your timezone\n$tz=\"Europe\/Tallinn\";\n\n# calculate offset for date_sunrise and date_sunset functions\n$today = date_create( date(\"Y-m-d\"), timezone_open($tz));\n$tz_offset = date_offset_get($today)\/3600;\n\n# functions\n\nfunction lights($lights_off_seconds_after_sunrise, $lights_on_seconds_after_sunset){\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # this function returns array about external lights status which should be turned on after sunset and off after sunrise\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global $timeformat;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global $latitude;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global $longitude;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global $zenith;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global $tz_offset;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $now=time();\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_time=date_sunrise($now, SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, $zenith, $tz_offset);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_time=date_sunset($now, SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, $zenith, $tz_offset);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $timenow=strftime($timeformat, $now);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise=strftime($timeformat, $sunrise_time);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_hour=strftime(\"%H:%M\", $sunrise_time);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset=strftime($timeformat, $sunset_time);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_hour=strftime(\"%H:%M\", $sunset_time);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights_on=$sunset_time+$lights_on_seconds_after_sunset;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights_off=$sunrise_time+$lights_off_seconds_after_sunrise;\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights_on_time=strftime($timeformat, $lights_on);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights_on_time_hour=strftime(\"%H:%M\", $lights_on);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights_off_time=strftime($timeformat, $lights_off);\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights_off_time_hour=strftime(\"%H:%M\", $lights_off);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($lights_off&lt;$now &amp;&amp; $lights_on&gt;$now){\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights=\"OFF\";\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $lights=\"ON\";\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return array(\"NOW\" =&gt; $timenow, \"SUNRISE\" =&gt; $sunrise, \"SUNRISE_HOUR\" =&gt;$sunrise_hour, \"SUNSET\" =&gt; $sunset, \"SUNSET_HOUR\" =&gt; $sunset_hour, \"Lights_on_time\" =&gt; $lights_on_time, \"Lights_on_time_hour\" =&gt; $lights_on_time_hour, \"Lights_off_time\" =&gt; $lights_off_time,\"Lights_off_time_hour\" =&gt; $lights_off_time_hour, \"Lights_should_be_now\" =&gt; $lights);\n\n}\n\n# in this switch we can configure different delays for different months which apply to sunrise-sunset \n# for example if during summer are long nights, we may keep lights off hour longer\n\n$month=strftime(\"%m\");\n\n# delays are in seconds\nswitch ($month) {\n&nbsp;&nbsp;&nbsp; case \"01\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=1800;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"02\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=900;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"03\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"04\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=600;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"05\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=900;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"06\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=900;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"07\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=900;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"08\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=600;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"09\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"10\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=900;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"11\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=1800;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n&nbsp;&nbsp;&nbsp; case \"12\":\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunset_delay=0;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $sunrise_delay=1800;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;\n}\n\n$lights_array=lights($sunrise_delay,$sunset_delay);\n\nif(isset($argv[1]) &amp;&amp; $argv[1]==\"list\"){\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print_r($lights_array);\n}else{\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo $lights_array[\"Lights_should_be_now\"];\n};\n\nexit;\n?&gt;<\/code><\/pre>\n<p><strong>Script: \/home\/lights\/lights_switch.sh<\/strong><\/p>\n<p>This script just runs relays according to the information it gets from php script above. It is executed with crontab. It also checks is clock synced and if not, it exits. You must configure board and relay what you intend to use in this script!<\/p>\n<pre><code class=\"language-bash\">#!\/bin\/bash\n\n# This script uses another php script to do sunset-sunrise calculations \n# and drives lights relay according to the output of that PHP script\n# Argo Ellisson 2014, BashPi.org, usage licence: GNU General Public License (GPL) Version 3\n# version 1.0\n\n# if time not synced dont do anything\n\n# use ntp-wait\n\/usr\/sbin\/ntp-wait -n 5 -s 3 \nRETVAL=$?\n\nif [ \"${RETVAL}\" != \"0\" ];then \n\n&nbsp;echo \"Timesync not done, exiting\"\n&nbsp;exit 1\n\nfi\n\n# Functions\n\n# this function gets user homedir\nget_homedir() {\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getent passwd ${1} |cut -d':' -f6\n}\n\n# change curent directory to script location\ncd $(dirname $0)\n\n# relay config\nRELAYUSER=\"relay\"\nRELAYHOME=`get_homedir ${RELAYUSER}`\nRELAYSCRIPT=\"${RELAYHOME}\/relay.sh\"\n# board1 is board alias, change if needed\nRELAYBOARD=\"board1\"\n# note that if relay alias is set up you can use it here like \"lights\" instead of \"a\"\nRELAY=\"a\"\n\nSTATUS=`\/usr\/bin\/php .\/lights_calculator.php`\n\nif [ \"${STATUS}\" = \"OFF\" ]; then\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sudo -u ${RELAYUSER} ${RELAYSCRIPT} ${RELAYBOARD} ${RELAY} off 0\n\nelse\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sudo -u ${RELAYUSER} ${RELAYSCRIPT} ${RELAYBOARD} ${RELAY} on 0\n\nfi\n\nexit 0<\/code><\/pre>\n<p><strong>Make scripts above executable!<\/strong><\/p>\n<p><strong>Cron job:<\/strong><\/p>\n<p>This job will run <strong>lights_switch.sh<\/strong> script with 10 minute interval. It should be enough even if you live near the equator. Add it to user lights crontab.<\/p>\n<pre><code class=\"language-bash\"># outdoor lights switching script\n9-59\/10 * * * * $HOME\/lights_switch.sh &gt; \/dev\/null 2&gt;&amp;1\n<\/code><\/pre>\n<p><strong>Sudo rules:<\/strong><\/p>\n<p>To allow user <em>lights<\/em> to run relay.sh script as user <em>relay<\/em>, drop following rules to some file in \/etc\/sudoers.d\/. I am using file name &#8220;lights_sudoers&#8221;. Note that if <em>relay<\/em> user has different homedir location, you have to change it in sudo rules.<\/p>\n<pre><code class=\"language-bash\"># list below commands and users who can do what\n# by default lights user can run everything as user relay\n# as wildcards are not secure\nCmnd_Alias LIGHTS_COMM = \/home\/relay\/relay.sh *\nUser_Alias LIGHTS_USER = lights\nRunas_Alias&nbsp; LIGHTS_RUN = relay\nLIGHTS_USER ALL = (LIGHTS_RUN) NOPASSWD: LIGHTS_COMM<\/code><\/pre>\n<p>If you managed to follow everything so far,&nbsp; you are welcome to use following automated setup. First thing you need is to download few kilobytes of code: <a href=\"http:\/\/www.bashpi.org\/wp-content\/uploads\/2014\/06\/lights.tar.gz\">lights.tar.gz<\/a><\/p>\n<p>After that put the file to your Raspberry Pi, unpack and run configuration as shown below.<\/p>\n<pre><code class=\"language-bash\">tar -xzvf lights.tar.gz\ncd lights\/\nsudo .\/configure.sh configure\n<\/code><\/pre>\n<p>After that switch to user lights as follows<\/p>\n<pre><code class=\"language-bash\">sudo su - lights<\/code><\/pre>\n<p>&#8230;. and edit <strong>lights_calculator.php<\/strong> file. You need to put your coordinates and timezone into that script, its described above.<\/p>\n<p>&#8230;. and edit <strong>lights_switch.sh<\/strong> file. You need to put your chosen board and relay to that script.<\/p>\n<p>Scripts in this page were tested on:<\/p>\n<ul>\n<li>Raspberry Pi Model B 512MB RAM. OS: Raspbian Wheezy, released in 2014-01-07. All updates installed on 1. september 2014.<\/li>\n<\/ul>\n<p>Thats it about outdoor lights and do you know whats best about it? If you come home late from the local pub and you see your house lights, you know that your Raspberry Pi is still working!<\/p>\n<p>If you found this useful, say thanks, click on some banners or <a href=\"http:\/\/www.bashpi.org\/?page_id=105\">donate<\/a>, I can always use some beer money.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is simple practical example what to do with your Raspberry Pi and CONNECTED relay-board. Its written from RPi perspective so if you have regular PC, you may have to do some things differently. If you have spare relay on your board, you don&#8217;t have to buy any switches with light sensitive&nbsp;sensor to switch your [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-168","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.bashpi.org\/index.php?rest_route=\/wp\/v2\/pages\/168","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bashpi.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.bashpi.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.bashpi.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bashpi.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=168"}],"version-history":[{"count":28,"href":"https:\/\/www.bashpi.org\/index.php?rest_route=\/wp\/v2\/pages\/168\/revisions"}],"predecessor-version":[{"id":759,"href":"https:\/\/www.bashpi.org\/index.php?rest_route=\/wp\/v2\/pages\/168\/revisions\/759"}],"wp:attachment":[{"href":"https:\/\/www.bashpi.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}