Hallo Daniel,
das Problem war (nicht zum erstenmal) die erste Zeile mit dem Status ("100;...") - die ;-Abrennung eines menschenlesbaren Kommentars war noch nicht sinnvoll drin. Außerdem hatte ich keine zeilenweise Behandlung der Socket-Rückgaben eingebaut.
Ist jetzt drin, Tests und Ergebnisse gerne gesehen, müsste mit Deiner Klasse tun nun :).
Viele Grüße
Martin
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 08/2013
*/
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 split and work through single lines if socket_read contained more then one line
* @param $in data read from socket
*/
function monitord_socket_parse($in) {
$monitord_lines_array = explode(PHP_EOL, $in);
foreach($monitord_lines_array as $out) {
$this->monitord_socket_parse_line($out);
}
}
/**
* @brief parses input data from socket, mainly calling function depending on type
* @param $in single line to be handled
*/
function monitord_socket_parse_line($in) {
if($in != "") {
// cut off human readable information (delimited by ';') first
// make it usable in array field named 'human_readable' later
$position = strpos($in, ';');
$human_readable = '';
if($position !== false) {
$human_readable = substr($in, $position+1);
$in = substr($in, 0, $position);
}
// NEXT LINE FOR DEBUGGING ONLY
// echo "\nIN AND HR: " . $in . ' - ' . $human_readable . "\n\n";
// explode machine readable data on ':' and add human readable
$monitord_line = explode(':', $in);
$monitord_line['human_readable'] = $human_readable;
// switch by monitord protocol code
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, 1024, 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.2 started\n\n";
$mpc = new monitord_php_client();
?>
Angepasster Code (abgeleitete Klasse von Daniel):
Code:
class test_monitord_php_client extends monitord_php_client{
function __construct($host='localhost', $port='9333') {
$this->debug = true;
parent::__construct($host, $port);
}
function monitord_work_unknown($monitord_line) {
/*
* dump all content for debugging process
*/
echo "INFO: UNKNOWN received, dumping:\n";
var_dump($monitord_line);
echo "\n";
/**
* Prüfung ob OK empfangen wurde
*/
if($monitord_line['0'] == '100') {
sleep(2);
$cmd = "210\r\n";
$write = socket_write($this->socket, $cmd, strlen($cmd));
echo "Es wurden " . $write . " Bytes geschrieben";
echo "\n";
$errorcode = socket_last_error($this->socket);
if($errorcode != 0 && $this->debug){
echo "DEBUG: errorcode was $this->errorcode ( " . socket_strerror($errorcode) . " )-- out was ";
var_dump($out);
}
}
}
}