Location: PHPKode > scripts > TellStick Home automation > tdtool.class.php
<?php
/**
 *  Wrapper for the TDTOOL that comes with the Tellstick software.
 *
 *  This class uses the tdtool aswell as creating cool features.
 *
 Generic information:


 Initialize the object:
    # Initializes devices, generates xml scheme / updates it if more devices is detected.
    # First arguement is the path to the tdtool. On Linux the path will be /blah/blah/blah/tdtool
    $stick = new TellStick('C:\Program Files (x86)\Telldus\tdtool.exe');


 Manual Tasks:
    Every device get's an ID. You may see the ID of the devices by using ListDevices() in TellStick class.
    When you have the ID of the device you want to turn off / on / dim... you can do:
    $stick->Device(1)->On();
    sleep(4);
    $stick->Device(1)->Off();
    sleep(4);
    $stick->Device(1)->Dim(125);
    sleep(4);
    $stick->Device(1)->Dim(255);  // Max dim!

    echo $stick->Device(1)->getStatus();

    This is COOL! See TellStickDevice class for more methods to use on a device.
    What will happen on the example above is that...
      1. Lights will turn on instantly.
      2. Lights will Turn off.
      3. Lights will dim up to 125 (Aprox half dimmed)
      4. Lights will Dim to full strength.

      the echo command: Status will be printed to whereas your script is.


   TASKS:
      Automated Tasks:
         This class can create advanced tasks, forexample: "Turn on" "lamp in the kitchen" "every monday" "IF the lamp in the bedroom is off"


         CREATING THE CRON ENTRY, (LET IT RUN ONCE A MINUTE). The Class will handle the rest.

         The tool is very simple and you only need to create a cron entry that runs these two lines (and also include this class ofcourse):

             $stick = new TellStick('C:\Program Files (x86)\Telldus\tdtool.exe');
             $stick->RunCheckTasks();

         Everything else is automated.
         Every device has a Task() method that initializes the TellStickTask class, You may create and delete tasks.

      Deleting all tasks for the device id #1:
         # You may access specific devices.
         $stick->Device(1)->Task()->Delete();


      Creating a new task. This will: TURN ON if its thirsday and the device with id '1' is statused to OFF.
         # You may create a sheduled task (cron syntax) for the device...
         $stick->Device(1)->Task()->Create('On','* * * * 2',false,array('1' => 'OFF'));



 *
 */
class TellStickDevice{
    private $core;
    private $device;
    private $name;
    private $status;
    private $xml;




    public function __construct(&$core,$device, $name='', $status=''){
        $this->core = &$core;
        $this->device = $device;
        $this->name = $name;
        $this->status = $status;

        // Set XML for this device.
        if ($this->core->xml){
        foreach($this->core->xml as $xmldev){
            if ($xmldev['id']==$this->getID()){
                $this->xml = $xmldev;
                $this->name = $xmldev['name'];
            }
        }
        }
        $this->UpdateDevice();

    }


    public function getStatus(){
        return $this->status;
    }
    public function getID(){
        return $this->device;
    }
    public function getName(){
        return $this->name;
    }
    public function getXML(){
        return $this->xml;
    }
    public function getCore(){
        return $this->core;
    }
    
    public function setImage($link){
        foreach($this->core->xml as $xmldev){
            if ($xmldev['id']==$this->getID()){
                if (!isset($xmldev->image))$xmldev->addChild('image', $link);
                else $xmldev->image = $link;
            }
        }

        $this->core->saveXML();
    }
    public function deleteImage(){
        $i = 0;
        foreach($this->core->xml as $k => $xmldev){
            if ($xmldev['id']==$this->getID()){
                if (isset($xmldev->image))unset($this->core->xml->device[$i]->image);
            }
        }

        $this->core->saveXML();
    }
    public function getImage(){
        return isset($this->xml->image) ? $this->xml->image : false;
    }
    
    
    public function setComment($comment){
        foreach($this->core->xml as $xmldev){
            if ($xmldev['id']==$this->getID()){
                if (!isset($xmldev->comment))$xmldev->addChild('comment', $comment);
                else $xmldev->comment = $comment;
            }
        }

        $this->core->saveXML();
    }
    public function deleteComment(){
        $i = 0;
        foreach($this->core->xml as $xmldev){
            if ($xmldev['id']==$this->getID()){
                if (isset($xmldev->comment))unset($this->core->xml->device[$i]->comment);
            }
        }

        $this->core->saveXML();
    }
    public function getComment(){
        return isset($this->xml->comment) ? $this->xml->comment : false;
    }
    
    
    

