Soderla
sofern nicht noch irgendwelche Bugs auftreten ist das mal meine Final Version.
Da ist nun die angekündigte Message Queue drinnen mit der sowohl sichergestellt wird das im Problemfall kein Kommando verlorengeht, und diese auch immer in der richtigen Reihenfolge ausgeliefert werden.
Befüllen kann man die Queue in beliebiger Geschwindigkeit. Man muß nicht auf den langsamen Droid Rücksicht nehmen.
Fehlerhandling und Recovery hab ich wesentlich verbessert und teilweise konfigurierbar gemacht.
Wie schon gesagt, Langzeiterfahrungen fehlen noch, soweit schauts aber gut aus.
Wäre nett wennst testen und ggfls. mitdebuggen könntest.
Hier das schon teilweise bekannte „sendData“ Script. Dieses übernimmt auslesen der MessageQueue und versenden an den Droid.
Errorrecovery, Timeouts, und Open/Close Client Socket werden darin komplett erledigt.
Installation:
1)ClientSocket anlegen, IP und Port Eintragen
2) unter Client Socket eine Registervariable mit Namen „regVarDataBuffer“ anlegen. Name MUSS mit Line 2 im Script übereinstimmen.
3)unter ClientSocket ein Script mit Namen „sendData“ anlegen den unteren Inhalt reinkopieren. Auch der Name des Scripts MUSS exakt so geschrieben sein.
- Sript einmal ausführen, weitere Variablen werden automatisch angelegt
$Id_ClientSocket = IPS_GetParent($_IPS['SELF']);
$IDRegVar = @IPS_GetObjectIDByName("regVarDataBuffer", $Id_ClientSocket);
$maxRetry = 10; // retries until giveup und clear buffer, further error processing
$socketReadyDelay = 10; //delay in sec if socket not ready
$msgDelay = 5; // delay in sec until command is resent
// Nothing to configure below this line
$IDBuffer = CreateVariableByName($Id_ClientSocket, 'BufferToSend', 3);
$IDerrorCount = CreateVariableByName($Id_ClientSocket, 'errorCount', 1);
Switch ($_IPS['SENDER'])
{
Case "Execute":
// reserved for debug
//break;
Case "RunScript":
if (IPS_GetInstance($Id_ClientSocket)['InstanceStatus'] != 102) {// Check if Socket is Active
CSCK_SetOpen($Id_ClientSocket,true);
IPS_ApplyChanges($Id_ClientSocket);
if (IPS_GetInstance($Id_ClientSocket)['InstanceStatus'] != 102) {
IPS_SetScriptTimer($IPS_SELF, $socketReadyDelay); //arm Timer for retry
echo "Keine Verbindung zu ".IPS_GetName($Id_ClientSocket);
Return; // Stop in case Socket Open fail
}
}
RegVar_SendText($IDRegVar, "quintessence
\r"); // start handshake
break;
Case "WebFront":
// reserved for future use
break;
Case "TimerEvent":
IPS_SetScriptTimer($IPS_SELF, 0); //arm Timer for retry
$errorCount=GetValue($IDerrorCount);
$errorCount=$errorCount+1;
if ($errorCount < $maxRetry) {
SetValue($IDerrorCount,$errorCount);
IPS_RunScript($_IPS['SELF']);// Run next try
}
else {
SetValue($IDerrorCount,0);
SetValueString($IDBuffer,"nothing to send");
// todo: add additional error processing there
}
break;
Case "Variable":
break;
Case "RegisterVariable":
$data = $IPS_VALUE;
$data = trim($data);
Switch ($data) {
Case "accept": // ready to send data
$buffer=GetValueString($IDBuffer); //re-read in case modified meanwhile
$data_to_send= substr($buffer,0,strpos ($buffer ,"_+_"));
RegVar_SendText($IDRegVar,$data_to_send."
\r"); //here the data is sent
IPS_SetScriptTimer($IPS_SELF, $msgDelay); //arm Timer for retry if Fail
break;
case "close": // data successfull send
IPS_SetScriptTimer($IPS_SELF, 0); //Send Ok, stop Timer
SetValue($IDerrorCount,0);
CSCK_SetOpen($Id_ClientSocket,false);
$buffer=GetValueString($IDBuffer); //re-read in case modified meanwhile
if (substr_count ($buffer,"_+_")> 1) {
$pos_next =strpos ($buffer ,"_+_");
SetValueString($IDBuffer,substr($buffer,$pos_next+3,strlen($buffer))); //update
sleep(1); // todo: find minimum delay
IPS_RunScript($_IPS['SELF']); // re-run to process next command
}
else{
SetValueString($IDBuffer,"nothing to send");
}
break;
case "declined": // any problem
// todo: add logic to recover,
CSCK_SetOpen($Id_ClientSocket,false);
IPS_SetScriptTimer($IPS_SELF, 1); //arm Timer for retry
break;
Default: // handshake
$data .= ":";
$hash = md5($data);
$hash .= "
";
RegVar_SendText($IDRegVar, $hash);
Break;
}
}
function CreateVariableByName($id, $name, $type)
{
global $IPS_SELF;
$vid = @IPS_GetVariableIDByName($name, $id);
if($vid===false) {
$vid = IPS_CreateVariable($type);
IPS_SetParent($vid, $id);
IPS_SetName($vid, $name);
IPS_SetInfo($vid, "This Variable was created by Script #$IPS_SELF");
}
return $vid;
}
Weiters benötigst noch die Function „SendtoDroid“ welche das Befüllen und Handling der Message Queue aus einem beliebigen eigenen Script übernimmt.
Wie diese Funktion aussieht wie sie aufzurufen ist und eine primitive Impementierung ist hier zu sehen:
$IDCSDroid_1 = 35066 /*[Client Socket Haustür Tablett]*/ ;
$IDBuffer_1 = @IPS_GetObjectIDByName("BufferToSend", $IDCSDroid_1);
$IDsendScript_1 = @IPS_GetObjectIDByName("sendData", $IDCSDroid_1);
SendtoDroid($IDBuffer_1,$IDsendScript_1,'DisplayOn');
SendtoDroid($IDBuffer_1,$IDsendScript_1,'showIPSWF');
SendtoDroid($IDBuffer_1,$IDsendScript_1,'sayGutenMorgen');
sleep(5);
SendtoDroid($IDBuffer_1,$IDsendScript_1,'DisplayOff');
//$IDCSDroid_2 = 'xxxxxx' /*[ClientSocket ID of your second Droid*// ;
//$IDBuffer_2 = @IPS_GetObjectIDByName("BufferToSend", $IDCSDroid_2);
//$IDsendScript_2 = @IPS_GetObjectIDByName("sendData", $IDCSDroid_2);
//SendtoDroid($IDBuffer_2,$IDsendScript_2,'DisplayOn');
//----------------------------------------------------------------------
// Call this function to add new command to ClientSocket message queue
// Args[$IDBuffer = ID of Buffer variable] [$new... command to be send]
function SendtoDroid($IDBuffer,$IDsendScript,$new) {
$maxQueueLenght = 20; // max Commands in Queue
$old = GetValueString($IDBuffer);
// cleanup queue if too much commands pending
if (substr_count ($old,"_+_")> $maxQueueLenght) {
$old ='nothing to send'; //todo: add error processing if required
}
if ($old =='nothing to send') {
SetValue($IDBuffer,$new."_+_");
IPS_RunScript($IDsendScript);
}
else {
SetValue($IDBuffer,$old.$new."_+_");
}
}
viel Glück
bb