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
User Interface
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", $envu, strlen($envu), 0);
system("reboot sys 1000");
}
else
{
if($envu == "")
{
$envu = "schedule=\r\n";
envu_write("envu", $envu, strlen($envu), 0);
}
}
?>
<!DOCTYPE html>
<html>
<?php
$stypeno_table = array(0, 1, 2);
$stype_table = array("RS232", "RS485", "RS422");
$baud_table = array(230400, 115200, 57600, 38400, 19200, 14400, 9600, 4800, 2400, 1200);
$parityno_table = array(0, 1, 2, 3, 4, 5);
$parity_table = array("None", "Even", "Odd", "Mark", "Space");
$fctrlno_table = array(0, 1, 2);
$fctrl_table = array("None", "RTS/CTS", "Xon/Xoff");
$operationno_table = array(0, 2);
$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)">✖</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)">✖</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 = '✚';
}
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 = '✔';
}
}
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)">✚</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.
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),
Working flow
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_pin, LOW);
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_pin, LOW);
}
}
?>
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),
Working flow
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.