Heizkörperthermostat Heizprogramme per WebFront einstellen

Ich beschäftige mich gerade auch wieder mit der Heizungssteuerung.
ich habe in meiner früheren Installation das Script von Ernie genutzt und soweit ich mich zurück erinnere, konnte man zusätzliche Variable als Auslöser der Termeratursteuerung nutzen.

Z.b. dann eben eine Varible, die das heisst „HomeOffice“ oder „Urlaub“ oder oder oder, die dann per Kalender betankt werden, was ich derzeit bereits mit der iCal-Calender Anbindung nutze.

Ich werde mir nun mal beide Script ansehen, was mit IPS5 und der bei mir noch vorhandenen ganz alten Wandthermostate am besten funktioniert.
Der PHP-Guru bin ich nämlich leider nicht :slight_smile:

Bin auch gerade am Überarbeiten meiner Heizungssteuerung. Ich trage im Moment die einzelnen Solltemperaturen pro Raum noch in txt-Dateien ein, welche per Skript augelesen werden und den einzelnen Reglern als Soll vorgegeben werden (sind sogar noch FS20 Geräte). Also nicht gerade Anwenderfreundlich.
Wo kann ich die neueste Version deines Skriptes herunterladen, damit ich zumindest die Temperaturtabelle Anwenderfreundlich neu befüllen kann?
Oder gibt es inzwischen bessere und einfachere IPS-Lösungen um pro Tag verschiedene Temperaturen vorzugeben?

LG. und danke schon mal, Werner

Guten Abend zusammen,

ich bekomme aktuell diesen Fehler:

Blockzitat Fatal error: Cannot redeclare CreateVariableByName() (previously declared in /var/lib/symcon/scripts/System.Functions.ips.php:115) in /var/lib/symcon/scripts/HM_Heizung_Funktionen.ips.php on line 179

Dieser bezieht sich auf diese Funktion, wenn ich diese auskommentiere, ist der Fehler weg.
Woran kann das liegen, bis vor kurzem ging das noch?

function CreateVariableByName($parentID, $name, $type, $profile, $ident, $position) 
    {
        $vid = @IPS_GetVariableIDByName($name, $parentID);
        if($vid === false)
        {
            $vid = IPS_CreateVariable($type);
            IPS_SetParent($vid, $parentID);
            IPS_SetName($vid, $name);
				IPS_SetPosition ($vid, $position);
            IPS_SetInfo($vid, "this variable was created by script #".$_IPS['SELF']);
            if($profile !== "") { IPS_SetVariableCustomProfile($vid, $profile); }
				if($ident !=="") {IPS_SetIdent ($vid , $ident );}
			}
	  	  return $vid;
  }

Danke und viele Grüße
Stephan

Antwort ist relativ einfach!

Wie der Fehler schon sagt, das ein erneutes Deklarieren der Funktion nicht erlaubt ist.

Du hast mein Script System.Functions.php.ips installiert und wahrscheinlich global via autoload.php zur Verfügung gestellt.

Da das Heizprogramm Skript auch von mir ist und auch schon recht alt ist hat es die Funktionen noch selber mitgebracht.

Kann nur empfehlen meinen Block Artikel zu meiner Skriptbibliothek zu lesen und zu verinnerlichen.

Aber es zeigt mir leider, das ich mit der Veröffentlichung meiner neuen Vorgehensweise ein Fehler gemacht habe. War wohl ein zu offensiver Ansatz :frowning:

Hallo Heiko,

danke für die schnelle Antwort.

So ganz verstehe ich es noch nicht. Ich habe bezüglich der Heizung noch das Ausgangsskript von Swifty im Einsatz. Aber da ist ja auch die Funktion drin.

Ah dann geht es vermutlich nicht mehr seit ich dein Solarprognose Skript installiert habe, da habe ich ja deine Skriptbibliothek eingesetzt.

Wie gehe ich jetzt am Besten vor? Kann ich die Funktion im Skript einfach auskommentiert lassen?

Danke und Grüße
Stephan

Hi Stephan,

schmeiß mein Script aus der _autoload.php raus und nutze das „require_once“ im Solar-Script.

Biste auf der sicheren Seite!

Gruß Heiko

Alles klar Heiko, mach ich so. Danke :sweat_smile:.

Gruß Stephan

Hallo @pitti,

hast Du hier für Heizkörperthermostat Heizprogramme per WebFront einstellen - #563 von vita
zufällig schon eine Lösung?
auch beim Profil Speichern bekomme ich Fehler.


Lesen der Profile funktioniert mit weglassen von „$channel“.

Vielen Dank im voraus

Gruß

Jürgen

Oh gott, das Thema habe ich schon lange nicht mehr auf dem Tisch gehabt :slight_smile:

Welche Version vom Script nutzt Du denn?

Ich habe Version: 1.2.20200219

# ------------------------------ Changelog -------------------------------------
#
# 02.01.2019 - Initalversion (v1.0)
# 22.02.2019 - Bugfixes, mehr Doku(Hinweise) und Speichern ermöglicht (v1.1)
# 19.02.2020 - Bugfixes, ReadParamSet erweitert für Request ohne "channel"
#

Ob da das Problem umfassend gelöst ist kann ich Dir gar nicht sagen!

Gruß Heiko

Und ich Scriptbezeichnung: HomeMatic.TempSchedule.ips.php

Version: 1.1.20190222

Kannst ja das hier mal versuchen, aber mehr kann ich dann wahrscheinlich auch nicht helfen …

