HomeHub 4.1

diverse Zusatzsoftware

Moderator: Co-Administratoren

log22
Beiträge: 15
Registriert: 25.10.2023, 10:57
System: CCU
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: HomeHub 4.1

Beitrag von log22 » 24.05.2024, 22:08

Hab noch ein nicht unterstütztes Gerät: Jalousie HmIP-BBL-2
Kann man da was machen?^^

steingarten
Beiträge: 327
Registriert: 28.10.2013, 18:38
Hat sich bedankt: 20 Mal
Danksagung erhalten: 46 Mal

Re: HomeHub 4.1

Beitrag von steingarten » 24.05.2024, 22:26

@log22: kannst du die "HmIP-BBL.php" unter components kopieren und als "HmIP-BBL-2.php" speichern. Darin den Funktionsnamen "HmIP_BBL($component)" durch "HmIP_BBL_2($component)" anpassen.

Im Ordner ja wäre die "script.js.php" noch anzupassen, in Zeile 214 noch zusätzlich einfügen "case 'HmIP-BBL-2':".

Wenn das passt, wird es übernommen.

Ggf. Kann jemand anderes es kurz prüfen und bei GitHub bereitstellen. Danke

Benutzeravatar
gnom
Beiträge: 358
Registriert: 23.06.2022, 05:33
System: Alternative CCU (auf Basis OCCU)
Wohnort: Brühl
Hat sich bedankt: 28 Mal
Danksagung erhalten: 61 Mal

Re: HomeHub 4.1

Beitrag von gnom » 25.05.2024, 08:22

@log22 - habe die Änderungen mal in das ZIP gepackt. Kannst Du das mal checken, habe das gerät nicht
HmIP-BBS-2 addition.zip
(13.14 KiB) 10-mal heruntergeladen
@steingarten - wollte das mal ausprobieren/üben, habe 2 pull requests geschickt. Wenn log22 das bestätigt, könnte das ja gemerged werden
Gruss, Chris

don't fear dying, fear not living (Marc Aurel)
strebst Du nach Respekt, handle selber danach (unbekannt)

2 Systeme:
- Home: Debmatic & IOBroker unter Debian 12 auf Laptop, HM-IP, Asksin++ (HB-+Innogy Devices), Zigbee, Tasmota/Shelly
- WE-Shed: Debmatic & IOBroker unter Debian 11 auf Laptop, HM classic, Asksin++ (HB-+Innogy Devices), RF, Tasmota/Shelly

log22
Beiträge: 15
Registriert: 25.10.2023, 10:57
System: CCU
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: HomeHub 4.1

Beitrag von log22 » 25.05.2024, 09:47

Funktioniert, dankeschön!
Kann aus meiner Sicht gemerged werden.

steingarten
Beiträge: 327
Registriert: 28.10.2013, 18:38
Hat sich bedankt: 20 Mal
Danksagung erhalten: 46 Mal

Re: HomeHub 4.1

Beitrag von steingarten » 25.05.2024, 09:52

gnoms pull requests wurden freigegeben. Danke gnom

log22
Beiträge: 15
Registriert: 25.10.2023, 10:57
System: CCU
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: HomeHub 4.1

Beitrag von log22 » 25.05.2024, 21:39

Ich hätte noch eine Frage:
Da ich die Rauchmelder HmIP-SWSD auch für Alarmfunktionen nutze, würde ich gern über die Oberfläche den Alarm aus- ( oder auch an) schalten können.
Aktuell wird nur der case 'SMOKE_DETECTOR_ALARM_STATUS' abgebildet.
Kann man das in der script.js.php hinzufügen?

Benutzeravatar
gnom
Beiträge: 358
Registriert: 23.06.2022, 05:33
System: Alternative CCU (auf Basis OCCU)
Wohnort: Brühl
Hat sich bedankt: 28 Mal
Danksagung erhalten: 61 Mal

Re: HomeHub 4.1

Beitrag von gnom » 26.05.2024, 07:17

da müßten die Coder ran :wink:

Als workaround kannst Du aber entweder über eine SysVar oder in der Art vorgehen.
Die Variable kannst Du dann ja in HH leicht einbinden und umschalten.

Das aber von dieser Nutzung regelmäßig von den Experten tunlichst abgeraten wird, weißt Du?
Ich hätte auch keine Lust, alle zwei Jahre oder so fest eingebaute Lithium-Batterien auszutauschen - nur einer der threads dazu. Auch z.B. das häufige scharf/unscharf schalten des Alarms kostet Strom.
Deine Entscheidung :)

Kap 10 im Gerätehandbuch.
Die Batterielebensdauer von typisch 10 Jahren kann nur
unter folgenden Bedingungen erreicht werden:

Pro Jahr dürfen max. 52 Funktionstests durchge-
führt werden und ein Vollalarm für 60 Sekunden
auftreten.

