ELV Bussystem HS485 für IPS ab V2.2

Zum schalten und empfangen mit IPS wird das Interface HS485 PCI USB Interface benötigt.

Das ganze soll als Anregung dienen und ist keine fertige Lösung. Die Scripts sind den eigenen Vorstellungen anzupassen.

[b]Script Datenauswertung.ips.php und HS485 Module.ips.php im Rootverzeichnis anlegen.
Moduladressen und Namen im Script HS485 Module eintragen.

In Zeile 62, ComNummer eintragen!! Danach 1 mal Script Datenauswertung von Hand ausführen.

                                                                                                                          Es wird die Kategorie ELV Bussystem HS485 sowie die Unterkategorie Module erstellt und  die Scripts in die Hauptkategorie verschoben. Außerdem wird der ComPort die RegisterVariable und eine StringVariable zum schalten    erstellt. Alle anderen Module, werden nachdem sie im Array eingetragen wurden, automatisch nach Datenempfang des entsprechenden Moduls, mit Variablen unter der Kategorie Module erstellt.  Jedes Modul erhält einen zuvor festgelegten Namen. 

[/b]Ein Aufruf zum schalten eines Ausgangs erfolgt z.B. hiermit.

SetValue(36736 /*[.HS485_Bussystem\HS485_Schalten]*/, "IOA6t");

hier wird Relais 6 vom IO127 geschaltet mit Event toggle.

Es gibt ja mittlerweile einige User, die das System einsetzen. Wer dazu etwas beitragen möchte, Script, Erweiterung usw. kann sich gerne melden, wird dann hier mit eingefügt.
Zum diskutieren, macht bitte einen eigenen Thread auf.

mit diesem Script werden alle benötigten Instanzen(Kategorien, ComPort, RegVar, StringVariable) angelegt.

Folgende Module laufen damit:

[ul]
[li]IO127[/li][li]HS_S[/li][li]HS_RS[/li][li]IO4 UP[/li][li]Luxsensor[/li][li]TFS.[/li][/ul]

Der Dimmer kann auch eingebunden werden, mangels Hardware ist er hier aber nicht vorhanden.
Die Module/Variablen werden dann auch automatisch angelegt. Kategorien und Variablen können nicht verschoben oder umbenannt werden. Für die Vergabe eigener Variablennamen wird automatisch eine Linkvariable mit angelegt, welche umbenannt, verschoben und geschaltet werden kann.

Script HS485 Datenauswertung.ips.php

<?
/**********************************
 IP-SYMCON Event Scripting
 ELV Bussystem HS485
***********************************
File: HS485 Datenauswertung.ips.php
**********************************/

##############################################################################################################
#    Script Datenauswertung.ips.php und HS485 Module.ips.php im Rootverzeichnis anlegen.                       #
#    Moduladressen und Namen im Script HS485 Module eintragen.                                                 #
#                                                                                                            #
#    In Zeile 62, ComNummer eintragen!!      Danach 1 mal Script Datenauswertung von Hand ausführen.           #
#                                                                                                                           #
#    Es wird die Kategorie ELV Bussystem HS485 sowie die Unterkategorie Module erstellt und                    #
#    die Scripts in die Hauptkategorie verschoben. Außerdem wird der ComPort und die RegisterVariable          #
#    erstellt. Alle anderen Module werden nachdem sie im Array eingetragen wurden, automatisch nach            #
#  Datenempfang des entsprechenden Moduls mit Variablen unter der Kategorie Module erstellt.                 #
#    Jedes Modul erhält einen zuvor festgelegten Namen.                                                                          #
#                                                                                                            #
##############################################################################################################

