Update 5.5 vom 08.11. und Register Variablen

Moin,
Seit dem 5.5 Update vom 08.11. funktioniert mein Abus Secvest Script nicht mehr.
Das Skript setzt eine sehr einfachen Mechanismus zum empfangen von Contact-ID (Notrufmessages) um. Im wesentlichen nimmt es das Datagramm entgegen und schreibt es in eine Variable. Dazu muss eine ACK message berechnet werden (mit CRC16 Prüfsumme).

Details zu meinen Skripten gibt’s übrigens hier: https://www.symcon.de/forum/threads/33746-ABUS-Secvest-2015-%28FUAA50000%29-an-IP-Symcon?highlight=secvest

Komischerweise hat es mit älteren Version der 5.5 noch funktioniert, aber seit gestern läuft es plötzlich nicht mehr richtig.

Hilfe! Irgendjemand eine Idee?
Möglicherweise eine PHP Inkompatibilität in der CRC Berechnung?

Ich bin zur Zeit Ratlos. Ich auch schon eine Weile her, dass ich das geschrieben habe.

<?
// Receiver for Contact-ID Messages
// 
if ($_IPS['SENDER'] != "RegisterVariable")
return false;

$ip = "192.168.178.12"; 	// IP-Adresse der Alarmanlage
$port = 9999;				// Port der Alarmanlage für die Antworten

$data ="";

// $data = RegVar_GetBuffer($_IPS['INSTANCE']);
$data .= $_IPS['VALUE'];

// Ein einfacher Check. Die Strings haben immer die gleiche Länge (53)
if(strlen($data) > 53)
	return false;

// Laenge und CRC der empgangenen Nachricht pruefen
$INcrc = substr($data, 1, 4); echo $INcrc.' ';
$INlen = substr($data, 5, 4); echo $INlen;
$INmessage = substr($data, 18, -22);  // -1 is for the invisible <CR>
$CHECKlen = dechex(strlen($INmessage));
$CHECKlen = str_pad($INlen, 4, '0', STR_PAD_LEFT);
$CHECKcrc = strtoupper(crc16($INmessage));
$CHECKcrc = str_pad($INcrc, 4, '0', STR_PAD_LEFT);
if ($INlen == $CHECKlen AND $INcrc == $CHECKcrc)
	$response = '"ACK"';
else
	$response = '"NAK"';

// Relevanten Teil ausschneiden, der Rest wird ignoriert
// Dieser Wert wird bei korrekt empfangener Nachricht in die Symcon raw Variable geschrieben
$cut = substr ($data, 40, 11);
if ($response =='"ACK"')
	SetValueString(27901, $cut);

// Zusammenbau der Antwort-Message mit Laengen+CRC Berechnung
$message = substr($data, 18, -22);
$messageACK = $response.$message.'[]';
if ($response == '"NAK"')
	$messageACK = substr_replace($messageACK, '0000', 5, 4);   // Die NAK Massage muss mit Sequence Number 0000 gesendet werden
$crc = strtoupper(crc16($messageACK));
$crc = str_pad($crc, 4, '0', STR_PAD_LEFT);
$len = dechex(strlen($messageACK));
$len = str_pad($len, 4, '0', STR_PAD_LEFT);

$output = "
".$crc.$len.$messageACK."\r";
RegVar_SendPacket(42884, $output, $ip, $port); // scheint immer 9999 zu sein, egal was man einstellt!


// -------------------------------------------------------------
// CRC-16_ARC with the following parameter:
// Poly = 0x8005; Init = 0x0000; Xor  = 0x0000
// Refin  = True; Refout = True; Output in Hex