Während der gesamten Laufzeit dürfen eine In-
betriebnahme, zwei Reichweitentests sowie ein
einmaliges Anlernen an eine Gruppe durchge-
führt werden.
Ob man diese Option per default in HH einbauen sollte - imho eher nein
Gruss, Chris

don't fear dying, fear not living (Marc Aurel)
strebst Du nach Respekt, handle selber danach (unbekannt)

2 Systeme:
- Home: Debmatic & IOBroker unter Debian 12 auf Laptop, HM-IP, Asksin++ (HB-+Innogy Devices), Zigbee, Tasmota/Shelly
- WE-Shed: Debmatic & IOBroker unter Debian 11 auf Laptop, HM classic, Asksin++ (HB-+Innogy Devices), RF, Tasmota/Shelly

log22
Beiträge: 15
Registriert: 25.10.2023, 10:57
System: CCU
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: HomeHub 4.1

Beitrag von log22 » 26.05.2024, 07:47

Ahja, diese Thematik war mir so noch gar nicht bewusst.
Die Steuerung über eine Variable sollte auch diesen Zweck erfüllen.

rentier-s
Beiträge: 400
Registriert: 19.06.2017, 09:24
Hat sich bedankt: 20 Mal
Danksagung erhalten: 70 Mal

Re: HomeHub 4.1

Beitrag von rentier-s » 29.05.2024, 15:20

steingarten hat geschrieben:
24.05.2024, 10:26
Ich freue mich auf jegliche Verbesserung meines hinzugefügten doch in viele stellen laienhaften Codes.
Was heißt laienhaft, ich würde sagen, Du hast da schon gewaltig was aus dem Boden gestampft.

Ich habe die interface.php so umgebaut, dass man die einzelnen Funktionen auch direkt aus anderen Skripten heraus aufrufen kann.

Auf den ersten Blick funktioniert bei mir alles, müsste aber trotzdem unbedingt noch ausgiebig in verschiedenen Konstellationen getestet werden.

Code: Alles auswählen

<?php

//   CCU User -> Falls authentifizierung notwendig, bitte in "config/config.php" wie folgt eintragen:
/*

$ccu_user = "";  // in die Anführungsstriche den Benutzernamen
$ccu_pass = "";  // in die Anführungsstriche das dazugehörige Kennwort

*/

require_once(__DIR__.'/config/config.php');

// Konfiguration als Array aus Config-Variablen zusammenbauen
if (!is_array($ccu)) $ccu = array(
  'host' => $homematicIp,
  'https' => !empty($ccu_https),
  'user' => $ccu_user,
  'pw' => $ccu_pass
);
// --

$ccu['url'] = "http".(!empty($ccu['https']) ? 's' : '')."://" . $ccu['host'] . ":".(!empty($ccu['https']) ? '4' : '')."8181/remoteskript.exe";


function ccu_remote($ccu, $ccu_request, $plain_result = false) {

  // Als indikator für die Rückgabe, um den Overhead zu filtern
  $delimeter = '---'.uniqid('hm-end').'---';
  if (!$plain_result) $ccu_request = $ccu_request."\nWriteLine(\"".$delimeter."\");";

  // curl Anfrage bauen
  $curl = curl_init($ccu['url']);
  if (!empty($ccu['user']) and !empty($ccu['pw'])) curl_setopt($curl, CURLOPT_USERPWD, $ccu['user'].':'.$ccu['pw']);
  curl_setopt($curl, CURLOPT_POST, 1);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $ccu_request);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
  curl_setopt($curl, CURLOPT_TIMEOUT, 20);
  if (!empty($ccu['https'])) {
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  }
  $content = curl_exec($curl);
  curl_close($curl);
  #var_dump($content);

  // Trenne Rückgabe vom Overhead
  if (!$plain_result) $content = strstr($content, $delimeter, true);

  // Konvertiere XML kritische Zeichen in HTML-Format      #  Maskierung sollte eigentlich nicht notwendig sein.
  #$content = str_replace('<', '&lt;', $content);          #  Ggf. sollten wir uns eine elegantere Variante überlegen, RegEx oder ähnliches,
  #$content = str_replace('>', '&gt;', $content);          #  oder im HM-Skript mit .replace() maskieren.
  #$content = str_replace('*&lt;*', '<', $content);
  #$content = str_replace('*&gt;*', '>', $content);

  return $content;
}

// ALLE STATES
if (strpos($_SERVER['QUERY_STRING'], "statelist.cgi") !== false) {
  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_statelist($ccu, isset($_GET['debug']));
}