if($IPS_SENDER == "Execute")
{
   $CatID = @IPS_GetCategoryIDByName("ELV Bussystem HS485", $parentID );
    if(IPS_CategoryExists($CatID)) return;
    
    $ScriptID = IPS_GetScriptIDByName("HS485 Datenauswertung", 0);
    $ScriptModuleID = IPS_GetScriptIDByName("HS485 Module", 0);
    
    if((!IPS_ScriptExists($ScriptID)) || (!IPS_ScriptExists($ScriptModuleID)))
    {
        echo "Fehler! Script mit dem Namen HS485 Datenauswertung oder HS485 Module existiert nicht im Root!";
        return;
    }
    else
    {
       $CatID = IPS_CreateCategory();              // Kategorie anlegen
        IPS_SetName($CatID, "ELV Bussystem HS485"); // Kategorie benennen
        $object = IPS_GetObject($CatID);
        $parentID = $object['ParentID'];

        $CatID = IPS_GetCategoryIDByName("ELV Bussystem HS485", $parentID );
        if(IPS_CategoryExists($CatID))
        {
           $CatModuleID = IPS_CreateCategory();    // Kategorie anlegen
            IPS_SetName($CatModuleID, "Module");    // Kategorie benennen
           IPS_SetParent($CatModuleID, $CatID);    // Kategorie in Hauptkategorie anlegen
           IPS_SetParent($ScriptID, $CatID);       // Kategorie in Hauptkategorie verschieben
           IPS_SetParent($ScriptModuleID, $CatID); // Kategorie in Hauptkategorie verschieben
            IPS_SetHidden($CatID, true);            // Kategorie für Webfront verstecken
            $CatLinkID = IPS_CreateCategory();  // Kategorie anlegen
            IPS_SetName($CatLinkID, "HS485 Linkvariablen"); // Kategorie benennen
            IPS_SetParent($CatLinkID, $CatID); // Kategorie in Hauptkategorie verschieben
            
            $comPortID = @IPS_GetInstanceIDByName("HS485 PC-Interface", 0);
            if(!IPS_InstanceExists($comPortID))
            {
               $comPortID = IPS_CreateInstance("{6DC3D946-0D31-450F-A8C6-C42DB8D7D4F1}"); // Comport anlegen
               IPS_SetName($comPortID, "HS485 PC-Interface");
            }
            COMPort_SetPort($comPortID, 'COM5'); // ComNummer welche dem PC-Interface zugewiesen ist!
           COMPort_SetBaudRate($comPortID, '19200');
            COMPort_SetDataBits($comPortID, '8');
            COMPort_SetStopBits($comPortID, '1');
           COMPort_SetParity($comPortID, 'Even');
           COMPort_SetOpen($comPortID, true);
           IPS_ApplyChanges($comPortID);
       
            $regVarID = @IPS_GetInstanceIDByName("HS485 RegisterVariable", $parentID);
            if(!IPS_InstanceExists($regVarID))
            {
                $regVarID = IPS_CreateInstance("{F3855B3C-7CD6-47CA-97AB-E66D346C037F}"); // Registervariable anlegen
            IPS_SetName($regVarID, "HS485 RegisterVariable");
            IPS_SetParent($regVarID, $CatID);
            }
            RegVar_SetRXObjectID($regVarID, $IPS_SELF);
            IPS_ConnectInstance($regVarID, $comPortID);
           IPS_ApplyChanges($regVarID);
           
           // StringVariable zum schalten anlegen
           $Hs485Schalten = IPS_CreateVariable(3);
           IPS_SetName($Hs485Schalten, "HS485_Schalten");
           IPS_SetParent($Hs485Schalten, $CatID);
           echo "Scripts und Instanzen wurden erfolgreich eingebunden";
        }
        else
        {
           echo "Fehler! Keine Kategoerie ELV Bussystem HS485 vorhanden";
           return;
        }
    }
}

