[Alpha] Ambient-Modul zur vollautomatischen Steuerung von Wifilight

Begonnen von ChristianKnorr, 18 Mai 2014, 14:00:19

Vorheriges Thema - Nächstes Thema

ChristianKnorr

Hallo zusammen,
nachdem ich auf das Wifilight-Modul aufmerksam wurde, und mir solche Controller organisiert habe, habe ich angefangen die Steuerung auf Vollautomatisch zu programmieren.
Das ist mir ganz wichtig; ich will doch nicht sagen: mach mal LEDs an und auf Farbwechsel, das muss das Haus selber wissen ;D

Die Kernfunktionen sind:
"Auto"-Modus:

  • Wenn keiner da, dann aus, oder wenn auf "Anwesenheits_Simulation" dann minütlicher Farbwechsel wenn draußen dunkel aber nicht nachts (zwischen x und y Uhr)
  • Wenn Jemand im Wohnbereich, antiproportional zur Außenhelligkeit:

    •  
    • Wenn TV an, zurvor definierte Fixfarbe
    • Wenn TV aus, minütlicher sanfter Farbwechsel

Nebenbei noch "Aus", "An_Ambient_Fix", "An_Ambient_Wechsel", "An_TV_Modus"

2 Farben (Ambient|TV-Modus) werden über je 4 Schieberegler (Hue|Saturation|Min-|Maxhelligkeit) voreingestellt und können wenn zuvor angehakt direkt angesehen werden.

Die Abhängigkeiten sind:
ganz viele Slider ;)
Die Namen sind teils Hardcodiert, teils nicht. Bedutet: man denkt sich im Groben einen Namen aus, in meinem Fall und diesem Beispiel: TV_Beleuchtung. Das Modul erwartet dann dummys die z.B. so heißen: Farbe_fuer_TV_Beleuchtung_Ambient_Fix_H.
Das macht es wie ich finde modular und übersichtlich, auch wenn es viel einzustellen gibt.
Folgend die dummys in Codeform direkt zum Eintragen in die fhem.cfg, oder (empfohlen) einer anderen cfg-Datei:
Hier stellt man die Farbe (Hue) ein, die angezeigt werden soll wenn man TV guckt:define Farbe_fuer_TV_Beleuchtung_TV_Modus_H dummy
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_H group 04 - TV-Licht - TV Modus
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_H room Wohnzimmer
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_H setList state:slider,0,1,359
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_H webCmd state:22
die Saturation:define Farbe_fuer_TV_Beleuchtung_TV_Modus_S dummy
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_S group 04 - TV-Licht - TV Modus
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_S room Wohnzimmer
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_S setList state:slider,0,1,100
attr Farbe_fuer_TV_Beleuchtung_TV_Modus_S webCmd state:90
die Minimalhelligkeit:define Minimalhelligkeit_TV_Beleuchtung_TV_Modus dummy
attr Minimalhelligkeit_TV_Beleuchtung_TV_Modus group 04 - TV-Licht - TV Modus
attr Minimalhelligkeit_TV_Beleuchtung_TV_Modus room Wohnzimmer
attr Minimalhelligkeit_TV_Beleuchtung_TV_Modus setList state:slider,0,1,100
attr Minimalhelligkeit_TV_Beleuchtung_TV_Modus webCmd state:25
und die Maximalhelligkeit:define Maximalhelligkeit_TV_Beleuchtung_TV_Modus dummy
attr Maximalhelligkeit_TV_Beleuchtung_TV_Modus group 04 - TV-Licht - TV Modus
attr Maximalhelligkeit_TV_Beleuchtung_TV_Modus room Wohnzimmer
attr Maximalhelligkeit_TV_Beleuchtung_TV_Modus setList state:slider,0,1,100
attr Maximalhelligkeit_TV_Beleuchtung_TV_Modus webCmd state:100


Das Gleiche für Ambient_Fix:
define Farbe_fuer_TV_Beleuchtung_Ambient_Fix_H dummy
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_H group 04 - TV-Licht - Ambient Fix
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_H room Wohnzimmer
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_H setList state:slider,0,1,359
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_H webCmd state:200

define Farbe_fuer_TV_Beleuchtung_Ambient_Fix_S dummy
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_S group 04 - TV-Licht - Ambient Fix
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_S room Wohnzimmer
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_S setList state:slider,0,1,100
attr Farbe_fuer_TV_Beleuchtung_Ambient_Fix_S webCmd state:100