<?php
################################################################################
# Script:   HomeMatic.TempSchedule.ips.php
# Version:  1.2.20200219
# Author:   Heiko Wilknitz (@Pitti)
#           Basierend auf Zapp (2011) for the IPS Community
#           Erweitert von Swifty (Heizungs_Scripte v 0.1 - 15.02.2014)
#
# Auslese, Modifizieren und Speichern von Temperatur-Wochenplan
# von HomeMatic(IP)-Themostaten.
#
# !!! KEINE ÜBERNAHME VON GARANTIEN - NUTZUNG AUF EIGENE GEFAHR !!!
#
# ------------------------------ Installation ----------------------------------
#
# Dieses Skript richtet automatisch alle nötigen Objekte bei manueller
# Ausführung ein. Eine weitere manuelle Ausführung setzt alle benötigten Objekte
# wieder auf den Ausgangszustand.
#
# - Neues Skript erstellen
# - Diesen PHP-Code hineinkopieren
# - Abschnitt 'Konfiguration' den eigenen Gegebenheiten anpassen 
# - Skript Abspeichern
# - Skript Ausführen
# - Visualisierung per Link auf entstandene Variablen erstellen
#
# ------------------------------ Visualisierung --------------------------------
#
# Kann natürlich jeder machen wie er möchte, hier ein schematischer Vorschlag
# wie man vorgehen könnte:
#
# Zweischpaltiges Splitpane Layout (Vertikal 50:50)
# 
#   LINKE SEITE                             RECHTE SEITE
# 1. Link auf "Zimmer"                   Dummy Modul "Profil editieren"
# 2. Link auf "Wochenprogramm"            1. Link auf "Tag"
# 3. Link auf "Profil"                    2. Link auf "Zeitabschnitt"
# 4. Link auf "Wochenprofil"              3. Link auf "Zeit"
# 5. Link auf "Tagesprofil"               4. Link auf "Temperatur"
#                                         5. Link auf "Abschnitt"
#                                        Dummy Modul "Tagesprofil kopieren"
#                                         1. Link auf "Tagesauswahl"
#                                         2.Link auf "Kopieren"
#                                        Dummy Modul "Wochenprofil übertragen"
#                                         1. Link auf "Zimmerauswahl"
#                                         2. Link auf "Programmauswahl"
#                                         1. Link auf "Übertragen"
#
# ------------------------------ Changelog -------------------------------------
#
# 02.01.2019 - Initalversion (v1.0)
# 22.02.2019 - Bugfixes, mehr Doku(Hinweise) und Speichern ermöglicht (v1.1)
# 19.02.2020 - Bugfixes, ReadParamSet erweitert für Request ohne "channel"
#
# ------------------------------ Konfiguration ---------------------------------
#
# RPC clients
$client = array();
#
# Service IP (CCUx)
$ip = 'xxx.xxx.x.x';
#
# Nach dem Übertragen eines Profils an die Geräte wird eine Meldung ausgegeben.
# Soll dafür WFC_SendNotification verwendet werden dann bitte die notwendige
# WebFront-ID hinterlegen, ansonsten erfolgt eine nicht ganz so schöne
# Echo-Ausgabe, welche leider die Überschrift "Fehler" hat :(
$wfc = 0;
#
# BidCos Service Port (true = vorhanden & aktiv) 
$service = array(
    array('ID' => 0, 'TYPE' =>'RF', 'PORT' =>2001, 'ACTIVE' => true),   // HM
    array('ID' => 1, 'TYPE' =>'IP', 'PORT' =>2010, 'ACTIVE' => true),   // HM IP
    array('ID' => 2, 'TYPE' =>'WD', 'PORT' =>2000, 'ACTIVE' => false)   // Wired
);
#
# Räume (siehe nachfolgende Elementbelegung) 
#  (0) Logische Id (einfach von 0 durchnummerieren, oder eigene Logik verwenden)
#  (1) Name des Raumes
#  (2) Icon (sollte leer bleiben)
#  (3) Farbe (RGB-Wert, default -1)
#  (4) Wandthermostat-ID (oder auch direkt ein Heizkörperthermostat möglich)
#  (5) 1.Heizkörperthermostat-ID [mit Wandtherostat gekoppelt] - optional
#  (6) 2.Heizkörperthermostat-ID [mit Wandtherostat gekoppelt] - optional
#  (+) x.Heizkörperthermostat-ID [mit Wandtherostat gekoppelt] - optional
#
# HINWEIS IDs:
#  HmIP-WTH-2       - Kanal:1 - HEATING_CLIMATECONTROL_TRANSCEIVER
#  HmIP-eTRV        - Kanal:1 - HEATING_CLIMATECONTROL_TRANSCEIVER
#  HmIP-eTRV-2      - Kanal:1 - HEATING_CLIMATECONTROL_TRANSCEIVER
#  HM-CC-TC         - Kanal:2 - CLIMATECONTROL_REGULATOR
#  HM-CC-RT-DN      - Kanal:2 - CLIMATECONTROL_RECEIVER (ungetestet!!!)
#  HM-TC-IT-WM-W-EU - Kanal:2 - THERMALCONTROL_TRANSMIT (ungetestet!!!)
$room = array (  
    array(12, '1 - KG: Hoppyraum', '', -1, 50660, 26857),
    array(21, '2 - EG: Küche', '', -1, 21113, 23635, 11542),
    array(22, '2 - EG: Wohnen', '', -1, 23498, 58689),
    array(31, '3 - OG: Bad', '', -1, 56832, 33650),
    array(32, '3 - OG: Gäste', '', -1, 20199, 11234),
    array(33, '3 - OG: Arbeit', '', -1, 55797, 56530),
    array(34, '3 - OG: Schlafen', '', -1, 30734, 43879, 52032),
    array(41, '4 - DG: Studio', '', -1, 20652, 52057),
    array(42, '4 - DG: Bad', '', -1, 50467, 13788),
);
# Wochenplan Profil
$program = array (
    array(1, 'Arbeitswoche', '', 255),  // oder Normal
    array(2, 'Zuhause', '', 255),       // oder Frei
    array(3, 'Aus', '', 255)            // oder Abwesend
);
# Auslesen/Speichern Profil
$readwrite = array(
    array(0, 'Auslesen', '', 0x008000),
    array(1, 'Speichern', '', 0xFF0000)
);
# Kopieren Profil 
$copy = array(
    array(0, ">", "", -1),
    array(1, "Kopieren", "", 0x008000),
);
# Übertragen Profil 
$move = array(
    array(0, ">", "", -1),
    array(1, "Übertragen", "", 0x008000),
);
# Wochentag Profil
$day = array(
    array(0, 'Mo', '', -1),
    array(1, 'Di', '', -1),
    array(2, 'Mi', '', -1),
    array(3, 'Do', '', -1),
    array(4, 'Fr', '', -1),
    array(5, 'Sa', '', -1),
    array(6, 'So', '', -1)
);
# Zeit Profil
$time = array(
    array(1, '-1 h', '', 0x00FF00),
    array(2, '-10 min', '', 0x00FF00),
    array(3, '+10 min', '', 0xFF8000),
    array(4, '+1 h', '', 0xFF8000)
);
# Temperatur Profil
$temperature = array(
    array(1, '-1 °C', '', 0x3366FF),
    array(2, '-0,5 °C', '', 0x3366FF),
    array(3, '+0,5 °C', '', 0xFF0000),
    array(4, '+1 °C', '', 0xFF0000)
);
# Abschnitt Profil
$slot = array(
    array(1, 'Löschen', '', 0xFFCC99),
    array(2, 'Anfügen', '', 0xCCFFCC)
);
# Wochentage
$weekday = array("MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY");
#
################################################################################

################################################################################
# HINWEIS: Ich arbeite mit einer alten Version der Xml-RPC API Datei,
#          welche ich extra patchen musste damit alles funktioniert.
#          Wer das nicht möchte kann auch die Version 4.3.0 installieren!
#          DANN die nachfolgende Zeile durch ...
#          require "phpxmlrpc-4.3.0/lib/xmlrpc.inc"; oder so ersetzen!!!
require "__xmlrpc.inc.php" ;
################################################################################

//Init XMLRPC clients
Init();
// wichtig, da sonst am Tag der Zeitumstellung WZ/SZ Konflikte auftreten.
date_default_timezone_set('UTC'); 