if($IPS_SENDER  == "RegisterVariable") 
{

   $parentID = 0;
   $CatID = IPS_GetCategoryIDByName("ELV Bussystem HS485", $parentID );
   $CatModuleID = IPS_GetCategoryIDByName("Module", $CatID); // prüfen ob KategorieID Module exsistiert
   $CatLinkID = IPS_GetCategoryIDByName("HS485 Linkvariablen", $CatID);
   
    // Steuerzeichen definieren
    define ("FD", "\xFD"); // Startzeichen
    define ("FE", "\xFE");
    define ("FC", "\xFC"); // ESCAPE-Zeichen
    
    $startzeichengefunden = false;
    $frameAktiv = false;
     $CRC16 = 1;
     $daten = "";
     $newFrame = "";
     
    $datenFrame = RegVar_GetBuffer($IPS_INSTANCE); // Buffer Registervariable auslesen
     $datenFrame .= $IPS_VALUE;
     $lastFrame = strpos($datenFrame, FD, 1);
     if(strlen($datenFrame) && $lastFrame)
    {
       $frameAktiv = true;
       $newFrame = substr(strrchr($datenFrame, FD), 0);
        $datenFrame = substr($datenFrame, 0, $lastFrame);
        if($newFrame == $datenFrame) $newFrame = "";
    }
 
     for($i=0; $i<strlen($datenFrame) && $CRC16 != 0; $i++)
     {
          $chr = $datenFrame[$i]; // Zeichen einlesen
          if(!$startzeichengefunden) // STARTZEICHEN schon gefunden?
          {
           if($chr == FD) // nein, daher suchen nach STARTZEICHEN
           {
               $startzeichengefunden = true; // STARTZEICHEN gefunden
                $daten = $chr;
           }
           continue; // STARTZEICHEN immer noch nicht gefunden
        }
          if($chr == FC) // falls ESCAPE gefunden wurde
          {
            $i++;  // ESCAPE verwerfen
           $chr = chr(ord($datenFrame[$i]) | 0x80); // und nachfolgendes Zeichen korrigieren
          }
        $daten .= $chr; // ab hier Checksumme suchen
          $CRC16 = CRC16($daten);
     }
    if($CRC16 != 0)
    {
       RegVar_SetBuffer($IPS_INSTANCE, $daten); // keine gültigen Daten empfangen, daher in Buffer schreiben
       if(strlen($daten) > 18) // wenn Buffer größer .. löschen
        {
           RegVar_SetBuffer($IPS_INSTANCE, "");
        }
       return;
    }
    else
    {
        RegVar_SetBuffer($IPS_INSTANCE, ""); // Daten gültig, Buffer kann gelöscht werden
        if($frameAktiv) RegVar_SetBuffer($IPS_INSTANCE, $newFrame);
    }
    $Zieladresse = substr($daten,1,4); // Zieladresse zuweisen
    $KontrollByte = ord(substr($daten,5,1)); // Kontrollzeichen zuweisen
    $Absenderadresse = substr($daten,6,4);  // Absenderadresse zuweisen
    $Moduladressen = String2Value($daten,6,4); // Moduladressen auslesen
    $Event = ord(substr($daten,11,1));
    $Taste = String2Value($daten,12,1);
    $daten = Str2Hex($daten);
    $daten = str_split($daten, 3);
   
    if($Zieladresse == "\xFF\xFF\xFF\xFF") $Zieladresse = "\x00\x00\x00\x00";

    $iFrameNachricht = ($KontrollByte & 0x01) == 0x00; // I-Nachricht
    $ackNachricht = ($KontrollByte & 0x97) == 0x11;    // ACK-Nachricht
    
   if(($KontrollByte & 0x01) == 0x00) // I-Nachricht
    {
       $Framelaenge = "\x02";
       $sendefolge = ($KontrollByte >> 1) & 0x03;
        $sendAck = (($sendefolge & 0x03) << 5) | 0x19;
        sendFrame($Absenderadresse.chr($sendAck).$Zieladresse.$Framelaenge);
        printf("I-Nachricht
");
        printf("Sendefolgenummer : %d
", ($KontrollByte >> 1) & 0x03);
        printf("Empfangsfolgenummer : %d
", ($KontrollByte >> 5) & 0x03);
        printf("SYN-Bit : %s
", $KontrollByte & 0x80 ? "gesetzt":"nicht gesetzt");
        printf("FIN-Bit : %s
", $KontrollByte & 0x10 ? "gesetzt":"nicht gesetzt");
        printf("Absenderadresse : %s
", $KontrollByte & 0x08 ? "enthalten":"keine");
    }
    elseif(($KontrollByte & 0x97) == 0x11)    // ACK-Nachricht
    {
       $Framelaenge = "\x02";
        $empfangsfolge = ($KontrollByte >> 5) & 0x03;
        $sendAck = (($empfangsfolge & 0x03) << 5) | 0x19;
        //sendFrame($Absenderadresse.chr($sendAck).$Zieladresse.$Framelaenge);
        printf("ACK-Nachricht
");
        printf("Empfangsfolgenummer : %d
", ($KontrollByte >> 5) & 0x03);
        printf("Absenderadresse : %s
", ($KontrollByte & 0x08)? "enthalten":"keine");
    }
    elseif(($KontrollByte & 0x07) == 0x03) // Discovery-Nachricht
    {
       printf("Discovery-Nachricht
");
       printf("Adressmaske : %d
",(($KontrollByte & 0xF8) >> 3)+1);
    }
    
//********************************************************************
// Array Relais und Eingänge IO127
    $IO127Relais = array('Relais 1' => 0x0C, 'Relais 2' => 0x0D,
                               'Relais 3' => 0x0E, 'Relais 5' => 0x0F,
                              'Relais 5' => 0x10, 'Relais 6' => 0x11,
                               'Relais 7' => 0x12);
                         
    $IO127Eingang = array('Eingang1' => 0x00, 'Eingang2' => 0x01,
                                 'Eingang' => 0x02, 'Eingang' => 0x03,
                                 'Eingang' => 0x04, 'Eingang' => 0x05,
                                 'Eingang' => 0x06, 'Eingang' => 0x07,
                                 'Eingang' => 0x08, 'Eingang' => 0x09,
                                 'Eingang' => 0x0A, 'Eingang' => 0x0B);
    
//********************************************************************
// Array Relais HS_S
    $HSSAktor = array('Aktor 1' => 0x00, 'Aktor 2' => 0x01);

//********************************************************************
// Array Tastereingang HS_RS
    $HSRSEingang = array('T1' => 0x01, 'T2' => 0x00);

//********************************************************************

    require "HS485 Module.ips.php";
    
    // Variablen/Kategorien für die einzelnen Module anlegen
    if(!in_array($Moduladressen, $module["Adresse"]))
    {
       IPS_LogMessage($IPS_SELF, "Adresse ".Str2Hex($Absenderadresse)." ist nicht in HS485 Module angelegt!");
       return;
    }
    else
    {
       $modulKey = array_search($Moduladressen, $module["Adresse"]); // array Index
       $IO4Key = @array_search($module["IO4_UP"][$modulKey], $module["IO4_UP"]);
       $tfsKey = @array_search($module["TFS"][$modulKey], $module["TFS"]);
       //TFS-Module anlegen
       if($tfsKey)
       {
           $TFSModuleID = @IPS_GetCategoryIDByName("TFS ".$module["TFS"][$modulKey], $CatModuleID); // prüfen ob KategorieID TFS exsistiert
    
           $feuchte = @IPS_GetVariableIDByName("relative Luftfeuchte ".$module["TFS"][$modulKey], $TFSModuleID); // IDs der Variablen
           $temp = @IPS_GetVariableIDByName("Temperatur ".$module["TFS"][$modulKey], $TFSModuleID); // IDs der Variablen

           if((!IPS_VariableExists($feuchte)) || (!IPS_VariableExists($temp))) // Prüfen ob ID der Variablen bereits vorhanden, wenn Nein, anlegen
            {
               if(!$TFSModuleID) // wenn nicht vorhanden, anlegen
                {
                   $TFSModuleID = IPS_CreateCategory(); // Kategorie TFS anlegen
                    @IPS_SetName($TFSModuleID, "TFS ".$module["TFS"][$modulKey]); // Kategorie benennen
                    IPS_SetParent($TFSModuleID, $CatModuleID); // nach Unterkategorie Module verschieben
                }
                $feuchte = IPS_CreateVariable(1); // Variable Integer anlegen
              @IPS_SetName($feuchte, "relative Luftfeuchte ".$module["TFS"][$modulKey]); // Der neu generierten ID einen Namen zuweisen
              IPS_SetVariableCustomProfile($feuchte, "~Humidity"); // Profil setzen
              $link = IPS_CreateLink();       //Link anlegen
                IPS_SetName($link, "relative Luftfeuchte ".$module["TFS"][$modulKey]); //Link benennen
                IPS_SetLinkChildID($link, $feuchte); //Link verknüpfen
                IPS_SetParent($link, $CatLinkID); // nach Kategorie HS485 Linkvariablen verschieben
              $temp = IPS_CreateVariable(2); // Variable Float anlegen
              @IPS_SetName($temp, "Temperatur ".$module["TFS"][$modulKey]); // Der neu generierten ID einen Namen zuweisen
              IPS_SetVariableCustomProfile($temp, "~Temperature"); // Profil setzen
              $link = IPS_CreateLink();       //Link anlegen
                IPS_SetName($link, "Temperatur ".$module["TFS"][$modulKey]); //Link benennen
                IPS_SetLinkChildID($link, $temp); //Link verknüpfen
                IPS_SetParent($feuchte, $TFSModuleID); // nach Kategorie TFS verschieben
                IPS_SetParent($temp, $TFSModuleID); // nach Kategorie TFS verschieben
                IPS_SetParent($link, $CatLinkID); // nach Kategorie HS485 Linkvariablen verschieben
            }
            // Auswertung Temperatur-Feuchtesensor JCU10_TFS. Bereich von 0-65°C und 0-100%
            $Temp = hexdec($daten[11].$daten[12])/10;
           $Feuchte = hexdec($daten[13]);
              SetValue($temp, $Temp);
              SetValue($feuchte, $Feuchte);
        }
        
      $lxKey = @array_search($module["LX"][$modulKey], $module["LX"]);
        // Lux-Modul anlegen
        if($lxKey)
      {
           $LXModuleID = @IPS_GetCategoryIDByName("LX 1", $CatModuleID); // prüfen ob KategorieID LX exsistiert
           $lux = @IPS_GetVariableIDByName("Lux Sensor",$LXModuleID);

            if(!IPS_VariableExists($lux)) // Prüfen ob ID der Variablen bereits vorhanden, wenn Nein, anlegen
             {
               if(!$LXModuleID) // wenn nicht vorhanden, anlegen
                {
                   $LXModuleID = IPS_CreateCategory(); // Kategorie LX anlegen
                    IPS_SetName($LXModuleID, "LX 1"); // Kategorie benennen
                    IPS_SetParent($LXModuleID, $CatModuleID); // nach Unterkategorie Module verschieben
                }
                $lux = IPS_CreateVariable(1); // Variable Integer anlegen
              IPS_SetName($lux, "Lux Sensor"); // Der neu generierten ID einen Namen zuweisen
                IPS_SetParent($lux, $LXModuleID);
                $link = IPS_CreateLink();       //Link anlegen
                IPS_SetName($link, "Lux Sensor"); //Link benennen
                IPS_SetLinkChildID($link, $lux); //Link verknüpfen
                IPS_SetParent($link, $CatLinkID); // nach Kategorie HS485 Linkvariablen verschieben
            }
          // Auswertung Helligkeitssensor LX1. Bereich von 0-200000 Lux
            $Helligkeit = hexdec($daten[11].$daten[12].$daten[13].$daten[14]);
           SetValue($lux, $Helligkeit);
        }
        
      $hssKey = @array_search($module["HS_S"][$modulKey], $module["HS_S"]);
      // HS_S-Module anlegen
      if($hssKey)
      {
         $aktorNr = @array_search(hexdec($daten[11]), $HSSAktor);
            $HS_SModulID = @IPS_GetCategoryIDByName("HS_S ".$module["HS_S"][$modulKey], $CatModuleID); // prüfen ob KategorieID HS_S exsistiert
            if((hexdec($daten[10]) == 0x04) && $aktorNr)
            {
                $aktor = @IPS_GetVariableIDByName($aktorNr." ".$module["HS_S"][$modulKey], $HS_SModulID); // IDs der Variablen
                if(!IPS_VariableExists($aktor)) // Prüfen ob ID der Variablen bereits vorhanden, wenn Nein, anlegen
                 {
                   if(!$HS_SModulID) // wenn nicht vorhanden, anlegen
                    {
                       $HS_SModulID = IPS_CreateCategory(); // Kategorie HS_S anlegen
                        @IPS_SetName($HS_SModulID, "HS_S ".$module["HS_S"][$modulKey]); // Kategorie benennen
                        IPS_SetParent($HS_SModulID, $CatModuleID); // nach Unterkategorie Module verschieben
                    }
                    $aktor = IPS_CreateVariable(0); // Variable Boolean anlegen
                  IPS_SetName($aktor, $aktorNr." ".$module["HS_S"][$modulKey]); // Der neu generierten ID einen Namen zuweisen
                  IPS_SetVariableCustomProfile($aktor, "~Switch"); // Profil setzen
                  IPS_SetParent($aktor, $HS_SModulID);
                  $link = IPS_CreateLink();       //Link anlegen
                    IPS_SetName($link, $aktorNr); //Link benennen
                    IPS_SetLinkChildID($link, $aktor); //Link verknüpfen
                    IPS_SetParent($link, $CatLinkID); // nach Kategorie HS485 Linkvariablen verschieben
              }
                SetValue($aktor, $daten[12]); // Rückmeldung Status Aktoren
            }
            $eingangNr = $Event.$Taste;
            if($eingangNr == 0x4B . $HSSAktor['Aktor 1'])
            {
               sendFrame("\x00\x00\x10\x98\x98\x00\x00\x00\x00\x04\x53\x00");
            }
            if($eingangNr == 0x4B . $HSSAktor['Aktor 2'])
            {
               sendFrame("\x00\x00\x10\x98\x98\x00\x00\x00\x00\x04\x53\x01");
            }
        }

      $hsrsKey = @array_search($module["HS_RS"][$modulKey], $module["HS_RS"]);
      // HS_RS-Module anlegen
      if($hsrsKey)
      {
         $aktorNr = @array_search(hexdec($daten[12]), $HSRSEingang);
            $HS_RSModulID = @IPS_GetCategoryIDByName("HS_RS ".$module["HS_RS"][$modulKey], $CatModuleID); // prüfen ob KategorieID HS_RS exsistiert
            if((hexdec($daten[11]) == 0x4B) && $aktorNr == "T1" || $aktorNr == "T2")
            {
                $aktor = @IPS_GetVariableIDByName("Status", $HS_RSModulID); // IDs der Variablen
                if(!IPS_VariableExists($aktor)) // Prüfen ob ID der Variablen bereits vorhanden, wenn Nein, anlegen
                 {
                   if(!$HS_RSModulID) // wenn nicht vorhanden, anlegen
                    {
                       $HS_RSModulID = IPS_CreateCategory(); // Kategorie HS_RS anlegen
                        @IPS_SetName($HS_RSModulID, "HS_RS ".$module["HS_RS"][$modulKey]); // Kategorie benennen
                        IPS_SetParent($HS_RSModulID, $CatModuleID); // nach Unterkategorie Module verschieben
                    }
                    $aktor = IPS_CreateVariable(1); // Variable Integer anlegen
                  IPS_SetName($aktor, "Status"); // Der neu generierten ID einen Namen zuweisen
                  IPS_SetVariableCustomProfile($aktor, "~Shutter.Association"); // Profil setzen
                  IPS_SetParent($aktor, $HS_RSModulID);
                  $link = IPS_CreateLink();       //Link anlegen
                    IPS_SetName($link, "Status"); //Link benennen
                    IPS_SetLinkChildID($link, $aktor); //Link verknüpfen
                    IPS_SetParent($link, $CatLinkID); // nach Kategorie HS485 Linkvariablen verschieben
              }
                SetValue($aktor, $daten[12]); // Rückmeldung Status Aktoren
            }
        }
        
      $IO127Key = @array_search($module["IO127"][$modulKey], $module["IO127"]);
      
      // IO127-Module anlegen
        if($IO127Key || $IO4Key)
        {
           $relaisNr = @array_search(hexdec($daten[11]), $IO127Relais);
            $IO127ModuleID = @IPS_GetCategoryIDByName("IO127 ".$module["IO127"][$modulKey], $CatModuleID); // prüfen ob KategorieID IO127 exsistiert

            if($relaisNr)
            {
               $status = @IPS_GetVariableIDByName($relaisNr, $IO127ModuleID);
                if(!IPS_VariableExists($status)) // Prüfen ob ID der Variablen bereits vorhanden, wenn Nein, anlegen
                 {
                       if(!$IO127ModuleID) // wenn nicht vorhanden, anlegen
                    {
                       $IO127ModuleID = IPS_CreateCategory(); // Kategorie IO127 anlegen
                        @IPS_SetName($IO127ModuleID, "IO127 ".$module["IO127"][$modulKey]); // Kategorie benennen
                        IPS_SetParent($IO127ModuleID, $CatModuleID); // nach Unterkategorie Module verschieben
                    }
                    $status = IPS_CreateVariable(0); // Variable Boolean anlegen
                    @IPS_SetName($status, $relaisNr); // Der neu generierten ID einen Namen zuweisen
                    IPS_SetVariableCustomProfile($status, "~Switch"); // Profil setzen
                    IPS_SetParent($status, $IO127ModuleID);
                    $link = IPS_CreateLink();       //Link anlegen
                    IPS_SetName($link, $relaisNr); //Link benennen
                    IPS_SetLinkChildID($link, $status); //Link verknüpfen
                    IPS_SetParent($link, $CatLinkID); // nach Kategorie HS485 Linkvariablen verschieben
                }
                SetValue($status, $daten[12]); // Rückmeldung Status Relais
            }
            $eingangNr = $Event.$Taste;
            if($eingangNr == 0x4B . $IO127Eingang['Eingang1'])
            {
               sendFrame("\x00\x00\x18\xEA\x98\x00\x00\x00\x00\x04\x53\x0C"); // Licht Waschküche
            }
            if($eingangNr == 0x4B . $IO127Eingang['Eingang2'])
            {
               sendFrame("\x00\x00\x18\xEA\x98\x00\x00\x00\x00\x04\x53\x0D"); // Licht Kellerabgang
            }
        }
    }
}

function sendByte($byte)
{
   $KontrollByte = ord(substr($byte,4,1)); // Kontrollzeichen auslesen
   if(($KontrollByte & 0x01) == 0x00) // I-Nachricht
    $empfangsfolge = ($KontrollByte >> 5) & 0x03;
    printf("Empfangsfolgenummer : %d
", ($KontrollByte >> 5) & 0x03);
    sendframe($byte);
}
function sendframe($frame)
{
   $startByte = "\xFD";
    $CRC16 = CRC16($startByte.$frame); // Checksumme berechnen
    $CRC16 = chr($CRC16 >> 8).chr($CRC16 & 0xff); // Hi-Lo-Byte der Checksumme extrahieren
   $frame16 = $frame.$CRC16; // Checksumme an Frame anhängen
    for($i=0; $i<strlen($frame16); $i++) // Frame 
    {
       $byte = $frame16[$i]; // Byte einlesen
       if(($byte == "\xFC") || ($byte == "\xFD") || ($byte == "\xFE")) // nach Sonderzeichen suchen
       $byte = "\xFC".$byte &= "\x7F" ; // wenn vorhanden ersetzen
        $startByte .= $byte; // und übergeben
    }
    $comPortID = @IPS_GetInstanceIDByName("HS485 PC-Interface", 0); // ComportID
    COMPort_SendText($comPortID, $startByte); // Datenframe senden
}

// Checksummenberechnung, bei fehlerfreiem Empfang muss Checksumme 0 (Null) ergeben
function CRC16($s)
{
     // die folgenden beiden Werte sind abhängig vom Anwendungszweck.
     // Für HS485 gilt:
     $CRCreg = 0xffff << 8;       // Startwert
     $PLYreg = 0x1002 << 8;       // Polynom
     $s .= "\x00\x00";
     $len = strlen($s);

     for ($cp=0; $cp<$len; $cp++)
     {
          $CRCreg |= ord($s[$cp]);
          for ($bp=0; $bp<8; $bp++)
          {
           $CRCreg <<= 1;
           if ($CRCreg & 0x1000000) $CRCreg ^= $PLYreg;
          }
    }
     return ($CRCreg >> 8) & 0xffff;
}

// Funktion zur Umwandlung eines String nach Hex
function Str2Hex($daten)
{
    $Hex = "";
     for($i=0; $i<strlen($daten); $i++)
   $Hex .= sprintf("%02X ", ord($daten[$i]));
     return $Hex; // String in hexadezimaler Schreibweise
}
// Funktion zur Umwandlung eines Teil eines String in eine Zahl, Zählung beginnt bei Null
function String2Value($str, $p, $c) // String, Position, Anzahl Characters
{
    $val = 0;
     for ($i=0; $i<$c; $i++)
     {
          $val <<= 8;
          $val += ord($str[$p+$i]);
     }
     return $val; // Rückgabe: Zahl
}

?>

Script HS485 Module.ips.php

<?
//******************************************************************************
// Array für Moduladressen und Namen welche dem Modul zugeordnet werden

    $module["IO127"][1]   = "Keller";
    $module["Adresse"][1] = 0x000018EA; //HS485_127IO
    $module["TFS"][2]     = "Keller";
    $module["Adresse"][2] = 0x000012F0; //HS485_TFS Keller
    $module["TFS"][3]     = "Waschküche";
    $module["Adresse"][3] = 0x000012DA; //HS485_TFS Waschküche
    $module["LX"][4]      = "Sensor";
    $module["Adresse"][4] = 0x00000CB2; //HS485_LX1
    $module["HS_S"][5]    = "Flur";
    $module["Adresse"][5] = 0x00001098; //HS485_S Flur Licht
    $module["HS_RS"][6]   = "Markise Balkon";
    $module["Adresse"][6] = 0x00003F01; //HS485_RS Markise
    $module["IO4_UP"][7]  = "Test";
    $module["Adresse"][7] = 0x00003E81; //HS485_IO4UP

//******************************************************************************


?>

Das ganze sieht dann in etwas so wie auf dem Bild aus.

Script HS485 AbfrageSensoren.ips.php

<?
/*
*******************************
 IP-SYMCON Event Scripting
*******************************
File     : HS485 Abfrage Sensoren.ips.php
Trigger  :
Interval : nach belieben
*/

require "HS485 Datenauswertung.ips.php";

// Zuweisung der Sendedaten
$Startzeichen      = "\xFD";                     // Startzeichen FD Vorgabe
$HS485_TFS_Keller  = "\x00\x00\x12\xF0";         // Moduladresse muss angepasst werden
$HS485_TFS_Wa      = "\x00\x00\x12\xDA";
$HS485_LX1         = "\x00\x00\x0C\xB2";
$Kontrollzeichen   = "\x98";                     // Kontrollzeichen 98 Vorgabe
$Absender          = "\x00\x00\x00\x00";         // Absenderadresse vom PC immer 0000
$Framelaenge       = "\x03";                     // Framelaenge ergibt sich aus Befehl und Checksumme
$Lux               = "\x4C";
$TF                = "\x46";                     // Befehl "F" zum abfragen der Temp/Feuchte

// Abfragen der Sensoren
sendFrame($HS485_TFS_Keller.$Kontrollzeichen.$Absender.$Framelaenge.$TF);

IPS_SLEEP(250);
sendFrame($HS485_TFS_Wa.$Kontrollzeichen.$Absender.$Framelaenge.$TF);

IPS_SLEEP(250);
sendFrame($HS485_LX1.$Kontrollzeichen.$Absender.$Framelaenge.$Lux);

?>

Zum schalten und auswerten.

<?
/*
*******************************
 IP-SYMCON Event Scripting
*******************************
File     : HS485_IO127_schalten.ips.php
Trigger  :
Interval :
*/
require "HS485 Datenauswertung.ips.php";

$HS485_Schalten = GetValue(36736 /*[.HS485_Bussystem\HS485_Schalten]*/);  // Triggervariable

// Zuweisung der Sendedaten
$HS485_127IO     = "\x00\x00\x18\xEA";   // Moduladresse muss angepasst werden !
$Kontrollzeichen = "\x98";               // Kontrollzeichen 98
$Absender        = "\x00\x00\x00\x00";   // Absenderadresse vom PC immer 0000
$Frame6          = "\x06";               // Framelaenge ergibt sich aus Befehl, Sensoreingang, Aktornummer, Event(Ein,Aus,Toggle) und Checksumme
$Frame4          = "\x04";
$Befehl_S        = "\x53";               // Aktorzustand abfragen
$Befehl_s        = "\x73";               // Aktor setzen
$Sensoreingang   = "\x00";               // beim setzen und Abfragen immer 0
$HS485_127IO_A1  = "\x0C";               // 127IO Relais 1
$HS485_127IO_A2  = "\x0D";               // 127IO Relais 2
$HS485_127IO_A3  = "\x0E";               // 127IO Relais 3
$HS485_127IO_A4  = "\x0F";               // 127IO Relais 4
$HS485_127IO_A5  = "\x10";               // 127IO Relais 5
$HS485_127IO_A6  = "\x11";               // 127IO Relais 6
$HS485_127IO_A7  = "\x12";               // 127IO Relais 7
$Ein             = "\x01";               // Event Ein
$Aus             = "\x00";               // Event Aus
$Toggle          = "\xFF";               // Event toggle



switch($HS485_Schalten)
{
    case "IOA1t": //Licht Waschküche
    sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A1.$Toggle);  // Datenframe
    sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A1);
    break;
  
    case "IOA1e": //Licht Waschküche
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A1.$Ein);  // Datenframe
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A1);
    break;

    case "IOA1a": //Licht Waschküche
    sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A1.$Aus);  // Datenframe
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A1);
      break;
  
      case "IOA2t": // Licht Keller
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A2.$Toggle);
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A2);
      break;

   case "IOA2e": // Licht Keller
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A2.$Ein);
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A2);
      break;
  
      case "IOA2a": // Licht Keller
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A2.$Aus);
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A2);
      break;
      
      case "IOA3e": // Ventilator Waschküche
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A3.$Ein);
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A3);
    break;

      case "IOA3a": // Ventilator Waschküche
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A3.$Aus);
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_127IO_A3);
      break;
  
      case "IOA4t":
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A4.$Toggle);
      break;

      case "IOA5t":
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A5.$Toggle);
      break;

      case "IOA6t": //Haustür aufschliessen
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A6.$Toggle);
      break;

      case "IOA7t": // Haustür zuschliessen
      sendFrame($HS485_127IO.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_127IO_A7.$Toggle);
      break;

}