    // Use to update status of the device.
    public function UpdateDevice(){
        $devices = $this->core->Telldus('--list');
        unset($devices[0]);
        foreach($devices as $d){
            $e = explode("\t", $d);

            list($id, $name, $status) = $e;
            if ($this->device == $id){
                $this->status = $status;
                return true;
            }
        }
        return false;
    }


    // Turn on device.
    public function On(){
        $r = $this->core->Telldus('--on '.$this->device);
        $this->UpdateDevice();
        return $r;
    }

    // Turn off device.
    public function Off(){
        $r= $this->core->Telldus('--off '.$this->device);
        $this->UpdateDevice();
        return $r;
    }

    // Dim device, 0 to 255 allowed to use as arguement.
    public function Dim($dimlevel=0){
        if ($dimlevel > 255 || $dimlevel < 0)throw new Exception("Could not dim to specified number. Must be between 0 and 255.",1);

        $r= $this->core->Telldus('--dimlevel '.$dimlevel.' --dim '.$this->device);
        $this->UpdateDevice();
        return $r;
    }

    // To use at doorbell devices.
    public function Bell(){
        $r= $this->core->Telldus('--bell '.$this->device);
        $this->UpdateDevice();
        return $r;
    }

    // Learn unit. Must be self-learning unit.
    public function Learn(){
        $r= $this->core->Telldus('--learn '.$this->device);
        $this->UpdateDevice();
        return $r;
    }

    // Raw Command
    public function Command($c){
        $r= $this->core->Telldus('--raw '.$c);
        $this->UpdateDevice();
        return $r;
    }


    // Create a sheduled task.
    public function Task(){
        return new TellTask($this);
    }

}

class TellTask{
    private $device;



    public function __construct(&$device){
        $this->device = &$device;
    }

    private function validateCron($cron){
        $e = explode(' ', $cron);
        $c = count($e);

        list($min, $hour, $day, $month, $week) = $e;

        // Check if this is a real formated cron.
        if ($c != 5
        || ($min   != '*'  &&   ($min < 0    || $min > 59))
        || ($hour  != '*'  &&   ($hour < 0   || $hour > 23))
        || ($day   != '*'  &&   ($day < 1    || $day > 31))
        || ($month != '*'  &&   ($month < 1  || $month > 12))
        || ($week  != '*'  &&   ($week < 0   || $week > 6))
        )throw new Exception("The cron format is not valid. It should be * * * * *, one space between the modifiers and 5 units. Read on google for syntax of cron format.",4);



        return $e;
    }
    
    public function ListTasks(){
       return $this->device->getXML()->tasks[0];
    }

    // param $TASK The method in the device class. Must be a VALID method.
    public function Create($TASK, $cron, $ARGUEMENTS=false,$if_schema=false){
        if (!method_exists($this->device, $TASK))throw new Exception("The defined Task in Task :: Create ( $TASK ) is not a valid task. Valid tasks is: ".print_r(get_class_methods($this->device), true),3);

        $this->validateCron($cron);

        $task = $this->device->getXML()->tasks[0]->addChild('task');
        $task->addAttribute('do',$TASK);
        $task->addAttribute('arguements',json_encode($ARGUEMENTS));
        $task->addAttribute('id',(count($this->device->getXML()->tasks[0])));
        $task->addAttribute('crontab',$cron);
        $task->addAttribute('lastrun',0);
        $task->addAttribute('if_schema',json_encode($if_schema));

        $task->addAttribute('active','-1');
        $task->addAttribute('ok','0');
        
        
        $this->device->getCore()->saveXML();



    }