// INSTALLATION
    if ($_IPS['SENDER']=='Execute') {
    $pos = 0;
    // Zimmer
    $vpn = "HM.Heating.Room";
    $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
    CreateProfileInteger($vpn, 'HouseRemote', '', '', 0, 0, 0, 0, $room);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Wochenprogramm
    $vpn = "HM.Heating.Program";
    $vid = CreateVariableByName($_IPS['SELF'], "Wochenprogramm", 1);
    CreateProfileInteger($vpn, 'Temperature', '', '', 0, 0, 0, 0, $program);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    SetValue($vid, 1);
    // Auslese/Speichern Button
    $vpn = "HM.Heating.ReadWrite";
    $vid = CreateVariableByName($_IPS['SELF'], "Profil", 1);
    CreateProfileInteger($vpn, 'Script', '', '', 0, 0, 0, 0, $readwrite);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    SetValue($vid, 0);
    // Wochen(Temperatur)profil
    $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprofil', 3);
    IPS_SetIcon($vid, "Calendar");
    IPS_SetVariableCustomProfile($vid, '~HTMLBox');
    IPS_SetPosition($vid, $pos++);
    // Tages(Temperatur)profil
    $vid = CreateVariableByName($_IPS['SELF'], 'Tagesprofil', 3);
    IPS_SetIcon($vid, "Clock");
    IPS_SetVariableCustomProfile($vid, '~HTMLBox');
    IPS_SetPosition($vid, $pos++);
    // Tagesauswahl
    $vpn = "HM.Heating.Day";
    $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
    CreateProfileInteger($vpn, 'Calendar', '', '', 0, 0, 0, 0, $day);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Zeitabschnitt auswählen
    $vpn = "HM.Heating.Slot";
    $vid = CreateVariableByName($_IPS['SELF'], "Zeitabschnitt", 1);
    CreateProfileInteger($vpn, 'Database', '', '. Zeitabschnitt', 1, 3, 1, 0);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Zeit editieren
    $vpn = "HM.Heating.Time";
    $vid = CreateVariableByName($_IPS['SELF'], "Zeit", 1);
    CreateProfileInteger($vpn, 'Clock', '', '', 0, 0, 0, 0, $time);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Temperatur editieren
    $vpn = "HM.Heating.Temperature";
    $vid = CreateVariableByName($_IPS['SELF'], "Temperatur", 1);
    CreateProfileInteger($vpn, 'Temperature', '', '', 0, 0, 0, 0, $temperature);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Abschnitt editieren
    $vpn = "HM.Heating.Edit";
    $vid = CreateVariableByName($_IPS['SELF'], "Abschnitt", 1);
    CreateProfileInteger($vpn, 'Edit', '', '', 0, 0, 0, 0, $slot);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Tagesauswahl kopieren
    $vpn = "HM.Heating.Day";
    $vid = CreateVariableByName($_IPS['SELF'], "Tagesauswahl", 1);
    CreateProfileInteger($vpn, 'Calendar', '', '', 0, 0, 0, 0, $day);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Kopieren
    $vpn = "HM.Heating.Copy";
    $vid = CreateVariableByName($_IPS['SELF'], "Kopieren", 1);
    CreateProfileInteger($vpn, 'Script', '', '', 0, 0, 0, 0, $copy);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    SetValue($vid, 0);
    // Zimmerauswahl
    $vpn = "HM.Heating.Room";
    $vid = CreateVariableByName($_IPS['SELF'], "Zimmerauswahl", 1);
    CreateProfileInteger($vpn, 'HouseRemote', '', '', 0, 0, 0, 0, $room);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    // Programmauswahl
    $vpn = "HM.Heating.Program";
    $vid = CreateVariableByName($_IPS['SELF'], "Programmauswahl", 1);
    CreateProfileInteger($vpn, 'Temperature', '', '', 0, 0, 0, 0, $program);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    SetValue($vid, 1);
    // Übertragen
    $vpn = "HM.Heating.Move";
    $vid = CreateVariableByName($_IPS['SELF'], "Übertragen", 1);
    CreateProfileInteger($vpn, 'Script', '', '', 0, 0, 0, 0, $move);
    IPS_SetVariableCustomProfile($vid, $vpn);
    IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
    IPS_SetPosition($vid, $pos++);
    SetValue($vid, 0);
    // Profile Cache
    $vid = CreateVariableByName($_IPS['SELF'], "Profiles", 3);
    IPS_SetHidden($vid, true);
    IPS_SetPosition($vid, -1);
    // Types Cache
    $vid = CreateVariableByName($_IPS['SELF'], "Types", 3);
    IPS_SetHidden($vid, true);
    IPS_SetPosition($vid, -1);
    }
    // AKTION VIA WEBFRONT
    else if($_IPS['SENDER'] == "WebFront") {
    // Aktion
    $name = IPS_GetName($_IPS['VARIABLE']);
    // ZIMMER -------------------------------------------------------------------
    if($name == 'Zimmer') {
        // Welcher Raum?
        $rn = $_IPS['VALUE'];
        // Welches Wochenprogramm?
        $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
        $wp = GetValue($vid);
        // Welcher Tag?
        $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
        $wd = GetValue($vid);
        // Rendern
        RenderProfile($rn, $wp, $wd);
    }
    // WOCHENPROGRANN -----------------------------------------------------------
    if($name == 'Wochenprogramm') {
        // Welches Zimmer?
        $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
        $rn = GetValue($vid);
        // Welches Wochenprogramm?
        $wp = $_IPS['VALUE'];	
        // Welcher Tag?
        $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
        $wd = GetValue($vid);
        // Rendern
        RenderProfile($rn, $wp, $wd);
    }
    // AUSLESEN/SPEICHERN -------------------------------------------------------
    if( $name == 'Profil') {
        // Welches Zimmer?
        $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
        $rn  = GetValue($vid);	
        // Welches Wochenprogramm?
        $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
        $wp  = GetValue($vid);
        // Welcher Tag?
        $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
        $wd = GetValue($vid);
        // AUSLESEN
        if($_IPS['VALUE'] == 0) {
            // Temperatur Profil vom Gerät auslesen
            foreach($room as $value) {
                if($value[0] == $rn) {
                    $profile = ReadTempProfile($value[4], false);
                    SetWeeklyProfile($rn, $profile);
                    break;
                }
            }
            // Rendern
            RenderProfile($rn, $wp, $wd);
        }
        // SPEICHERN
        if($_IPS['VALUE'] ==1) {
            // Wochenprofil ermitteln
            $profile = GetWeeklyProfile($rn, $wp);
            // Teste Integrität der Tagesprofile
            $check = CheckWeeklyProfile($profile);
            if($check == "OK") {
                foreach($room as $value) {
                    if($value[0] == $rn) {
                        // Profil zum Gerät übertragen
                        $count = count($value);
                        for($d = 4; $d < $count; $d++) {
                            //echo $value[$d].PHP_EOL;
                            $check = WriteTempProfile($value[$d], $profile, $wp);
                            // IPS_Sleep(2000); 
                        }
                    }
                }
                if ($check == true) {
                    $check ="Speichern Erfolgreich";
                }
            }
            // Erolgsmeldung?!
            if($wfc != 0) {
                WFC_SendNotification($wfc, 'HM Heizungsplan', $check, 'Information', 5);
            }
            else {
                echo $check;
            }
        }
        $_IPS['VALUE'] = 0;
    }
    // TAG ----------------------------------------------------------------------
    if( $name == 'Tag') {
        // Welches Zimmer?
        $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
        $rn  = GetValue($vid);	
        // Welches Wochenprogramm?
        $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
        $wp  = GetValue($vid);
        // Welcher Tag?
        $wd  = $_IPS['VALUE'];
        // Rendern
        RenderProfile($rn, $wp, $wd);
    }
    // ZEITABSCHNITT ------------------------------------------------------------
    if( $name == 'Zeitabschnitt') {
        // Welches Zimmer?
        $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
        $rn  = GetValue($vid);	
        // Welches Wochenprogramm?
        $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
        $wp  = GetValue($vid);
        // Welcher Tag?
        $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
        $wd = GetValue($vid);
        // Profil extrahieren
        $profile = GetWeeklyProfile($rn, $wp);
        $profile = GetDailyProfile($profile, $wd);
        // Welcher Zeitabschnitt? 
        $ts = $_IPS['VALUE'];
        // Render Tagesprofil
        $vid = CreateVariableByName($_IPS['SELF'], 'Tagesprofil', 3);
        SetValue($vid, RenderDailyProfile($profile, $ts));		
    }
    // ZEIT EDITIEREN -----------------------------------------------------------
    if($name == 'Zeit') {
        // Welches Zimmer?
        $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
        $rn = GetValue($vid);
        // Welches Wochenprogramm?
        $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
        $wp  = GetValue($vid);
        // Welcher Tag?
        $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
        $wd = GetValue($vid);
        // Welcher Zeitabschnitt? 
        $vid = CreateVariableByName($_IPS['SELF'], "Zeitabschnitt", 1);
        $ts = GetValue($vid);
        // Wochenprofil ermitteln
        $profile = GetWeeklyProfile($rn, $wp);
        // Tagesprofil ermitteln
        $profile = GetDailyProfile($profile, $wd);
        // Aktion nur für die ersten Zeitabschnitte
        if($ts < count($profile['EndTimes'])) {
            // Verhindert dass die Zeit des letzten Slots geändert wird (immer 24:00)
            if($ts == 1) {
                $start = "00:00";
            }
            else {
                $start = $profile['EndTimes'][$ts-2];
            }
            $end  = $profile['EndTimes'][$ts-1];
            $next = $profile['EndTimes'][$ts];
            // Welche Aktion?		
            switch($_IPS['VALUE']) {
                case 1: // -1h
                    if((strtotime($end)-(60*60))> strtotime($start)) {
                        $end = date("H:i", (strtotime($end)-(60*60)));
                    }
                    $profile['EndTimes'][$ts-1] = $end;
                    break;
                case 2: // -10min
                    if((strtotime($end)-(10*60))> strtotime($start)) {
                        $end = date("H:i", (strtotime($end)-(10*60)));
                    }
                    $profile['EndTimes'][$ts-1] = $end;
                    break;
                case 3: // +10min
                    if((strtotime($end)+(10*60))< strtotime($next)) {
                        $end = date("H:i", (strtotime($end)+(10*60)));
                    }
                    $profile['EndTimes'][$ts-1] = $end;
                    break;
                case 4: // +1h
                    if((strtotime($end)+(60*60))< strtotime($next)) {
                        $end = date("H:i", (strtotime($end)+(60*60)));
                    }
                    $profile['EndTimes'][$ts-1] = $end;
                    break;
            }
            // Schreiben
            SetDailyProfile($rn, $wp, $wd, $profile);
            // Rendern
            RenderProfile($rn, $wp, $wd, $ts);
        }
        // Keine Auswahl
        $_IPS['VALUE'] = 0;		 	   
    }
    // TEMPERATUR EDITIEREN -----------------------------------------------------
    if($name == 'Temperatur') {
        // Welches Zimmer?
        $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
        $rn = GetValue($vid);
        // Welches Wochenprogramm?
        $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
        $wp  = GetValue($vid);
        // Welcher Tag?
        $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
        $wd = GetValue($vid);
        // Welcher Zeitabschnitt? 
        $vid = CreateVariableByName($_IPS['SELF'], "Zeitabschnitt", 1);
        $ts = GetValue($vid);
        // Wochenprofil ermitteln
        $profile = GetWeeklyProfile($rn, $wp);
        // Tagesprofil ermitteln
        $profile = GetDailyProfile($profile, $wd);
        // Welche Temperatur?
        $temperatur = $profile['Values'][$ts-1];
        // Welche Aktion?		
        switch($_IPS['VALUE']) {
            case 1: // -1°C
                if(($temperatur-1) >= 4.99) {
                    $temperatur = $temperatur-1;
                    $profile['Values'][$ts-1] = $temperatur;
                }
                break;
            case 2: // -0.5°C
                if(($temperatur-0.5) > 4.9) {
                    $temperatur = $temperatur-0.5;
                    $profile['Values'][$ts-1] = $temperatur;
                }
                break;
            case 3: // +0.5°C
                if(($temperatur+0.5) < 30.1) {
                    $temperatur = $temperatur+0.5;
                    $profile['Values'][$ts-1] = $temperatur;
                }
                break;
            case 4: // +1°C
                if(($temperatur+1) <= 30.01) {
                    $temperatur = $temperatur+1;
                    $profile['Values'][$ts-1] = $temperatur;
                }
                break;
        }
        // Schreiben
        SetDailyProfile($rn, $wp, $wd, $profile);
        // Rendern
        RenderProfile($rn, $wp, $wd, $ts);
        // Keine Auswahl
        $_IPS['VALUE'] = 0;
    }
    // ABSCHNITT EDITIEREN ------------------------------------------------------
    if( $name == 'Abschnitt') {
        // Welches Zimmer?
        $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
        $rn = GetValue($vid);
        // Welches Wochenprogramm?
        $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
        $wp  = GetValue($vid);
        // Welcher Tag?
        $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
        $wd = GetValue($vid);
        // Welcher Zeitabschnitt? 
        $vid = CreateVariableByName($_IPS['SELF'], "Zeitabschnitt", 1);
        $ts = GetValue($vid);
        // Wochenprofil ermitteln
        $profile = GetWeeklyProfile($rn, $wp);
        // Tagesprofil ermitteln
        $profile = GetDailyProfile($profile, $wd);
        // Wieviel Zeitabschnitte?
        $count = count($profile['EndTimes']);
        // Welche Aktion?		
        switch($_IPS['VALUE']) {
            case 1: // Löschen
                // letzter TimeSlot darf nicht gelöscht werden
                if ($count >1) {
                    array_splice($profile['EndTimes'], $ts-1, 1);
                    array_splice($profile['Values'], $ts-1, 1);
                    // letzten TimeSlot Ende immer 24:00
                    $profile['EndTimes'][$count-2]="24:00";
                }
                break;
            case 2: // Anfügen
                // max 13 TimeSlots zulässig (manche können auch 24, aber das sollte reichen)
                If ($count <13)  
                {
                    array_splice($profile['EndTimes'], $count, 0, "24:00");
                    array_splice($profile['Values'], $count, 0, "17");
                    // minimaler TimeSlot ist 10 min
                    $profile['EndTimes'][$count-1]="23:50";
                }
                break;
        }
        // Wurde was geändert?
        if($count <> count($profile['EndTimes'])) {
            SetDailyProfile($rn, $wp, $wd, $profile);
            // Rendern
            RenderProfile($rn, $wp, $wd);
        }
        // Keine Auswahl
        $_IPS['VALUE'] = 0;
    }
    // TAGESPROFIL KOPIEREN -----------------------------------------------------
    if( $name == 'Kopieren') {
        if($_IPS['VALUE'] ==1) {
            // Welchem Zimmer?
            $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
            $rn = GetValue($vid);
            // Welches Wochenprogramm?
            $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
            $wp  = GetValue($vid);
            // Von welcher Tag?
            $vid = CreateVariableByName($_IPS['SELF'], "Tag", 1);
            $wd = GetValue($vid);
            // Nach Welchen Tag? 
            $vid = CreateVariableByName($_IPS['SELF'], "Tagesauswahl", 1);
            $ta = GetValue($vid);
            if($wd == $ta) {
                echo ('Bitte anderen Tag auswählen!');
            }
            else {
                // Wochenprofil ermitteln
                $profile = GetWeeklyProfile($rn, $wp);
                // Tagesprofil von 
                $profile = GetDailyProfile($profile, $wd);
                // kopieren nach
                SetDailyProfile($rn, $wp, $ta, $profile);
                // Rendern
                RenderProfile($rn, $wp, $wd);
            }
        }
        $_IPS['VALUE'] = 0;
    }
    // WOCHENPROFIL ÜBERTRAGEN --------------------------------------------------
    if( $name == 'Übertragen') {
        if($_IPS['VALUE'] ==1) {
            // Welchem Zimmer?
            $vid = CreateVariableByName($_IPS['SELF'], "Zimmer", 1);
            $rn = GetValue($vid);
            // Welches Wochenprogramm?
            $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprogramm', 1);
            $wp  = GetValue($vid);
            // Nach welchen Zimmer?
            $vid = CreateVariableByName($_IPS['SELF'], "Zimmerauswahl", 1);
            $za = GetValue($vid);
            // Nach welchen Program? 
            $vid = CreateVariableByName($_IPS['SELF'], "Programmauswahl", 1);
            $pa = GetValue($vid);
            if(($rn == $za) and ($wp == $pa)) {
                echo ('Auf sich selber zu übertragen macht keinen Sinn!');
            }	
            else {
                // Wochenprofil holen
                $profile = GetWeeklyProfile($rn, $wp);
                // Übertragen
                SetWeeklyProfile($za, $profile, $pa);
            }
        }
        $_IPS['VALUE'] = 0;
    }
    // DATENÜBERNAHME ------------------------------------------------------
    SetValue($_IPS['VARIABLE'], $_IPS['VALUE']);
}