?>

zum schalten des Moduls HS485 S.

<?
/*
*******************************
 IP-SYMCON Event Scripting
*******************************
File     : HS485_S.ips.php
Trigger  : OnUpdate HS485_Schalten
*/


$HS485_Schalten = GetValueString(36736 /*[.HS485_Bussystem\HS485_Schalten]*/);  // Triggervariable

// Zuweisung der Sendedaten
$Startzeichen    = "\xFD";               // Startzeichen FD
$HS485_S         = "\x00\x00\x10\x98";   // Moduladresse muss angepasst werden !
$Kontrollzeichen = "\x98";               // Kontrollzeichen 98
$Absender        = "\x00\x00\x00\x00";   // Absenderadresse vom PC immer 0000
$Frame6          = "\x06";               // Framelaenge ergibt sich aus Befehl, Sensoreingang, Aktornummer, Event(Ein,Aus,Toggle) und Checksumme
$Frame4          = "\x04";
$Befehl_S        = "\x53";               // Framedaten hier Befehl "S" Abfrage Relaiszustand
$Befehl_s        = "\x73";               // Framedaten hier Befehl "s" Aktor setzen
$Sensoreingang   = "\x00";               // beim setzen und Abfragen immer 0
$HS485_S_A1      = "\x00";               // Aktor, Relais 1
$HS485_S_A2      = "\x01";               // Aktor, Relais 2
$Ein             = "\x01";               // Event Ein
$Aus             = "\x00";               // Event Aus
$Toggle          = "\xFF";               // Event Toggle
$CRC             = "\x00\x00";           // wird an Datenframe übergeben und durch berechnete Checksumme ersetzt