function crc16($data) {
	$crc = 0x0000;      // Init
        $len = strlen($data);
        $i = 0;
        while ($len--) {
            $crc ^= reversebyte(ord($data[$i++])) << 8;
            $crc &= 0xffff;
            for ($j = 0; $j < 8; $j++){
                $crc = ($crc & 0x8000) ? ($crc << 1) ^ 0x8005 : $crc << 1;
                $crc &= 0xffff;
            }
        }
		// $crc ^= 0x0000;   // Final XOR
        $crc = reversebits($crc);
        $crc = dechex($crc);
	    return $crc;
    }

    function reversebyte($byte) {
        $ob = 0;
        $b = (1 << 7);
        for ($i = 0; $i <= 7; $i++) {
            if (($byte & $b) !== 0) {
                $ob |= (1 << $i);
            }
            $b >>= 1;
        }
        return $ob;
    }

    function reversebits($cc) {
        $ob = 0;
        $b = (1 << 15);
        for ($i = 0; $i <= 15; $i++) {
            if (($cc & $b) !== 0) {
                $ob |= (1 << $i);
            }
            $b >>= 1;
        }
        return $ob;
    }

// -------------------------------------------------------------

?>

Hmm, ich weiss ja, dass das Skript unsauber programmiert ist.

Anscheinend hat ein einkommendes Paket das Skript immer ein 2. Mal getriggert und es hat nach dem ACK (an die Secvest) noch mit einem NCK geantwortet, weil das 2. Paket leer war.

Ich stoppe das Skript jetzt immer, wenn den Länge <> 53 ist. Vorher habe ich nur auf Länge > 53 geprüft. (Das ist aber auch nicht wirklich sauber, weil ein fehlerhaftes Paket ja durchaus eine andere Länge haben kann.)

19:07:41.134007 IP secvest.fritz.box.9999 > mini.fritz.box.1793: Flags [.], ack 1, win 4380, length 0
19:07:41.173403 IP secvest.fritz.box.9999 > mini.fritz.box.1793: Flags [P.], seq 1:54, ack 1, win 4380, length 53
19:07:41.173476 IP mini.fritz.box.1793 > secvest.fritz.box.9999: Flags [.], ack 54, win 64187, length 0
19:07:41.176875 IP mini.fritz.box.1793 > secvest.fritz.box.9999: Flags [P.], seq 1:31, ack 54, win 64187, length 30
19:07:41.177157 IP secvest.fritz.box.9999 > mini.fritz.box.1793: Flags [.], ack 31, win 4380, length 0

Kann es sein, dass diese 0 Byte Inhalt Messages das Skript der RegisterVarible in den älteren Symcom-Versionen nicht getriggtert haben???
Ich nehme mal an, dass das TCP ACK Messages sind.

ServerSocket als IO,oder ?
Da gibt das schon länger als ein Jahr, oder zwei, eine Änderung beim Datenempfang:
https://www.symcon.de/service/dokumentation/konzepte/skripte/systemvariablen/#RegisterVariable

Du kommst jetzt den Verbindungsauf und ab-bau im Feld $_IPS[‚TYPE‘].
Wenn die Verbindung getrennt wird, ist $_IPS[‚VALUE‘] dabei immer leer. Und das wird dein Problem sein :slight_smile:

Und noch länger gibt es schon das hier, damit musst du die IP und den (eigentlich dynamischen) Port des Client nicht fest im Script haben…
$_IPS[‚CLIENTIP‘] (nur bei I/O ServerSocket) Empfangene IP-Adresse des Clients
$_IPS[‚CLIENTPORT‘] (nur bei I/O ServerSocket) Empfangsport des Clients

Michael

Danke, Michael,

Ich werde am Anfang des Skripts also noch auf TYPE=data prüfen. Sollte ja dann den gleichen Effekt haben wie 0-Pakete zu ignorieren.

Komisch ist nur, dass es bis zu letzten Update (5.5-92 vom 8.11.) auch immer ohne diese Prüfung funktioniert hat.

Mein Theorie dazu: Das Skript wurde vorher beim Verbindungsabbau nicht getriggert. Ein Bug?

Kann durchaus sein. Am serversocket gab es ja so einige Änderungen.
Michael