define Minimalhelligkeit_TV_Beleuchtung_Ambient_Fix dummy
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Fix group 04 - TV-Licht - Ambient Fix
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Fix room Wohnzimmer
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Fix setList state:slider,0,1,100
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Fix webCmd state:25

define Maximalhelligkeit_TV_Beleuchtung_Ambient_Fix dummy
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Fix group 04 - TV-Licht - Ambient Fix
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Fix room Wohnzimmer
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Fix setList state:slider,0,1,100
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Fix webCmd state:100


und für den Farbwechsel:define Farbe_fuer_TV_Beleuchtung_Ambient_Wechsel dummy
attr Farbe_fuer_TV_Beleuchtung_Ambient_Wechsel group 04 - TV-Licht - Ambient Wechsel
attr Farbe_fuer_TV_Beleuchtung_Ambient_Wechsel room Wohnzimmer
attr Farbe_fuer_TV_Beleuchtung_Ambient_Wechsel setList state:slider,0,1,360
attr Farbe_fuer_TV_Beleuchtung_Ambient_Wechsel webCmd state:0

define Spreizung_fuer_TV_Beleuchtung_Ambient_Wechsel dummy
attr Spreizung_fuer_TV_Beleuchtung_Ambient_Wechsel group 04 - TV-Licht - Ambient Wechsel
attr Spreizung_fuer_TV_Beleuchtung_Ambient_Wechsel room Wohnzimmer
attr Spreizung_fuer_TV_Beleuchtung_Ambient_Wechsel setList state:slider,60,1,360
attr Spreizung_fuer_TV_Beleuchtung_Ambient_Wechsel webCmd state:60:120:180:240:360

define Minimalhelligkeit_TV_Beleuchtung_Ambient_Wechsel dummy
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Wechsel group 04 - TV-Licht - Ambient Wechsel
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Wechsel room Wohnzimmer
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Wechsel setList state:slider,0,1,100
attr Minimalhelligkeit_TV_Beleuchtung_Ambient_Wechsel webCmd state:0:20:50:100

define Maximalhelligkeit_TV_Beleuchtung_Ambient_Wechsel dummy
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Wechsel group 04 - TV-Licht - Ambient Wechsel
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Wechsel room Wohnzimmer
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Wechsel setList state:slider,0,1,100
attr Maximalhelligkeit_TV_Beleuchtung_Ambient_Wechsel webCmd state:100

define WechselZeit_fuer_TV_Beleuchtung_Ambient_Wechsel dummy
attr WechselZeit_fuer_TV_Beleuchtung_Ambient_Wechsel group 04 - TV-Licht - Ambient Wechsel
attr WechselZeit_fuer_TV_Beleuchtung_Ambient_Wechsel room Wohnzimmer
attr WechselZeit_fuer_TV_Beleuchtung_Ambient_Wechsel setList state:slider,0,1,20
attr WechselZeit_fuer_TV_Beleuchtung_Ambient_Wechsel webCmd state:0:3:5:10:15:20


Dann muss man noch wissen ob der Fernseher an ist (oder wie ich es mache: den AVR nach der Eingangsquelle abfrage):define WohnzimmerTV_ist_an dummy
attr WohnzimmerTV_ist_an devStateIcon .*1:rc_GREEN .*0:rc_STOP
attr WohnzimmerTV_ist_an group 2 - Multimedia
attr WohnzimmerTV_ist_an icon it_television
attr WohnzimmerTV_ist_an room _Wohnzimmer


Das braucht man wenn Änderungen am Slider direkt umgesetzt werden werden sollen (Vorschau) oder nicht:define Ambilight_notify notify wz_TV_Ambilight trigger Aktiviere_TV_Ambient_notify
attr Ambilight_notify group TV-Licht
attr Ambilight_notify room _Wohnzimmer

define wz_TV_Ambient_Aenderung_sofort_uebernehmen dummy
attr wz_TV_Ambient_Aenderung_sofort_uebernehmen alias Aenderung_sofort_uebernehmen
attr wz_TV_Ambient_Aenderung_sofort_uebernehmen devStateIcon .*Ja:rc_GREEN:Nein .*Nein:rc_STOP:Ja
attr wz_TV_Ambient_Aenderung_sofort_uebernehmen group 04 - TV-Licht
attr wz_TV_Ambient_Aenderung_sofort_uebernehmen room Wohnzimmer
attr wz_TV_Ambient_Aenderung_sofort_uebernehmen setList state:Ja,Nein
attr wz_TV_Ambient_Aenderung_sofort_uebernehmen webCmd Ja:Nein

