Anbindung Mediola AIO Remote und AIO Gateway zur Steuerung von IR Geräten

Mit Hilfe des AIO Gateways sind Geräte bedienbar, die sonst über IR-Fernbedienungen oder mit Funk 433/868 MHz steuerbar sind. Das AIO Gateway unterstützt auch die Steuerung von FS20 Komponenten.
Die AIO Remote ist die Steuerungssoftware die für verschiedene Softwareplattformen verfügbar ist unter anderm auch für iOS.

Die Kommunikation der AIO Remote erfolgt mit IPS über XML. Das AIO Gateway erhält die Befehle per http.

Mit Hilfe der Skripte und ein bischen Basteln ist eine Anbindung der AIO Remote und des AIO Gateways an IPS möglich.

Zur Anbindung der AIO Remote werden im AIO Creator ein mControl 1.0 Server als Gateway angelegt. Die ausgesuchte Portnummer des Servers ist zu notieren.
Anschließend können Geräte mit dem Gateway mControl im AIO Creator angelegt werden. Hier ist die Bezeichnung sowie der Bereich und Gerät zu notieren.

In IPS wird nun zunächst ein Serversocket eingerichtet mit der Portnummer die im AIO Creator vergeben worden ist. Anschließend legt man eine Registervariable an, die man mit dem Server Socket verknüpft. Die Registervariable startet folgendes Zielskript:



	// neu empfangene Daten an $data übergeben
	$data = $IPS_VALUE;

  // Inhalt von $data im Puffer der RegisterVariable-Instanz speichern
  RegVar_SetBuffer($IPS_INSTANCE, $data);
  IPS_LogMessage( "Empfangen von AIO Remote" , $data );

