Domoticz: PHP event handling

It is possible to let PHP handle Domoticz events. Place the lua script script_device_php.lua in the lua folder of your Domoticz scripts folder. All scripts with a name that start with script_device_*.lua are executed upon every device update.

# script_device_php.lua
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
 
devicechanged = json:encode(devicechanged)
deviceslastupdate = json:encode(otherdevices_lastupdate)
 
command = string.format("php /home/pi/php/test.php '%s' '%s' &", devicechanged, deviceslastupdate)
os.execute(command)
-- Use print to write to domoticz log
-- print(command)
 
commandArray = {}
return commandArray

Install php.

sudo vi /etc/apt/sources.list.d/10-buster.list
 
# Add this line
deb http://mirrordirector.raspbian.org/raspbian/ buster main contrib non-free rpi
 
sudo vi /etc/apt/preferences.d/10-buster
# And paste in the follwing
Package: *
Pin: release n=stretch
Pin-Priority: 900
 
Package: *
Pin: release n=buster
Pin-Priority: 750
 
sudo apt-get update
 
# To install common PHP packages
sudo apt-get install -t buster php7.2 php7.2-curl php7.2-gd php7.2-fpm php7.2-cli php7.2-opcache php7.2-mbstring php7.2-xml php7.2-zip
 
# Install minimum required
sudo apt-get install -t buster php7.2-cli  php7.2-curl
 
# When you get this error:
# libc6-dev : Breaks: binutils (< 2.26) but 2.25-5+deb8u1 is to be installed
sudo apt-get remove binutils
sudo apt-get install -t buster php7.2-cli
 
# Check PHP install
php -v

The script that I use to handle motion detection in the entrence to switch a light on and off:

<?php
date_default_timezone_set('Europe/Amsterdam');
 
$domoticz = new Domoticz($argv);
$domoticz->process();
 
/**
 * Get an item from an array using "dot" notation.
 *
 * @param  array   $array
 * @param  string  $key
 * @param  mixed   $default
 * @return mixed
 */
function array_get($array, $key, $default = null)
{
    if (is_null($key)) return $array;
    if (isset($array[$key])) return $array[$key];
    foreach (explode('.', $key) as $segment)
    {
        if ( ! is_array($array) || ! array_key_exists($segment, $array))
        {
            return value($default);
        }
        $array = $array[$segment];
    }
    return $array;
}
 
class Domoticz
{
	const MOTION_ENTRENCE = 'Motion entrence';
	const ENTRENCE_LUX = 'Lux entrence';
	const DEVICE_STATUS_ON = 'On';
	const DEVICE_STATUS_OFF = 'Off';
	const ENTRENCE_LIGHT = 'Entrence';
	const DEVICE_ID_ENTRENCE = '21';
	const MINIMUM_LUX_LEVEL = 25;
 
	protected $deviceschanged;
	protected $deviceslastupdate;
	protected $otherDevices;
 
	public function __construct($param)
	{
		if (isset($param) && count($param) > 2) {
			$this->deviceschanged = json_decode($param[1], true);
			$this->deviceslastupdate = json_decode($param[2], true);
			$this->otherDevices = json_decode($param[3], true);
		}
 
		$this->url = '192.168.0.1:8080' . '/json.htm';
        $this->username = 'username';
        $this->password = 'password';
	}
 
	private function getActiveDevices()
	{
		$activeDevices[self::MOTION_ENTRENCE] = true;
 
		return $activeDevices;
 
		$now = time();
		foreach ($this->deviceslastupdate as $key => $value) {
			error_log(date("Y-m-d H:i:s") . " Key $key" . PHP_EOL, 3, "/tmp/my-errors.log");
			if ($key == self::MOTION_ENTRENCE) {
				$lastUpdate = strtotime($value);
				if (($now - $lastUpdate) > 9) {
					error_log(date("Y-m-d H:i:s") . " Now $now" . PHP_EOL, 3, "/tmp/my-errors.log");
					error_log(date("Y-m-d H:i:s") . " lastUpdate $lastUpdate" . PHP_EOL, 3, "/tmp/my-errors.log");
					$activeDevices[self::MOTION_ENTRENCE] = false; 		
				}		
			}
		}
		return $activeDevices;
	}
 
	public function process()
	{
		foreach ($this->deviceschanged as $key => $value) {
			if ($key == self::MOTION_ENTRENCE) {
				$this->processMotionEntrence($value);		
			}
		}
	}
 
	private function processMotionEntrence($status)
	{
		$activeDevices = $this->getActiveDevices();
		if ($activeDevices[self::MOTION_ENTRENCE]) {
			if ($status == self::DEVICE_STATUS_ON && 
				array_get($this->otherDevices, self::ENTRENCE_LIGHT, '') == self::DEVICE_STATUS_OFF &&
				array_get($this->otherDevices, self::ENTRENCE_LUX, 0) <= self::MINIMUM_LUX_LEVEL)
			{
				$this->switchLight(self::DEVICE_STATUS_ON);
			} elseif ($status == self::DEVICE_STATUS_OFF && 
				array_get($this->otherDevices, self::ENTRENCE_LIGHT, '') == self::DEVICE_STATUS_ON)
			{
				$this->switchLight(self::DEVICE_STATUS_OFF);
			}
		}
	}
 
	private function switchLight($status)
    {
        $param = [
            'type' => 'command',
            'param' => 'switchlight',
            'idx' => self::DEVICE_ID_ENTRENCE,
            'switchcmd' => $status,
            'level' => '0'
        ];
 
        $this->execute($param);
    }
 
	private function execute($param)
    {
        if (!empty($param)) {
            $query = [];
            foreach ($param as $key => $value) {
                $query[] = $key . '=' . rawurlencode($value);
            }
            $this->url .= '?' . implode('&', $query);
        }
 
        $connection = curl_init($this->url);
        curl_setopt($connection, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($connection, CURLOPT_USERPWD, $this->username . ':' . $this->password);
        $data = curl_exec($connection);
        $info = curl_getinfo($connection);
        if ($info['http_code'] === 200 && json_decode($data)) {
            $this->data = json_decode($data);
            return true;
        }
        return false;
    }
}