Was ist denn das? Ein Gerät mit RS232, welches aus dem Tritt kommt wenn der Port ‚offen‘ ist. 
Du suchts die Funktion IPS_SetProperty — IP-Symcon :: Automatisierungssoftware. Ist aber wirklich eine schlechte Idee. Wenn es nicht anders geht…
COMPort heißt schon länger SPRT, eventuell reicht es ja schon mit SPRT_SetBreak, SetDTR oder SetRTS entsprechende Steuersignale an das Gerät zu senden ?
Aber was machst du mit Usern welche keine RS232 nutzen, sondern z.B. einen TCP Clientsocket und eine RS232/LAN-Adapter nutzen ? Oder einen XBee als Funkstrecke ? Das kannst du schlecht alles berücksichtigen.
Grundsätzlich hat sich bei mir folgendes bewährt; auch wenn du es jetzt vielleicht nicht direkt nutzen kannst (habe auch endlich mal mein RGB Modul entsprechend geändert
):
In der Reihenfolge vom IPS-Systemstart:
-
Create:
— Definition der Settings der Instanz (RegisterProperty)
— Instanz ‚verbindet‘ intern den IO-Parent.
-
Applychanges:
— Registrieren auf IPS ist Betriebsbereit.
— und auf Änderungen der IPS internen ‚Datenverbindung‘ mit RegisterMessage (Siehe 1)
— VariableProfile anlegen, Statusvariablen anlegen, wenn statisch.
— Abbruch der Funktion, da IPS_GetKernelRunlevel meldet dass der Kernel nicht 'bereit ist.
IPS wird ‚betriebsbereit‘ und feuert die Methode MessageSink, ausgelöst durch IPS_KERNELSTARTED
- MessageSink (siehe 4)
— Wenn IPS_KERNELSTARTED der Auslöser war, merken wir uns unseren IO und registrieren uns auf IM_CHANGESTATUS (siehe 2) .
— Und wenn unser IO ‚active‘ ist, dann Kommunikation starten (bei mir IOChangeState, siehe 5)
Nun wird deine Instanz umkonfiguriert und Übernehmen geklickt.
IPS führt ApplyChanges aus.
- Applychanges:
— Registrieren auf IPS ist Betriebsbereit. (jetzt egal)
— und auf Änderungen der IPS internen ‚Datenverbindung‘ mit RegisterMessage (Siehe 1)
— VariableProfile anlegen, Statusvariablen anlegen, wenn statisch.
— Da IPS_GetKernelRunlevel nun den Kernel als 'bereit liefert geht es weiter.
— Wir prüfen ob unser Parent aktiv ist (siehe 3), und starten die Kommunikation (siehe 5)
Der User wählt eine andere IO-Instanz als übergeordnete Instanz aus.
Somit muss die Kommunikation neu gestartet werden. Da wir mit RegisterMessage auf DM_CONNECT und DM_DISCONNECT registriert haben, feuert IPS wieder MessageSink.
- MessageSink (siehe 4)
— Wenn DM_CONNECT oder DM_DISCONNECT der Auslöser war, löschen wir die alte Registrierung auf IM_CHANGESTATUS.
— Merken wir uns den eventuell neuen IO und registrieren uns auf diesen wieder mit IM_CHANGESTATUS (siehe 2).
— Und wenn unser IO ‚active‘ ist, dann Kommunikation starten (siehe 5)
Nun merkt der User, er hat den falschen ComPort eingestellt. Also schnell ändern und Übernehmen im IO.
Oder der User zieht den USB-Stick mit dem ComPort ab… oder bei einer transparenten / virtuellen COMPort ist die Verbindung weg etc… Der COMPort ist ‚tot‘ und geht in IPS in Fehler.
IPS feuert wieder MessageSink ausgelöst durch IM_CHANGESTATUS.
- MessageSink (siehe 4)
— Wenn IM_CHANGESTATUS der Auslöser war, und er ist in Fehler gegangen, dann können wir nicht mehr senden.
— Ist er wieder in ‚active‘, dann wieder Kommunikation starten (bei mir IOChangeState mit IS_ACTIVE)
1
$this->RegisterMessage(0, IPS_KERNELSTARTED);
$this->RegisterMessage($this->InstanceID, DM_CONNECT);
$this->RegisterMessage($this->InstanceID, DM_DISCONNECT);
2
protected function RegisterParent()
{
$OldParentId = $this->GetBuffer('ParentID');
$ParentId = @IPS_GetInstance($this->InstanceID)['ConnectionID'];
if ($ParentId <> $OldParentId)
{
if ($OldParentId > 0)
$this->UnregisterMessage($OldParentId, IM_CHANGESTATUS);
if ($ParentId > 0)
$this->RegisterMessage($ParentId, IM_CHANGESTATUS);
else
$ParentId = 0;
$this->SetBuffer('ParentID') = $ParentId;
}
return $ParentId;
}
3
/**
* Prüft den Parent auf vorhandensein und Status.
*
* @access protected
* @return bool True wenn Parent vorhanden und in Status 102, sonst false.
*/
protected function HasActiveParent()
{
$instance = IPS_GetInstance($this->InstanceID);
if ($instance['ConnectionID'] > 0)
{
$parent = IPS_GetInstance($instance['ConnectionID']);
if ($parent['InstanceStatus'] == 102)
return true;
}
return false;
}
4
/**
* Interne Funktion des SDK.
*
* @access public
*/
protected function MessageSink($TimeStamp, $SenderID, $Message, $Data)
{
switch ($Message)
{
case IPS_KERNELSTARTED:
case DM_CONNECT:
$this->RegisterParent();
if ($this->HasActiveParent())
$this->IOChangeState(IS_ACTIVE);
else
$this->IOChangeState(IS_INACTIVE);
break;
case DM_DISCONNECT:
$this->RegisterParent();
$this->IOChangeState(IS_INACTIVE);
break;
case IM_CHANGESTATUS:
if ($SenderID == $this->ParentID)
$this->IOChangeState($Data[0]);
break;
}
}
5
/**
* Wird ausgeführt wenn sich der Status vom Parent ändert und wenn IPS startet.
* @access protected
*/
protected function IOChangeState($State)
{
// Wenn der IO Aktiv wurde
if ($State == IS_ACTIVE)
{
$this->startCommunication();
}
else // und wenn nicht setzen wir uns auf inactive
{
$this->SetStatus(IS_INACTIVE);
}
}