//Anfang vor XML abschneiden
$ONLY_XML= substr($data, strpos ($data,'<'),strlen($data) - strpos ($data,'<'));
$xml = simplexml_load_string($ONLY_XML,'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
$kind = $xml->request->attributes()->name;
		
// Auf Befehl oder Statusabfrage prüfen
// Wenn ExecuteCommand dann Befehl ausführen

if ($kind == "ExecuteCommand")
	{
	// Gerät auslesen
	// Value auslesen
	$valuerow = $xml->request->param->attributes()->value;
	$value = (string) $valuerow;
	
	SetValue(47585 /*[Server Socket AIO Remote\XML_Get\Commandvalue]*/, $value); /* Setzt den Status */
	$value = GetValue(47585 /*[Server Socket AIO Remote\XML_Get\Commandvalue]*/); // Value des Geräts auslesen
	IPS_LogMessage( "Value:" , $value );
	if ($value == 'Gruppe.Geraetename.Befehl')
		{
     
		$status = GetValue(47786 /*[Mittelgeschoss\Bad\Status]*/); // Status des Geräts auslesen
	   
	   if ($status == "off")// Befehl ausführen
			{
         IPS_LogMessage( "Befehl ausführen:" , "Anschalten" );
			IPS_RunScript(25449 /*[Mittelgeschoss\Bad\Beleuchtung an]*/);
			}
		elseif ($status == "on")// Befehl ausführen
			{
         IPS_LogMessage( "Befehl ausführen:" , "Ausschalten" );
			IPS_RunScript(49886 /*[Mittelgeschoss\Bad\Beleuchtung aus]*/);
			}
			// Warte 0,5 Sekunden
			usleep(500000);

			$status = GetValue(47786 /*[Mittelgeschoss\Bad\Status]*/); // Status des Geräts auslesen
			IPS_LogMessage( "Status:" , $status );
		}
   elseif ($value == 'Wohnzimmer.Lampe.toggle')
		{
      
		$status = GetValue(24890 /*[Erdgeschoss\Wohnzimmer\Steckdosen\Stehlampe\Status]*/); // Status des Geräts auslesen
	   IPS_LogMessage( "Wohnzimmerlampe erkannt:" , "Richtig" );
	   if ($status == "off")// Befehl ausführen
			{
         IPS_LogMessage( "Befehl ausführen:" , "Anschalten" );
			IPS_RunScript(49661 /*[Erdgeschoss\Wohnzimmer\Steckdosen\Stehlampe\Stehlampe an]*/);
			}
		elseif ($status == "on")// Befehl ausführen
			{
         IPS_LogMessage( "Befehl ausführen:" , "Ausschalten" );
			IPS_RunScript(58174 /*[Erdgeschoss\Wohnzimmer\Steckdosen\Stehlampe\Stehlampe aus]*/);
			}
			// Warte 0,5 Sekunden
			usleep(500000);

			$status = GetValue(24890 /*[Erdgeschoss\Wohnzimmer\Steckdosen\Stehlampe\Status]*/); // Status des Geräts auslesen
			IPS_LogMessage( "Status:" , $status );
		}
		// Hier sind die Geräte zu ergänzen die im AIO Creator angelegt worden sind
		
   	elseif ($value == 'Gruppe.Geraetename.Befehl')
			{
			echo "hier wird dann der Befehl ausgelöst 
";

			}

  	// Rückmeldung des Gerätestatus
	include '35452.ips.php'; //aiocommandresponse.xml

   $xmlhead1 = "XML
";

	// Generiert XML Response
	$len = strlen($xmlstr); // Länge des XML
	$xmlhead2 = str_pad($len, 8, "0", STR_PAD_LEFT)."
";  // gibt die Länge als 8 stellige Zahl mit führenden Nullen aus

	$response = $xmlhead1.$xmlhead2.$xmlstr;
	//Response versenden
	include '33645.ips.php'; //sendresponse.xml
	IPS_LogMessage( "Response auf Command:" , $response );


	}
   

// Wenn Statusabfrage
// Wenn GetStates dann Statusabfrage zurücksenden

if ($kind == "GetStates")
	{
	
	include '43079.ips.php'; //aiostatusresponse.xml
	$count = $xml->request->param->count(); //Anzahl der Param Childs im Request
	
	$xmlreq = new SimpleXMLElement($xmlresponse);
	for ($i = 0; $i <= $count-1; $i++)
		 	{
		 	$regxmlname = $xml->request->param[$i]->attributes()->name; // liest Gerätenamen aus
		 	// print utf8_decode($xml->request->param[$i]->attributes()->name)."
<br>"; // Gerätename
			$xmlreturn = $xmlreq->response->addChild('return');
	      $xmlreturn->addAttribute('name', $regxmlname); // Legt neues Child und Attribut mit Gerätenamen an
			if ($regxmlname == "Steckdosen.Bad")
			{
			$status = GetValue(47786 /*[Mittelgeschoss\Bad\Status]*/); // Status des Geräts auslesen
			$xmlreturn->addAttribute('value', $status);
			}
         elseif ($regxmlname == "Garten.Terasse")
			{
         $status = GetValue(56062 /*[Garten\Terassenbeleuchtung\Terassenbeleuchtung\Status]*/); // Status des Geräts auslesen
			$xmlreturn->addAttribute('value', $status);
			}
			// Hier sind die Geräte zu Ergänzen die im AIO Creator angelegt worden sind
			
      }

	$xmlhead1 = "XML
";
	$xmllen = $xmlreq->asXML();

	// Generiert XML Response
	$len = strlen($xmllen); // Länge des XML
	$xmlhead2 = str_pad($len, 8, "0", STR_PAD_LEFT)."
";  // gibt die Länge als 8 stellige Zahl mit führenden Nullen aus

	$response = $xmlhead1.$xmlhead2.$xmllen;

	// SetValue(34546 /*[Server Socket AIO Remote\XML_Get\XML_Daten]*/, $data); /* Setzt den Status */
	include '33645.ips.php'; //sendresponse.xml
	IPS_LogMessage( "Response auf Request:" , $response );
	}





Das Zielskript nimmt das gesendete XML der AIO Remote entgegen und generiert den passenden XML Response.
Im Skript sind weitere Skripts eingebunden die aufgerufen werden.

aiocommandresponse:


$xmlstr = <<<XML
<?xml version="1.0"?>
<mctrlmessage>
<response>
<return name="status" value="success" />
</response>
</mctrlmessage>
XML;

Ist immer gleich und wird auf ein Command als Response an die AIO remote zurückgesendet.

aiostatusresponse:


// Beachte keine Umlaute im Creator verwenden
$xmlresponse = <<<XML
<?xml version="1.0"?>
<mctrlmessage>
<response>
</response>
</mctrlmessage>
XML;


Enthält das XML Grundgerüst das dann durch das Skript ergänzt wird.

sendresponse:


<?
$serversocket = 16770 /*[Server Socket AIO Remote]*/;
SSCK_SendText($serversocket, $response);

SSCK_SetOpen($serversocket,false); // Port schließen
IPS_ApplyChanges($serversocket);
SSCK_SetOpen($serversocket,true); // Port öffnen
IPS_ApplyChanges($serversocket);

?>

Sendet den Response und schließt kurz den Serversocket damit die Kommunikation z.B. mit dem Ipad funktioniert.

Die Befehle an das AIO Gateway werden per http gesendet. Eine komplette Beschreibung wie die Befehle an das Gateway zu übergeben sind findet man hier:

Ein Befehl sind dann so aus:


$FS20_Code = GetValue(11287 /*[Mediola\IP_AIO_Gateway]*/).GetValue(27093 /*[Mediola\FS20\FS20_sendstring]*/).GetValue(48558 /*[Garten\Quellstein\Hexcode Beleuchtung]*/).GetValue(22886 /*[Mediola\FS20\FS20_ein]*/);

file_get_contents("http://$FS20_Code");
$status = "on";
SetValue(29231 /*[Garten\Quellstein\Status Beleuchtung]*/, $status); /* Setzt den Status */

Es wird jeweils eine Variable für das Gerät benötigt um den Status des Geräts zu speichern.

Der Code zum Senden an ein FS20 Gerät kann wie folgt berechnet werden:


<?

$HC1 = "3421"; //HC1 Wert aus dem AIO Creator
$HC2 = "2143"; //HC2 Wert aus dem AIO Creator
$FS20_Adr = "1114"; // Adresse aus dem AIO Creator
$FS20_Code = $HC1.$HC2.$FS20_Adr;
$FS20_an = "1000";
$FS20_aus = "0000";

/*
0000 - Ausschalten
0100 - Auf 6,25% dimmen
0200 - Auf 12,50% dimmen (im Creator ~10%)
0300 - Auf 18,75% dimmen (im Creator ~20%)
0400 - Auf 25,00% dimmen
0500 - Auf 31,25% dimmen (im Creator ~30%)
0600 - Auf 37,50% dimmen (im Creator ~40%)
0700 - Auf 43,75% dimmen
0800 - Auf 50,00% dimmen (im Creator ~50%)
0900 - Auf 59,25% dimmen (im Creator ~60%)
0A00 - Auf 62,50% dimmen
0B00 - Auf 68,75% dimmen (im Creator ~70%)
0C00 - Auf 75,00% dimmen
0D00 - Auf 81,25% dimmen (im Creator ~80%)
0E00 - Auf 87,50% dimmen (im Creator ~90%)
0F00 - Auf 93,75% dimmen
1000 - Einschalten
1100 - Auf den letzten, gespeicherten Wert einschalten
1200 - Ein <-> Ausschalten (Toggle)
1300 - Hochdimmen
1400 - Runterdimmen
*/

echo "HC1 ist $HC1 
";
echo "HC2 ist $HC2 
";
echo "FS20 Adresse ist $FS20_Adr 
";
echo "FS20 Code ist $FS20_Code 
";


$arr1 = str_split($FS20_Code);

/* Stelle um 1 reduzieren */
for ($i = 0; $i <= 11; $i++)
	{
      $arr1[$i] = $arr1[$i] -1;
   }

/* Aufteilung in Zweierblöcke */
/* Die jeweils erste Zahl eines Blocks wird mit 4 multipliziert und mit der zweiten Zahl addiert */
for ($i = 0; $i <= 10; $i=$i+2)
	{
      $arr2[$i] = $arr1[$i] * 4 + $arr1[$i+1];
   }

/* Jeder Block wird nun in seine Hexadezimaldarstellung überführt (0-9, A-F) */
for ($i = 0; $i <= 10; $i=$i+2)
	{
      $arr2[$i] = dechex($arr2[$i]);
   }

$FS20_send = $arr2[0].$arr2[2].$arr2[4].$arr2[6].$arr2[8].$arr2[10];
print "Der berechnete Code lautet $FS20_send 
";

$aio_send = "http://192.168.55.116/command?XC_FNC=SendSC&type=FS20&data=".$FS20_send.$FS20_an;
print "Zum Einschalten ist an das A.I.O. Gateway  $aio_send zu senden.
";
$aio_send = "http://192.168.55.116/command?XC_FNC=SendSC&type=FS20&data=".$FS20_send.$FS20_aus;
print "Zum Ausschalten ist an das A.I.O. Gateway  $aio_send zu senden.
";

?>

Viel Erfolg beim Ausprobieren allen die AIO Remote und ein AIO Gateway besitzten.

Fonzo

Hallo,

ich teste gerade die Scipts von Fonzo.

So halbwegs funktioniert das Ganze bei mir auch aber:

  1. Am IPAD habe ich nach dem Ausführen eines Befehls dauernd das „laden“ Symbol links oben (sieht so aus als ob es eine Antwort erwartet.

  2. Das sendresponse Script wird als fehlerhaft gekenntzeichnet; geändert habe ich $serversocket und die dazugehörigen Ports

Die Visualisierung sieht es toll aus.
Ich hoffe Ihr könnt mir weiterhelfen, meine Testversion läuft nur mehr 15 Tage und bevor nicht alles klappt möchte ich mir die Software nicht kaufen.

Danke

Jörg

Hier noch ein Bild des ServerSocket:

Sorry ich habe hier länger nicht reingeschaut wenn Du das genaue Fehlerprotokoll postet kann ich vielleicht bei der Fehlersuche helfen.

Hallo,

hat sich erledigt. Ich arbeite im Moment bei aioremote ohne IPS.

Jörg

Danke für deine Arbeit, funktioniert super, leider hab ich noch ein kleines Problem.

Wenn ich mit dem I Phone im Mediola App von einer Seite mit Staturückmeldungen auf eine andere Seite mit Statusrückmeldung wechsle, stürzt das App ab. Im Log von IP-Symcon bekomme ich dann das angezeigt:

Also 2 mal hintereinander Client verbunden…

Mit aio remote auf dem PC tritt der Fehler nicht auf.

Hast du zufällig eine Idee?

lg Chris

Aus dem Log kann ich zunächst nichts Auffälliges erkennen. Kannst Du eventuell mal den Code der xml der Remoteseite posten, von der Du die Befehle absendest.

Welche aio Creator Version benutzt Du denn zur Zeit?

Hier der XML Code der Seite

Die Creator Version ist 1.512

Danke für deine Hilfe :wink:

Ich schau mal drüber ob ich etwas finde.

Im Übrigen hat Mediola heute ein a.i.o. Creator Funktionsmodul für IP-Symcon veröffentlicht, mit dem man den Creator um eine Anbindung an IP-Symcon erweitern kann.

Der oben beschriebene, wenn auch sehr umständliche Weg geht nach wie vor. Wesentlich einfacher und komfortabler geht es nun mit dem neuen a.i.o. Creator Funktionsmodul für IP-Symcon.

Der a.i.o. Creator kann alle existierenden Module in IP-Symcon auslesen und diesen im Creator ein Gerät zuordnen. Der Creator kann beliebige Scripte in IP-Symcon starten. Damit ist es also möglich die a.i.o. Remote als frei definierbare Anzeige und Eingabetool für IP-Symcon zu verwenden.

Hallo Leute,

ich Versuche gerade mittles Push Statusmeldungen an Mediola zu schicken.
Leider bekomme ich folgende Fehlermeldung:

Fatal error: Call to undefined function socket_create() in [Push] on line 6

Die Scripte sehen folgendermaßen aus:

<?

$status = GetValue(59380 /*[42LG6000\Power]*/); // Status des Geräts auslesen
if ($status == "True")
   {
   $push = "True";
   $medioladevice = "HiFi.42LG6000";//Name des Geräts im AIO Creator (Gruppe.Name)
   //Pushskript einbinden
   include '19339.ips.php';
   }
else
   {
   $push = "False";
   $medioladevice = "HiFi.42LG6000";//Name des Geräts im AIO Creator (Gruppe.Name)
   //Pushskript einbinden
   include '19339.ips.php';
   }


?>

$port = 1902; //Push Port
    $msg = '{XC_EVT}{"type":"ST","data":"'.$medioladevice.':'.$push.'"}'; //Push Message data an device mit Bezeichnung Gruppe.Name den Status der auslösenden Variable
      $len = strlen($msg);//Länge der Message
    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1);
    socket_sendto($sock, $msg, $len, 0, '255.255.255.255', $port);
    socket_close($sock);

Könnt Ihr da was entdecken?

Danke
Jörg

Hi,

hast du die php_sockets.dll auch unter C:\IP-Symcon\ext Oderner?
Dienst neugestartet?

Hallo,

ja läuft inzwischen auch.
Ich hatte nur übersehen das ich den Dienst beenden und neustarten muss.
Leider funktioniert aber die Einbindung in Mediola noch nicht ganz, sollte beim nächsten Update aber funktionieren.

Jörg

Hallo zusammen

Ich habe mir jetzt mal die Testversion von Mediola installiert.
Mich Interessiert besonders die einfache und Optische gute Visualisierung.
Ich habe jetzt schon mal ein wenig getestet.
Ich habe bis jetzt noch keine Möglichkeit gefunden selbst erstellte Variablen(IPS) in
Mediola Anzeigen oder Verändern zu können.
So wie ich das sehe kann ich nur Variablen benutzen die unter Instanzen liegen.
Gibt es eine Möglichkeit jede Variable von IPS in Mediola zu nutzen.

Mfg Stefan

Du kannst entweder die selbst erstellten Variablen unterhalb einer Dummyinstanz legen, dies macht das Auffinden der Befehle innerhalb des AIO Creators einfacher. Ansonsten werden alle Variablen, die nicht unterhalb einer Instanz liegen unterhalb vom Gerät *** im AIO Creator zusammengefasst. Dem Gerät *** ist dann im AIO Creator ein Gerät zuzuweisen, dann können die Variablen über dieses Gerät angezeigt werden.
Voraussetzung hierfür ist das a.i.o. creator Funktionsmodul IP-Symcon, damit der AIO Creator mit IP-Symcon zusammenarbeiten kann.

Genau das hatte ich gerade vor, nur wird mir die Dummyinstanz nicht im NEO angezeigt. Die einzelnen Variablen/Skripte darin schon.
Ab einer gewissen Anzahl von Instanzen wäre eine Struktur echt wichtig.

(Symcon 5.0, RPI)

Was steuerst Du denn genau aus NEO an Geräten an? Vielleicht gibt es dafür ja eine richtige Instanz dann sollte diese auch so in NEO angezeigt werden.

Ich bin mittlerweile bei 14 Geräten die ich in Symcon einbinden und schlussendlich über Neo steuern will.

(Apple TV 2x, Denon x2400h, Homematic CCU2, LG OLED B7D, Optoma DE-3120EGA, Optoma HD25-LV, Philips 48PFK6609/12, Philips HUE, PS4, VU+Duo2, VU+ Zero, Deckenventilator, usw…).

Für vieles gibt es eigene Module, die ich auch zum Größten teil versuche zu nutzen. Bei den VU+ Geräten z.B. reicht mir aber zum ansteuern ein Simpler Curl per Skript den ich dann per Neo-Button auslösen will.

Aufgrund der menge an Skripten/Befehlen (VU+ Boxen zum Beispiel) wird das im Gerätemanager bei NEO sehr unübersichtlich. Eine Gruppierung über das Dummymodul wäre mir da echt hilfreich.
Es schein ja mal funktioniert zu haben (2013)?

in sofern das ein PHP Modul ist und damit auch eine IP-Symcon Instanz sollte diese Instanz nach einem Import in NEO auch als Gerät angezeigt werden.

Ich kann nur empfehlen:

[ul]
[li]bei Skripten diesen zugehörig zum Gerät ein Präfix voran zu stellen. Also Kinderzimmerlampe Power Off, Kinderzimmerlampe Power On statt das Skript z.B. nur Power On zu nennen.[/li][li]Grundsätzlich Dummy Instanzen zu verwenden, wenn es sich nicht um eine IP-Symcon Instanz handelt und darunter dann eigene Variablen anzulegen, auf die Variable kommt dann ein Action Skript[/li][/ul]

Eine Gruppierung über ein Dummy Modul geht auch immer noch, habe ich gerade noch mal probiert.


Dummy in IPS mit Varibale auf der ein Actionscript liegt


<?

 SetValue($_IPS['VARIABLE'], $_IPS['VALUE']);
// Skript ergänzen das dann aufgerufen werden soll mit IPS_RunScriptEx
// https://www.symcon.de/service/dokumentation/befehlsreferenz/ablaufsteuerung/ips-runscriptex/

?>

Nach Import in NEO sieht das so aus
NEO Dummy.png

Ansonsten poste doch mal wie das bei Dir konkret aussieht, vielleicht findet man dann den Unterschied.

Vielen Dank. Ich glaube ich hab es verstanden.

Wenn ich eine Variable dem Dummy hinzufüge wird mir der Dummy (inklusive der veränderbaren Variable) auch im NEO angezeigt. Stehen unterhalb des Dummys nur meine Curl-Skripte ist er nicht auffindbar.

Mein Gedankengang war, dass ich direkt unter einer Dummyinstanz meine Flut an Curl-Skripten ablegen kann und mir die dann auch so im NEO angezeigt werden (Gerät/DummyModul wählen -> Befehl/Skript wählen). Sodass, meine Skripte nach Geräten gegliedert ihm NEO-Gerätemanager liegen.

Wenn ich das jetzt richtig verstanden habe, muss ich für jeden Befehl Varibalen und Actionscripte erstellen.
Ich glaube da bleibe ich lieber bei den Präfixen und scroll halt um einiges mehr.

Nach dem Import der einzelnen Befehle gibt es ja die Möglichkeit nach „Räumen“ zu sortieren. Das werde ich nutzen denk ich.

Wie man das macht ist jedem persönlich überlassen. Wenn die Skripte zumindest schon mal mit dem gleichen Präfix anfangen, findet man diese dann auch weil diese in NEO alphabetisch sortiert werden.

Es mag ja im ersten Moment umständlich erscheinen sich eine Dummy Instanz mit einer Variable anzulegen, aber das hat durchaus mehrere Vorteile und ist eine einmalige Sache.

[ul]
[li]Du kannst dann erstens Variablenprofile nutzten und bekommst genau diese auch in NEO zur Verfügung gestellt.[/li][li]Du kannst auch den Webfront nutzten oder die mobile App von IPS, alternativ zum Schalten über NEO.[/li][li]Wenn Du nicht nur etwas ausführen willst, sondern auch den Status darstellen mit einer Grafik oder Button, braucht Du so oder so eine Variable[/li][li]Der Inhalt der Variable lässt sich dank des Variablenprofils in NEO einfach darstellen[/li][li]Optional braucht man für Alexa, Google usw. so oder so eine Variable mit Variablenprofil und Actionskript[/li][/ul]

Das alles geht Dir verloren wenn Du ausschließlich über Skripte arbeitest. Ich bin mir auch sicher, das man Deine Flut an Curl-Skripten in Kombination mit einer Variable deutlich reduzieren kann, wenn nicht sogar auf ein oder wenige Skripte eindampfen kann, das macht das Ganze auf Dauer übersichtlicher. Wie Du das im Detail nutzt und löst ist aber Dir überlassen.

Falls Du Hilfe brauchen solltest, oder ein Beispiel wie man Deine Flut an Skripten eindämmen kann, dann müsstest Du mal ein paar Skripte als Beispiel posten.

Das kannst Du machen, in dem Fall ist ein Raum dann halt ein Gerät.

Ich steh halt noch sehr am Anfang was IPS und PHP angeht und bin für jede Hilfe offen.

Immer und immer wiederkehrend wäre beispielsweise sowas:

Bsp. 1: Genutzt bei Denon x2400h, Vu+,


<?

$bef="MNCDN"; 
$ip="192.168.xxx.xxx:8080";  
$ch=curl_init("http://$ip//goform/formiPhoneAppDirect.xml?$bef"); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
$result=$command=curl_exec($ch);  

?>

Bsp. 2: IR-Befehle zu einem Global Cache Gateway
(In Verbindung mit einem Client Socket 53893)


<?

CSCK_SendText(53893, "sendir,1:1,1,38000,1,69,341,172,21,21,21,65,21,65,21,65,21,21,21,65,21,65,21,65,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,65,21,65,21,65,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,65,21,65,21,65,21,21,21,65,21,21,21,65,21,1425,341,85,21,3651\r")

?>