########################################################################################################################
# Group.pm
#-----------------------------------------------------------------------------------------------------------------------
#
# Steuerung von Ikea Tradfri Gruppen
#
#
# Aufruf           : use TSS::Ikea::Tradfri::Group;
#                    my $gobjDevice = TSS::Ikea::Tradfri::Group->new( gateway => <Gateway>, devicedata => <Gruppendaten> );
#                    my $gobjDevice=$gobjGateway->getGroupInfo("itfg131075"); # itfg131075=Device-ID-gruppen
#                    else { print "$gobjDevice\n"; };
#                      > <datapoint deviceid='itfg131075' name='Wohnzimmer' devicetype='group' status='1' brightness='0' scene='itfs196614' devices='itfl65543,itfl65537,itfl65544' ' temperature='2' ct='375' color='5' xyY='30015,26870,75' hsv='5427,42596,75' />
#
#                    Version ausgeben:
#                    -----------------
#                    print "Version: ".$TSS::Ikea::Tradfri::Group::VERSION."\n";
#                      > Version: v3.0.0
# 
#                    Name der Gruppe ausgeben:
#                    -------------------------
#                    print $gobjDevice->name()."\n";
#                      > <datapoint deviceid='itfg131075' name='Wohnzimmer' />
# 
#                    Adresse der Gruppe ausgeben:
#                    ----------------------------
#                    print $gobjDevice->deviceid()."\n";
#                      > <datapoint deviceid='itfg131075' />
# 
#                    Typ der Gruppe ausgeben:
#                    ------------------------
#                    print $gobjDevice->devicetype()."\n";
#                      > <datapoint deviceid='itfg131075' devicetype='group' />
# 
#                    Power-Status der Gruppe ausgeben:
#                    ---------------------------------
#                    print $gobjDevice->status()."\n";
#                      > <datapoint deviceid='itfg131075' status='1' />
#
#                    Helligkeit der Gruppe ausgeben:
#                    -------------------------------
#                    print $gobjDevice->brightness()."\n";
#                      > <datapoint deviceid='itfg131075' brightness='0' />
#
#                    Farbtemperatur der Gruppe ausgeben:
#                    -----------------------------------
#                    print $gobjDevice->temperature()."\n";
#                      > <datapoint deviceid='itfg131075' temperature='2' />
#
#                    Farbtemperatur über ct-Wert der Gruppe ausgeben:
#                    ------------------------------------------------
#                    print $gobjDevice->ct()."\n";
#                      > <datapoint deviceid='itfg131075' ct='375' />
#
#                    Farbe über Farbwert des Gerätes ausgeben:
#                    -----------------------------------------
#                    print $gobjDevice->color()."\n";
#                      > <datapoint deviceid='itfg131075' color='5' />
#
#                    Farbe über xyY-Wert des Gerätes ausgeben:
#                    -----------------------------------------
#                    print $gobjDevice->xyy()."\n";
#                      > <datapoint deviceid='itfg131075' xyY='30015,26870,181' />
#
#                    Farbe über HSV-Wert des Gerätes ausgeben:
#                    -----------------------------------------
#                    print $gobjDevice->hsv()."\n";
#                      > <datapoint deviceid='itfg131075' hsv='5427,42596,181' />
# 
#                    Aktive Szene der Gruppe ausgeben:
#                    ---------------------------------
#                    print $gobjDevice->scene()."\n";
#                      > <datapoint deviceid='itfg131075' scene='itfs196614' />
# 
#                    Geräte der Gruppe ausgeben:
#                    ---------------------------
#                    print $gobjDevice->devices()."\n";
#                      > <datapoint deviceid='itfg131075' devices='itfl65543,itfl65537,itfl65544' />
#        
#                    Gesamtstatus der Gruppe ausgeben:
#                    ---------------------------------
#                    print $gobjDevice->devicestate()."\n";
#                      >  <datapoint deviceid='itfg131075' name='Wohnzimmer' devicetype='group' status='1' brightness='0' scene='itfs196614' devices='itfl65543,itfl65537,itfl65544' ' temperature='2' ct='375' color='5' xyY='30015,26870,75' hsv='5427,42596,75' />
#        
#                    Alle Gruppeninformationen neu einlesen:
#                    ---------------------------------------
#                    my $gintResult=$gobjDevice->readDeviceInfo();
#                    if (! defined($gintResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    print $gobjDevice->devicestate()."\n"; 
#                      >  <datapoint deviceid='itfg131075' name='Wohnzimmer' devicetype='group' status='1' brightness='0' scene='itfs196614' devices='itfl65543,itfl65537,itfl65544' ' temperature='2' ct='375' color='5' xyY='30015,26870,75' hsv='5427,42596,75' />
#        
#                    Die Gruppe aus-/einschalten:
#                    ----------------------------
#                    my $gstrResult=$gobjDevice->setPower(x); # 0=aus, 1=ein
#                    if (! defined($gstrResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    else { print "$gstrResult\n"; }
#                      >  <datapoint deviceid='itfg131075' status='1' />
# 
#                    Helligkeit der Gruppe ändern:
#                    -----------------------------
#                    my $gstrResult=$gobjDevice->setBrightness(x); # 0-254
#                    if (! defined($gstrResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    else { print "$gstrResult\n"; }
#                      > <datapoint deviceid='itfg131075' brightness='0' /> 
# 
#                    Farbemperatur der Gruppe über ct-Wert ändern:
#                    ---------------------------------------------
#                    my $gstrResult=$gobjDevice->setCT(x); # 153-500
#                    if (! defined($gstrResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    else { print "$gstrResult\n"; }
#                      > <datapoint deviceid='itfg131075' ct='500' />
# 
#                    Farbemperatur der Gruppe ändern:
#                    --------------------------------
#                    my $gstrResult=$gobjDevice->setTemperature(x); # 1-3
#                    if (! defined($gstrResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    else { print "$gstrResult\n"; }
#                      > <datapoint deviceid='itfg131075' temperature='2' /> 
# 
#                    Farbe der Gruppe über Farbwert ändern:
#                    --------------------------------------
#                    my $gstrResult=$gobjDevice->setColor(x); # 1-20
#                    if (! defined($gstrResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    else { print "$gstrResult\n"; }
#                      > <datapoint deviceid='itfg131075' color='5' />
# 
#                    Farbe der Gruppe über xyY-Wert ändern:
#                    --------------------------------------
#                    my $gstrResult=$gobjDevice->setXYY(x); # 0-65535,0-65535,0-254
#                    if (! defined($gstrResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    else { print "$gstrResult\n"; }
#                      > <datapoint deviceid='itfg131075' xyY='28853,26411,64' />
# 
#                    Farbe der Gruppe über HSV-Wert ändern:
#                    --------------------------------------
#                    my $gstrResult=$gobjDevice>setHsv(x); # 0-65535,0-65279,0-254
#                    if (! defined($gstrResult)) { print "Befehl nicht erfolgreich! Fehler:\"".$gobjGateway->{"error"}."\"\n"; exit(1); }
#                    else { print "$gstrResult\n"; }
#                      > <datapoint deviceid='itfg131075' hsv='43690,65279,75' />
#
# Attribute        : Fehlertext              = $lobjSelf->{"error"}
#                    Gateway                 = $lobjSelf->{"gateway"} (Übergeordnetes Objekt)
#                    Gerätedaten JSON-String = $lobjSelf->{"devicedata"}
# 
#                    Gerätedaten Gerätetyp unabhängig:
#                    Gerätetyp               = $lobjSelf->{"devicetype"} ("bulb:fixed_white,dimmable", "bulb:color,tunable_white,dimmable", "plug", "motionsensor", "repeater", "fernbedienung", "on/off-switch", "blind")
#                    Name                    = $lobjSelf->{"name"}
#                    Anmeldedatum            = $lobjSelf->{"created"} (Unix Timestamp)
#                    Geräte-ID               = $lobjSelf->{"deviceid"}
#
#                    Gerätestatus Gruppen
#                    Power-Status            = $lobjSelf->{"status"} (0=off, 1=on)
#                    Helligkeit              = $lobjSelf->{"brightness"} (1 - 254)
#                    Aktive Szene            = $lobjSelf->{"scene"}
#                    Geräte-IDs              = $lobjSelf->{"devices"}
#                    Farbtemperatur          = $lobjSelf->{"temperature"} (Optional 1 - 3)
#                    Farbemperatur ct-Wert   = $lobjSelf->{"ct"} (optional 153-500)
#                    Farbe über Farbwert     = $lobjSelf->{"color"} (optional 1-20)
#                    Farbe über Farbwert     = $lobjSelf->{"xyy"} (optional 0-65535,0-65535,0-254)
#                    Farbe über Farbwert     = $lobjSelf->{"hsv"} (optional 0-65535,0-65279,0-254)
#
# Methoden         : Name ausgeben                        = $gobjDevice->name()
#                    Adresse ausgeben                     = $gobjDevice->deviceid()
#                    Typ ausgeben                         = $gobjDevice->devicetype()
#                    Power-Status ausgeben                = $gobjDevice->status()
#                    Helligkeit ausgeben                  = $gobjDevice->brightness()
#                    Farbemperatur ausgeben               = $gobjDevice->temperature()
#                    Farbemperatur über ct-Wert ausgeben  = $gobjDevice->ct()
#                    Farbe über Farbwert                  = $gobjDevice->color()
#                    Farbe über xyY-Wert                  = $gobjDevice->xyy()
#                    Farbe über HSV-Wert                  = $gobjDevice->hsv()
#                    Aktive Szene ausgeben                = $gobjDevice->scene()
#                    Geräte der Gruppe ausgeben           = $gobjDevice->devices()
#                    Gesamtstatus ausgeben                = $gobjDevice->devicestate()
#                    Geräteinformationen neu einlesen     = $gobjDevice->readDeviceInfo()
#                    Aus-/einschalten                     = $gobjDevice->setPower(<Status>)           -> <Status>     : 0=aus, 1=ein
#                    Helligkeit ändern                    = $gobjDevice->setBrightness(<Helligkeit>)  -> <Helligkeit> : 0-254=Helligkeit
#                    Farbemperatur ändern                 = $gobjDevice->setTemperature(<Temperatur>) -> <Temperatur> : 1-3=Temperatur
#                    Farbemperatur über ct-Wert ändern    = $gobjDevice->setCT(<Temperatur>)          -> <Temperatur> : 153-500=Temperatur
#                    Farbe über Farbwert ändern           = $gobjDevice->setColor(<Farbe>)            -> <Farbe>      : 1-20=Farbe
#                    Farbe über xyY-Wert ändern           = $gobjDevice->setXYY(<Farbe>)              -> <Farbe>      : 0-65535,0-65535,0-254=x,y,Y
#                    Farbe über HSV-Wert ändern           = $gobjDevice->setHSv(<Farbe>)              -> <Farbe>      : 0-65535,0-65279,0-254=H,S,V
#
# Farben           : 1             = "dcf0f8"
#                    2             = "eaf6fb"
#                    3             = "f5faf6" (coldwhite)
#                    4             = "f2eccf"
#                    5             = "f1e0b5" (normalwhite)
#                    6             = "efd275" (warmwhite)
#                    7             = "ebb63e"
#                    8             = "e78834"
#                    9             = "e57345"
#                    10             = "da5d41"
#                    11            = "dc4b31"
#                    12            = "e491af"
#                    13            = "e8bedd"
#                    14            = "d9337c"
#                    15            = "c984bb"
#                    16            = "8f2686"
#                    17            = "4a418a"
#                    18            = "6c83ba"
#                    19            = "a9d62b"
#                    20            = "d6e44b"
#
# Weißtöne         : 1 = "f5faf6" (coldwhite)
#                    2 = "f1e0b5" (normalwhite)
#                    3 = "efd275" (warmwhite)
#
# Gerätetypen      : "TRADFRI bulb E14 W op/ch 400lm"  = Lampe weiß fix, dimmbar
#                    "TRADFRI bulb E27 CWS opal 600lm" = Lampe farbe steuerbar, weiß steuerbar, dimmbar
#                    "TRADFRI bulb E14 CWS opal 600lm" = Lampe farbe steuerbar, weiß steuerbar, dimmbar
#                    "TRADFRI remote control"          = Fernbedinung rund 5 Tasten
#                    "TRADFRI on/off switch"           = Fernbedinung quadradisch 2 Tasten
#
# Zugriffstyp      : 0=Fernbedienung
#                    1=Slave Fernbedienung
#                    2=Lampe
#                    3=Steckdose
#                    4=Bewegungsmelder
#                    6=Repeater
#                    7=Rollo
#
# Stromquellen     : 0=Unbekannt
#                    1=Netzteil
#                    2=Externe Batterie
#                    3=Batterie
#                    4=PowerOverEthernet
#                    5=USB
#                    6=AC_Power
#                    7=Solar
#
# Präfixe Device-ID: itfb Rollos (b=blind)
#                    itfg Gruppen (g=group)
#                    itfl Leuchten (l=light)
#                    itfm Bewegungsmelder (m=motion)
#                    itfp Steckdosen (p=plug)
#                    itfr Fernbedienungen (r=Remote)
#                    itfs Szenen (s=scene)
#         
# Version          : 10.11.2019 v1.0.0 Initiale Version
#                    19.12.2019 v3.0.0 Neue Version
#                    20.12.2019 v3.0.1 Namensangelichungen mit anderen Modulen
#                    20.01.2020 v3.0.2 Befüllung des Attribut Geräteliste des Gateways - Hash mit allen Tradfri-IDs (Key) und Typ (Value), Keine Gruppen, Tradfri-Id's ohne Präfix (it[x])
#                    21.01.2020 v3.0.3 Workaround für fehlerhafte Gruppensati
#                    21.01.2020 v3.0.4 Farbsteuerung für Gruppen
#                    06.02.2020 v3.0.5 Copyright und Warranty hinzugefügt
#
#
# Copyright & Warranty:
# =====================
#
# Copyright (C) 2019 Thomas Schütz-Schneider 
#
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. 
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 
#
# You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. 
#
########################################################################################################################