    // param $id The Task id (attribute id on the task element ).
    public function Delete($id=false){
        if (!$id){
            unset($this->device->getXML()->tasks[0]);
            $this->device->getXML()->addChild('tasks');
        }else{
            unset($this->device->getXML()->tasks[0]->task[$id-1]);
        }
        $this->device->getCore()->saveXML();
    }
}


// Unit.
class TellStickCore{

    public $TelldusPath;
    public $TelldusExe;
    public $deviceconfigfile = 'device.xml';
    public $xml;

    // Start TellStick.
    public function __construct($path){
        $this->TelldusPath = '"'.$path.'"';
        $this->checkXML();

    }

    public function RunCheckTasks(){
        $devices = $this->ListDevices();
        if (count($this->xml) > 0){
            foreach($this->xml->device as $device){
                if (count($device->tasks[0]) > 0){
                foreach($device->tasks[0] as $task){
                    $lastrun = $task['lastrun'];
                    $cron = explode(' ',$task['crontab']);

                    list($min, $hour, $day, $month, $week) = $cron;


                    if ($task['if_schema'] != 'false'){
                        $if = json_decode($task['if_schema']);
                        $device_block=false;
                        // Now check.
                        foreach($if as $id => $sentence){
                            foreach($devices as $dev){
                                if ($dev->getID() == $id && $dev->getStatus() != $sentence)$device_block=true;
                            }
                        }
                    }

                    $cron = new CronParser();
    
                    //if one of cron crashed
                    if ($task['ok'] == false){

                    }
                    
                    if ($cron->calcLastRan($task['crontab'])){
                        if ($cron->getLastRanUnix() > $task['lastrun']){
                            echo $cron->getLastRanUnix(), " VS " ,$task['lastrun'];
                            $task['ok'] = true;

                            $dev = $this->Device($task['id']);
                            $method = $task['do'];
                            $arg = '';
                            if ($task['arguements'] != 'false'){
                                $args = json_decode($task['arguements']);
                                $i = 0;
                                foreach($args as $a){
                                    if ($i==0)$arg .= $a;
                                    else $arg .= ','.$a;
                                    $i++;
                                }
                            }
                            // Special case of running it .. Use of eval makes it so simple and  - beautiful can be discussed.
                            eval("\$return = \$dev->$method($arg);");
                            $task['lastrun'] = time();


                        }else{
                            // Wait for next time
                        }

                    }else{
                        // Not possible to parse the cront time ... should not go here really...
                    }


                }
                }
            }

            $this->saveXML();
        }
    }



    public function Device($device){
        return new TellStickDevice($this, $device);
    }

    public function ListDevices(){
        $devices = $this->Telldus('--list');
        if ($devices[0]=='Number of devices: -1')throw new Exception("No devices found! Please check if APACHE/PHP has access to root/admin.",2);
        $a = array();
        unset($devices[0]);
        foreach($devices as $d){
            $e = explode("\t", $d);
            list($id, $name, $status) = $e;
            $a[] = new TellStickDevice($this, $id, $name, $status);
        }
        return $a;
    }

    public function saveXML(){
        file_put_contents($this->deviceconfigfile,$this->xml->asXML());
    }

    public function checkXML(){
        $devices = $this->ListDevices();
        if (file_exists($this->deviceconfigfile)){
            $this->xml = simplexml_load_string(file_get_contents($this->deviceconfigfile));
        }else{
            $string = "<?xml version='1.0'?>
            <devices>
            </devices>
            ";
            $this->xml = simplexml_load_string($string);
        }
            $added=0;
            if (count($devices) > 0){
                foreach($devices as $dev){
                    $add=true;
                    foreach($this->xml as $xmldev){
                        if ($xmldev['id']==$dev->getID())$add=false;
                    }

                    if ($add){
                        $added++;

                        $device = $this->xml->addChild('device');
                        $device->addAttribute('id',$dev->getID());
                        $device->addAttribute('name',$dev->getName());
                        $tasks = $device->addChild('tasks');
                    }
                }
            }
            if ($added > 0){
                $this->saveXML();
            }
    }