# ------------------------------ Funktionen ------------------------------------

// Erzeugt pro aktiven Interface ein Client.
function Init() {
    global $ip, $service, $client;
    # Return Code 
    $ret = true;
    # Check all Services
    foreach($service as $s) {
        if($s['ACTIVE'] == true) {
            if (!isset($client[$s['TYPE']]) || $client[$s['TYPE']] !== false) {
                $client[$s['TYPE']] = new xmlrpc_client("http://".$ip.":".$s['PORT']);
            if ($client[$s['TYPE']] !== false) {
                    $ret &= true;
                }
                else {
                    $ret = false;
                }
            }
        }
    }
    // client existieren schon
    return false;
}

// Liefert alle Geräte der aktivierten Interfaces 
function DevicesList() {
    global $service, $client;
    //	listDevices
    $request = new xmlrpcmsg('listDevices');
    // merge all together
    $devices = array();
    foreach($service as $s) {
        if($s['ACTIVE'] == true) {
            $ret = Send($request, $s['TYPE']);
            foreach($ret as $device) {
                $device['INTERFACE'] = $s['ID'];
                $devices[] = $device;
            }
            //$devices = array_merge($devices, Send($request, $s['TYPE']));
        }
    }
    return $devices;
}

// Ermittelt den Typ des HM Gerätes (HM terminology)
function DeviceType($device) {
    // Cache auslesen
    $cid = CreateVariableByName($_IPS['SELF'], "Types", 3);
    $types = unserialize(GetValue($cid));
    // HM Adresse vom Device
    $address = explode(":", IPS_GetProperty($device, 'Address'));
    $serial  = $address[0];
    $channel = $address[1];
    // schon mal gelesen
    if(!is_array($types) || array_key_exists($serial, $types) == false) {
        $type = false;
        $list = DevicesList();
        foreach($list as $dev) {
            if (strpos($dev['ADDRESS'], $serial) !== false) {
                $type = $dev['TYPE'].':'.$dev['INTERFACE'];
                $types[$serial] = $type;
                SetValue($cid, serialize($types));
                break;  // We stop at the first one we find
            }
        }
    }
    else
    {
        $type=$types[$serial];
    }
    return $type;
}