# ========================
#  Package-Name
# ========================
package TSS::Ikea::Tradfri::Group;

# ========================
#  Definition der Pragmas
# ========================
use strict;
use warnings;
use JSON::Parse 'parse_json';
use TSS::Ikea::Tradfri::Common;

# ===============
#  Vererbung aus
# ===============
our @ISA = qw( TSS::Ikea::Tradfri::Common );

# ==================================
#  Definition der Versions-Variable
# ==================================
our $VERSION = "v3.0.5";

# ================================================
#  Überladung: Klassenattribute als Text ausgeben
# ================================================
use overload '""' => '_stringify';

########################################################################################################################
# Interne Variable
#-----------------------------------------------------------------------------------------------------------------------
my %ghshMapColorHex=(); # Tradfri-Farben
   $ghshMapColorHex{"0"}="";
   $ghshMapColorHex{"1"}="dcf0f8";
   $ghshMapColorHex{"2"}="eaf6fb";
   $ghshMapColorHex{"3"}="f5faf6";
   $ghshMapColorHex{"4"}="f2eccf";
   $ghshMapColorHex{"5"}="f1e0b5";
   $ghshMapColorHex{"6"}="efd275";
   $ghshMapColorHex{"7"}="ebb63e";
   $ghshMapColorHex{"8"}="e78834";
   $ghshMapColorHex{"9"}="e57345";
   $ghshMapColorHex{"10"}="da5d41";
   $ghshMapColorHex{"11"}="dc4b31";
   $ghshMapColorHex{"12"}="e491af";
   $ghshMapColorHex{"13"}="e8bedd";
   $ghshMapColorHex{"14"}="d9337c";
   $ghshMapColorHex{"15"}="c984bb";
   $ghshMapColorHex{"16"}="8f2686";
   $ghshMapColorHex{"17"}="4a418a";
   $ghshMapColorHex{"18"}="6c83ba";
   $ghshMapColorHex{"19"}="a9d62b";
   $ghshMapColorHex{"20"}="d6e44b";
   