require "HS485 Datenauswertung.ips.php";

switch($HS485_Schalten)  // Schalten der Ausgänge des Schalters HS485 S
{
  case "S1t":  // Aktor 1 Toggle und Schaltzustand abfragen
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_S_A1.$Toggle);
  IPS_SLEEP(250);
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_S_A1);
  break;

  case "S1e":  // Aktor 1 Einschalten und Schaltzustand abfragen
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_S_A1.$Ein);
  IPS_SLEEP(250);
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_S_A1);
  break;

  case "S1a":   // Aktor 1 Ausschalten und Schaltzustand abfragen
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_S_A1.$Aus);
  IPS_SLEEP(250);
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_S_A1);
  break;

  case "S2t":   // Aktor 2 Toggle und Schaltzustand abfragen
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_S_A2.$Toggle);
  IPS_SLEEP(250);
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_S_A2);
  break;

  case "S2e":   // Aktor 2 Einschalten und Schaltzustand abfragen
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_S_A2.$Ein);
  IPS_SLEEP(250);
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_S_A2);
  break;

  case "S2a":   // Aktor 2 Ausschalten und Schaltzustand abfragen
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame6.$Befehl_s.$Sensoreingang.$HS485_S_A2.$Aus);
  IPS_SLEEP(250);
  sendFrame($HS485_S.$Kontrollzeichen.$Absender.$Frame4.$Befehl_S.$HS485_S_A2);
  break;
}

?>