    public function Telldus($c){
        exec($this->TelldusPath.' '.$c,$array);
        return $array;
    }
}



/**####################################################################################################**\
   Version: V1.01
   Release Date: 12 Sep 2005
   Licence: GPL
   By: Nikol S
   Please send bug reports to hide@address.com
\**####################################################################################################**/

/* This class is based on the concept in the CronParser class written by Mick Sear http://www.ecreate.co.uk
 * The following functions are direct copies from or based on the original class:
 * getLastRan(), getDebug(), debug(), expand_ranges()
 *
 * Who can use this class?
 * This class is idea for people who can not use the traditional Unix cron through shell.
 * One way of using is embedding the calling script in a web page which is often visited.
 * The script will work out the last due time, by comparing with run log timestamp. The scrip
 * will envoke any scripts needed to run, be it deleting older table records, or updating prices.
 * It can parse the same cron string used by Unix.
 */

/* Usage example:

$cron_str0 = "0,12,30-51 3,21-23,10 1-25 9-12,1 0,3-7";
require_once("CronParser.php");
$cron = new CronParser();
$cron->calcLastRan($cron_str0);
// $cron->getLastRanUnix() returns an Unix timestamp
echo "Cron '$cron_str0' last due at: " . date('r', $cron->getLastRanUnix()) . "<p>";
// $cron->getLastRan() returns last due time in an array
print_r($cron->getLastRan());
echo "Debug:<br>" . nl2br($cron->getDebug());

$cron_str1 = "3 12 * * *";
if ($cron->calcLastRan($cron_str1))
{
   echo "<p>Cron '$cron_str1' last due at: " . date('r', $cron->getLastRanUnix()) . "<p>";
   print_r($cron->getLastRan());
}
else
{
   echo "Error parsing";
}
echo "Debug:<br>" . nl2br($cron->getDebug());

 *#######################################################################################################
 */

class CronParser
{

 	var $bits = Array(); //exploded String like 0 1 * * *
 	var $now = Array();	//Array of cron-style entries for time()
 	var $lastRan; 		//Timestamp of last ran time.
 	var $taken;
 	var $debug;
	var $year;
	var $month;
	var $day;
	var $hour;
	var $minute;
	var $minutes_arr = array();	//minutes array based on cron string
	var $hours_arr = array();	//hours array based on cron string
	var $months_arr = array();	//months array based on cron string

	function getLastRan()
	{
		return explode(",", strftime("%M,%H,%d,%m,%w,%Y", $this->lastRan)); //Get the values for now in a format we can use
	}

	function getLastRanUnix()
	{
		return $this->lastRan;
	}

	function getDebug()
	{
 		return $this->debug;
	}

	function debug($str)
	{
		if (is_array($str))
		{
			$this->debug .= "\nArray: ";
			foreach($str as $k=>$v)
			{
				$this->debug .= "$k=>$v, ";
			}

		}
		else
		{
			$this->debug .= "\n$str";
		}
		//echo nl2br($this->debug);
	}

	/**
	 * Assumes that value is not *, and creates an array of valid numbers that
	 * the string represents.  Returns an array.
	 */
	function expand_ranges($str)
	{
		if (strstr($str,  ","))
		{
			$arParts = explode(',', $str);
			foreach ($arParts AS $part)
			{
				if (strstr($part, '-'))
				{
					$arRange = explode('-', $part);
					for ($i = $arRange[0]; $i <= $arRange[1]; $i++)
					{
						$ret[] = $i;
					}
				}
				else
				{
					$ret[] = $part;
				}
			}
		}
		elseif (strstr($str,  '-'))
		{
			$arRange = explode('-', $str);
			for ($i = $arRange[0]; $i <= $arRange[1]; $i++)
			{
				$ret[] = $i;
			}
		}
		else
		{
			$ret[] = $str;
		}
		$ret = array_unique($ret);
		sort($ret);
		return $ret;
	}

