283 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
//Constants
 | 
						|
define( "EOL", "\n");
 | 
						|
define("Z2M", "zigbee2mqtt");
 | 
						|
 | 
						|
// log levels
 | 
						|
/*define( "DEBUG", 0);
 | 
						|
define( "INFO", 1);
 | 
						|
define( "WARNING", 3);
 | 
						|
define( "ERROR", 4);*/
 | 
						|
$logLevel = LOG_DEBUG;
 | 
						|
 | 
						|
 | 
						|
declare(ticks = 1);
 | 
						|
 | 
						|
$listProperties = array("powerSource" => "batterie");
 | 
						|
$listPropertiesKeys = array("property");
 | 
						|
 | 
						|
class Message
 | 
						|
{
 | 
						|
	public $id;
 | 
						|
	public $state = false;
 | 
						|
	public $msg;
 | 
						|
}
 | 
						|
 | 
						|
class topic {
 | 
						|
	public $mid;
 | 
						|
	public $status;
 | 
						|
	public $info;
 | 
						|
	public $devices;
 | 
						|
	public $groups;
 | 
						|
	public $extensions;
 | 
						|
	public $config;
 | 
						|
}
 | 
						|
 | 
						|
class device
 | 
						|
{
 | 
						|
	public $method;    //auto or manual
 | 
						|
	public $topic;
 | 
						|
	public $device;
 | 
						|
	public $ieeeAddress;
 | 
						|
	public $groupID;
 | 
						|
	public $friendlyName;
 | 
						|
	public $type;					// if true then not a device but parameter of device(eg. topic/FRIENDLYNAME/PARAMETER
 | 
						|
	public $powerSource;
 | 
						|
	public $description;
 | 
						|
	public $functions;
 | 
						|
	public $payload;
 | 
						|
 | 
						|
	public function set($event)
 | 
						|
	{
 | 
						|
		publish($this, $this->payload, "set", $event);
 | 
						|
	}
 | 
						|
 | 
						|
	public function get()
 | 
						|
	{
 | 
						|
		publish($this, $this->payload, "get", $event);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
class ranges
 | 
						|
{
 | 
						|
	public $start;			//datetime
 | 
						|
	public $end;			//datetime
 | 
						|
}
 | 
						|
 | 
						|
class event
 | 
						|
{
 | 
						|
	public $ieeeAddress;
 | 
						|
	public $topic;
 | 
						|
	public $param;
 | 
						|
	public $value;
 | 
						|
	public $device;
 | 
						|
	public $published;
 | 
						|
	public $dateTimeEvent;			// datetime : next occurence for recurrent event
 | 
						|
	public $startDatetime;
 | 
						|
	public $stopDatetime;
 | 
						|
	public $recurrenceInterval;		// interval : for recurrent event
 | 
						|
	public $exceptionInterval;		// array of object ranges
 | 
						|
}
 | 
						|
 | 
						|
class interval
 | 
						|
{
 | 
						|
	public $startDate;
 | 
						|
	public $endDate;
 | 
						|
}
 | 
						|
 | 
						|
class notificationMethod
 | 
						|
{
 | 
						|
	public $url;
 | 
						|
	public $msg;
 | 
						|
 | 
						|
	function __construct($url)
 | 
						|
	{
 | 
						|
		$this->url = $url;
 | 
						|
	}
 | 
						|
 | 
						|
	public function send($text=null)
 | 
						|
	{
 | 
						|
		if (empty($text)) $text= $this->msg;
 | 
						|
		if (!empty($msg))
 | 
						|
		{
 | 
						|
			$opts = array(
 | 
						|
				'http'=>array(
 | 
						|
					'method'=>"GET",
 | 
						|
					'header'=>"Accept-language: fr\r\n"
 | 
						|
				)
 | 
						|
			);
 | 
						|
			$context = stream_context_create($opts);
 | 
						|
 | 
						|
			/* Envoi une requête HTTP vers $url
 | 
						|
			avec les en-têtes additionnels ci-dessus */
 | 
						|
			$fp = fopen($url . "/" . $msg, 'r', false, $context);
 | 
						|
			$response = stream_get_contents($fp, -1, 0);
 | 
						|
			fclose($fp);
 | 
						|
		}else
 | 
						|
		{
 | 
						|
			// TODO log_error("notificationMethod : $msg is null");
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//global variables
 | 
						|
$topics = array();				// list of topics
 | 
						|
$mids = array();				// list of message IDs
 | 
						|
$devices = array();				// array of device objetcs
 | 
						|
$indexDevices = array();		// index devices by ieee_address
 | 
						|
$hooks = array();				// array of hooks
 | 
						|
$notificationMethods = array();	// array of notification methods objects
 | 
						|
$events = array();				// list of event objects
 | 
						|
$changed = array();				// list of changed devices
 | 
						|
$dbInit = false;				// flag to indicate that desvices db is initialized
 | 
						|
$connected = false;				// connected to MQTT server
 | 
						|
$nSubscribed = 0;				// Number of topics subsribed
 | 
						|
$included = false;				// flag indicate scripts are loaded
 | 
						|
$logFh = null;					// filehandle of log file
 | 
						|
 | 
						|
// topics definition
 | 
						|
$topics["zigbee2mqtt"] = new topic;
 | 
						|
 | 
						|
// gettext
 | 
						|
bindtextdomain("moha", "./locale");
 | 
						|
textdomain("moha");
 | 
						|
 | 
						|
if (!init()) exit(1);
 | 
						|
 | 
						|
require "mqtt_functions.php";
 | 
						|
require "utils.php";
 | 
						|
require "events.php";
 | 
						|
require "db_functions.php";
 | 
						|
 | 
						|
$client = new Mosquitto\Client();
 | 
						|
$client->onConnect('connectResponse');
 | 
						|
$client->onDisconnect('disconnectResponse');
 | 
						|
$client->onSubscribe('subscribeResponse');
 | 
						|
$client->onUnsubscribe('unsubscribeResponse');
 | 
						|
 | 
						|
$client->onMessage('message');
 | 
						|
$client->onLog('logger');
 | 
						|
$client->onPublish('publishResponse');
 | 
						|
 | 
						|
 | 
						|
//signal handling
 | 
						|
pcntl_signal(SIGTERM, 'signalHandler');// Termination ('kill' was called)
 | 
						|
pcntl_signal(SIGHUP, 'signalHandler'); // Terminal log-out
 | 
						|
pcntl_signal(SIGINT, 'signalHandler');
 | 
						|
 | 
						|
// Program start
 | 
						|
 | 
						|
 | 
						|
$client->connect("192.168.1.253", 1883, 5);
 | 
						|
foreach($topics as $name => $topic)
 | 
						|
{
 | 
						|
	//echo $name;
 | 
						|
	$topic->mid = $client->subscribe($name . "/#", 2);
 | 
						|
	$mids[$topic->mid] = $name;
 | 
						|
	$topic->status = false;
 | 
						|
}
 | 
						|
 | 
						|
while (true)
 | 
						|
{
 | 
						|
	$client->loop();
 | 
						|
	if ($dbInit == 2 and ! $included)
 | 
						|
	{
 | 
						|
		$hooksList = array();
 | 
						|
		loadHooks("./hooks", $hooksList);
 | 
						|
		//print_r($hooksList);
 | 
						|
		if (!empty($hooksList))
 | 
						|
		{
 | 
						|
			foreach ($hooksList as $hook)
 | 
						|
			{
 | 
						|
				echo "Including $hook" . EOL;
 | 
						|
				include $hook;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}elseif($dbInit == 2 and $included)
 | 
						|
	{
 | 
						|
		checkEvents();
 | 
						|
		if (empty($flag))
 | 
						|
		{
 | 
						|
			$flag = true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
endMoha();
 | 
						|
 | 
						|
function init()
 | 
						|
{
 | 
						|
	global $logFh, $client;
 | 
						|
	date_default_timezone_set('Europe/Paris');
 | 
						|
 | 
						|
	if (! $logFh = fopen("moha.log", "w") )
 | 
						|
	{
 | 
						|
		echo _("error opening log file");
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
function loadHooks($dir, &$hookList)
 | 
						|
{
 | 
						|
	global $included;
 | 
						|
	$files = scandir($dir);
 | 
						|
	//print_r($files);
 | 
						|
	foreach ($files as $file)
 | 
						|
	{
 | 
						|
		//echo "=====> $file" . EOL;
 | 
						|
 | 
						|
		if ($file != "." and $file != "..")
 | 
						|
		{
 | 
						|
			//echo "not . or .." . EOL;echo strpos($file, ".php", -4) . EOL;
 | 
						|
			if (is_dir($dir . "/" . $file))
 | 
						|
			{
 | 
						|
				//echo "directory : " . $dir . '/' . $file . EOL;
 | 
						|
				loadHooks($dir . '/' . $file, $hookList);
 | 
						|
			}elseif (strpos($file, ".php", -4) !== false)
 | 
						|
			{
 | 
						|
				//echo "file : " . $dir . "/" . $file . EOL;
 | 
						|
				$hookList[] = $dir . "/" . $file;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	//print_r($hookList);
 | 
						|
	$included = true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
function endMoha()
 | 
						|
{
 | 
						|
	global $topics, $nSubscribed ,$client, $logFh, $connected;
 | 
						|
	$x = 0;
 | 
						|
	/*foreach($topics as $topic => $object)
 | 
						|
	{
 | 
						|
		if ($object->status)
 | 
						|
		{*/
 | 
						|
			$mid = $client->unsubscribe("#");
 | 
						|
			/*$mids[$mid] = $topic;
 | 
						|
		}
 | 
						|
	}*/
 | 
						|
 | 
						|
	while ($connected)
 | 
						|
	{
 | 
						|
		//echo $nSubscribed;0x00124b0022ebac5c
 | 
						|
		if ( $x++ > 60)
 | 
						|
		{
 | 
						|
			$client->disconnect();
 | 
						|
			fclose($logFh);
 | 
						|
			exit (1);
 | 
						|
		}
 | 
						|
		$client->loop();
 | 
						|
	}
 | 
						|
	fclose($logFh);
 | 
						|
	exit(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
?>
 |