define WifiLight_TV_Licht_Farbe_uebernehmen notify (.*_TV_Beleuchtung_TV_Modus.*|.*_TV_Beleuchtung_Ambient_Fix.*|.*_TV_Beleuchtung_Ambient_Wechsel.*) {\
  my $c = Value("wz_TV_Ambient_Aenderung_sofort_uebernehmen");;\
  my $device = Value("TV_Ambilight_device");;\
\
  if ( $c eq "Ja" ) {\
    fhem("trigger Aktiviere_TV_Ambient_notify");;\
  }\
}
attr WifiLight_TV_Licht_Farbe_uebernehmen group TV-Licht
attr WifiLight_TV_Licht_Farbe_uebernehmen room _Wohnzimmer


Eine structure wenn man mehrere Controller hat:define Wohnzimmer_RGB_LEDs structure room LED_WohnzimmerTV LED_Gardine
attr Wohnzimmer_RGB_LEDs room Wohnzimmer


Damit das Modul weiß welcher Controller kontrolliert werden soll (braucht man trotzdem, auch wenn nur einer existiert):define TV_Ambilight_device dummy
attr TV_Ambilight_device alias Geraet
attr TV_Ambilight_device group 04 - TV-Licht
attr TV_Ambilight_device room Wohnzimmer
attr TV_Ambilight_device setList state:LED_WohnzimmerTV,LED_Gardine,Wohnzimmer_RGB_LEDs
attr TV_Ambilight_device webCmd state



Dann das eigentliche Modul unter dem Dateinamen 99_WifiLED_Utils.pm gespeichert:package main;
use strict;
use warnings;
use POSIX;

sub
WifiLight_Utils_Initialize($$)
{
  my ($hash) = @_;
}

