Outdoor lights switching

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’t have to buy any switches with light sensitive sensor to switch your outdoor lights, house number lights etc. Also in urban environment these regular switches which use photoresistors 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 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.

So… 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)

It is possible and farely simple if you are not seeking for ultimate precision but there are few requirements:

  • You have to have BV4627 relayboard up&running with your RPi as instructed in this how-to and one free relay.
  • 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 RTC, you must modify the lights_switch.sh script.
  • You have to get your location’s geographical coordinates from somewhere f.e. go to Google maps, find your neighbours house, right-click, select “what’s here” and take latitude/longitude coordinates from there.
  • You need PHP (CLI – command line interface ) as PHP already has suitable function for calculating sunset & sunrise.

1. install php-cli. If you have Raspberry Pi with Raspbian Wheezy, you can install it and all its dependencies using following commands:

sudo apt-get update
sudo apt-get install php5-cli

2. User account

Lets create system account named lights. Command creates also homedir for user lights.

sudo useradd -r -m lights

3. Create scripts, cron job and sudo rules

Switch to user lights and create following files. If homedir is different , change the paths.

Script: /home/lights/lights_calculator.php

This script calculates what should be lights status in the moment.  Run it with parameter “list” from commandline to see detailed information about sunrise and sunset. You should change coordinates in the script. Latitude & longitude on planet earth are enough, milky-way address is not needed. PHP functions date_sunset and date_sunrise have also third parameter named zenith what I really don’t understand and/or care. Adjust zenith if you get incorrect sunrise/sunset times (check with “list” parameter). For comparison use sunrise&sunset times from some local weather-station. Please also set your timezone in this script so that your offset from GMT could be calculated.

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.


# this script calculates sunset and sunrise times and echos what should be current lights status 
# php is used to make calculations easier 
# Argo Ellisson 2014, BashPi.org, usage licence: GNU General Public License (GPL) Version 3
# version 1.0

# USE parameter "list" to see detailed output

# Comment in if you want timesync check also here, otherwise its done by parent bash script
#exec ('/usr/sbin/ntp-wait -n 5 -s 3',$output,$retval);
#if($retval != 0) exit;

# parameters

$timeformat="%Y-%m-%d %H:%M:%S";

# Set your geographical coordinates

# Set zenith for date_sunrise and date_sunset functions. It should be approx 90 but what it really is I dont know. 
# So either check it out or just change until sunset-sunrise will match something what is confirmed to be correct 

# Set your timezone

# calculate offset for date_sunrise and date_sunset functions
$today = date_create( date("Y-m-d"), timezone_open($tz));
$tz_offset = date_offset_get($today)/3600;

# functions