// Liest das Temperaturprofil von einem Thermostat für den übergebenen Tag.
// $device: IPS Instance ID
// $day: Name des Tages in English (not case-sensitive) oder false für alle Tage
// $weekprofil: nur für HM-TC-IT-WM-W-EU & HmIP-WTH-2; 
//   gültige Werte 1,2,3; bei -1 werden alle Profile (1-3) zurückgegeben
function ReadTempProfile($device, $day = false, $weekprofil =-1) {
    global $service, $weekday;
    // HM Adresse vom Device
    $address = explode(":", IPS_GetProperty($device, 'Address'));
    $serial  = $address[0];
    $channel = $address[1];

    $days = $weekday;
    $temp = array();

    if ($day != false) {
        if(!in_array($day, $weekday)) die("Error: Unknown Day parameter in function ReadTempProfile!");
        $days = array($day);
    }
    // Was für ein HM Gerätetyp & Interface
    $dt 	= explode(":", DeviceType($device));
    $type = $dt[0];
    $if	= $dt[1];
    // Konvert Interface
    foreach($service as $s) {
        if($s['ID'] == $if) {
            $if = $s['TYPE'];
            break;
        }
    }	
    // HM-CC-TC Profil auslesen (hat nur eins)
    if($type == "HM-CC-TC") {
        $params = ReadParamSet($if, $serial, $channel);
        foreach($days as $day) {
            $thisEndTimes 	= array();
            $thisValues		= array();
            $timePrevious 	= "00:00";
            for($index 	= 1; $index <= 24; $index++) {
                $keyTemp 	= "TEMPERATUR_".strtoupper($day)."_".$index;
                $keyTO 		= "TIMEOUT_".strtoupper($day)."_".$index;
                $thisTemp 	= $params[$keyTemp];
                $thisTO 		= $params[$keyTO];
                $thisTime 	= date('H:i', mktime(0, $thisTO)); // $timePassed + TO
                if($thisTO >= 1440) $thisTime = "24:00";
                $timePrevious = $thisTime;
                array_push($thisEndTimes,	$thisTime);
                array_push($thisValues,		$thisTemp);
                if($thisTO >= 1440) break;
            }
            $temp["P1"][$day]['EndTimes'] = $thisEndTimes;
            $temp["P1"][$day]['Values'] 	= $thisValues;
        }
        return $temp;
    }
    // HM-CC-RT-DN Profil auslesen (hat nur eins)	
    if($type == "HM-CC-RT-DN") {
        $params = ReadParamSet($if, $serial, null);
        foreach($days as $day) {
            $thisEndTimes 	= array();
            $thisValues		= array();
            $timePrevious  = "00:00";
            for($index = 1; $index <= 13; $index++) {
                $keyTemp 	= "TEMPERATURE_".strtoupper($day)."_".$index;
                $keyTO 		= "ENDTIME_".strtoupper($day)."_".$index;
                $thisTemp 	= $params[$keyTemp];
                $thisTO 		= $params[$keyTO];
                $thisTime = date('H:i', mktime(0, $thisTO)); // $timePassed + TO
                if($thisTO >= 1440) $thisTime = "24:00";
                $timePrevious = $thisTime;
                array_push($thisEndTimes,  $thisTime);
                array_push($thisValues,		$thisTemp);
                if($thisTO >= 1440) break;
            }
            $temp["P1"][$day]['EndTimes'] = $thisEndTimes;
            $temp["P1"][$day]['Values'] 	= $thisValues;
        }
        return $temp;
    }	
    // HM-TC-IT-WM-W-EU Profil auslesen (1-3)	
    if($type == "HM-TC-IT-WM-W-EU") {
        $params = ReadParamSet($if, $serial, $channel);
        // 3 Profile
        for ($p=1; $p<=3; $p++) {
            foreach($days as $day) {
                $thisEndTimes 	= array();
                $thisValues		= array();
                $timePrevious 	= "00:00";
                for($index 	= 1; $index <= 13; $index++) {
                    $keyTemp 	= "P". $p ."_TEMPERATURE_".strtoupper($day)."_".$index;
                    $keyTO 		= "P". $p ."_ENDTIME_".strtoupper($day)."_".$index;
                    //* notwendig da Firmeware beim LAN-Adapter abweicht und beim Profil 1 dort das Präfix "P1_" fehlt.
                    if(array_key_exists($keyTemp, $params)) {
                        $thisTemp 	= $params[$keyTemp];
                        $thisTO 		= $params[$keyTO];
                    }
                    else {
                        $keyTemp 	= "TEMPERATURE_".strtoupper($day)."_".$index;
                        $keyTO 		= "ENDTIME_".strtoupper($day)."_".$index;
                        $thisTemp 	= $params[$keyTemp];
                        $thisTO 		= $params[$keyTO];
                    }
                    $thisTime = date('H:i', mktime(0, $thisTO)); // $timePassed + TO
                    if ($thisTO >= 1440) $thisTime = "24:00";
                    $timePrevious = $thisTime;
                    array_push($thisEndTimes,	$thisTime);
                    array_push($thisValues,		$thisTemp);
                    if($thisTO >= 1440) break;
                }
                $temp["P".$p][$day]['EndTimes'] 	= $thisEndTimes;
                $temp["P".$p][$day]['Values'] 	= $thisValues;
            }
        }
        if($weekprofil > 0 and $weekprofil <= 3) {
            return $temp["P".$weekprofil];
        }
        else {
            return $temp;
        }
    }
    // HmIP-WTH-2 || 	HMIP-eTRV || HmIP-eTRV-2 Profil auslesen (1-3 von 6)	
    if($type == "HmIP-WTH-2" or $type =="HmIP-eTRV-2" or $type == "HMIP-eTRV") {
        $params = ReadParamSet($if, $serial, $channel);
        // 3 Profile
        for ($p=1; $p<=3; $p++) {
            foreach($days as $day) {
                $thisEndTimes 	= array();
                $thisValues		= array();
                $timePrevious 	= "00:00";
                for($index 	= 1; $index <= 13; $index++) {
                    $keyTemp 	= "P". $p ."_TEMPERATURE_".strtoupper($day)."_".$index;
                    $keyTO 		= "P". $p ."_ENDTIME_".strtoupper($day)."_".$index;
                    $thisTemp 	= $params[$keyTemp];
                    $thisTO 		= $params[$keyTO];
                    $thisTime 	= date('H:i', mktime(0, $thisTO)); // $timePassed + TO
                    if ($thisTO >= 1440) $thisTime = "24:00";
                    $timePrevious = $thisTime;
                    array_push($thisEndTimes,	$thisTime);
                    array_push($thisValues,		$thisTemp);
                    if($thisTO >= 1440) break;
                }
                $temp["P".$p][$day]['EndTimes'] 	= $thisEndTimes;
                $temp["P".$p][$day]['Values'] 	= $thisValues;
            }
        }
        if($weekprofil > 0 and $weekprofil <= 3) {
            return $temp["P".$weekprofil];
        }
        else {
            return $temp;
        }
    }
    echo $type;
    if($type != "HM-CC-RT-DN" and $type != "HM-CC-TC" and $type != "HM-TC-IT-WM-W-EU" and $type != "HmIP-WTH-2" and $type != "HMIP-eTRV" and $type != "HmIP-eTRV-2") {
        die("Error: ReadTempProfile() Device $device is not of Type HM-CC-TC,HM-CC-RT-DN, HM-TC-IT-WM-W-EU, HmIP-WTH-2, HMIP-eTRV or HmIP-eTRV-2!");
    }
}

