Weekly Scheduling for IoT Smart Devices

Some smart devices may need to be able to be set weekly and daily schedules. If so, some functionality can be activated/deactivated at some specific period of time. In this article, I show how to do schedule with PHPoC (Blue/Black). Based on this program, you can make as many various applications as you can imagine. At the end of the article, I will show some application examples which use the scheduling function. Al source codes are available to download.

Outline:
  • Basic Code
    • Making schedule via Webpage
    • Handling schedule
  • Application examples.
    • Example 1: Only allowing people to turn on/off the light in working time.
    • Example 2: Detecting people going into entrance. Make alert in working time


Basic Code

A smart device which has scheduling function should have a RTC (Real-time clock). PHPoC Black and Blue are equipped with RTC, allowing to do schedule easily.

Making schedule via Webpage

Click image for larger version  Name:	schedule_Dataflow.png Views:	1 Size:	31.9 KB ID:	521

User Interface

Click image for larger version  Name:	schedule_UI.png Views:	1 Size:	46.1 KB ID:	522


Source code (index.php)

PHP Code:
<?php
set_time_limit
(30);

include_once 
"/lib/sc_envu.php";

$envu =  envu_read("envu");

if(
_SERVER("REQUEST_METHOD") == "POST")
{
    
$data       _POST("data");

    
envu_update($envu"schedule"$data);
    
envu_write("envu"$envustrlen($envu), 0);
    
system("reboot sys 1000");
}
else
{
    if(
$envu == "")
    {
        
$envu "schedule=\r\n";
        
envu_write("envu"$envustrlen($envu), 0);
    }
}