	function daysinmonth($month, $year)
	{
		return date('t', mktime(0, 0, 0, $month, 1, $year));
	}

	/**
	 *  Calculate the last due time before this moment
	 */
	function calcLastRan($string)
	{

 		$tstart = microtime();
		$this->debug = "";
		$this->lastRan = 0;
		$this->year = NULL;
		$this->month = NULL;
		$this->day = NULL;
		$this->hour = NULL;
		$this->minute = NULL;
		$this->hours_arr = array();
		$this->minutes_arr = array();
		$this->months_arr = array();

		$string = preg_replace('/[\s]{2,}/', ' ', $string);

		if (preg_match('/[^-,* \\d]/', $string) !== 0)
		{
			$this->debug("Cron String contains invalid character");
			return false;
		}

		$this->debug("<b>Working on cron schedule: $string</b>");
 		$this->bits = @explode(" ", $string);

		if (count($this->bits) != 5)
		{
			$this->debug("Cron string is invalid. Too many or too little sections after explode");
			return false;
		}

		//put the current time into an array
		$t = strftime("%M,%H,%d,%m,%w,%Y", time());
		$this->now = explode(",", $t);

		$this->year = $this->now[5];

		$arMonths = $this->_getMonthsArray();

		do
		{
			$this->month = array_pop($arMonths);
		}
		while ($this->month > $this->now[3]);

		if ($this->month === NULL)
		{
			$this->year = $this->year - 1;
			$this->debug("Not due within this year. So checking the previous year " . $this->year);
			$arMonths = $this->_getMonthsArray();
			$this->_prevMonth($arMonths);
		}
		elseif ($this->month == $this->now[3]) //now Sep, month = array(7,9,12)
		{
			$this->debug("Cron is due this month, getting days array.");
			$arDays = $this->_getDaysArray($this->month, $this->year);

			do
			{
				$this->day = array_pop($arDays);
			}
			while ($this->day > $this->now[2]);

			if ($this->day === NULL)
			{
				$this->debug("Smallest day is even greater than today");
				$this->_prevMonth($arMonths);
			}
			elseif ($this->day == $this->now[2])
			{
				$this->debug("Due to run today");
				$arHours = $this->_getHoursArray();

				do
				{
					$this->hour = array_pop($arHours);
				}
				while ($this->hour > $this->now[1]);

				if ($this->hour === NULL) // now =2, arHours = array(3,5,7)
				{
					$this->debug("Not due this hour and some earlier hours, so go for previous day");
					$this->_prevDay($arDays, $arMonths);
				}
				elseif ($this->hour < $this->now[1]) //now =2, arHours = array(1,3,5)
				{
					$this->minute = $this->_getLastMinute();
				}
				else // now =2, arHours = array(1,2,5)
				{
					$this->debug("Due this hour");
					$arMinutes = $this->_getMinutesArray();
					do
					{
						$this->minute = array_pop($arMinutes);
					}
					while ($this->minute > $this->now[0]);

					if ($this->minute === NULL)
					{
						$this->debug("Not due this minute, so go for previous hour.");
						$this->_prevHour($arHours, $arDays, $arMonths);
					}
					else
					{
						$this->debug("Due this very minute or some earlier minutes before this moment within this hour.");
					}
				}
			}
			else
			{
				$this->debug("Cron was due on " . $this->day . " of this month");
				$this->hour = $this->_getLastHour();
				$this->minute = $this->_getLastMinute();
			}
		}
		else //now Sep, arrMonths=array(7, 10)
		{
			$this->debug("Cron was due before this month. Previous month is: " . $this->year . '-' . $this->month);
			$this->day = $this->_getLastDay($this->month, $this->year);
			if ($this->day === NULL)
			{
				//No scheduled date within this month. So we will try the previous month in the month array
				$this->_prevMonth($arMonths);
			}
			else
			{
				$this->hour = $this->_getLastHour();
				$this->minute = $this->_getLastMinute();
			}
		}

		$tend = microtime();
		$this->taken = $tend - $tstart;
		$this->debug("Parsing $string taken " . $this->taken . " seconds");

		//if the last due is beyond 1970
		if ($this->minute === NULL)
		{
			$this->debug("Error calculating last due time");
			return false;
		}
		else
		{
			$this->debug("LAST DUE: " . $this->hour . ":" . $this->minute . " on " . $this->day . "/" . $this->month . "/" . $this->year);
			$this->lastRan = mktime($this->hour, $this->minute, 0, $this->month, $this->day, $this->year);
			return true;
		}
	}

