Cron-Jobs Manager for openHAB

It all started before christmas, when my wife asked me to implement a cron-job for the christmas tree lights on short notice. Long story short: After much research (hopefully I have not overlooked anything) I gave up; frustrated and used an old fashioned clock timer.

However, during my search I run across the post from villaRob (https://community.openhab.org/u/villaRob) Input field for number/free text for openHAB UIs.

Together with a php script from Gustav Genberg (Crontab.class.php) I have come up now with the following output:

Cron-Job Manager for openHAB
Before reading further, please note that I am not a programmer but everything done was hands on; so the coding might look a little “robust”.

In principle it consists of three different webview images (see at the end of this post “sitemap”):

  • Create a Cron-Job (Erstellen von Cron-Jobs)
  • All active Cron-Jobs for openHAB (Cron-Jobs Online)
  • Deletion of Cron-Jobs (Löschen von Cron-Jobs)

Create a Cron-Job:
This task relies on four files; all of them need to be placed in the folder /var/www/html (raspberry pi) or the corresponding Apache2 Debian Default folder (same for all the other files following).

  • crontabclass.php (see afore here only as file attached)
  • crontabtimer.html (see below)
  • crontabvalue.php (see below)
  • crontabcommand.php (see below)

crontabtimer.html

<html>
        <body>
                <form method="post" action="crontabvalue.php">
                        <select name="Wochentage[ ]" multiple>
                                <option value="1">Montag</option>
                                <option value="2">Dienstag</option>
                                <option value="3">Mittwoch</option>
                                <option value="4">Donnerstag</option>
                                <option value="5">Freitag</option>
                                <option value="6">Samstag</option>
                                <option value="7">Sonntag</option>
                        </select>
						<select name="Stunden[ ]" multiple>
                                <option value="0">0 Uhr</option>
                                <option value="1">1 Uhr</option>
                                <option value="2">2 Uhr</option>
                                <option value="3">3 Uhr</option>
                                <option value="4">4 Uhr</option>
                                <option value="5">5 Uhr</option>
                                <option value="6">6 Uhr</option>
                                <option value="7">7 Uhr</option>
                                <option value="8">8 Uhr</option>
                                <option value="9">9 Uhr</option>
                                <option value="10">10 Uhr</option>
                                <option value="11">11 Uhr</option>
                                <option value="12">12 Uhr</option>
                                <option value="13">13 Uhr</option>
                                <option value="14">14 Uhr</option>
                                <option value="15">15 Uhr</option>
                                <option value="16">16 Uhr</option>
                                <option value="17">17 Uhr</option>
                                <option value="18">18 Uhr</option>
                                <option value="19">19 Uhr</option>
                                <option value="20">20 Uhr</option>
                                <option value="21">21 Uhr</option>
                                <option value="22">22 Uhr</option>
                                <option value="23">23 Uhr</option>
                        </select>
						<select name="Minuten[ ]" multiple>
                                <option value="0">0 Minuten</option>
                                <option value="5">5 Minuten</option>
                                <option value="10">10 Minuten</option>
                                <option value="15">15 Minuten</option>
                                <option value="20">20 Minuten</option>
                                <option value="25">25 Minuten</option>
                                <option value="30">30 Minuten</option>
                                <option value="35">35 Minuten</option>
                                <option value="40">40 Minuten</option>
                                <option value="45">45 Minuten</option>
                                <option value="50">50 Minuten</option>
                                <option value="55">55 Minuten</option>
                        </select>
						<select name="Item[ ]" multiple>
                                <option value="HUE">Hue Beleuchtung Wohnzimmer</option>
                                <option value="MarantzMainZone">Marantz Main Zone</option>
                                <option value="SteckdoseHIFI">Steckdose HIFI</option>
                                <option value="LichtVar1">Variable Steckdose 1</option>
                        </select>
						<select name="Command[ ]" multiple>
                                <option value="ON">ON</option>
                                <option value="OFF">OFF</option>
                        </select>
                        <input type="submit" name="submit" value=Submit>
                </form>
        </body>
</html>

As you can see, it is quite a simple piece of code which can easily modified and adapted to the needs.
I was satiesfied with the possibility to have multiple choises of houes and minutes as well as days of the week. Together with the item and command options the necessary input parameters are generated for a cron job.

The value of the items

<option value="MarantzMainZone">Marantz Main Zone</option>

are exactly the names you have given your items in the opnehab.item file (in this example item=MarantzMainZone).

The commands must also be exaclty as needed within openHAB. In the present cases all items are switches such the corresponding values for the commands are “ON” and “OFF”.

Via post-method (and the submit button - see picture afore) these parameters are handed over to the php script “crontabvalue.php”.

crontabvalue.php

<?php

require_once("/var/www/html/crontabclass.php");

// ###### Auswertung der html Seite #########
// https://stackoverflow.com/questions/2407284/how-to-get-multiple-selected-values-of-select-box-in-php


$i = 1;
$j = 1;
$k = 1;
$l = 1;
$m = 1;


foreach ($_POST['Wochentage'] as $names) {
        if ($i == 1) {
            	$Wochentage  = $names;
			$i = 2;
            }
        else {$Wochentage  = $Wochentage.",".$names;}
}
if ($Wochentage == "") {$Wochentage = "*";}

foreach ($_POST['Stunden'] as $names) {
        if ($j == 1) {
           	$Stunden  = $names;
			$j = 2;
            }
        else {$Stunden  = $Stunden.",".$names;}
}
if ($Stunden == "") {$Stunden = "*";}

foreach ($_POST['Minuten'] as $names)
{
        if ($k == 1) {
            $Minuten  = $names;
			$k = 2;
            }
        else {$Minuten  = $Minuten.",".$names;}
}
if ($Minuten == "") {$Minuten = "*";}

foreach ($_POST['Item'] as $names)
{$Item  = $names;}

foreach ($_POST['Command'] as $names)
{$Command  = $names;}

$Cron = $Minuten." ".$Stunden." * "." * ".$Wochentage." php /var/www/html/crontabcommand.php ".$Item." ".$Command;

Crontab::Add($Cron);

print $Cron;

?>

This piece of php code grabs the input parameters and puts them together to a “cron-job string”. Please note that this script uses the crontabclass.php (“require_once”) mentioned earlier and developed by Gustav Genberg in 2017.
The command of this cron-job relies then again on the last php code:

crontabcommand.php

<?php

$Item = $argv[1];
$Command = $argv[2];

$Output = sendCommand($Item, $Command);


function sendCommand($item, $data) {
      $url = "http://192.168.1.116:8080/rest/items/" . $item;
    
      $options = array(
        'http' => array(
            'header'  => "Content-type: text/plain\r\n",
            'method'  => 'POST',
            'content' => $data  //http_build_query($data),
        ),
      );
    
      $context  = stream_context_create($options);
      $result = file_get_contents($url, false, $context);
    
      return $result;
    }

?>

This php script is based on the information provided in Samples-REST of the openHAB-wiki.

After everything has been set and submitted (Submit button) the result is seen on scren like this:


The syntax of the cron-job is provided for last check (cron-job syntax according to Wiki - Cron-Jobs.

As one definitely needs to be aware of all the cron jobs established, the second part of the screen shows all the active cron jobs. This is displayed with the follwing php script:

crontabview.php

<?php
$i = 0;
$cronfiles=exec('crontab -l -u www-data',$output);
foreach ( $output as $item ) {
        echo "[".$i."] ".$item . "<br/>";
		$i = $i + 1;
    }
?>

I believe pretty straight forward.

Last but not least - in a similar manner than afore - cron-jobs need also to be deleted again.
This is done with the follwing scrips:

  • crontabclass.php
  • crontabdelete.html
  • crontabdelete.php

crontabdelete.html

<html>
        <body>
                <form method="post" action="crontabdelete.php">
								  Nummer des zu loeschenden Cron-Jobs :<br>
  								<input name="Delete" ><br>
                       <input type="submit" name="submit" value=Submit>
                </form>
        </body>
</html>

Here the only thing relevant is that the number of the conjob to be deleted corresponds to the number of the cron job provided in the active cron job list.

crontabdelete.php

<?php
$i = $_POST['Delete'];
require_once("/var/www/html/crontabclass.php");
// ###### Auswertung der html Seite #########
// https://stackoverflow.com/questions/2407284/how-to-get-multiple-selected-values-of-select-box-in-php
$cronfiles=exec('crontab -l -u www-data',$output);
Crontab::Remove($output[$i]);
//print_r("Gelöschter Cron-Job: ".$output[$i]);
$i="";
header('Location: crontabdelete.html');
exit;
?>

Sitemap
Last but not least I implemented these scripts in my sitemap as follows:

Frame label="Cron" {
	Group item=Cron icon="clock"{
		Frame label="Erstellen von Cron-Job"{
			Webview url="http://192.168.1.116/crontabtimer.html" height=2
		}
		Frame label="Cronjobs Online" icon="Online" {		
			Webview url="http://192.168.1.116/crontabview.php" height=10
		}
		Frame label="Löschen von Cron-Job"{
			Webview url="http://192.168.1.116/crontabdelete.html" height=2
		}
	}
}

The update is done by Webview automatically.
Please note:
(1) As Webview does update itself automatically every approx. 30 seconds, the input for the cron-job has to be done within this time fame. Otherwise all fields will be blank again.
(2) At some point in time I adopted the rights for www-data (user of the apache folder) by using visudo - see as follows:
Visudo

However, I do not believe that is was really needed.

Hope it helps someone and maybe it might be a start for a binding, 'cause what I personnally believe is, that such a cron-job tool does make openHAB much more flexible.

PS: Could not upload files so here the crontabclass.php:

<?php

class Crontab {

  /*

  (c) Gustav Genberg 2017

  This script uses PHP shell_exec! Make sure it is enabled before using!
  Also make sure that the user running this script (usually www-data) have access to the crontab command!

  Note that this script should be working fine as it is (Apache2)

  Crontab usage:  crontab [-u user] file
                  crontab [ -u user ] [ -i ] { -e | -l | -r }
                          (default operation is replace, per 1003.2)
                  -e      (edit user's crontab)
                  -l      (list user's crontab)
                  -r      (delete user's crontab)
                  -i      (prompt before deleting user's crontab)



  PHP-Crontab usage:  Crontab::[ Read ] [ Set ] [ Add ] [ Remove ] [ Check ]

                      Read      (Returns array of ALL [usually www-data] 's cronjobs)
                      Set       (Takes array with cronjobs and REPLACES the existing cronjobs)
                      Add       (Takes string formatted as a cronjob and adds it)
                      Remove    (Takes string and will remove all cronjobs that matches the provided string [case-sensitive])
                      Check     (Returns boolean based on cronjob existance)

  Examples:

    Crontab::Add('0 0 * * 6 sh /backup/run.sh');

    Crontab::Remove('0 0 * * 6 sh /backup/run.sh');
    // OR
    Crontab::Remove('/backup/run.sh');

    Crontab::Check('/backup/run.sh'); // false

  */

  public static function Read () {

    $Jobs = shell_exec('crontab -l');

    $Jobs = explode("\n", $Jobs);

    array_pop($Jobs);

    return $Jobs;

  }

  public static function Set ($Jobs) {

    $file = fopen('/tmp/php-crontab.tmp', 'w');

    for($i = 0; $i < count($Jobs); $i++) {

      fwrite($file, $Jobs[$i] . "\n");

    }

    fclose($file);

    shell_exec('crontab /tmp/php-crontab.tmp');

    unlink('/tmp/php-crontab.tmp');

  }

  public static function Add ($Job) {

    $Jobs = Crontab::Read();

    if(Crontab::Check($Job)) return;

    array_push($Jobs, $Job);

    Crontab::Set($Jobs);

  }

  public static function Remove ($Job) {

    $Jobs = Crontab::Read();

    $UpdatedJobs = [];

    for($i = 0; $i < count($Jobs); $i++) {

      if(strpos($Jobs[$i], $Job) !== false) continue;

      array_push($UpdatedJobs, $Jobs[$i]);

    }

    Crontab::Set($UpdatedJobs);

  }

  public static function Check ($Job) {

    $Jobs = Crontab::Read();

    for($i = 0; $i < count($Jobs); $i++) {

      if(strpos($Jobs[$i], $Job) !== false) return true;

    }

    return false;

  }

}

?>

3 Likes