?>
<!DOCTYPE html>
<html>
<?php
$stypeno_table 
= array(012);
$stype_table = array("RS232""RS485""RS422");
$baud_table = array(230400115200576003840019200144009600480024001200);
$parityno_table = array(012345);
$parity_table = array("None""Even""Odd""Mark""Space");
$fctrlno_table = array(012);
$fctrl_table = array("None""RTS/CTS""Xon/Xoff");
$operationno_table = array(02);
$operation_table = array("TCP Server""TCP Client");
?>
<head>
    <title><?php echo system("uname -i");?> WEB Configuration</title>
    <meta content="initial-scale=0.5, maximum-scale=1.0, minimum-scale=0.5, width=device-width, user-scalable=yes" name="viewport">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
    <style type="text/css">
        body { font-family: verdana, Helvetica, Arial, sans-serif, gulim; }
        h1 { font-weight: bold; font-family : verdana, Helvetica, Arial, verdana, sans-serif, gulim; font-size:15pt; padding-bottom:5px;}
        .schedule {border-collapse:collapse; width:640px;  font-size:14pt; table-layout: fixed;}
        .theader { font-weight: bold;}
        tr {height :28px; border-bottom: 1px solid #ccc;}
        td { padding-left: 10px; text-align: center;}
        .delete { font-weight: bold; text-align: center !important;}
        .superHeader {height: 2em; color: white; background-color: rgb(0,153,153); font-size:9pt; position:fixed; left:0; right:0; top:0; z-index:5;  }        
        .right {
          color: white;
          position: absolute;
          right: 3em;
          bottom: 4px;
          font-size:12pt;          
        }    
        .left {
          color: white;
          position: absolute;
          left: 3em;
          bottom: 4px;
          font-size:12pt;          
        }
        .right a, .left a
        {
          color: white;
          background-color: transparent;
          text-decoration: none;
          margin: 0;
          padding:0 2ex 0 2ex;
        }            
        .right a:hover, .left a:hover
        {
          color: white;
          text-decoration: underline;
         }        
        .midHeader {color: white; background-color: rgb(6, 38, 111);  position:fixed; left:0; right:0; top:1.5em;  z-index:3;}
        .headerTitle {
          font-size: 250%;
          font-weight: normal;
          margin: 0 0 0 4mm;
          padding: 0.25ex 0 1ex 0;
          font-family: impact;
        }
        #footer{margin:0 auto; height:auto !important; height:100%; margin-bottom:-100px;  }
        .superFooter {
            height: 2em; color: white; background-color: rgb(6, 38, 111); font-size:12pt; position:fixed; left:0; right:0; bottom:0; z-index:4;
        }                
        .zebra {background-color : #ECECEC;}
        .del_icon {
            color: #cc0000;
            font-size: 120%;
            font-weight: bold;
        }
        .del_icon:hover {
            color: red;
            cursor: pointer;
        }
        .add_icon {
            color: #009933;
            font-size: 150%;
            font-weight: 900;
        }
        .add_icon:hover {
            color: #1aff66;
            cursor: pointer;
        }
    </style>
    <script type="text/javascript">
    <?php
        $envu 
=  envu_read("envu");
        
$schedule envu_find($envu"schedule");

    
?>
    var schedule_list = new Array();

    function init()
    {    
        var scheduleTable = document.getElementById("scheduleTable");

        var data = "<?php echo $schedule?>";

        if(data != "")
            schedule_list = data.split("||");  

        for(var i = 0; i < schedule_list.length; i++)
        {
            schedule_list[i] = schedule_list[i].split("|");
            // display schedule on schedule table
            var row = scheduleTable.insertRow();
            //row.style.color = "#1E90FF";
            var rowHtml = '<td width="190px">';
            rowHtml += schedule_list[i][0];
            rowHtml += '</td><td>';
            rowHtml += schedule_list[i][1];
            rowHtml += '</td><td>';
            rowHtml += schedule_list[i][2];
            rowHtml += '</td><td class="delete"><span class="del_icon" onclick="del_schedule(this)">&#x2716;</span></td>';    

            row.innerHTML = rowHtml;
        }
    }

    function del_schedule(e)
    {
        var row_index = e.parentElement.parentElement.rowIndex;
        console.log(row_index);
        document.getElementById("scheduleTable").deleteRow(row_index);
        schedule_list.splice(row_index-1, 1);
    }

    function update_schedule(e)
    {
        var table = document.getElementById("scheduleTable");
        var row = table.insertRow();
        row.innerHTML = '<td width="190px">DAY</td><td>FROM</td><td>TO</td><td class="delete"><span class="del_icon" onclick="del_schedule(this)">X</span></td>';    
    }

    function add_schedule()
    {
        var addTable = document.getElementById("addTable");
        var scheduleTable = document.getElementById("scheduleTable");

        var numRow = addTable.rows.length;
        if(numRow > 0)
        {
            var row  = addTable.rows[0];
            var days = row.cells[0].childNodes[0];
            var day = days.options[days.selectedIndex].value;
            var startTime = row.cells[1].childNodes[0].value;
            var endTime = row.cells[2].childNodes[0].value;
            console.log(day + ":" + startTime + ":" + endTime);

            //add new row in schedule table
            row = scheduleTable.insertRow();
            row.style.color = "#1E90FF";
            var rowHtml = '<td width="190px">';
            rowHtml += day;
            rowHtml += '</td><td>';
            rowHtml += startTime;
            rowHtml += '</td><td>';
            rowHtml += endTime;
            rowHtml += '</td><td class="delete"><span class="del_icon" onclick="del_schedule(this)">&#x2716;</span></td>';    
            schedule_list.push([day, startTime, endTime]);

            row.innerHTML = rowHtml;

            //delete old row in add table
            addTable.deleteRow(0);

            //change confirm to add sign
            document.getElementById("add_icon").innerHTML = '&#x271A;';
        }
        else
        {        
            var newRow = addTable.insertRow();
            var cell0 = newRow.insertCell();
            var cell1 = newRow.insertCell();
            var cell2 = newRow.insertCell();
            var cell3 = newRow.insertCell();

            var select = '<select>';
            select += '<option value="Sun">Sunday</option>';
            select += '<option value="Mon">Monday</option>';
            select += '<option value="Tue">Tuesday</option>';
            select += '<option value="Wed">Wednesday</option>';
            select += '<option value="Thu">Thursday</option>';
            select += '<option value="Fri">Friday</option>';
            select += '<option value="Sat">Saturday</option>';                          
            select += '</select>';
            cell0.innerHTML += select;
            cell1.innerHTML = '<input type="time" name="usr_time" value="09:00">';
            cell2.innerHTML = '<input type="time" name="usr_time" value="18:00">';
            cell3.innerHTML = "";

            //change add to confirm sign
            document.getElementById("add_icon").innerHTML = '&#x2714;';
        }
    }

    function excSubmit()
    {    
        var schedule_form = document.schedule_form;

        var data = new Array();

        for(var i = 0; i < schedule_list.length; i++)
        {
            data.push(schedule_list[i].join("|")) ;
        }

        schedule_form.data.value = data.join("||");

        schedule_form.submit();        
    }

    window.onload = init;
    </script>
</head>
<body>
    <div id="header">
        <div class="superHeader">        
            <div class="left">
            </div>    
            <div class="right">
                <a href="http://www.phpoc.com/forum/" target="_blank">PHPoC Forum</a>
            </div>
        </div>

        <div class="midHeader">
            <h1 class="headerTitle"><center>Scheduler</center></h1>
            <div class="left">            
            </div>
        </div>

        <div class="subHeader">
        </div>        
    </div>    
    <br /><br /><br /><br />    
    <center>
        <form name="schedule_form" action="index.php" method="post">    
        <hr style="margin:50px 0 -10px 0; width:640px;" size="6" noshade>
        <h1></h1>

        <table id="scheduleTable" class="schedule">
            <tr class="zebra">
                <td class="theader">DAY</td>    
                <td class="theader">FROM</td>
                <td class="theader">TO</td>
                <td class="delete"><i class="fa fa-trash"></i></td>    
            </tr>    
        </table>
        <input type="hidden" name="data" value="">
        </form>
        <br>
        <table id="addTable" class="schedule">
        </table>

        <table style="width:640px;">
            <tr>
                <td class="theader" style="text-align: right;"><span class="add_icon" id="add_icon" onclick="add_schedule(this)">&#x271A;</span></td>    
            </tr>
            <tr>
                <td class="theader" style="text-align: center;"><a href="javascript:excSubmit();">SAVE</a></td>    
            </tr>
        </table>

    </center>    
    <br /><br /><br /><br />
    <div id="footer">
        <div class="superFooter">
        </div>
    </div>    
</body>
</html>



Handling Schedule

The main program is a program running continuously on devices. Main program will check whet her current time is on scheduling time or not and then take actions (e.g read DI/sensor value, control DO/send email/update SQL…) basing on it.

Click image for larger version  Name:	image_284.png Views:	1 Size:	28.8 KB ID:	523

Source code (task0.php)

PHP Code:
<?php

if(_SERVER("REQUEST_METHOD"))
    exit; 
// avoid php execution via http request

include_once "/lib/sc_envu.php";

$envu =  envu_read("envu");
$schedules envu_find($envu"schedule");

$count 0;

if(
$schedules != "")
{
    
$schedules explode("||"$schedules);

    
$count count($schedules);

    for(
$i 0$i $count$i++)
    {
        
$schedules[$i] = explode("|"$schedules[$i]);
    }
}
else
    
$schedules = array();

$is_activate true;

while(
1)
{
    if(
$count)
    {
        
$is_activate false;

        
$day date("D");
        
$hour = (int)date("H");
        
$minute = (int)date("i");
        
$current_time $hour*60 $minute;//in minute

        
for($i 0$i $count$i++)
        {
            if(
$day == $schedules[$i][0])
            {
                
$temp explode(":"$schedules[$i][1]);
                
$start_time = ((int)$temp[0])*60 + (int)$temp[1];//in minute

                
$temp explode(":"$schedules[$i][2]);
                
$end_time = ((int)$temp[0])*60 + (int)$temp[1];//in minute

                
if($current_time >= $start_time && $current_time <= $end_time)
                {
                    
$is_activate true;
                    break;
                }
            }
        }
    }

    if(
$is_activate)
    {
        
//TODO
    
}
    else
    {
        
//TODO
    
}
}    
?>





Application Examples

For any applications, we just need modify task0.php file. index.php file is kept unchanged

Example 1: Only allowing people to turn on/off the light in working time

Things Used In This Project
  • PHPoC Blue or Black
  • An on/off switch
  • A relay
  • A lamp


In my case, since I have a relay with MikroBUS interface, I use mikroBUS™ Expansion Board (you can find it here http://www.phpoc.com/expansion_board.php#mikro_bus),

Click image for larger version  Name:	schedule_ex1_things.jpg Views:	1 Size:	56.3 KB ID:	524

Working flow

Click image for larger version  Name:	schedule_ex1_working_flow.png Views:	1 Size:	35.5 KB ID:	525

Demo



Source code (task0.php)

PHP Code:
<?php

if(_SERVER("REQUEST_METHOD"))
    exit; 
// avoid php execution via http request

include_once "/lib/sc_envu.php";
include_once 
"/lib/sd_340.php";

$envu =  envu_read("envu");
$schedules envu_find($envu"schedule");

$count 0;

if(
$schedules != "")
{
    
$schedules explode("||"$schedules);

    
$count count($schedules);

    for(
$i 0$i $count$i++)
    {
        
$schedules[$i] = explode("|"$schedules[$i]);
    }
}
else
    
$schedules = array();

$is_activate false;

$in_pin 7;
$out_pin 18;
//Input pin
uio_setup(0$in_pin"in");

//Output pin
uio_setup(0$out_pin"out");
uio_out(0$out_pinLOW);

while(
1)
{
    
$is_activate false;

    if(
$count)
    {    
        
$day date("D");
        
$hour = (int)date("H");
        
$minute = (int)date("i");
        
$current_time $hour*60 $minute;//in minute

        
for($i 0$i $count$i++)
        {
            if(
$day == $schedules[$i][0])
            {
                
$temp explode(":"$schedules[$i][1]);
                
$start_time = ((int)$temp[0])*60 + (int)$temp[1];//in minute

                
$temp explode(":"$schedules[$i][2]);
                
$end_time = ((int)$temp[0])*60 + (int)$temp[1];//in minute

                
if($current_time >= $start_time && $current_time <= $end_time)
                {
                    
$is_activate true;
                    break;
                }
            }
        }
    }

    if(
$is_activate)
    {
        
//TODO
        
$input_value uio_in(0$in_pin);

        
uio_out(0$out_pin$input_value);
    }
    else
    {
        
uio_out(0$out_pinLOW);
    }
}    

?>



Example 2: Detecting people going into entrance. Make alert in working time.

Things Used In This Project
  • PHPoC Blue or Black
  • An ultrasonic sensor
  • A relay
  • A lamp or buzzer or horn


Here I use the simple method to detect people based on distance got from ultrasonic sensor. Since I have a relay with MikroBUS interface, I use mikroBUS™ Expansion Board (you can find it here http://www.phpoc.com/expansion_board.php#mikro_bus),

Click image for larger version  Name:	schedule_ex2_things.jpg Views:	1 Size:	68.7 KB ID:	526

Working flow
Click image for larger version  Name:	schedule_ex2_working_flow.png Views:	1 Size:	35.7 KB ID:	527

Demo



Source code (task0.php)

PHP Code:
<?php

if(_SERVER("REQUEST_METHOD"))
    exit; 
// avoid php execution via http request

include_once "/lib/sc_envu.php";
include_once 
"/lib/sd_340.php";

$envu =  envu_read("envu");
$schedules envu_find($envu"schedule");

$count 0;

if(
$schedules != "")
{
    
$schedules explode("||"$schedules);

    
$count count($schedules);

    for(
$i 0$i $count$i++)
    {
        
$schedules[$i] = explode("|"$schedules[$i]);
    }
}
else
    
$schedules = array();

$is_activate false;

//seting to work with distance sensor
$ht_trig 1;
$ht_echo 0;

// setup trigger pulse timer
ht_ioctl($ht_trig"set mode output pulse");
ht_ioctl($ht_trig"set div us");
ht_ioctl($ht_trig"set repc 1");
ht_ioctl($ht_trig"set count 5 10"); // 10us pulse width

// setup echo capture timer
ht_ioctl($ht_echo"reset");
ht_ioctl($ht_echo"set div us");
ht_ioctl($ht_echo"set mode capture toggle");
ht_ioctl($ht_echo"set trigger from pin rise");
ht_ioctl($ht_echo"set repc 4");

//Control the alert
st_ioctl(0"set mode output pulse");
st_ioctl(0"set count 100 200");
st_ioctl(0"set output dev uio0 18");

while(
1)
{
    
$is_activate false;

    if(
$count)
    {    
        
$day date("D");
        
$hour = (int)date("H");
        
$minute = (int)date("i");
        
$current_time $hour*60 $minute;//in minute

        
for($i 0$i $count$i++)
        {
            if(
$day == $schedules[$i][0])
            {
                
$temp explode(":"$schedules[$i][1]);
                
$start_time = ((int)$temp[0])*60 + (int)$temp[1];//in minute

                
$temp explode(":"$schedules[$i][2]);
                
$end_time = ((int)$temp[0])*60 + (int)$temp[1];//in minute

                
if($current_time >= $start_time && $current_time <= $end_time)
                {
                    
$is_activate true;
                    break;
                }
            }
        }
    }

    if(
$is_activate)
    {
        
//TODO
        
ht_ioctl($ht_echo"start"); // we should start capture timer first
        
ht_ioctl($ht_trig"start"); // start trigger pulse

        
usleep(100000); // sleep 100ms
        
ht_ioctl($ht_echo"stop");

        
// 1st capture value ("get count 0") is always zero.
        // we should get 2nd capture value;
        
$us ht_ioctl($ht_echo"get count 1");

        
$dist $us 340.0 2;
        
$dist $dist 10000//in centimeter

        
if($dist 70)
        {
            
st_ioctl(0"start");        
        }
        else
        {
            
st_ioctl(0"stop");
            
st_ioctl(0"set output low");
        }
        
usleep(10000);
    }
    else
    {
        
st_ioctl(0"stop");
        
st_ioctl(0"set output low");
    }
}    
?>



If you have any question, please leave a comment.