sub WifiLight_control_Ambient_Dev($$$$$$) {
# ****************************************************************
# * Param: 1-Jmd Wohnbereich                                     *
# *        2-Licht                                               *
# *        3-Device                                              *
# *        4-Funktion                                            *
# *        5-TV on                                               *
# *        6-Slidername                                          *
# * Author: Christian Knorr                                      *
# *         http://forum.fhem.de/index.php?action=profile;u=5167 *
# ****************************************************************
  my ($wohn,$licht,$device,$function,$tv,$inputname) = @_;
  Log3 ("WifiLight_control_Ambient_Dev", 4, "wohn: $wohn,licht: $licht,device: $device,function: $function,tv: $tv,inputname: $inputname");
  my $Ambient_Fix_H = "Farbe_fuer_" . $inputname . "_Ambient_Fix_H";
  my $Ambient_Fix_S = "Farbe_fuer_" . $inputname . "_Ambient_Fix_S";
  my $Ambient_Fix_min = "Minimalhelligkeit_" . $inputname . "_Ambient_Fix";
  my $Ambient_Fix_max = "Maximalhelligkeit_" . $inputname . "_Ambient_Fix";

  my $Ambient_Wechsel = "Farbe_fuer_" . $inputname . "_Ambient_Wechsel";
  my $Spreizung_Wechsel = "Spreizung_fuer_" . $inputname . "_Ambient_Wechsel";
  my $Ambient_Wechsel_min = "Minimalhelligkeit_" . $inputname . "_Ambient_Wechsel";
  my $Ambient_Wechsel_max = "Maximalhelligkeit_" . $inputname . "_Ambient_Wechsel";
  my $Ambient_Wechsel_fade = "WechselZeit_fuer_" . $inputname . "_Ambient_Wechsel";

  my $TV_Modus_H = "Farbe_fuer_" . $inputname . "_TV_Modus_H";
  my $TV_Modus_S = "Farbe_fuer_" . $inputname . "_TV_Modus_S";
  my $TV_Modus_min = "Minimalhelligkeit_" . $inputname . "_TV_Modus";
  my $TV_Modus_max = "Maximalhelligkeit_" . $inputname . "_TV_Modus";

  my $state = Value($device);

  $Ambient_Fix_H = ReadingsVal("$Ambient_Fix_H","state",22);
  $Ambient_Fix_S = ReadingsVal("$Ambient_Fix_S","state",100);
  $Ambient_Fix_min = ReadingsVal("$Ambient_Fix_min","state",25);
  $Ambient_Fix_max = ReadingsVal("$Ambient_Fix_max","state",100);

  $Ambient_Wechsel = ReadingsVal("$Ambient_Wechsel","state",1);
  $Spreizung_Wechsel = ReadingsVal("$Spreizung_Wechsel","state",180);
  $Ambient_Wechsel_min = ReadingsVal("$Ambient_Wechsel_min","state",20);
  $Ambient_Wechsel_max = ReadingsVal("$Ambient_Wechsel_max","state",100);
  $Ambient_Wechsel_fade = ReadingsVal("$Ambient_Wechsel_fade","state",5);

  $TV_Modus_H = ReadingsVal("$TV_Modus_H","state",22);
  $TV_Modus_S = ReadingsVal("$TV_Modus_S","state",90);
  $TV_Modus_min = ReadingsVal("$TV_Modus_min","state",25);
  $TV_Modus_max = ReadingsVal("$TV_Modus_max","state",100);

  my $now_color_H = ReadingsVal("$device","hue",0);
  my $now_color_S = ReadingsVal("$device","saturation",0);
  my $now_color_V = ReadingsVal("$device","brightness",0);

  if (
    ( $wohn == 1 ) ||
    ( $function eq "Anwesenheits_Simulation" )
  )
  {
    if ( $function eq
"An_Ambient_Fix" ) {
      WifiLight_switch_color(
        $device,
        "HSV",
        $Ambient_Wechsel_fade,
        $Ambient_Fix_H,
        $Ambient_Fix_S,
        WifiLight_calc_new_bright(
          $licht,
          100,
          $Ambient_Fix_min,
          $Ambient_Fix_max),
        $Ambient_Wechsel_fade);
    } elsif ( $function eq
"An_Ambient_Wechsel" ) {
      my ($new_H,$new_S,$other_H) = WifiLight_calc_rand_color(
        $now_color_H,
        $now_color_S,
        $Ambient_Wechsel,
        $Spreizung_Wechsel
      );
      WifiLight_switch_color(
        $device,
        "HSV",
        $Ambient_Wechsel_fade,
        $new_H,
        $new_S,
        WifiLight_calc_new_bright(
          $licht,
          100,
          $Ambient_Wechsel_min,
          $Ambient_Wechsel_max),
        $Ambient_Wechsel_fade);
    } elsif ( $function eq
"An_TV_Modus" ) {
      WifiLight_switch_color(
        $device,
        "HSV",
        $Ambient_Wechsel_fade,
        $TV_Modus_H,
        $TV_Modus_S,
        WifiLight_calc_new_bright(
          $licht,
          100,
          $TV_Modus_min,
          $TV_Modus_max),
        $Ambient_Wechsel_fade
      );
    } elsif ( $function eq
"Aus" ) {
      if ( $state eq "on" ) {
        WifiLight_switch_color(
          $device,
          "off",
          $Ambient_Wechsel_fade
        );
      }
    } elsif ( $function eq
"Auto" ) {
      if ( $tv == 1 ) {
        WifiLight_control_Ambient_Dev(
          $wohn,
          $licht,
          $device,
          "An_TV_Modus",
          $tv,
          $inputname);
      } else {
        WifiLight_control_Ambient_Dev(
          $wohn,
          $licht,
          $device,
          "An_Ambient_Wechsel",
          $tv,
          $inputname);
      }
    } elsif ( $function eq
"Anwesenheits_Simulation" ) {
      if ( $licht < 10 ) {
        my $hour = aktuelleStunde();
        if ( $hour > 6 && $hour < 23 ) {
          WifiLight_control_Ambient_Dev(
            "1",
            $licht,
            $device,
            "Auto_Ambient_Wechsel",
            "0",
            $inputname);
        } else {
          WifiLight_control_Ambient_Dev(
            "1",
            "85",
            $device,
            "Auto_Ambient_Wechsel",
            "0",
            $inputname);
        }
      } else {
        if ( Value("$device") eq "on" ) {
          WifiLight_control_Ambient_Dev(
            "1",
            $licht,
            $device,
            "Aus",
            $tv,
            $inputname);
        }
      }
    }
  } else {
    if ( Value("$device") eq "on" ) {
      WifiLight_switch_color(
        $device,
        "off",
        $Ambient_Wechsel_fade
      );
    }
  }
}