	//get the due time before current month
	function _prevMonth($arMonths)
	{
		$this->month = array_pop($arMonths);
		if ($this->month === NULL)
		{
			$this->year = $this->year -1;
			if ($this->year <= 1970)
			{
				$this->debug("Can not calculate last due time. At least not before 1970..");
			}
			else
			{
				$this->debug("Have to go for previous year " . $this->year);
				$arMonths = $this->_getMonthsArray();
				$this->_prevMonth($arMonths);
			}
		}
		else
		{
			$this->debug("Getting the last day for previous month: " . $this->year . '-' . $this->month);
			$this->day = $this->_getLastDay($this->month, $this->year);

			if ($this->day === NULL)
			{
				//no available date schedule in this month
				$this->_prevMonth($arMonths);
			}
			else
			{
				$this->hour = $this->_getLastHour();
				$this->minute = $this->_getLastMinute();
			}
		}

	}

	//get the due time before current day
	function _prevDay($arDays, $arMonths)
	{
		$this->debug("Go for the previous day");
		$this->day = array_pop($arDays);
		if ($this->day === NULL)
		{
			$this->debug("Have to go for previous month");
			$this->_prevMonth($arMonths);
		}
		else
		{
			$this->hour = $this->_getLastHour();
			$this->minute = $this->_getLastMinute();
		}
	}

	//get the due time before current hour
	function _prevHour($arHours, $arDays, $arMonths)
	{
		$this->debug("Going for previous hour");
		$this->hour = array_pop($arHours);
		if ($this->hour === NULL)
		{
			$this->debug("Have to go for previous day");
			$this->_prevDay($arDays, $arMonths);
		}
		else
		{
			$this->minute = $this->_getLastMinute();
		}
	}

	//not used at the moment
	function _getLastMonth()
	{
		$months = $this->_getMonthsArray();
		$month = array_pop($months);

		return $month;
	}

	function _getLastDay($month, $year)
	{
		//put the available days for that month into an array
		$days = $this->_getDaysArray($month, $year);
		$day = array_pop($days);

		return $day;
	}

	function _getLastHour()
	{
		$hours = $this->_getHoursArray();
		$hour = array_pop($hours);

		return $hour;
	}

	function _getLastMinute()
	{
		$minutes = $this->_getMinutesArray();
		$minute = array_pop($minutes);

		return $minute;
	}

	//remove the out of range array elements. $arr should be sorted already and does not contain duplicates
	function _sanitize ($arr, $low, $high)
	{
		$count = count($arr);
		for ($i = 0; $i <= ($count - 1); $i++)
		{
			if ($arr[$i] < $low)
			{
				$this->debug("Remove out of range element. {$arr[$i]} is outside $low - $high");
				unset($arr[$i]);
			}
			else
			{
				break;
			}
		}

		for ($i = ($count - 1); $i >= 0; $i--)
		{
			if ($arr[$i] > $high)
			{
				$this->debug("Remove out of range element. {$arr[$i]} is outside $low - $high");
				unset ($arr[$i]);
			}
			else
			{
				break;
			}
		}

		//re-assign keys
		sort($arr);
		return $arr;
	}