my %ghshMapHexColor=(); # Tradfri-Farben
   $ghshMapHexColor{"dcf0f8"}="1";
   $ghshMapHexColor{"eaf6fb"}="2";
   $ghshMapHexColor{"f5faf6"}="3";
   $ghshMapHexColor{"f2eccf"}="4";
   $ghshMapHexColor{"f1e0b5"}="5";
   $ghshMapHexColor{"efd275"}="6";
   $ghshMapHexColor{"ebb63e"}="7";
   $ghshMapHexColor{"e78834"}="8";
   $ghshMapHexColor{"e57345"}="9";
   $ghshMapHexColor{"da5d41"}="10";
   $ghshMapHexColor{"dc4b31"}="11";
   $ghshMapHexColor{"e491af"}="12";
   $ghshMapHexColor{"e8bedd"}="13";
   $ghshMapHexColor{"d9337c"}="14";
   $ghshMapHexColor{"c984bb"}="15";
   $ghshMapHexColor{"8f2686"}="16";
   $ghshMapHexColor{"4a418a"}="17";
   $ghshMapHexColor{"6c83ba"}="18";
   $ghshMapHexColor{"a9d62b"}="19";
   $ghshMapHexColor{"d6e44b"}="20";
   
my %ghshMapWhiteHex=(); # Tradfri-Weißtöne
   $ghshMapWhiteHex{"0"}="";
   $ghshMapWhiteHex{"1"}="f5faf6"; # coldwhite
   $ghshMapWhiteHex{"2"}="f1e0b5"; # normalwhite
   $ghshMapWhiteHex{"3"}="efd275"; # warmwhite
   