sub WifiLight_switch_color($$$@) {
# ****************************************************************
# * Author: Christian Knorr                                      *
# *         http://forum.fhem.de/index.php?action=profile;u=5167 *
# ****************************************************************
  my ($device,$func,$fade,@vars) = @_;
  my $h = ReadingsVal("$device","hue",0);
  my $s = ReadingsVal("$device","saturation",0);
  my $v = ReadingsVal("$device","brightness",0);
  Log3("WifiLight_switch_color",4,"WifiLight_switch_color: device=$device func=$func fade=$fade h=$h s=$s v=$v");
  if ( $func eq "on" ) {
    Log3("WifiLight_switch_color",4,"WifiLight_switch_color: on");
    fhem("set $device HSV 1,1,1");
  } elsif ( ( $v == 0 ) && ( $vars[2] == 0 ) ) {
    Log3("WifiLight_switch_color",4,"WifiLight_switch_color: bleibt off");
  } elsif ( ( $func eq "off" ) || ( $vars[2] == 0 ) ) {
    Log3("WifiLight_switch_color",4,"WifiLight_switch_color: off");
    fhem("set $device off $fade");
  } elsif ( $func eq "HSV" ) {
    Log3("WifiLight_switch_color",4,"WifiLight_switch_color: HSV");
  if ( Value("$device") ne "on" ) {
      Log3("WifiLight_switch_color",4,"WifiLight_switch_color: on (weil nicht on)");
      fhem("set $device HSV 0,0,0");
  }
    if
    (
      (
        ( $h != $vars[0] ) ||
        ( $s != $vars[1] ) ||
        ( $v != $vars[2] )
      )
    &&
      ( $vars[2] != 0 )
    ) {
      Log3("WifiLight_switch_color",4,"WifiLight_switch_color: Farbaenderung nach $vars[0],$vars[1],$vars[2] ramp $vars[3]");
      fhem("set $device $func $vars[0],$vars[1],$vars[2] $vars[3]");
    }
  }
}

sub WifiLight_calc_rand_color($$$$) {
# ****************************************************************
# * Param: 1-old color                                           *
# *        2-old Saturation                                      *
# *        3-new color (0-360°)                                  *
# *        4-new color range (0-180°)                            *
# * Return: 1-new color                                          *
# *         2-new Saturation                                     *
# *         3-other color1 (+-180°) | for 2nd of 2 LED           *
# *         4-other color2a (+120°) | for 2nd of 3 LED           *
# *         5-other color2b (-120°) | for 3rd of 3 LED           *
# * Author: Christian Knorr                                      *
# *         http://forum.fhem.de/index.php?action=profile;u=5167 *
# ****************************************************************
  my ($old_H,$old_S,$color,$range) = @_;
  my $loglevel = 4;
  #todo WifiLight_calc_rand_color: unzufrieden :(

  my $minsaturation = 50; # sonst zuviel Weiß
  my $new_S = int( $minsaturation + (rand(100-$minsaturation)) );

  my $minrange = ( $range / 12 );
  my $new_H = 0 + int( $old_H + $minrange - ( $range / 2 ) + rand($range-$minrange) );
  Log3("WifiLight_calc_rand_color",$loglevel,"1 - alt:$old_H neu:$new_H");
  if ( $new_H > ( 360 + $color + ( $range / 2 ) ) ) { $new_H = $new_H - $range }
  Log3("WifiLight_calc_rand_color",$loglevel,"2 - ".$new_H);
  my $range_max = 360 + ( $color + ( $range / 2 ) );
  my $range_min = 360 + ( $color - ( $range / 2 ) );
  Log3("WifiLight_calc_rand_color",$loglevel,"3 - $range_min bis $range_max. $new_H");
  while ( ( $new_H > $range_max ) || ( $new_H < $range_min ) ) {
    if ( $new_H > $range_max ) { $new_H = $new_H - $range; }
    if ( $new_H < $range_min ) { $new_H = $new_H + $range; }
  }
  Log3("WifiLight_calc_rand_color",$loglevel,"4 - $range_min bis $range_max. $new_H");
  $new_H = $new_H - 360;
  if ( $new_H > 360 ) {
    $new_H = ( $new_H - 360 );
  } elsif ( $new_H < 0 ) {
    $new_H = ( $new_H + 360 );
  }
  Log3("WifiLight_calc_rand_color",$loglevel,"5 - $range_min bis $range_max. $new_H");
  Log3("WifiLight_calc_rand_color",$loglevel,"");

  my $other_Ha;
  if ( $new_H > 180 ) {
    $other_Ha = ( $new_H - 180 );
  } else {
    $other_Ha = ( $new_H + 180 );
  }
  my $other_Hba;
  my $other_Hbb;
  if ( $new_H < 120 ) {
    $other_Hba = ( $new_H + 120 );
    $other_Hbb = ( $other_Hba + 120 );
  } elsif ( $new_H >= 240 ) {
    $other_Hba = ( $new_H - 120 );
    $other_Hbb = ( $other_Hba - 120 );
  } else {
    $other_Hba = ( $new_H + 120 );
    $other_Hbb = ( $new_H - 120 );
  }
  Log3 ("WifiLight_calc_rand_color", $loglevel, "WifiLight_calc_rand_color return: $new_H,$new_S,$other_Ha,$other_Hba,$other_Hbb");
  return ($new_H,$new_S,$other_Ha,$other_Hba,$other_Hbb);
}