function lights($lights_off_seconds_after_sunrise, $lights_on_seconds_after_sunset){

        # this function returns array about external lights status which should be turned on after sunset and off after sunrise

        global $timeformat;
        global $latitude;
        global $longitude;
        global $zenith;
        global $tz_offset;

        $sunrise_time=date_sunrise($now, SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, $zenith, $tz_offset);
        $sunset_time=date_sunset($now, SUNFUNCS_RET_TIMESTAMP, $latitude, $longitude, $zenith, $tz_offset);

        $timenow=strftime($timeformat, $now);
        $sunrise=strftime($timeformat, $sunrise_time);
        $sunrise_hour=strftime("%H:%M", $sunrise_time);
        $sunset=strftime($timeformat, $sunset_time);
        $sunset_hour=strftime("%H:%M", $sunset_time);


        $lights_on_time=strftime($timeformat, $lights_on);
        $lights_on_time_hour=strftime("%H:%M", $lights_on);
        $lights_off_time=strftime($timeformat, $lights_off);
        $lights_off_time_hour=strftime("%H:%M", $lights_off);

        if($lights_off<$now && $lights_on>$now){

        return array("NOW" => $timenow, "SUNRISE" => $sunrise, "SUNRISE_HOUR" =>$sunrise_hour, "SUNSET" => $sunset, "SUNSET_HOUR" => $sunset_hour, "Lights_on_time" => $lights_on_time, "Lights_on_time_hour" => $lights_on_time_hour, "Lights_off_time" => $lights_off_time,"Lights_off_time_hour" => $lights_off_time_hour, "Lights_should_be_now" => $lights);


# in this switch we can configure different delays for different months which apply to sunrise-sunset 
# for example if during summer are long nights, we may keep lights off hour longer


# delays are in seconds
switch ($month) {
    case "01":
    case "02":
    case "03":
    case "04":
    case "05":
    case "06":
    case "07":
    case "08":
    case "09":
    case "10":
    case "11":
    case "12":


if(isset($argv[1]) && $argv[1]=="list"){
        echo $lights_array["Lights_should_be_now"];


Script: /home/lights/lights_switch.sh

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!


# This script uses another php script to do sunset-sunrise calculations 
# and drives lights relay according to the output of that PHP script
# Argo Ellisson 2014, BashPi.org, usage licence: GNU General Public License (GPL) Version 3
# version 1.0

# if time not synced dont do anything

# use ntp-wait
/usr/sbin/ntp-wait -n 5 -s 3 

if [ "${RETVAL}" != "0" ];then 

 echo "Timesync not done, exiting"
 exit 1


# Functions

# this function gets user homedir
get_homedir() {
       getent passwd ${1} |cut -d':' -f6

# change curent directory to script location
cd $(dirname $0)

# relay config
RELAYHOME=`get_homedir ${RELAYUSER}`
# board1 is board alias, change if needed
# note that if relay alias is set up you can use it here like "lights" instead of "a"

STATUS=`/usr/bin/php ./lights_calculator.php`

if [ "${STATUS}" = "OFF" ]; then

        sudo -u ${RELAYUSER} ${RELAYSCRIPT} ${RELAYBOARD} ${RELAY} off 0


        sudo -u ${RELAYUSER} ${RELAYSCRIPT} ${RELAYBOARD} ${RELAY} on 0


exit 0

Make scripts above executable!

Cron job:

This job will run lights_switch.sh script with 10 minute interval. It should be enough even if you live near the equator. Add it to user lights crontab.

# outdoor lights switching script
9-59/10 * * * * $HOME/lights_switch.sh > /dev/null 2>&1

Sudo rules:

To allow user lights to run relay.sh script as user relay, drop following rules to some file in /etc/sudoers.d/. I am using file name “lights_sudoers”. Note that if relay user has different homedir location, you have to change it in sudo rules.

# list below commands and users who can do what
# by default lights user can run everything as user relay
# as wildcards are not secure
Cmnd_Alias LIGHTS_COMM = /home/relay/relay.sh *
User_Alias LIGHTS_USER = lights
Runas_Alias  LIGHTS_RUN = relay

If you managed to follow everything so far,  you are welcome to use following automated setup. First thing you need is to download few kilobytes of code: lights.tar.gz

After that put the file to your Raspberry Pi, unpack and run configuration as shown below.

tar -xzvf lights.tar.gz
cd lights/
sudo ./configure.sh configure

After that switch to user lights as follows

sudo su - lights

…. and edit lights_calculator.php file. You need to put your coordinates and timezone into that script, its described above.

…. and edit lights_switch.sh file. You need to put your chosen board and relay to that script.

Scripts in this page were tested on:

  • Raspberry Pi Model B 512MB RAM. OS: Raspbian Wheezy, released in 2014-01-07. All updates installed on 1. september 2014.

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!

If you found this useful, say thanks, click on some banners or donate, I can always use some beer money.

4 thoughts on “Outdoor lights switching

  1. Jules

    Want to do something similar, without any relay light switching.
    I have a USB webcam connected to RPi, running with \”motion\” and taking a picture every 10 mins, saving to a file. Every hour, all except the last 20 photos are deleted. To save the SD card read and write, I want to disable the webcam with a cron job at sunset, and have it come on at sunrise. Any ideas if this is possible?

  2. eu

    I\’ve used some of your code to trigger a sonoff DIY R3 basic
    I\’ve removed the relay board part and replaced with a curl HTTP post command
    the script run on a x86 server that\’s used also as mysql and apache server and video surveillance
    I\’ve used to have a Rpi but also the Rpi4 is too under powered for video surveillance.
    In Cron job: section yoy wrote lights_switch.php istead of sh.
    best regards

Comments are closed.