my %ghshMapHexWhite=(); # Tradfri-Weißtöne
   $ghshMapHexWhite{"f5faf6"}="1"; # coldwhite
   $ghshMapHexWhite{"f1e0b5"}="2"; # normalwhite
   $ghshMapHexWhite{"efd275"}="3"; # warmwhite
########################################################################################################################


########################################################################################################################
# Gruppendaten aus JSON-String auswerten 
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $objSelf->_decodeDevicedata();
#
# Übergabe: -
#
# Rückgabe: -
#
#-----------------------------------------------------------------------------------------------------------------------
sub _decodeDevicedata {
  my $lobjSelf=shift;     # Klasse-Name abfangen
  my $lptrResult="";      # Zeiger auf ein Array, Hash oder Sclar eines dekodierten JSON-Strings
  my $lprtDevices="";     # Zeiger auf ein Array, Hash oder Sclar eines dekodierten JSON-Strings
  my $lintPowerStatus=0;  # Powerstatus der Gruppe
  my $lintBrightness=0;   # Helligkeit der Gruppe
  
  # Ist noch keine Geräteliste vorhanden?
  if (scalar(keys %{$lobjSelf->{"gateway"}{"devices"}}) < 1) {
    # Liste der vorhandenen realen Geräte-ID's (ohne führendes "itfX") ermitteln
    my $tptrResult=$lobjSelf->{"gateway"}->_getAllRealObjectIds("5684/15001");
    if (! defined($tptrResult)) { return; }

    # Alle ID's bearbeiten
    foreach my $tstrDeviceId (@{$tptrResult}) {
      # Alle Geräteinformationen auslesen
      my $tstrResponse=$lobjSelf->{"gateway"}->_requestGateway(0,"","5684/15001/$tstrDeviceId");

      # Ist ein Fehler aufgetreten?
      if (!defined($tstrResponse)) { return; }

      # Verzweigung nach Geräteart - Lampe
      if ( $tstrResponse =~ /"3311"/) { $lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId}="itfl".$tstrDeviceId; }
      # Steckdose
      elsif ( $tstrResponse =~ /"3312"/) { $lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId}="itfp".$tstrDeviceId; }
      # Fernbedienung
      elsif ( $tstrResponse =~ /"15009"/) { $lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId}="itfr".$tstrDeviceId; }
      # Unbekannt
      else {}
    }
  }
  
  # JSON-String dekodieren
  $lptrResult=parse_json($lobjSelf->{'devicedata'});
  
  # Unerwaretetes Ergebnis?
  if (ref($lptrResult) ne "HASH") { $lobjSelf->{"error"}="_decodeDevicedata: Unerwartetes Ergebnisformat (".ref($lptrResult).") !"; return; }

  # Gruppendaten
  #-------------
  # Name
  if (defined($lptrResult->{"9001"})) { $lobjSelf->{"name"}=$lptrResult->{"9001"}; } else { $lobjSelf->{"name"}=""; }
  # Anmeldedatum (Unix Timestamp)
  if (defined($lptrResult->{"9002"})) { $lobjSelf->{"created"}=$lptrResult->{"9002"}; } else { $lobjSelf->{"created"}=""; }
  # Geräte-ID-Gruppen
  if (defined($lptrResult->{"9003"})) { $lobjSelf->{"deviceid"}="itfg".$lptrResult->{"9003"}; } else { $lobjSelf->{"deviceid"}=""; }
  # ID der aktiven Szene
  if (defined($lptrResult->{"9039"})) { $lobjSelf->{"scene"}="itfs".$lptrResult->{"9039"}; } else { $lobjSelf->{"scene"}=0; }
  # Geräte-IDs übernehmen
  $lprtDevices=$lptrResult->{"9018"}->{"15002"}->{"9003"};
  foreach my $tintDeviceId (@{$lprtDevices}) {
    push(@{$lobjSelf->{"devices"}},$lobjSelf->{"gateway"}{"devices"}{$tintDeviceId});
    # Workaraound für Fehlerhafte Gruppenstati
    my $tobjDevice=$lobjSelf->{"gateway"}->getDeviceInfo($lobjSelf->{"gateway"}{"devices"}{$tintDeviceId});
    if ($tobjDevice->{"online"} > 0) {
      # Powerstatus
      if (defined($tobjDevice->{"status"})) { $lintPowerStatus=1 if ($tobjDevice->{"status"} > 0); }
      # Brightness
      if (defined($tobjDevice->{"brightness"})) { $lintBrightness=$tobjDevice->{"brightness"}; }
    }
    # Farbtemperatur
    if (defined($tobjDevice->{"colorhex"})) {
      my $tintTemperature=$ghshMapHexWhite{$tobjDevice->{"colorhex"}};
      if (defined($tintTemperature)) { $lobjSelf->{"temperature"}=$tintTemperature; }
      else { $lobjSelf->{"temperature"}=0; }
    }
    # Farbemperatur über ct-Wert
    if (defined($tobjDevice->{"colorx"})) {
      my $tstrValueXy=sprintf("%.4f,%.4f",($tobjDevice->{"colorx"}/65535),($tobjDevice->{"colory"}/65535));
      my $tstrValueCt=$lobjSelf->{"gateway"}->_xy2ct($tstrValueXy);
      $lobjSelf->{"ct"}=$tstrValueCt;
    }
    # Farbe über Farbwert
    if (defined($tobjDevice->{"colorhex"})) {
      my $lintColor="";
      if (defined($ghshMapHexColor{$tobjDevice->{"colorhex"}})) { $lintColor=$ghshMapHexColor{$tobjDevice->{"colorhex"}}; }
      else { $lintColor=0 }
      $lobjSelf->{"color"}=$lintColor;
    }
    # Farbe über xyY-Wert
    if (defined($tobjDevice->{"colorx"})) {
      my $lstrColorxyY=$tobjDevice->{"colorx"}.",".$tobjDevice->{"colory"}.",".$tobjDevice->{"brightness"};
      $lobjSelf->{"xyy"}=$lstrColorxyY;
    }
    # Farbe über HSV-Wert
    if (defined($tobjDevice->{"hue"})) {
      my $lstrColorHsv=$tobjDevice->{"hue"}.",".$tobjDevice->{"saturation"}.",".$tobjDevice->{"brightness"};
      $lobjSelf->{"hsv"}=$lstrColorHsv;
    }
  }
  # Power-Status (0=off, 1=on)
  #if (defined($lptrResult->{"5850"})) { $lobjSelf->{"status"}=$lptrResult->{"5850"}; } else { $lobjSelf->{"status"}=0; }
  if (defined($lptrResult->{"5850"})) { $lobjSelf->{"status"}=$lintPowerStatus; } else { $lobjSelf->{"status"}=0; }
  # Helligkeit (1 - 254)
  #if (defined($lptrResult->{"5851"})) { $lobjSelf->{"brightness"}=$lptrResult->{"5851"}; } else { $lobjSelf->{"brightness"}=0; }
  if (defined($lptrResult->{"5851"})) { $lobjSelf->{"brightness"}=$lintBrightness; } else { $lobjSelf->{"brightness"}=0; }
  # Gerätetyp
  $lobjSelf->{"devicetype"}="group";
  # Erfolgreiche Rückmeldung
  return(0);
}
########################################################################################################################