sub WifiLight_calc_new_bright($$$$) {
# ****************************************************************
# * Param: 1-real light (0-100% from eg Twilight)                *
# *        2-base light (0-100% from slider wish)                *
# *        3-min light (0-100% from slider wish)                 *
# *        4-max light (0-100% from slider wish)                 *
# * Author: Christian Knorr                                      *
# *         http://forum.fhem.de/index.php?action=profile;u=5167 *
# ****************************************************************
  my ($real_light,$base_light,$minlight,$maxlight) = @_;
  Log3("WifiLight_calc_new_bright",4,"WifiLight_calc_new_bright: real_light=$real_light base_light=$base_light minlight=$minlight maxlight=$maxlight");
  my $new_light = (int((100-$real_light)/100*$base_light));
  if ( $new_light < $minlight ) { return $minlight; }
  if ( $new_light > $maxlight ) { return $maxlight; }
  return $new_light;
}

sub wakeUp {
# Dauer in Minuten (minimum 4 min)
my $dauer = $_[0];
# Initialisiern des Lichterarrays
my @lichter = ($_[1],$_[2],$_[3],$_[4]);

my @farben = (
["240,100,2",20],
["240,100,5",20],
["240,100,8",20],
["210,100,10",30],
["190,100,12",1],
["90,100,14",1],
["70,100,16",1],
["10,100,24",2],
["30,100,40",30],
["40,100,60",30],
["45,100,80",30],
["50,100,100",30],
["50,0,28",5],
["50,0,80",30]
);

my $gesamtdauersek = $dauer*60;

my $dauerfarben = 0;
foreach my $farbe ( @farben ) {
$dauerfarben+=$farbe->[1];
}

my $anteiligedauer = $gesamtdauersek/$dauerfarben;

Log3 (undef, 3, "WakeUp: start, angegebene Gesamtdauer in Sekunden $gesamtdauersek, Dauer Farben $dauerfarben, Anteil $anteiligedauer");

# Ausschalten der Lampen (Schalter - off)
foreach my $licht ( @lichter ) {
if(defined $licht) {
fhem("set $licht off");
}
}

# Dunkelblau als Startfarbe (Schalter - on)
foreach my $licht ( @lichter ) {
if(defined $licht) {
fhem("set $licht on 240,100,0");
}
}

# Durchlauf der Farbsimulation
my $i = 0;
foreach my $farbe ( @farben ) {
foreach my $licht ( @lichter ) {
if(defined $licht) {
if($i == 0) {
fhem("set $licht HSV ".($farben[$i][0])." ".ceil($anteiligedauer*($farben[$i][1])));
} else {
fhem("set $licht HSV ".($farben[$i][0])." ".ceil($anteiligedauer*($farben[$i][1]))." q");
}
}
}
$i++;
}
}

sub sunset {
# Sonnenaufgangssimulation für bis zu 4 Devices
# Author : Sandra Ohmayer (http://www.animeschatten.net)
# Aufruf: wakeUp(<Zeit in Minuten>,"<Devicename>"),wakeUp(<Zeit in Minuten>,"<Devicename1>","<Devicename2>") ...
# Dauer in Minuten (minimum 4 min)
my $dauer = $_[0];
# Initialisiern des Lichterarrays
my @lichter = ($_[1],$_[2],$_[3],$_[4]);

my @farben = (
["50,0,80",30],
["50,0,28",5],
["50,100,100",30],
["45,100,80",30],
["40,100,60",30],
["30,100,40",30],
["10,100,24",2],
["70,100,16",1],
["90,100,14",1],
["190,100,12",1],
["210,100,10",30],
["240,100,8",20],
["240,100,5",20],
["240,100,2",20]
);

my $gesamtdauersek = $dauer*60;

my $dauerfarben = 0;
foreach my $farbe ( @farben ) {
$dauerfarben+=$farbe->[1];
}

my $anteiligedauer = $gesamtdauersek/$dauerfarben;

Log3 (undef, 3, "sunset: start, angegebene Gesamtdauer in Sekunden $gesamtdauersek, Dauer Farben $dauerfarben, Anteil $anteiligedauer");

# Dunkelrot als Startfarbe (Schalter - on)
foreach my $licht ( @lichter ) {
if(defined $licht) {
fhem("set $licht on 50,0,100");
}
}

# Durchlauf der Farbsimulation
my $i = 0;
foreach my $farbe ( @farben ) {
foreach my $licht ( @lichter ) {
if(defined $licht) {
if($i == 0) {
fhem("set $licht HSV ".($farben[$i][0])." ".ceil($anteiligedauer*($farben[$i][1])));
} else {
fhem("set $licht HSV ".($farben[$i][0])." ".ceil($anteiligedauer*($farben[$i][1]))." q");
}
}
}
$i++;
}
# Ausschalten der Lampen (Schalter - off)
foreach my $licht ( @lichter ) {
if(defined $licht) {
fhem("set $licht off");
}
}
}

