PHP-Socketclient für den monitord
Hallo zusammen,
als Eigenbedarf zusammengehackt, vor der Veröffentlichung ein bisschen kommentiert: Eine PHP-Klasse, die den eingetragenen monitord am Socket connectet und fortan dessen Ausgaben nach Typ verarbeiten kann. Die Verarbeitung ist dabei noch offen, der Code hier verbindet nur und kann in den entsprechenden Abschnitten mit Leben gefüllt werden.
Anwendungsfälle:
* automatische Programmstarts
* SMS-/Mail-Versand (mit externer API)
* ...
Vorteile gegenüber dem monitord-internen LUA-Skripting:
* statefulness (heißt, man kann z.B. bei Fünftonfolgen auf Doppelalarmierungen filtern, da nicht bei jedem Telegramm neu verbunden/aufgerufen wird und der Vorgänger nicht bekannt ist)
* in Verbindung mit einem XAMPP oder ähnlichem flexibel einsetzbar einschließlich mySQL
* remote nutzbar
Offene Baustellen:
* Standard-Anwendungsfälle (SMS-Versand, Programmausführung) sind noch nicht implementert (wer mag: bauen und schicken :)!
* Login-Prozedur für den monitord noch nicht implementiert (wäre wichtig für Remote-Nutzung)
* Client-Server-Kommunikation noch nicht implementiert (derzeit nur Annahme von Daten und Verarbeitung, keinerlei Steueraufgaben)
ACHTUNG: Neue Version später im Thread!
Code der Klasse:
Code:
<?php
/**
* @brief minimalistic monitord PHP client - connects via socket and can react on ZVEI, FMS, POCSAG telegrams
* @author mdiedrich/Martin Diedrich 03/2012
*/
class monitord_php_client {
/**
* @brief constructor including main() loop
*/
function monitord_php_client($host='localhost', $port='9333') {
$this->host = $host;
$this->port = $port;
$this->socket = null;
$this->sock_retrycount = 0;
$this->sock_errcount = 0;
$this->errorcode = 0;
$this->sleeptime = 10;
while($this->monitord_socket_error_handler() === true) {
}
}
/**
* @brief parses input data from socket, mainly calling function depending on type
* @param $in data read from socket
*/
function monitord_socket_parse($in) {
if($in != "") {
$monitord_line = explode(':', $in);
switch($monitord_line['0']) {
case '300' : $this->monitord_work_zvei($monitord_line);break;
case '310' : $this->monitord_work_fms($monitord_line);break;
case '320' : $this->monitord_work_pocsag($monitord_line);break;
default : $this->monitord_work_unknown($monitord_line);
}
return true;
} else {
return false;
}
}
/**
* @brief main part, connecting and reading from socket calling parser method
* @return bool true normally, false on critical failure
*/
function monitord_socket_error_handler() {
if($this->socket === null) {
$socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
$this->errorcode = socket_last_error($socket);
echo 'ERR_ABORT: ' . $this->errorcode;
return false;
} else {
echo "INFO: Socket created.\n";
$this->socket = $socket;
}
}
$out = @socket_read($this->socket, 255, PHP_BINARY_READ);
$this->errorcode = socket_last_error($this->socket);
// echo "DEBUG: errorcode was $this->errorcode -- out was ";
// var_dump($out);
if( ($this->sock_retrycount < 10) && ($this->errorcode == 10054 || $this->errorcode == 10057) ) {
if($this->errorcode == 10054) {
socket_shutdown($this->socket);
socket_close($this->socket);
$this->socket = null;
return true;
}
socket_clear_error($this->socket);
$address = gethostbyname($this->host);
echo "INFO: Trying to connect $address ...\n";
$result = @socket_connect($this->socket, $address, $this->port);
if ($result == false) {
echo 'WARN: Socket could not be connected. Retrying in ' . ($this->sleeptime * ($this->sock_retrycount+1)) . 's (';
echo $this->sock_retrycount+1 . "/10).\n";
$this->sock_retrycount++;
sleep($this->sleeptime * ($this->sock_retrycount+1));
return true;
} else {
echo "INFO: Socket connected.\n";
$this->sock_retrycount = 0;
return true;
}
}
if($this->sock_retrycount == 30) {
echo "ERR_ABORT: Socket retrycount (30) exceeded, exiting.";
return false;
}
$this->monitord_socket_parse($out);
return true;
}
/**
* @brief handling FMS data
* @param $monitord_line (310:{Zeit}:Kanalnummer:FMSKennung:Status:Baustufe:Richtung:TKI:FMSText)
*/
function monitord_work_fms($monitord_line) {
echo "INFO: FMS received [".$monitord_line["2"].":".$monitord_line["3"].":".$monitord_line["6"].":".$monitord_line["4"]."]\n";
}
/**
* @brief handling ZVEI data
* @param $monitord_line (300:Zeit:Kanalnummer(char):Schleife(text5):Sirenenalarmierung(char):Text)
*/
function monitord_work_zvei($monitord_line) {
echo "INFO: ZVEI received [".$monitord_line["2"].":".$monitord_line["3"]."]\n";
}
/**
* @brief handling POCSAG data
*/
function monitord_work_pocsag($monitord_line) {
echo "INFO: POCSAG received\n";
}
/**
* @brief handling data of unknown type
*/
function monitord_work_unknown($monitord_line) {
echo "INFO: UNKNOWN received, dumping:\n";
var_dump($monitord_line);
echo "\n";
}
}
?>
Instanziierung:
Code:
<?php
require_once('./monitord_php_client.class.php');
echo "\nmonitord PHP Client v0.1 started\n\n";
$mpc = new monitord_php_client();
?>
Any comments :)?
Viele Grüße
Martin