########################################################################################################################
# Farbemperatur des Gerätes ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->temperature()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Farbemperatur des Gerätes
#
#-----------------------------------------------------------------------------------------------------------------------
sub temperature {
  my $lobjSelf=shift;    # Klasse-Name abfangen
  my $lintTemperature=0; # Farbemperatur
  if (defined($lobjSelf->{"temperature"})) {
    $lintTemperature=$lobjSelf->{"temperature"};
  } else { $lintTemperature=-1; }
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' temperature='".$lintTemperature."' />");
}
########################################################################################################################


########################################################################################################################
# Farbemperatur über ct-Wert des Gerätes ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objObject->ct()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Farbemperatur des Gerätes
#
#-----------------------------------------------------------------------------------------------------------------------
sub ct {
  my $lobjSelf=shift;    # Klasse-Name abfangen
  # Kann am gerät eine Farbe eingestellt werden?
  if (defined($lobjSelf->{"ct"})) {
    return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' ct='".$lobjSelf->{"ct"}."' />");
  }
  else { return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' ct='-1' />"); }
}
########################################################################################################################


########################################################################################################################
# Farbe über Farbwert des Gerätes ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->color()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Farbe des Gerätes
#
#-----------------------------------------------------------------------------------------------------------------------
sub color {
  my $lobjSelf=shift; # Klasse-Name abfangen
  my $lintColor=0;    # Farbwert
  if (defined($lobjSelf->{"color"})) {
    return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' color='".$lobjSelf->{"color"}."' />");
  } else { return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' color='-1' />"); }
}
########################################################################################################################


########################################################################################################################
# Farbe über xyY-Wert des Gerätes ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->xyy()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Farbe des Gerätes
#
#-----------------------------------------------------------------------------------------------------------------------
sub xyy {
  my $lobjSelf=shift; # Klasse-Name abfangen
  my $lstrColorxyY=0; # xyY-Farbwert
  if (defined($lobjSelf->{"xyy"})) {
    return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' xyY='".$lobjSelf->{"xyy"}."' />");
  } else { return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' xyY='-1,-1,-1' />"); }
}
########################################################################################################################


########################################################################################################################
# Farbe über HSV-Wert des Gerätes ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->hsv()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Farbe des Gerätes
#
#-----------------------------------------------------------------------------------------------------------------------
sub hsv {
  my $lobjSelf=shift; # Klasse-Name abfangen
  my $lstrColorxyY=0; # xyY-Farbwert
  if (defined($lobjSelf->{"hsv"})) {
    return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' hsv='".$lobjSelf->{"hsv"}."' />");
  } else { return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' hsv='-1,-1,-1' />"); }
}
########################################################################################################################


########################################################################################################################
# Aktive Szene der Gruppe ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->scene()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Aktive Szene der Gruppe
#
#-----------------------------------------------------------------------------------------------------------------------
sub scene {
  my $lobjSelf=shift; # Klasse-Name abfangen
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' scene='".$lobjSelf->{"scene"}."' />");
}
########################################################################################################################


########################################################################################################################
# Geräte der Gruppe ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->devices()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Geräte der Gruppe
#
#-----------------------------------------------------------------------------------------------------------------------
sub devices {
  my $lobjSelf=shift; # Klasse-Name abfangen
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' devices='".join(",",@{$lobjSelf->{"devices"}})."' />");
}
########################################################################################################################


########################################################################################################################
# Gesamtstatus der Gruppe ausgeben
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objGroup->devicestate()
#
# Übergabe: -
#
# Rückgabe: $strResponse = Gesamtstatus der Gruppe
#
#-----------------------------------------------------------------------------------------------------------------------
sub devicestate {
  my $lobjSelf=shift; # Klasse-Name abfangen
  my $lstrReturn="";  # Rückgabestring
  # Rückgabestring einleiten
  $lstrReturn="<datapoint deviceid='".$lobjSelf->{"deviceid"}."'";
  # Name der Gruppe
  $lstrReturn=$lstrReturn." name='".$lobjSelf->{"name"}."'";
  # Typ des Gerätes
  $lstrReturn=$lstrReturn." devicetype='".$lobjSelf->{"devicetype"}."'";
  # Power-Status der Gruppe
  $lstrReturn=$lstrReturn." status='".$lobjSelf->{"status"}."'";
  # Helligkeit der Gruppe
  $lstrReturn=$lstrReturn." brightness='".$lobjSelf->{"brightness"}."'";
  # Szene der Gruppe
  $lstrReturn=$lstrReturn." scene='".$lobjSelf->{"scene"}."'";
  # Geräte der Gruppe
  $lstrReturn=$lstrReturn." devices='".join(",",@{$lobjSelf->{"devices"}})."'";
  # Farbtemperatur der Gruppe
  if (defined($lobjSelf->{"temperature"})) { $lstrReturn=$lstrReturn." temperature='".$lobjSelf->{"temperature"}."'"; }
  # Farbemperatur über ct-Wert
  if (defined($lobjSelf->{"ct"})) { $lstrReturn=$lstrReturn." ct='".$lobjSelf->{"ct"}."'"; }
  # Farbe über Farbwert
  if (defined($lobjSelf->{"color"})) { $lstrReturn=$lstrReturn." color='".$lobjSelf->{"color"}."'"; }
  # Farbe über xyY-Wert
  if (defined($lobjSelf->{"xyy"})) { $lstrReturn=$lstrReturn." xyY='".$lobjSelf->{"xyy"}."'"; }
  # Farbe über HSV-Wert
  if (defined($lobjSelf->{"hsv"})) { $lstrReturn=$lstrReturn." hsv='".$lobjSelf->{"hsv"}."'"; }
 
  # Rückgabestring abschließen
  $lstrReturn=$lstrReturn." />";
  return($lstrReturn);
}
########################################################################################################################


########################################################################################################################
# Farbtemperatur der Gruppe ändern
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->setTemperature($intTemperature);
#
# Übergabe: $intTemperature = Neue Farbtemperatur (1-3)
#
# Rückgabe: $strResponse    = String=Erfolgreich, undef=Ein Fehler ist aufgetreten (Beschreibung in $objSelf->{"error"})
#
#-----------------------------------------------------------------------------------------------------------------------
sub setTemperature {
  my $lobjSelf=shift;        # Klasse-Name abfangen
  my $lintTemperature=shift; # Neue Farbtemperatur (1-3)
  my $lstrResponse="";       # Antwort des Tradfri Gateways
  my $lstrRealDeviceId="";   # Reale Geräte-ID-Lampen (ohne führendes itfl)
  my $lintResult=0;          # Ergebnisvariable
  
  # Kann an dem Gerät gar keine Farbtemeratur eingestellt werden?
  if (!defined($lobjSelf->{"temperature"})) { return ("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' temperature='-1' />"); }
  
  # Parameterprüfung
  if ($lintTemperature !~ /^[0-9]+$/) { $lintTemperature=2; }
  if ($lintTemperature < 1) { $lintTemperature=1; }
  if ($lintTemperature > 3) { $lintTemperature=3; }
  
  foreach my $tstrDeviceId ( @{$lobjSelf->{"devices"}} ) {
    $tstrDeviceId=~s/^itf[bglmprs]//;
    my $tobjDevice=$lobjSelf->{"gateway"}->getDeviceInfo($lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId});
    # Farbtemperatur
    if (defined($tobjDevice->{"colorhex"})) {
      # Kommunikation mit dem Tradfri Gateway -> Tradfri Gerät Farbe Hex ändern
      $lstrResponse=$tobjDevice->{"gateway"}->_requestGateway(1,"{ \"3311\": [{ \"5706\": \"".$ghshMapWhiteHex{$lintTemperature}."\" }] }","5684/15001/".$tstrDeviceId);
      # Ist ein Fehler aufgetreten?
      if (!defined($lstrResponse)) { return; }
    }
  }
  
  # Alle Geräteinformationen neu einlesen 
  $lintResult=$lobjSelf->readDeviceInfo();
  if (! defined($lintResult)) { return; }

  # Erfolgreiche Rückmeldung
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' temperature='".$lintTemperature."' />");
}
########################################################################################################################


########################################################################################################################
# Farbtemperatur der Gruppe über ct-Wert ändern
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->setCT($intTemperature);
#
# Übergabe: $intTemperature = Neue Farbtemperatur (153 - 500)
#
# Rückgabe: $strResponse    = String=Erfolgreich, undef=Ein Fehler ist aufgetreten (Beschreibung in $objSelf->{"error"})
#
#-----------------------------------------------------------------------------------------------------------------------
sub setCT {
  my $lobjSelf=shift;        # Klasse-Name abfangen
  my $lintTemperature=shift; # Neue Farbtemperatur (153 - 500)
  my $lstrResponse="";       # Antwort des Tradfri Gateways
  my $lstrRealDeviceId="";   # Reale Geräte-ID-Lampen (ohne führendes itfl)
  my $lintResult=0;          # Ergebnisvariable
  
  # Kann an dem Gerät gar keine Farbe über xyY-Wert eingestellt werden?
  if (!defined($lobjSelf->{"ct"})) { return ("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' xyY='-1,-1,-1' />"); }
  
  # Parameterprüfung
  if ($lintTemperature !~ /^[0-9]+$/) { $lintTemperature=153; }
  if ($lintTemperature < 153) { $lintTemperature=153; }
  if ($lintTemperature > 500) { $lintTemperature=500; }
  
  # xy-Wert der Farbtemperatur holen
  my $tstrValXyY=$lobjSelf->{"gateway"}->_ct2xy($lintTemperature);
  my ($tstrValX,$tstrValY)=split(/,/,$tstrValXyY);
  
  # Werteanpassung
  $tstrValX=int($tstrValX*65535);
  $tstrValY=int($tstrValY*65535);

  foreach my $tstrDeviceId ( @{$lobjSelf->{"devices"}} ) {
    $tstrDeviceId=~s/^itf[bglmprs]//;
    my $tobjDevice=$lobjSelf->{"gateway"}->getDeviceInfo($lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId});
    # Farbtemperatur ct
    if (defined($tobjDevice->{"colorx"})) {
      
      # Kommunikation mit dem Tradfri Gateway -> Tradfri Gerät Farbeändern
      $lstrResponse=$tobjDevice->{"gateway"}->_requestGateway(1,"{ \"3311\": [{ \"5709\": ".$tstrValX.", \"5710\": ".$tstrValY.", \"5851\":".$tobjDevice->{"brightness"}." }] }","5684/15001/".$tstrDeviceId);
      # Ist ein Fehler aufgetreten?
      if (!defined($lstrResponse)) { return; }
    }
  }
  
  # Alle Geräteinformationen neu einlesen 
  $lintResult=$lobjSelf->readDeviceInfo();
  if (! defined($lintResult)) { return; }

  # Erfolgreiche Rückmeldung
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' ct='".$lintTemperature."' />");
}
########################################################################################################################


########################################################################################################################
# Farbe der Gruppe über Farbwert ändern
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->setColor($intColor);
#
# Übergabe: $intColor    = Neue Farbe (1-20)
#
# Rückgabe: $strResponse = String=Erfolgreich, undef=Ein Fehler ist aufgetreten (Beschreibung in $objSelf->{"error"})
#
#-----------------------------------------------------------------------------------------------------------------------
sub setColor {
  my $lobjSelf=shift;      # Klasse-Name abfangen
  my $lintColor=shift;     # Neue Farbe (1-20)
  my $lstrResponse="";     # Antwort des Tradfri Gateways
  my $lstrRealDeviceId=""; # Reale Geräte-ID-Lampen (ohne führendes itfl)
  my $lintResult=0;        # Ergebnisvariable
  
  # Kann an dem Gerät gar keine Farbe über Farbwert eingestellt werden?
  if (!defined($lobjSelf->{"color"})) { return ("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' color='-1' />"); }
  
  # Parameterprüfung
  if ($lintColor !~ /^[0-9]+$/) { $lintColor=1; }
  if ($lintColor < 1) { $lintColor=1; }
  if ($lintColor > 20) { $lintColor=20; }
  
  foreach my $tstrDeviceId ( @{$lobjSelf->{"devices"}} ) {
    $tstrDeviceId=~s/^itf[bglmprs]//;
    my $tobjDevice=$lobjSelf->{"gateway"}->getDeviceInfo($lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId});
    # Farbe
    if (defined($tobjDevice->{"hue"})) {
      # Kommunikation mit dem Tradfri Gateway -> Tradfri Gerät Farbeändern
      $lstrResponse=$tobjDevice->{"gateway"}->_requestGateway(1,"{ \"3311\": [{ \"5706\": \"".$ghshMapColorHex{$lintColor}."\" }] }","5684/15001/".$tstrDeviceId);
      # Ist ein Fehler aufgetreten?
      if (!defined($lstrResponse)) { return; }
    }
  }
  
  # Alle Geräteinformationen neu einlesen 
  $lintResult=$lobjSelf->readDeviceInfo();
  if (! defined($lintResult)) { return; }

  # Erfolgreiche Rückmeldung
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' color='".$lintColor."' />");
}
########################################################################################################################


########################################################################################################################
# Farbe der Gruppe über xyY-Wert ändern
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->setXYY($strColor);
#
# Übergabe: $strColor    = Neue Farbe (0-65535,0-65535,0-254)
#
# Rückgabe: $strResponse = StringErfolgreich, undef=Ein Fehler ist aufgetreten (Beschreibung in $objSelf->{"error"})
#
#-----------------------------------------------------------------------------------------------------------------------
sub setXYY {
  my $lobjSelf=shift;      # Klasse-Name abfangen
  my $lstrColor=shift;     # Neue Farbe (0-65535,0-65535,0-254)
  my $lstrResponse="";     # Antwort des Tradfri Gateways
  my $lstrRealDeviceId=""; # Reale Geräte-ID-Lampen (ohne führendes itfl)
  my $lintResult=0;        # Ergebnisvariable
  
  # Kann an dem Gerät gar keine Farbe über xyY-Wert eingestellt werden?
  if (!defined($lobjSelf->{"xyy"})) { return ("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' xyY='-1,-1,-1' />"); }
  
  # Parameterprüfung
  my ($tintX,$tintY,$tintBri)=split(/,/,$lstrColor,3);
  if ($tintX !~ /^[0-9]+$/) { $tintX=0; }
  if ($tintX < 0) { $tintX=0; }
  if ($tintX > 65535) { $tintX=65535; }
  if ($tintY !~ /^[0-9]+$/) { $tintY=0; }
  if ($tintY < 0) { $tintY=0; }
  if ($tintY > 65535) { $tintY=65535; }
  if ($tintBri !~ /^[0-9]+$/) { $tintBri=0; }
  if ($tintBri < 0) { $tintBri=0; }
  if ($tintBri > 254) { $tintBri=254; }
  
  foreach my $tstrDeviceId ( @{$lobjSelf->{"devices"}} ) {
    $tstrDeviceId=~s/^itf[bglmprs]//;
    my $tobjDevice=$lobjSelf->{"gateway"}->getDeviceInfo($lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId});
    # Farbe
    if (defined($tobjDevice->{"colorx"})) {
      # Kommunikation mit dem Tradfri Gateway -> Tradfri Gerät Farbeändern
      $lstrResponse=$tobjDevice->{"gateway"}->_requestGateway(1,"{ \"3311\": [{ \"5709\": ".$tintX.", \"5710\": ".$tintY.", \"5851\":".$tintBri." }] }","5684/15001/".$tstrDeviceId);
      # Ist ein Fehler aufgetreten?
      if (!defined($lstrResponse)) { return; }
    }
  }
  
  # Alle Geräteinformationen neu einlesen 
  $lintResult=$lobjSelf->readDeviceInfo();
  if (! defined($lintResult)) { return; }

  # Erfolgreiche Rückmeldung
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' xyY='".$lstrColor."' />");
}
########################################################################################################################