// Schreibt das Temperaturprofil in ein Thermostat/Stellantrieb.
// $device: IPS Instance ID
// $profile: Temperaturprofil wie von ReadTempProfile() geliefert
// $weekprofil: nur für HM-TC-IT-WM-W-EU & HmIP-WTH-2; 
//   gültige Werte 1,2,3; bei -1 werden alle Profile (1-3) zurückgegeben
function WriteTempProfile(int $device, array $profile, int $weekprofile=0) {
    global $service, $weekday;
    // HM Adresse vom Device
    $address = explode(":", IPS_GetProperty($device, 'Address'));
    $serial  = $address[0];
    $channel = $address[1];
    // Was für ein HM Gerätetyp & Interface
    $dt 	= explode(":", DeviceType($device));
    $type = $dt[0];
    $if 	= $dt[1];
    // Konvert Interface
    foreach($service as $s) {if($s['ID'] == $if) {$if = $s['TYPE'];break;}}
    // HM-CC-TC Profil schreiben (hat nur eins)
    if($type == "HM-CC-TC") {
        $params = new xmlrpcval();
        foreach($profile as $day => $values) {
            $timePrevious = "00:00";
            for($index=1; $index <= count($values['EndTimes']); $index++) {
                $key = "TEMPERATUR_".strtoupper($day)."_".$index;
                $temp = array($key => new xmlrpcval($values['Values'][$index-1], "double"));
                $params->addStruct($temp);
                $key = "TIMEOUT_".strtoupper($day)."_".$index;
                if ($values['EndTimes'][$index-1] > $timePrevious) {
                    // Convert end time to Timeout
                    $thisDayStart = mktime(0, 0);
                    $timeEndArray = explode(":", $values['EndTimes'][$index-1]);
                    if ($timeEndArray[1] % 10) die("Error: Invalid End Time (must be 10mn increments) for $day at index $index in WriteTempProfile()!");
                    $timeEndts = mktime($timeEndArray[0], $timeEndArray[1]);
                    $timeout = (($timeEndts - $thisDayStart)/60); // TODO, works  ?
                    $paramTime = array($key => new xmlrpcval("$timeout", "int")); // i4
                    $params->addStruct($paramTime);
                }
                else {
                    die("Error: Invalid End Time for $day at index $index in WriteTempProfile()!");
                }
                $timePrevious = $values['EndTimes'][$index-1];
            }
        }
        $request = new xmlrpcmsg("putParamset",
            array(new xmlrpcval("$serial:2", "string"),
                    new xmlrpcval("MASTER", "string"), $params));
        $result = Send($request, $if);
        return true;
    }
    // HM-CC-RT-DN Profil schreiben (hat nur eins)	
    if($type == "HM-CC-RT-DN") {
        $params = new xmlrpcval();
        foreach ($profile as $day => $values) {
            $timePrevious = "00:00";
            for($index=1; $index <= count($values['EndTimes']); $index++) {
                $key = "TEMPERATURE_".strtoupper($day)."_".$index;
                $temp = array($key => new xmlrpcval($values['Values'][$index-1], "double"));
                $params->addStruct($temp);
                $key = "ENDTIME_".strtoupper($day)."_".$index;
                if ($index>13) break; // HM-CC-RT-DN hat nur 13 Tages - Timeslots
                if ($values['EndTimes'][$index-1] > $timePrevious) {
                    // Convert end time to Timeout
                    $thisDayStart = mktime(0, 0);
                    $timeEndArray = explode(":", $values['EndTimes'][$index-1]);
                    if ($timeEndArray[1] % 10) die("Error: Invalid End Time (must be 10mn increments) for $day at index $index in WriteTempProfile()!");
                    $timeEndts = mktime($timeEndArray[0], $timeEndArray[1]);
                    $timeout = (($timeEndts - $thisDayStart)/60); // TODO, works  ?
                    $paramTime = array($key => new xmlrpcval("$timeout", "int")); // i4
                    $params->addStruct($paramTime);
                }
                else {
                    die("Error: Invalid End Time for $day at index $index in WriteTempProfile()!");
                }
                $timePrevious = $values['EndTimes'][$index-1];
            }
        }
        $request = new xmlrpcmsg("putParamset",
            array(new xmlrpcval("$serial", "string"), // no channel NOT TESTED????
                    new xmlrpcval("MASTER", "string"), $params));
        $result = Send($request, $if);
        return true;
    }
    // HM-TC-IT-WM-W-EU Profil schreiben (1-3)	
    if ($type == "HM-TC-IT-WM-W-EU") {
        $prefix="P".$weekprofile."_";
        $params = new xmlrpcval();
        foreach ($profile as $day => $values) {
            $timePrevious = "00:00";
            for ($index=1; $index <= count($values['EndTimes']); $index++) {
                $key = $prefix ."TEMPERATURE_".strtoupper($day)."_".$index;
                $temp = array($key => new xmlrpcval($values['Values'][$index-1], "double"));
                $params->addStruct($temp);
                $key = $prefix ."ENDTIME_".strtoupper($day)."_".$index;
                if ($index>13) break; // HM-TC-IT-WM-W-EU hat nur 13 Tages - Timeslots
                if ($values['EndTimes'][$index-1] > $timePrevious) {
                    // Convert end time to Timeout
                    $thisDayStart = mktime(0, 0);
                    $timeEndArray = explode(":", $values['EndTimes'][$index-1]);
                    if ($timeEndArray[1] % 5) die("Error: Invalid End Time (must be 10mn increments) for $day at index $index in WriteTempProfile()!");
                    $timeEndts = mktime($timeEndArray[0], $timeEndArray[1]);
                    $timeout = (($timeEndts - $thisDayStart)/60); // TODO, works  ?
                    $paramTime = array($key => new xmlrpcval("$timeout", "int")); // i4
                    $params->addStruct($paramTime);
                }
                else {
                    die("Error: Invalid End Time for $day at index $index in WriteTempProfile()!");
                }
                $timePrevious = $values['EndTimes'][$index-1];
            }
        }
        $request = new xmlrpcmsg("putParamset",
            array(new xmlrpcval("$serial", "string"), // no channel NOT TESTED????
                    new xmlrpcval("MASTER", "string"), $params));
        $result = Send($request, $if);
        return true;
    }
    // HmIP-WTH-2 || 	HMIP-eTRV || HmIP-eTRV-2 Profil schreiben (1-3 von 6)	
    if($type == "HmIP-WTH-2" or $type =="HmIP-eTRV-2" or $type == "HMIP-eTRV") {
        $prefix="P".$weekprofile."_";
        $params = new xmlrpcval();
        foreach ($profile as $day => $values) {
            $timePrevious = "00:00";
            for ($index=1; $index <= count($values['EndTimes']); $index++) {
                $key = $prefix ."TEMPERATURE_".strtoupper($day)."_".$index;
                $temp = array($key => new xmlrpcval($values['Values'][$index-1], "double"));
                $params->addStruct($temp);
                $key = $prefix ."ENDTIME_".strtoupper($day)."_".$index;
                if ($index>13) break; // nur 13 Tages - Timeslots
                if ($values['EndTimes'][$index-1] > $timePrevious) {
                    // Convert end time to Timeout
                    $thisDayStart = mktime(0, 0);
                    $timeEndArray = explode(":", $values['EndTimes'][$index-1]);
                    if ($timeEndArray[1] % 5) die("Error: Invalid End Time (must be 10mn increments) for $day at index $index in HMXML_setTempProfile()<br>\n");
                    $timeEndts = mktime($timeEndArray[0], $timeEndArray[1]);
                    $timeout = (($timeEndts - $thisDayStart)/60); // TODO, works  ?
                    $paramTime = array($key => new xmlrpcval("$timeout", "int")); // i4
                    $params->addStruct($paramTime);
                }
                else {
                    die("Error: Invalid End Time for $day at index $index in WriteTempProfile()!");
                }
                $timePrevious = $values['EndTimes'][$index-1];
            }
        }
        $request = new xmlrpcmsg("putParamset",
            array(new xmlrpcval("$serial:$channel", "string"),
                    new xmlrpcval("MASTER", "string"), $params));
        //var_dump($params);
        $result = Send($request, $if);
        return true;
    }
    if($type != "HM-CC-RT-DN" and $type != "HM-CC-TC" and $type != "HM-TC-IT-WM-W-EU" and $type != "HmIP-WTH-2" and $type != "HMIP-eTRV" and $type != "HmIP-eTRV-2") {
        die("Error: WriteTempProfile() Device $device is not of Type HM-CC-TC,HM-CC-RT-DN, HM-TC-IT-WM-W-EU, HmIP-WTH-2, HMIP-eTRV or HmIP-eTRV-2!");
    }
}

// Liest die Parameter von einem Gerät aus.
// $if: HM Inteface
// $adress: HM adress
// $channel: HM device chanvel
// $param: Ein spezifischer Parameter wird ausgelesen (siehe HomeMatic Specficiation),sonst alle
function ReadParamSet($if, $address, $channel, $param = false) {
    // Build request
    $value = $address;
    if($channel != null) {
        $value .= ":".$channel;
    }
    $request = new xmlrpcmsg("getParamset",
        array(new xmlrpcval("$value", "string"), new xmlrpcval("MASTER", "string")));
    $messages = Send($request, $if);
    //var_dump($messages);
    if ($param !== false) return $messages[$param];
    return $messages;
}