function api_statelist($ccu, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
WriteLine("<stateList>");
integer show_remote = 1;
integer show_internal = 1;
string id;
! Alle Datenpunkte durchlaufen

!foreach(id, dom.GetObject(ID_DEVICES).EnumUsedIDs()) {
	foreach(id, root.Devices().EnumUsedIDs()) {
  ! Einzelnen Datenpunkt holen
  object oDevice = dom.GetObject(id);

  integer iDevInterfaceId = oDevice.Interface();
  object oDeviceInterface = dom.GetObject(iDevInterfaceId);
  ! Namen und Wert des Elements ausgeben - geht nicht -> logged  info

  boolean bDevReady = oDevice.ReadyConfig();
  string sDevInterface   = oDeviceInterface.Name();
  string sDevType        = oDevice.HssType();

  WriteLine("<device name='" # oDevice.Name() #"' ise_id='" # oDevice.ID() # "' unreach='false' sticky_unreach='false' config_pending='false'>");

  string cid;
  integer x = 0;
  ! Alle Datenpunkte durchlaufen
  foreach(cid, oDevice.Channels()) {

    ! Einzelnen Kanal holen
    var ch = dom.GetObject(cid);
    ! Namen und Wert des Kanals ausgeben
    Write("<channel name='"#ch.Name()#"' ise_id='"#ch.ID()#"' direction='' index='"# x #"'");

    if (false == ch.Internal()) {
      Write(" visible='" # ch.Visible() # "'");
    } else {
      Write(" visible=''");
    }

    Write(" ready_config='' operate='");
    if (false == ch.Internal()) {
     if( ch.UserAccessRights(iulOtherThanAdmin) == iarFullAccess ) {
        Write("true");
      } else {
         Write("false");
      }
    }
    Write("'>");
    WriteLine("");


    string did;

    ! Alle Datenpunkte durchlaufen
    foreach(did, ch.DPs().EnumUsedIDs()) {
      var dp = dom.GetObject(did);
	     string dpA = dp.Name().StrValueByIndex(".", 2);

                if( (dpA != "ON_TIME") && (dpA != "INHIBIT") && (dpA != "CMD_RETS") && (dpA != "CMD_RETL") && (dpA != "CMD_SETS") && (dpA != "CMD_SETL") ) {
      WriteLine("<datapoint name='"#dp.Name()#"' type='" # dp.Name().StrValueByIndex(".", 2) #"' ise_id='"#dp.ID()#"' state='"#dp.Value()#"' value='"#dp.Value()#"' valuetype='"#dp.ValueType()#"' valueunit='" # dp.ValueUnit() # "' timestamp='" # dp.Timestamp().ToInteger()# "' operations='"#dp.Operations()#"'/>");
				  }
    }
    WriteLine("</channel>");
	  x=x+1;
  }


  WriteLine("</device>");
}
WriteLine("</stateList>");
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// ALLE STATES
if (strpos($_SERVER['QUERY_STRING'], "statelistall.cgi") !== false) {
  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_statelistall($ccu, isset($_GET['debug']));
}

function api_statelistall($ccu, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
WriteLine("<stateList>");
integer show_remote = 1;
integer show_internal = 1;
string id;
! Alle Datenpunkte durchlaufen

!foreach(id, dom.GetObject(ID_DEVICES).EnumUsedIDs()) {
	foreach(id, root.Devices().EnumUsedIDs()) {
  ! Einzelnen Datenpunkt holen
  object oDevice = dom.GetObject(id);

  integer iDevInterfaceId = oDevice.Interface();
  object oDeviceInterface = dom.GetObject(iDevInterfaceId);
  ! Namen und Wert des Elements ausgeben - geht nicht -> logged  info

  boolean bDevReady = oDevice.ReadyConfig();
  string sDevInterface   = oDeviceInterface.Name();
  string sDevType        = oDevice.HssType();

  WriteLine("<device name='" # oDevice.Name() #"' ise_id='" # oDevice.ID() # "' unreach='false' sticky_unreach='false' config_pending='false'>");

  string cid;
  integer x = 0;
  ! Alle Datenpunkte durchlaufen
  foreach(cid, oDevice.Channels()) {

    ! Einzelnen Kanal holen
    var ch = dom.GetObject(cid);
    ! Namen und Wert des Kanals ausgeben
    Write("<channel name='"#ch.Name()#"' ise_id='"#ch.ID()#"' direction='' index='"# x #"'  timestamp='" # ch.LastTimestamp().ToInteger()# "'");

    if (false == ch.Internal()) {
      Write(" visible='" # ch.Visible() # "'");
    } else {
      Write(" visible=''");
    }

    Write(" ready_config='' operate='");
    if (false == ch.Internal()) {
     if( ch.UserAccessRights(iulOtherThanAdmin) == iarFullAccess ) {
        Write("true");
      } else {
         Write("false");
      }
    }
    Write("'>");
    WriteLine("");


    string did;

    ! Alle Datenpunkte durchlaufen
    foreach(did, ch.DPs()) {
      var dp = dom.GetObject(did);
	     string dpA = dp.Name().StrValueByIndex(".", 2);

                if( (dpA != "ON_TIME") && (dpA != "INHIBIT") && (dpA != "CMD_RETS") && (dpA != "CMD_RETL") && (dpA != "CMD_SETS") && (dpA != "CMD_SETL") ) {
      WriteLine("<datapoint name='"#dp.Name()#"' type='" # dp.Name().StrValueByIndex(".", 2) #"' ise_id='"#dp.ID()#"' state='"#dp.Value()#"' value='"#dp.Value()#"' valuetype='"#dp.ValueType()#"' valueunit='" # dp.ValueUnit() # "' timestamp='" # dp.LastTimestamp().ToInteger()# "' operations='"#dp.Operations()#"'/>");
				  }
    }
    WriteLine("</channel>");
	  x=x+1;
  }


  WriteLine("</device>");
}
WriteLine("</stateList>");
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// ALLE DEVICES
if (strpos($_SERVER['QUERY_STRING'], "devicelist.cgi") !== false) {
  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_devicelist($ccu, isset($_GET['debug']));
}

function api_devicelist($ccu, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
WriteLine("");
    string  PARTNER_INVALID = "65535";
integer show_internal = "} 1 {";
      integer show_remote = "} 1 {";
  WriteLine("<deviceList>");
string id;
! Alle Datenpunkte durchlaufen

foreach(id, dom.GetObject(ID_DEVICES).EnumUsedIDs()) {
!	foreach(id, root.Devices().EnumUsedIDs()) {
  ! Einzelnen Datenpunkt holen
  object oDevice = dom.GetObject(id);

  integer iDevInterfaceId = oDevice.Interface();
  object oDeviceInterface = dom.GetObject(iDevInterfaceId);
  ! Namen und Wert des Elements ausgeben - geht nicht -> logged  info



  boolean bDevReady = oDevice.ReadyConfig();
  string sDevInterface   = oDeviceInterface.Name();
  string sDevType        = oDevice.HssType();
  Write("<device name='" # oDevice.Name() #"' address='" # oDevice.Address() # "' ise_id='" # oDevice.ID() # "' interface='" # sDevInterface # "' device_type='" # sDevType # "' ready_config='" # bDevReady # "' >");
  WriteLine("");

  string cid;
  integer x = 0;

  ! Alle Datenpunkte durchlaufen
  foreach(cid, oDevice.Channels()) {



    ! Einzelnen Kanal holen
    var ch = dom.GetObject(cid);
    ! Namen und Wert des Kanals ausgeben
    !WriteLine(ch.Name() # ": " # ch.ID());
	string  sChnPartnerId = ch.ChnGroupPartnerId();
	if (PARTNER_INVALID == sChnPartnerId) { sChnPartnerId = ""; }
    Write("<channel name='"#ch.Name()#"' type='"#ch.ChannelType()#"' address='"#ch.Address()#"' ise_id='"#ch.ID()#"' direction='' parent_device='"#ch.Device()#"' index='"# x #"' group_partner='" # sChnPartnerId # "' aes_available='' transmission_mode=''");

 if (false == ch.Internal()) {
                Write(" visible='" # ch.Visible() # "'");
              } else {
                Write(" visible=''");
              }

 Write(" ready_config='' operate='");
 if (false == ch.Internal()) {
   if( ch.UserAccessRights(iulOtherThanAdmin) == iarFullAccess ) {
                  Write("true");
                } else {
                  Write("false");
                }
}
Write("' />");
 WriteLine("");


 x=x+1;



  }
 WriteLine("</device>");


}
WriteLine("</deviceList>");
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// ALLE PROGRAMME
if (strpos($_SERVER['QUERY_STRING'], "programlist.cgi") !== false) {
  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_programlist($ccu, isset($_GET['debug']));
}

function api_programlist($ccu, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
WriteLine("<programList>");
string id;
! Alle Datenpunkte durchlaufen
foreach(id, dom.GetObject(ID_PROGRAMS).EnumUsedIDs()) {
  ! Einzelnen Datenpunkt holen
  var sysProgram = dom.GetObject(id);
  ! Namen und Wert des Elements ausgeben - speziell -> operate=''
  Write("<program id='" # sysProgram.ID() # "' active='" # sysProgram.Active() # "' timestamp='" # sysProgram.ProgramLastExecuteTime().ToInteger() # "' name='" # sysProgram.Name() # "' description='" # sysProgram.PrgInfo() # "' visible='" # sysProgram.Visible() # "' operate='");
  object o_sysVar = dom.GetObject(sysProgram.ID());
  if( o_sysVar.UserAccessRights(iulOtherThanAdmin) == iarFullAccess ) {
    Write("true'/>");
  } else {
    Write("false'/>");
  }
  WriteLine("");
}
WriteLine("</programList>");
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// ALLE SYSTEMVARIABLEN
if (strpos($_SERVER['QUERY_STRING'], "sysvarlist.cgi") !== false) {
  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_sysvarlist($ccu, isset($_GET['debug']));
}

function api_sysvarlist($ccu, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
WriteLine("<systemVariables>");

string id;
! Alle Datenpunkte durchlaufen
foreach(id, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()){
  ! Einzelnen Datenpunkt holen
  var oSysVar = dom.GetObject(id);
  ! Namen und Wert des Elements ausgeben - fehlt -> visible
  Write("<systemVariable name='" # oSysVar.Name() # "' ");
    if (oSysVar.ValueSubType() == 6) {
      Write("variable='" # oSysVar.AlType() # "' ");
    } else {
      Write("variable='" # oSysVar.Variable() # "' ");
    }
    Write("value='" # oSysVar.Value() # "' ");
    Write("value_list='");
    if (oSysVar.ValueType() == 16) {
      Write( oSysVar.ValueList());
    }
	Write("' ise_id='"#oSysVar.ID()#"' ");
    Write("  min='");
    if (oSysVar.ValueType() == 4) {
      Write( oSysVar.ValueMin());
    }

    Write("' max='");
    if (oSysVar.ValueType() == 4) {
      Write( oSysVar.ValueMax());
    }
	Write("' ");
	Write("unit='" # oSysVar.ValueUnit() # "' type='" # oSysVar.ValueType() # "' subtype='" # oSysVar.ValueSubType() # "' logged='" # oSysVar.DPArchive() # "' visible='" # oSysVar.Visible() # "' timestamp='" # oSysVar.Timestamp().ToInteger()# "' value_name_0='" # oSysVar.ValueName0() # "' value_name_1='" # oSysVar.ValueName1() # "' info='" # oSysVar.DPInfo() # "'/>\n");
  }
  WriteLine("</systemVariables>");
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// PROGRAMM
if (strpos($_SERVER['QUERY_STRING'], "runprogram.cgi") !== false) {
  $prog_id = ( !empty($_GET['program_id']) ? intval($_GET['program_id']) : false );

  // Beende wenn keine Program_ID übergeben wird
  if(empty($prog_id))
  {
	die('Program-ID fehlt');
  }

  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_runprogram($ccu, $prog_id, isset($_GET['debug']));
}

function api_runprogram($ccu, int $prog_id, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
dom.GetObject("$prog_id").ProgramExecute();
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// WERTÄNDERUNG
if (strpos($_SERVER['QUERY_STRING'], "statechange.cgi") !== false) {
  
  // Beende, wenn keine Ise_ID übergeben wird
  if (empty($_GET['ise_id'])) die('Ise-ID fehlt');

  // Beende, wenn keine Werte übergeben werden
  if (!isset($_GET['new_value'])) die('Wert fehlt');

  // Trenne ise_id und new_value anhand , auf und setze als assoziatives Array zusammen
  $iseids = $_GET['ise_id'];
  $a_iseids = str_getcsv($iseids, ',', '"', '\\');
  $iseids = ( count($a_iseids) ? $a_iseids : $iseids );
  $newvalues = $_GET['new_value'];
  $a_newvalues = str_getcsv($newvalues, ',', '"', '\\');
  $newvalues = ( count($a_newvalues) ? array_map('rawurldecode', $a_newvalues) : rawurldecode($newvalues) );
  if (count($iseids) != count($newvalues)) die('Anzahl Parameter stimmt nicht überein');
  $set = array_combine($iseids, $newvalues);

  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_statechange($ccu, $set, isset($_GET['debug']));
}

function api_statechange($ccu, $set, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = '';
  foreach ($set as $ise_id => $new_value) {
	if (ctype_digit($ise_id)) {
	  $ccu_request = $ccu_request."dom.GetObject(\"".$ise_id."\").State(\"".addslashes($new_value)."\");\n";
    }
  }

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request, true);

}


//SYSVAR

if (strpos($_SERVER['QUERY_STRING'], "sysvar.cgi") !== false) {

  // Beende, wenn keine Ise_ID übergeben wird
  if (empty($_GET['ise_id'])) die('Ise-ID fehlt');

  $ise_id = $_GET['ise_id'];

  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_sysvar($ccu, $ise_id, isset($_GET['debug']));
}

function api_sysvar($ccu, $ise_id, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = "WriteLine(\"<systemVariables>\");
string id;
! Alle Datenpunkte durchlaufen
foreach(id, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()){

  ! Einzelnen Datenpunkt holen
  var sysVar = dom.GetObject(id);
   if(".$ise_id." == sysVar.ID()) {
  ! Namen und Wert des Elements ausgeben - fehlt -> visible
  Write(\"<systemVariable name='\" # sysVar.Name() # \"' variable='\" # sysVar.Variable() # \"' value='\" # sysVar.Value() # \"' value_list='\" # sysVar.ValueList() # \"' ise_id='\" # sysVar.ID() # \"' min='\" # sysVar.ValueMin() # \"' max='\" # sysVar.ValueMax() # \"' unit='\" # sysVar.ValueUnit() # \"' type='\" # sysVar.ValueType() # \"' subtype='\" # sysVar.ValueSubType() # \"' logged='\" # sysVar.DPArchive() # \"' visible='\" # sysVar.Visible() # \"' timestamp='\" # sysVar.Timestamp().ToInteger()# \"' value_name_0='\" # sysVar.ValueName0() # \"' value_name_1='\" # sysVar.ValueName1() # \"' info='\" # sysVar.DPInfo() # \"'/>\");
  WriteLine(\"\");
  }
}
WriteLine(\"</systemVariables>\");
";

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// STATUS
if (strpos($_SERVER['QUERY_STRING'], "state.cgi") !== false) {

  // Beende, wenn keine Program_ID übergeben wird
  if (empty($_GET['datapoint_id'])) die('Datapoint-ID fehlt');
  $datapoints = $_GET['datapoint_id'];
  $datapoints = str_replace("t", "", $datapoints);
  $a_datapoints = str_getcsv($datapoints, ',', '"', '\\');
  $datapoints = ( count($a_datapoints) ? $a_datapoints : $datapoints );

  //Bei Diagram Collect darf nicht optimiert werden
  if(!isset($_GET['onlyvalue']))
  {
    $datapoints = array_unique($datapoints);
  }

  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_state($ccu, $datapoints, isset($_GET['debug']));
}

function api_state($ccu, $datapoints, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = "WriteLine(\"<state>\");\r\n";
  foreach ($datapoints as $datapoint) {

	if (ctype_digit($datapoint) ) {
	  $ccu_request = $ccu_request . "object oDatapoint = dom.GetObject(".$datapoint.");\r\n";
	  // Wenn es sich um ein Datenpunkt handelt gib value aus
	  $ccu_request = $ccu_request . "if (oDatapoint.IsTypeOf(OT_DP)) {\r\n";
	  $ccu_request = $ccu_request . "WriteLine(\"<datapoint ise_id='".$datapoint."' value='\"#dom.GetObject(".$datapoint.").Value().ToString()#\"'/>\");\r\n";
	  $ccu_request = $ccu_request . "}\r\n";
	  if (!isset($_GET['onlyvalue']))
	  {
	    // Wenn es sich um einen Channel handelt gib Timestamp aus
	    $ccu_request = $ccu_request . "if (oDatapoint.IsTypeOf(OT_CHANNEL)) {\r\n";
	    $ccu_request = $ccu_request . "WriteLine(\"<datapoint ise_id='".$datapoint."t' value='\"#dom.GetObject(".$datapoint.").LastDPActionTime().ToString(\"%m.%d.%Y %H:%M:%S\")#\"'/>\");";
	    $ccu_request = $ccu_request . "}\r\n";
	    // Wenn es sich um einen Datenpunkt handelt gib Timestamp aus
	    $ccu_request = $ccu_request . "if (oDatapoint.IsTypeOf(OT_DP)) {\r\n";
	    $ccu_request = $ccu_request . "WriteLine(\"<datapoint ise_id='".$datapoint."t' value='\"#dom.GetObject(".$datapoint.").Timestamp().ToString(\"%m.%d.%Y %H:%M:%S\")#\"'/>\");";
	    $ccu_request = $ccu_request . "}\r\n";
	    // Wenn es sich um ein Programm handelt gib Timestamp aus
	    $ccu_request = $ccu_request . "if (oDatapoint.IsTypeOf(OT_PROGRAM)) {\r\n";
	    $ccu_request = $ccu_request . "WriteLine(\"<datapoint ise_id='".$datapoint."t' value='\"#dom.GetObject(".$datapoint.").ProgramLastExecuteTime().ToString(\"%m.%d.%Y %H:%M:%S\")#\"'/>\");";
	    $ccu_request = $ccu_request . "}\r\n";
	   }
    }

  }
  $ccu_request = $ccu_request . "WriteLine(\"</state>\");\r\n";

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// SYSTEMNOTIFICATION
if (strpos($_SERVER['QUERY_STRING'], "systemNotification.cgi") !== false) {
  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_systemNotification($ccu, $prog_id, isset($_GET['debug']));
}

function api_systemNotification($ccu, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
  WriteLine("<systemNotification>");
  string id;
  ! Alle Datenpunkte durchlaufen
  foreach(id, dom.GetObject(ID_SERVICES).EnumUsedIDs()){

    ! Einzelnen Datenpunkt holen
    var serviceVar = dom.GetObject(id);
    object trigDP = dom.GetObject(serviceVar.AlTriggerDP());
    if( serviceVar.IsTypeOf( OT_ALARMDP ) && ( serviceVar.AlState() == asOncoming ) ){
      ! Namen und Wert des Elements ausgeben - fehlt -> visible
      Write("<notification ise_id='" # serviceVar.AlTriggerDP() # "' name='" # trigDP.Name() # "' type='" # trigDP.HssType() # "' timestamp='" # serviceVar.LastTriggerTime().ToInteger() # "'/>");
      WriteLine("");
    }
  }
  WriteLine("</systemNotification>");
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request);

}


// SYSTEMNOTIFICATIONCLEAR
if (strpos($_SERVER['QUERY_STRING'], "systemNotificationClear.cgi") !== false) {
  header("Content-Type: text/xml; charset=ISO-8859-1");
  echo api_systemNotificationClear($ccu, isset($_GET['debug']));
}

function api_systemNotificationClear($ccu, $debug = false) {

  // Baue Skript zusammen
  $ccu_request = <<<EOHM
string itemID;
string address;
object aldp_obj;

foreach(itemID, dom.GetObject(ID_DEVICES).EnumUsedIDs()) {
address = dom.GetObject(itemID).Address();
aldp_obj = dom.GetObject(\"AL-\" # address # \":0.STICKY_UNREACH\");
if (aldp_obj) {
if (aldp_obj.Value()) {
aldp_obj.AlReceipt();
}
}
}
EOHM;

  // Debug Mode
  if ($debug) return($ccu_request);

  // Schreibe Ausgabe
  return "<?xml version='1.0' encoding='ISO-8859-1' ?>\n".ccu_remote($ccu, $ccu_request, true);

}

?>
Die entsprechend angepasste import.php

Code: Alles auswählen

<?php

ini_set('display_errors', 'on');
ini_set('display_startup_errors', 'on');

$beginn = microtime(true);

$exportFile = __DIR__.'/config/export.json';

// Wenn Konfiguration nicht existiert wechsele zum Setup
if(!file_exists(__DIR__.'/config/config.php'))
{
	header('Location: ./setup.php');
	exit;
}

require_once(__DIR__.'/interface.php');

$export = array();

// Devices und Channels von der CCU laden
$devicesXml = simplexml_load_string(api_devicelist($ccu));
$statesXml = simplexml_load_string(api_statelist($ccu));

// Devices
foreach ($devicesXml->device as $device) {
	$dummy = array();
	foreach($device->attributes() as $attribute => $value) {
		$dummy[strval($attribute)] = strval($value);
	}

	$statesXmlDevice = $statesXml->xpath('//device[@ise_id="' . strval($device['ise_id']) . '"]');
	if(isset($statesXmlDevice[0])) {
		foreach($statesXmlDevice[0]->attributes() as $attribute => $value) {
			$dummy[strval($attribute)] = strval($value);
		}
	}

	$export['devices'][] = $dummy;
}

// Virtuelle Fernbedienung
$device = $statesXml->xpath('//device[contains(@name, "HM-RCV-50")]');
if(count((array)$device) > 0) {
	$device = $device[0];

	$dummy = array(
		'name' => strval($device['name']),
		'address' => 'BidCos-RF',
		'ise_id' => strval($device['ise_id']),
		'interface' => 'BidCos-RF',
		'device_type' => 'HM-RCV-50'
	);

	$export['devices'][] = $dummy;
}

// Channels
$channelDevicesXml = $devicesXml->xpath('//channel');
foreach ($channelDevicesXml as $channel) {
	$device = $devicesXml->xpath('//device[@ise_id="' . strval($channel['parent_device']) . '"]');
	$device = $device[0];

	$dummy = array();

	if(strval($device['interface']) <> 'CUxD') {
		$dummy['component'] = strval($device['device_type']);
	} else {
		$dummy['component'] = substr(strval($device['address']), 0, 7);
	}
	$dummy['parent_device_type'] = strval($device['device_type']);
	$dummy['parent_device_interface'] = strval($device['interface']);

	foreach($channel->attributes() as $attribute => $value) {
		$dummy[strval($attribute)] = strval($value);
	}

	$channelStatesXml = $statesXml->xpath('//channel[@ise_id="' . strval($channel['ise_id']) . '"]');
	if(isset($channelStatesXml[0])) {
		foreach($channelStatesXml[0]->attributes() as $attribute => $value) {
			$dummy[strval($attribute)] = strval($value);
		}

		foreach($channelStatesXml[0]->datapoint as $datapoint) {
			$dummy2 = array();
			foreach($datapoint->attributes() as $attribute => $value) {
				$dummy2[strval($attribute)] = strval($value);
			}

			$dummy['datapoints'][] = $dummy2;
		}
	}

	$export['channels'][] = $dummy;
}

// Channels Virtuelle Fernbedienung
$device = $statesXml->xpath('//device[contains(@name, "HM-RCV-50")]');
if(count((array)$device) > 0) {
	$device = $device[0];

	$channelXml = $statesXml->xpath('//device[@ise_id="' . strval($device['ise_id']) . '"]/channel');
	foreach ($channelXml as $channel) {
		$dummy = array();
		$dummy['component'] = 'HM-RCV-50';
		$dummy['parent_device_type'] = 'HM-RCV-50';
		$dummy['parent_device_interface'] = 'BidCos-RF';

		foreach($channel->attributes() as $attribute => $value) {
			$dummy[strval($attribute)] = strval($value);
		}

		foreach ($channel->datapoint as $datapoint) {
			$dummy2 = array();
			foreach($datapoint->attributes() as $attribute => $value) {
				$dummy2[strval($attribute)] = strval($value);
			}

			$dummy['datapoints'][] = $dummy2;
		}

		$export['channels'][] = $dummy;
	}
}

// Aufräumen
unset($devicesXml);
unset($statesXml);

// Systemvariablen von der CCU laden
$sysvarsXml = simplexml_load_string(api_sysvarlist($ccu));

// Systemvariablen
foreach ($sysvarsXml->systemVariable as $sysvar) {
	$dummy = array();
	$dummy['component'] = 'SysVar';

	foreach($sysvar->attributes() as $attribute => $value) {
		$dummy[strval($attribute)] = strval($value);
	}
	$export['systemvariables'][] = $dummy;
}

// Aufräumen
unset($sysvarsXml);

// Programme von der CCU laden
$programsXml = simplexml_load_string(api_programlist($ccu));

// Programme
foreach ($programsXml->program as $program) {
	$dummy = array();
	$dummy['component'] = 'Program';

	foreach($program->attributes() as $attribute => $value) {
		// Unstimmigkeit in der XML-API korrigieren
		if(strval($attribute) == 'id') {
			$dummy['ise_id'] = strval($value);
		} else {
			$dummy[strval($attribute)] = strval($value);
		}
	}
	$export['programs'][] = $dummy;
}

// Aufräumen
unset($programsXml);

// Umlaute ersetzen
$json = str_replace(
	array('\u00c4', '\u00e4', '\u00d6', '\u00f6', '\u00dc', '\u00fc', '\u00df'),
	array('Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', 'ß'),
	json_encode($export)
);
file_put_contents($exportFile, $json);

if(isset($_GET['debug']))
{
	$dauer = microtime(true) - $beginn;
	echo "Verarbeitung des Skripts: ".$dauer." Sek.";
	exit();
}
else
{
	header('Location: index.php');
}

?>
In der index.php wurden die Systemmeldungen auch über den Umweg eines HTTP-Aufrufs geladen.

Code: Alles auswählen

...
require_once(__DIR__.'/interface.php');
...

Zeile 426 von
    $xml = simplexml_load_file($interface.'interface.php?systemNotification.cgi');
ändern zu
    $xml = simplexml_load_string(api_systemNotification($ccu));
Zur config.php war mein Vorschlag, die Konfiguration in ein Array zu packen. So lässt es sich leichter an Funktionen übergeben. Im Moment wird das in der interface.php zusammengebaut.
Da ich mir die anderen Skripte noch nicht im Detail angeschaut habe, ist die Frage, welcher Aufwand es wäre, das überall anzupassen.

Code: Alles auswählen

$ccu = Array(
  'host' => 'homematic-ccu',  // Hostname oder IP-Adresse der CCU. In der CCU-Firewall muss die IP-Adresse dieses Servers freigegeben sein.
  'user' => 'Remote-User',    // Benutzername für die Remote-Skript API
  'pw' => 'Remote-Password',  // Kennwort für die Remote-Skript API
  'https' => true             // true, wenn die Verbindung zur CCU über HTTPS aufgebaut werden soll, ansonsten false
);

steingarten
Beiträge: 327
Registriert: 28.10.2013, 18:38
Hat sich bedankt: 20 Mal
Danksagung erhalten: 46 Mal

Re: HomeHub 4.1

Beitrag von steingarten » 29.05.2024, 23:07

Eine Anpassung der config halte ich immer für sehr kritisch, da dann ein Update nicht mehr einfach möglich ist, daher habe ich dort die Finger immer möglichst weggelassen.

Ggf, könnte man den Code aber so Anpassen, das die config bei nicht validen oder fehlenden Einstellungen ein Setup aufruft und die config entsprechend schreibt. Das müsste man noch programmieren, aber dies könnte bei Updates so etwas "abfangen".

Deine Verbesserungen spiele ich mal Zuhause durch, ich befürchte, außer den den bei dir genannten Servicemeldungen und dem Import werden wir keine Optimierung hinbekommen, da alle anderen Aufrufe über Javascript getriggert werde . Aber jede Millisekunde zählt ;-)

P. S. : Ggf. noch bei den Diagrammen.

Antworten

Zurück zu „Sonstige Addons“