	//given a month/year, list all the days within that month fell into the week days list.
	function _getDaysArray($month, $year = 0)
	{
		if ($year == 0)
		{
			$year = $this->year;
		}

		$days = array();

		//return everyday of the month if both bit[2] and bit[4] are '*'
		if ($this->bits[2] == '*' AND $this->bits[4] == '*')
		{
			$days = $this->getDays($month, $year);
		}
		else
		{
			//create an array for the weekdays
			if ($this->bits[4] == '*')
			{
				for ($i = 0; $i <= 6; $i++)
				{
					$arWeekdays[] = $i;
				}
			}
			else
			{
				$arWeekdays = $this->expand_ranges($this->bits[4]);
				$arWeekdays = $this->_sanitize($arWeekdays, 0, 7);

				//map 7 to 0, both represents Sunday. Array is sorted already!
				if (in_array(7, $arWeekdays))
				{
					if (in_array(0, $arWeekdays))
					{
						array_pop($arWeekdays);
					}
					else
					{
						$tmp[] = 0;
						array_pop($arWeekdays);
						$arWeekdays = array_merge($tmp, $arWeekdays);
					}
				}
			}
			$this->debug("Array for the weekdays");
			$this->debug($arWeekdays);

			if ($this->bits[2] == '*')
			{
				$daysmonth = $this->getDays($month, $year);
			}
			else
			{
				$daysmonth = $this->expand_ranges($this->bits[2]);
				// so that we do not end up with 31 of Feb
				$daysinmonth = $this->daysinmonth($month, $year);
				$daysmonth = $this->_sanitize($daysmonth, 1, $daysinmonth);
			}

			//Now match these days with weekdays
			foreach ($daysmonth AS $day)
			{
				$wkday = date('w', mktime(0, 0, 0, $month, $day, $year));
				if (in_array($wkday, $arWeekdays))
				{
					$days[] = $day;
				}
			}
		}
		$this->debug("Days array matching weekdays for $year-$month");
		$this->debug($days);
		return $days;
	}

	//given a month/year, return an array containing all the days in that month
	function getDays($month, $year)
	{
		$daysinmonth = $this->daysinmonth($month, $year);
		$this->debug("Number of days in $year-$month : $daysinmonth");
		$days = array();
		for ($i = 1; $i <= $daysinmonth; $i++)
		{
			$days[] = $i;
		}
		return $days;
	}

	function _getHoursArray()
	{
		if (empty($this->hours_arr))
		{
			$hours = array();

			if ($this->bits[1] == '*')
			{
				for ($i = 0; $i <= 23; $i++)
				{
					$hours[] = $i;
				}
			}
			else
			{
				$hours = $this->expand_ranges($this->bits[1]);
				$hours = $this->_sanitize($hours, 0, 23);
			}

			$this->debug("Hour array");
			$this->debug($hours);
			$this->hours_arr = $hours;
		}
		return $this->hours_arr;
	}

	function _getMinutesArray()
	{
		if (empty($this->minutes_arr))
		{
			$minutes = array();

			if ($this->bits[0] == '*')
			{
				for ($i = 0; $i <= 60; $i++)
				{
					$minutes[] = $i;
				}
			}
			else
			{
				$minutes = $this->expand_ranges($this->bits[0]);
				$minutes = $this->_sanitize($minutes, 0, 59);
			}
			$this->debug("Minutes array");
			$this->debug($minutes);
			$this->minutes_arr = $minutes;
		}
		return $this->minutes_arr;
	}

	function _getMonthsArray()
	{
		if (empty($this->months_arr))
		{
			$months = array();
			if ($this->bits[3] == '*')
			{
				for ($i = 1; $i <= 12; $i++)
				{
					$months[] = $i;
				}
			}
			else
			{
				$months = $this->expand_ranges($this->bits[3]);
				$months = $this->_sanitize($months, 1, 12);
			}
			$this->debug("Months array");
			$this->debug($months);
			$this->months_arr = $months;
		}
		return $this->months_arr;
	}

}


?>
Return current item: TellStick Home automation