// Creates XMLRPC Client Instance and sends request
function Send($request, $type) 
{
    global $client;
    // If the client does not exist, initialise it here
    if (isset($client[$type]) &&  $client[$type] !== false) {
        $response = $client[$type]->send($request);
        if ( $response->errno == 0 ) {
        $messages = php_xmlrpc_decode($response->value());
        }
        else {
            die("Error: Send() Request to $type Service failed -> $response->errstr!\n");
        }
    }
    return $messages;
}

// Extrahiert für den übergebenen Raum und Wochenprofil das entsprechende
// Temperaturprofil soweit es schon man ausgelesen und gecached wurde. 
function GetWeeklyProfile(int $rn, int $wp) {
    // Rückgabefeld
    $profil = array();
    // Cache auslesen
    $cid = CreateVariableByName($_IPS['SELF'], "Profiles", 3);
    $profiles = unserialize(GetValue($cid));
    // unseres dabei?
    if(isset($profiles[$rn])) {
        if(isset($profiles[$rn]["P".$wp])) {
            //	"HM-TC-IT-WM-W-EU" oder "HmIP-WTH-2"
            $profil = $profiles[$rn]["P".$wp];
        }
        else {
            //	Quickhack :( "HM-CC-TC" oder "HM-CC-RT-DN"
            $profil = $profiles[$rn]["P1"];
        }
    }
    return $profil;
}

// Speichert für den übergebenen Raum die Wochenprofil(e).
function SetWeeklyProfile(int $rn, array $profile, int $wp =-1) {
    // Cache auslesen
    $cid = CreateVariableByName($_IPS['SELF'], "Profiles", 3);
    $profiles = unserialize(GetValue($cid));
    if($wp > 0 and $wp <= 3) {
        $profiles[$rn]["P".$wp] = $profile;
    }
    else {
        $profiles[$rn] = $profile;
    }
    // Cache updaten
    SetValue($cid, serialize($profiles));
}

// Extrahiert für den übergebenen Tag das Tagesprofil
function GetDailyProfile(array $week, int $day) {
global $weekday;
    // Rückgabefeld
    $profil = array();
    // unseres dabei?
    if(isset($week[$weekday[$day]])) {
        $profil = $week[$weekday[$day]];
    }
    return $profil;
}

// Speichert für den übergebenen Raum die Wochenprofil(e).
function SetDailyProfile(int $rn, int $wp, int $day, array $dp) {
    global $weekday;
    // Cache auslesen
    $cid = CreateVariableByName($_IPS['SELF'], "Profiles", 3);
    $profiles = unserialize(GetValue($cid));
    // Tagesprofil austauschen
    if(isset($profiles[$rn]["P".$wp])) {
        //	"HM-TC-IT-WM-W-EU" oder "HmIP-WTH-2"
        $profiles[$rn]["P".$wp][$weekday[$day]] = $dp;
    }
    else {
        //	"HM-CC-TC" oder "HM-CC-RT-DN"
        $profiles[$rn][$weekday[$day]] = $dp;
    }
    // Cache updaten
    SetValue($cid, serialize($profiles));
}

// Prüfen ob Profil konsistent ist
function CheckWeeklyProfile($profile) {
    global $weekday;
    // Ergebniss
    $ret = "OK";
    foreach($weekday as $key => $day) {
        $time1='00:00';
        foreach($profile[$weekday[$key]]['EndTimes'] as $ts => $time2) {
            // Speicherslots des HM WT in min
            if(strtotime($time2) <= strtotime($time1)) {
                $slot = $ts+1;
                $ret="Fehler im Tagesprofil $weekday[$key] (Slot: $slot Start: $time1 - Ende: $time2 )";
                break;
            }
            $time1 = $time2;
        }
    }
    return $ret;
}

// Zeitabschnitt Auswahl im Webfront Anzeige auf Anzahl
// der belegten Slots im HM WT beschränken
function SetTimeSlotProfile($profile, $hl=99) {
    // Profilename
    $vpn = "HM.Heating.Slot";
    // Anzahl Slots
    $count = 0;
    if(!empty($profile)) {
        $count = count($profile['EndTimes']);
    }
    // Auswahl anpassen?!
    $vid = CreateVariableByName($_IPS['SELF'], "Zeitabschnitt", 1);
    if($count > 0) {
        IPS_SetVariableProfileValues ($vpn, 1, $count, 1);
        if($hl <= $count) {
            SetValue($vid, $hl);
            return $hl;
        }
        else {
            SetValue($vid, 1);
            return 1;
        }		
    }
    else {
        IPS_SetVariableProfileValues ($vpn, 1, 1, 1);
        SetValue($vid, 0);
    }
    return 99;
}

// Erzeugt vom übergebenen Wochen-Temperaturprofil das entsprechende HTML
function RenderWeeklyProfile(array $profile, $hl = 99) {
    global $day, $weekday;
    // Temeraturen => 15, 16, 17, 18, 19, 20, 21, 22
    if(!empty($profile)) {
        foreach ($weekday as $k => $d)	{
            $time1='00:00';
            foreach ($profile[$weekday[$k]]['EndTimes'] as $time2) {
                // Speicherslots des HM WT in min
                $times[$d][]=(strtotime("01.01.2001 ". $time2)-strtotime("01.01.2001 ". $time1))/60; 
                $time1=$time2;
            }
            foreach ($profile[$weekday[$k]]['Values'] as $v) {
                if($v <= 15) 		$temp[$d][] = 't15';	// sehr kalt
                elseif ($v <= 16)	$temp[$d][] = 't16';	// kalt
                elseif ($v <= 17)	$temp[$d][] = 't17';	// Kühl
                elseif ($v <= 18)	$temp[$d][] = 't18';	// normal
                elseif ($v <= 19)	$temp[$d][] = 't19';	// warm
                elseif ($v <= 20)	$temp[$d][] = 't20';	// sehr warm
                elseif ($v <= 21)	$temp[$d][] = 't21';	// heiß
                else 					$temp[$d][] = 't22';	// sehr heiß
            }
        }
    }
    else {
        // kein Profil kein Highlight!
        $hl = 99;
    }	
    // styles definieren
    $style = '';
    $style = $style.'<style type="text/css">';
    $style = $style.'body {margin: 0px;}';
    $style = $style.'table.tp {border-collapse: collapse; font-size: 11px; width: 100%; border-right: 1px solid rgba(255, 255, 255, 0.2);}';
    $style = $style.'td.fst {vertical-align: middle; text-align: center; width: 4%; padding: 2px; border-left: 1px solid rgba(255, 255, 255, 0.2); border-right: 1px solid rgba(255, 255, 255, 0.2); border-top: 1px solid rgba(255, 255, 255, 0.1); }';
    $style = $style.'td.mid {vertical-align: middle; text-align: center; width: 4%; padding: 2px; border-right: 1px solid rgba(255, 255, 255, 0.2); border-top: 1px solid rgba(255, 255, 255, 0.1); }';
    $style = $style.'td.lst {vertical-align: middle; text-align: center; width: 4%; padding: 2px; border-right: 1px solid rgba(255, 255, 255, 0.2); border-top: 1px solid rgba(255, 255, 255, 0.1); }';
    $style = $style.'tr:last-child {border-bottom: 1px solid rgba(255, 255, 255, 0.2); }';
    $style = $style.'.th { color: rgb(255, 255, 255); background-color: rgba(255, 255, 255,0.25); font-weight:bold; background-image: linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 28%,rgba(0,0,0,0.3) 100%); background-image: -o-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 28%,rgba(0,0,0,0.3) 100%); background-image: -moz-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 28%,rgba(0,0,0,0.3) 100%); background-image: -webkit-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 28%,rgba(0,0,0,0.3) 100%); background-image: -ms-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 28%,rgba(0,0,0,0.3) 100%); }';
    $style = $style.'.hl {background-color: black; opacity: 0.5;}';
    $style = $style.'.t15 {background-color: #6600CC; opacity: 0.9;}'; // lila (sehr kalt) <= 15
    $style = $style.'.t16 {background-color: #0000FF; opacity: 0.9;}'; // dunkelblau (kalt) = 16
    $style = $style.'.t17 {background-color: #0080FF; opacity: 0.9;}'; // hellblau (kühl) = 17
    $style = $style.'.t18 {background-color: #00FFFF; opacity: 0.9;}'; // türkis (normal) 18
    $style = $style.'.t19 {background-color: #00FF00; opacity: 0.9;}'; // grün (warm) =19
    $style = $style.'.t20 {background-color: #FFFF00; opacity: 0.9;}'; // gelb (sehr warm) = 20
    $style = $style.'.t21 {background-color: #FF8000; opacity: 0.9;}'; // orange (heiß) = 21
    $style = $style.'.t22 {background-color: #FF0000; opacity: 0.9;}'; // rot (sehr heiß) >= 22
    $style = $style.'</style>';
    // HTML Table erzeugen
    $html = $style;	
    $html = $html.'<table class="tp">';
    $html = $html.'<tr>';

    for($i=0; $i <= 24; $i++) {
        if($i == 0) {
            $html = $html.'<td class=""></td>';
        }
        elseif ($i == 24) {
            $html = $html.'<td class="lst th" colspan="12">'.sprintf("%02d", $i).'</td>';
        }
        else {
            $html = $html.'<td class="mid th" colspan="12">'.sprintf("%02d", $i).'</td>';
        }
    }
    $html = $html.'</tr>';

    foreach ($weekday as $k => $d)	{
        // wurde Wochentag mit übergeben (0=Mo, 1=Di ... 99=kein Wochentag vorgegeben)
        if($hl <> $k) {
            $html = $html.'<tr><td class="fst th">'. $day[$k][1] .'</td>';
        }
        else {
            $html = $html.'<tr class="hl"><td class="fst th">'. $day[$k][1] .'</td>';
        }
        if(isset($times)) {
            foreach ($times[$d] as $key => $time) {
                $html = $html.'<td colspan="'.($time/5).'" class="'.$temp[$d][$key].'"> </td>';
            }
        }
        else {
            for($i=0; $i < 24; $i++) {
                $html = $html.'<td colspan="12"> </td>';
            }
        }
        $html = $html.'</tr>';
    }
    $html = $html.'</table>';
    $html = $html.'<div style="height:8px;"><nbsp /></div>';
    // Index Tabelle (Temperatur-Spektrum)
    $html = $html.'<table style="border: 0px; font-size:11px; text-shadow:1px 1px #000000; width:100%; text-align: center">';
    $html = $html.'<tr>';
    $html = $html.'<td class="t15" style="width:12%"><= 15°C</td>';
    $html = $html.'<td class="t16" style="width:13%"><= 16°C</td>';
    $html = $html.'<td class="t17" style="width:12%"><= 17°C</td>';
    $html = $html.'<td class="t18" style="width:13%"><= 18°C</td>';
    $html = $html.'<td class="t19" style="width:12%"><= 19°C</td>';
    $html = $html.'<td class="t20" style="width:13%"><= 20°C</td>';
    $html = $html.'<td class="t21" style="width:12%"><= 21°C</td>';
    $html = $html.'<td class="t22" style="width:13%">>= 22°C</td>';
    $html = $html.'</tr></table>';
    // Rückgabe
    return $html;
}