1;
(sub sunset und sub wakeUp sind einfach nur geklaut und habe ich noch nie getestet)

Ein at damit ein minütlicher Farbwechsel stattfindet:define TV_Ambient_Dunkel at +*00:01:00 {fhem("trigger Aktiviere_TV_Ambient_notify")}
attr TV_Ambient_Dunkel group TV-Licht
attr TV_Ambient_Dunkel icon it_television
attr TV_Ambient_Dunkel room _Wohnzimmer


Ein notify was das Ganze anstößt:define Aktiviere_TV_Ambient_notify notify Aktiviere_TV_Ambient_notify {\
  my $wohn = Value("JemandWohn.Anwesenheit");;\
  my $licht = ReadingsVal("Twilight","twilight_weather",0);;\
  Samsung_TV_status("wz_Onkyo","WohnzimmerTV_ist_an");;\
  my $tv = Value("WohnzimmerTV_ist_an");;\
  my $function = Value("wz_TV_Ambilight");;\
  my $device = Value("wz_TV_Ambilight_device");;\
\
  WifiLight_control_Ambient_Dev(\
   $wohn,\
   $licht,\
   $device,\
   $function,\
   $tv,\
   "TV_Beleuchtung"\
  );;\
}
attr Aktiviere_TV_Ambient_notify group TV-Licht
attr Aktiviere_TV_Ambient_notify icon it_television
attr Aktiviere_TV_Ambient_notify room _Wohnzimmer
Hier muss jetzt jeder selber wissen wie er den dummy WohnzimmerTV_ist_an schaltet. Bei mir macht das die sub Samsung_TV_status.
Die Variable $wohn bestimmt ob Jemand im Wohnbereich ist oder nicht (0|1).
Die Variable $licht hole ich mir von Twilight. Sie repräsentiert die (theoretische) Außenhelligkeit zwischen 0% (Nacht) und 100% (Taghell).

-----------------------------------------------------------------------------------------------------------------------------------

Boah, ganz schön viel Code. Ich hoffe ich hab keinen erschreckt und alles funktioniert :)

Was definitiv nicht funktioniert und wo ich mir die Zähne dran ausbeiße ist die sub WifiLight_calc_rand_color. Für erste Tests genügt es aber.

So, jetzt ihr... (und sonnigen Sonntag noch)

Starkstrombastler

Hallo,

das ist wirklich eine Menge Code. Wie sieht das denn auf der Web-Oberfläche aus?

Was ich noch nicht verstehe: Ist dies ein Ersatz für WifiLight oder ein AddOn?

ByTheWay:
Zitat
    Wenn TV an, zuvor definierte Fixfarbe
    Wenn TV aus, minütlicher sanfter Farbwechsel
ist natürlich Geschmackssache. Bei mir läuft mit etwas Bastellei
    Wenn TV an, dann hole Farbe vom Philips TV
    Wenn TV aus, stelle auf definierte Fixfarbe


IPC\Ubuntu + Fhem, 1wire, Shellies, Siemens Logo!, Z-Wave, PhilipsTV, Vu+duo2, KM200

herrmannj

Hi,

Ist dies ein Ersatz für WifiLight oder ein AddOn?
christian hat damit ein ziemlich cooles add-on geschrieben.

Wenn TV an, dann hole Farbe vom Philips TV
wie holst Du die Farbe vom philips ?

danke und vg
jörg

Starkstrombastler

#3
Zitatwie holst Du die Farbe vom philips ?

Den Zustand des TVs prüfe ich in 30 sec Abstand mit einem PRESENCE:

define prscPhilipsTV PRESENCE lan-ping 192.168.178.22 90 30
attr prscPhilipsTV alias Philips-TV
attr prscPhilipsTV event-on-change-reading state




Im zugehörigen Notify benutze ich eine Sub CheckMyTV(), welche die Ambicolor vom TV holt und in ein Reading schreibt. Das Reading übergebe ich an Wifilight:

define nTVon notify prscPhilipsTV:present {
fhem "setstate PhilipsTVdummy present";
CheckMyTV("192.168.178.22","TV");
my $Ambi=ReadingsVal("TV","Ambilight","888800");
fhem "set myLW12 RGB $Ambi 5";
}


Die Sub CheckMyTV() holt einige Daten vom TV und füllt Readings.
Anm.:
Inzwischen gibt es das PHTV-Modul, was das vermutlich noch besser macht, aber ich habe noch nicht umgestellt.

sub
CheckMyTV($$)
{
my $ip_adress = shift;
my $device = shift;   # fhem-device-definition
my $ID = "no ID";
my $Progr ="no Progr";
my $Type ="Television";

my $Ambi =get_Ambilight($ip_adress);

$ip_adress .= ":1925";   # wg uneinheitlicher Programmierung

my $Src = get_Source($ip_adress); # sat, hdmi.., etc.

if ($Src eq "sat" ){
    $ID = get_ChannelID($ip_adress);
    $Progr = ChannelIDtoChannelName($ID);
} else {
    $Progr = SourceIDtoSourceName($ID);
}

my $Volume=get_Audio($ip_adress);

if ($Ambi eq 151515){$Type = "Radio";}

setReadingsVal($defs{$device},"Ambilight",$Ambi,TimeNow());
setReadingsVal($defs{$device},"ID",$ID,TimeNow());
setReadingsVal($defs{$device},"Quelle",$Src,TimeNow());
setReadingsVal($defs{$device},"Program",$Progr,TimeNow());
setReadingsVal($defs{$device},"Lautstärke",$Volume,TimeNow());
setReadingsVal($defs{$device},"Typ",$Type,TimeNow());

fhem "setstate $device $Progr";
my $Str=$Progr.":channels/ch_".$Progr;
fhem "attr $device devStateIcon $Str";

fhem "setstate PhilipsVolume $Volume";
return $Progr;
};



Hier das eigentliche "Holen" der Farbwerte für die zweite LED von oben per JSON. Im Beispiel wird der jeweils kleinste Wert von rechts und links weiter gegeben.
Die hier benutzte Sub PhilipsTV_GetValue() ist Bestandteil vom 74_PhilipsTV.pm-Modul, das wurde vor Längerem im Forum vorgestellt.

sub
get_Ambilight($)
{
my $device_ip=shift;
my $json = JSON::PP->new;
my $JS_Stream = PhilipsTV_GetValue("/1/ambilight/processed",$device_ip);
my $data   = $json->decode($JS_Stream);
my $Layer1 = $data->{layer1};
my $Left   = $Layer1->{left};
my $Right  = $Layer1->{right};

my $Red =   Mmin( $Left->{1}->{r} , $Right->{1}->{r} );
my $Green = Mmin( $Left->{1}->{g} , $Right->{1}->{g} );
my $Blue =  Mmin( $Left->{1}->{b} , $Right->{1}->{b} );

my $str = sprintf('%02x',$Red).sprintf('%02x',$Green).sprintf('%02x',$Blue);
#Log(1,"$Red $Green $Blue ===>  $str");
return $str;
}
#------------
sub
Mmin($$)
{
my $A=shift;
my $B=shift;
if ($A > $B) {return $B;}
else {return $A;}
}


Obenstehender Code stellt gewissermaßen auch eine "Ambient-Funktion" dar. Im weiteren Ausbau könnten diverse Quellen (TVs, Enigma,...) und Senken (LEDs, etc.) universell verknüpft werden.
IPC\Ubuntu + Fhem, 1wire, Shellies, Siemens Logo!, Z-Wave, PhilipsTV, Vu+duo2, KM200

herrmannj

iss ja cool. Das werde ich beim nächsten Kauf mit berücksichtigen.

Wobei 30 Sekunden und pollen mir noch etwas langsam für echtes ambilight feeling erscheint. Wie "fühlt" sich das in der praxis so an ?

vg
jörg

Starkstrombastler

ZitatWie "fühlt" sich das in der praxis so an ?
Die 30 Sekunden habe ich gewählt um die FritzBox nicht allzusehr zu belasten. Im Ergebnis ist mein Ambilight meistens verkehrt, aber trotzdem schön, wenn sich etwas tut.
Das Ganze werde ich auf einen Raspi schieben, und dort einen 1-Sekunden-Takt probieren.
IPC\Ubuntu + Fhem, 1wire, Shellies, Siemens Logo!, Z-Wave, PhilipsTV, Vu+duo2, KM200