########################################################################################################################
# Farbe der Gruppe über HSV-Wert ändern
#-----------------------------------------------------------------------------------------------------------------------
# Aufruf  : $strResponse=$objDevice->setHsv($strColor);
#
# Übergabe: $strColor    = Neue Farbe (0-65535,0-65279,0-254)
#
# Rückgabe: $strResponse = StringErfolgreich, undef=Ein Fehler ist aufgetreten (Beschreibung in $objSelf->{"error"})
#
#-----------------------------------------------------------------------------------------------------------------------
sub setHsv {
  my $lobjSelf=shift;      # Klasse-Name abfangen
  my $lstrColor=shift;     # Neue Farbe (0-65535,0-65279,0-254)
  my $lstrResponse="";     # Antwort des Tradfri Gateways
  my $lstrRealDeviceId=""; # Reale Geräte-ID-Lampen (ohne führendes itfl)
  my $lintResult=0;        # Ergebnisvariable
  
  # Kann an dem Gerät gar keine Farbe über HSV-Wert eingestellt werden?
  if (!defined($lobjSelf->{"hsv"})) { return ("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' hsv='-1,-1,-1' />"); }
  
  # Parameterprüfung
  my ($tintH,$tintS,$tintBri)=split(/,/,$lstrColor,3);
  if ($tintH !~ /^[0-9]+$/) { $tintH=0; }
  if ($tintH < 0) { $tintH=0; }
  if ($tintH > 65535) { $tintH=65535; }
  if ($tintS !~ /^[0-9]+$/) { $tintS=0; }
  if ($tintS < 0) { $tintS=0; }
  if ($tintS > 65279) { $tintS=65279; }
  if ($tintBri !~ /^[0-9]+$/) { $tintBri=0; }
  if ($tintBri < 0) { $tintBri=0; }
  if ($tintBri > 254) { $tintBri=254; }
  foreach my $tstrDeviceId ( @{$lobjSelf->{"devices"}} ) {
    $tstrDeviceId=~s/^itf[bglmprs]//;
    my $tobjDevice=$lobjSelf->{"gateway"}->getDeviceInfo($lobjSelf->{"gateway"}{"devices"}{$tstrDeviceId});
    # Farbe
    if (defined($tobjDevice->{"hue"})) {
      # Kommunikation mit dem Tradfri Gateway -> Tradfri Gerät Farbeändern
      $lstrResponse=$tobjDevice->{"gateway"}->_requestGateway(1,"{ \"3311\": [{ \"5707\": ".$tintH.", \"5708\": ".$tintS.", \"5851\":".$tintBri." }] }","5684/15001/".$tstrDeviceId);
      # Ist ein Fehler aufgetreten?
      if (!defined($lstrResponse)) { return; }
    }
  }
  
  # Alle Geräteinformationen neu einlesen 
  $lintResult=$lobjSelf->readDeviceInfo();
  if (! defined($lintResult)) { return; }

  # Erfolgreiche Rückmeldung
  return("<datapoint deviceid='".$lobjSelf->{"deviceid"}."' hsv='".$lstrColor."' />");
}
########################################################################################################################


########################################################################################################################
# Modul Aufräumen
#-----------------------------------------------------------------------------------------------------------------------
1;
########################################################################################################################