// Erzeugt vom übergebenen Tages-Temperaturprofil das entsprechende HTML
function RenderDailyProfile(array $profile, int $hl=99) {
    // styles definieren
    $html = '<style>
    body {margin: 0px;}
    ::-webkit-scrollbar { width: 8px; }
    ::-webkit-scrollbar-track { background: transparent; }
    ::-webkit-scrollbar-thumb { background: #555; border-radius: 20px; }
    ::-webkit-scrollbar-thumb:hover { background: #555; }
    ul {font-size:12px;padding-left: 20px;}
    em {font-size: xx-small;}
    .time {font-size:12px;}
    .list {font-size:14px; font-weight: bold; padding-top: 10px;}
    </style>';	
    $html = $html.'<table class="tp">';
    $html = $html.'<tr><td class=""></td><td class="mid th">Startzeit</td><td class="mid th">Endzeit</td><td class="lst th">Temperatur</td></tr>';
    // rendern
    if(!empty($profile)) {
        $start="00:00";
        foreach($profile['EndTimes'] as $key => $end) {
            $temp = number_format($profile['Values'][$key], 1,",",".");
            if($key <> $hl-1) {
                $html = $html.'<tr><td class="fst th">'.($key+1) .'. Zeitabschnitt</td><td class="mid">'.$start.'</td><td class="mid">'.$end.'</td><td class="lst">'.$temp.' °C</td></tr>';
            }
            else {
                $html = $html.'<tr class ="hl"><td class="fst th">'.($key+1). '. Zeitabschnitt</td><td class="mid">'.$start.'</td><td class="mid">'.$end.'</td><td class="lst">'.$temp.' °C</td></tr>';
            }
            $start=$end;
        }
    }
    else {
        // kein Profil vorhanden!
        $html = $html.'<tr><td class="fst th">-<td class="mid">-</td><td class="mid">-</td><td class="lst">-</td></tr>';
    }
    $html = $html.'</table>';
    // Rückgabe
    return $html;
}

// Update HTML
function RenderProfile(int $rn, int $wp, int $wd, int $ts = 99) {
    // Profil extrahieren
    $profile = GetWeeklyProfile($rn, $wp);
    // Rendern Wochenprofil
    $vid = CreateVariableByName($_IPS['SELF'], 'Wochenprofil', 3);
    SetValue($vid, RenderWeeklyProfile($profile, $wd));		
    // Profil extrahieren
    $profile = GetDailyProfile($profile, $wd);
    $ts = SetTimeSlotProfile($profile, $ts);
    // Render Tagesprofil
    $vid = CreateVariableByName($_IPS['SELF'], 'Tagesprofil', 3);
    SetValue($vid, RenderDailyProfile($profile, $ts));		
}

################################################################################
?>

Musst natürlich die richtigen Geräte eintragen!

Viel Erfolg Heiko

Danke, ich versuch mal mein Glück.

Gruß

Jürgen

Hallo Heiko,

im Skript kommt jetzt dieser Fehler:

Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, int given in C:\ProgramData\Symcon\scripts\System.Functions.ips.php:713
Stack trace:
#0 C:\ProgramData\Symcon\scripts\31879.ips.php(178): CreateProfileInteger('HM.Heating.Room', 'HouseRemote', '', '', 0, 0, 0, 0, Array)
#1 {main}
  thrown in C:\ProgramData\Symcon\scripts\System.Functions.ips.php on line 713

In deiner „System.Functions“, „Version: 4.0.20231005“ fehlt nach $step das $digits. Hab mir diese direkt von GitHub geladen.
Dort im ChangeLog schreibst du " CreateProfilInteger korrigiert (ACHTUNG)". Was ist da zu beachten?

Gruß

Jürgen

Hallo Jürgen,

oh je - wie geschrieben alles schon sehr alt - lass mal sein.

Ich baue eine neue Version die dann auf der Höhe der Zeit seien sollte :slight_smile:
Stelle sie dann hier ein - sollte ich heute noch schaffen!

Gruß HEiko

Ahh super, freue mich drauf.

Danke

Gruß

Jürgen

Lief die nur für HM IP?

Ich stelle gerade fest, dass meine eingesetzte Swifty Version mit den Jahren einfach mitgewandert ist. Ist aber auch erst ein Jahrzehnt her. :smile:

Gruß

Nein, es gingen auch „ältere“ HM Geräte.

Ich meinte mehr das Script selbt mit Höhe der Zeit :smiley:

Gruß Heiko

Ok, ich wollte erst seit 10 oder 11 Jahren (irgendwo am Beginn dies Threads 2013) etwas umbauen und zentral steuern.

Aber wie es so läuft. Time goes by :grinning:

Gruß

So, war hoffentlich einfacher als erwartet …

FILE ENTFERNT WEIL FEHLERHAFT!!!

Jürgen, schau mal ob es läuft bei Dir!

Danke, aber ich habe glaube noch die falsche „__xmlrpc.inc.php“.
Du hattest doch eine von dir angepasste. Könntest du sie mir bitte zukommen lassen?

Gruß

jürgen