Sonos Alarm. Aktion koppeln

Begonnen von Gidiano, 25 November 2015, 20:42:35

Vorheriges Thema - Nächstes Thema

Gidiano

Hallo zusammen,

nach Recherche in den bestehenden Informationen bin ich leider nicht weiter gekommen :-(
Ich möchte gern an meinen Sonos-Alarm eine Aktion koppeln, z.B. das Einschalten der Beleuchtung.
Momentan habe ich in einem Floorplan Buttons angeordnet, mit denen ich verschiedene Uhrzeiten zum Wecken aktivieren kann. Hier zwei davon:
#----------------------------------------------------------------------------------------------------
define Set_WakeUp_01 DOIF ([WakeUp_01] eq "0")\
(set WakeUp.* 0, set Sonos_Schlafzimmer Stop, {UpdateSonosAlarm ("4", "0", "12", "05:30:00", "00:15:00")})\
DOELSEIF ([WakeUp_01] eq "1")\
    (set WakeUp.* 0, set WakeUp_01 1, set Sonos_Schlafzimmer Volume 21, {UpdateSonosAlarm ("4", "1", "12", "05:30:00", "00:15:00")})
attr Set_WakeUp_01 room SONOS
#----------------------------------------------------------------------------------------------------
define Set_WakeUp_02 DOIF ([WakeUp_02] eq "0")\
(set WakeUp.* 0, set Sonos_Schlafzimmer Stop,  {UpdateSonosAlarm ("4", "0", "12", "06:00:00", "00:15:00")})\
DOELSEIF ([WakeUp_02] eq "1")\
(set WakeUp.* 0, set WakeUp_02 1, set Sonos_Schlafzimmer Volume 21, {UpdateSonosAlarm ("4", "1", "12", "06:00:00", "00:15:00")})
attr Set_WakeUp_02 room SONOS
#----------------------------------------------------------------------------------------------------

An die jeweilige Aktion möchte ich bei Start des Alarms die Lampen starten. Hat jemand einen Ansatz, wie ich ggf mit einem DOIF unter jeder Uhrzeit-Prozedur den Alarm feststelle und dann die Lamen einschalten? "AlarmRunning" hab ich da im Visier, aber leider keine Codeschnipsel gefunden.
Ich bin nicht so der Programmierer, wie man am Code sieht, aber ich versuche mich zu arrangieren und hoffe auf Eure Milde!

Vielen Dank!
Christian
Grüße,
Christian

rapster

#1
Hi Christian,

habe mir hierzu mal was für mein "wakeupLight" gebaut welches das Licht im SZ beim nächstgelegenen Alarm des Tages hochdimmt, falls es draußen dunkel ist.

Dazu folgendes in deine myUtils, diese Funktion liefert dir immer die nächste (aktive) Weckzeit des Sonosplayers am heutigen oder nächsten Tag:
### Returns todays first alarm of a player in seconds after midnight ###
# 1st parameter must be the sonos-player
# e.g. sonosWakupTime("Sonos_Schlafzimmer");
sub sonosWakeupTime(@) {
    my $sonosplayer = shift;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    my @days = ("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
    my $recurrence_day = "Recurrence_".$days[$wday];
    my $alarmList = eval(ReadingsVal($sonosplayer,"AlarmList","{}"));
    my $currentSec = ($hour*3600 + $min*60 + $sec);

    my @wakeUpTimes = ();
    for (sort keys %{$alarmList}) {
        next if( !$alarmList->{$_}->{Enabled}
                 || !($alarmList->{$_}->{$recurrence_day} || $alarmList->{$_}->{Recurrence_Once})
                 || $alarmList->{$_}->{StartTime} !~ /(\d+):(\d+):(\d+)/
               );
        push(@wakeUpTimes,($1*3600 + $2*60 + $3)) if( ($1*3600 + $2*60 + $3) >= $currentSec );
    }
   
    unless(scalar @wakeUpTimes) {   #Check next day
        $wday = ($wday < 6) ? ($wday + 1) : 0;
        $recurrence_day = "Recurrence_".$days[$wday];
        for (sort keys %{$alarmList}) {
            next if( !$alarmList->{$_}->{Enabled}
                     || !($alarmList->{$_}->{$recurrence_day} || $alarmList->{$_}->{Recurrence_Once})
                     || $alarmList->{$_}->{StartTime} !~ /(\d+):(\d+):(\d+)/
                   );
            push(@wakeUpTimes,($1*3600 + $2*60 + $3));
        }
    }

    return 'off' unless(scalar @wakeUpTimes);
    return (sort @wakeUpTimes)[0];
}
###############################################################################

### Convert seconds to (DDD:)HH:MM:SS ###
sub time_sec2hms($) {
    my $s = shift;
    my $m = $s / 60;
    $s = $s % 60;
    my $h = $m / 60;
    $m %= 60;
    return sprintf("%02d:%02d:%02d", $h, $m, $s) if($h < 24);
    my $d = $h / 24;
    $h %= 24;
    return sprintf "%d:%02d:%02d:%02d", $d, $h, $m, $s;
}
###############################################################################


Dazu habe ich mir noch ein DOIF zu Steuerung gebastelt (die Definition bitte über DEF eintragen, nicht in die fhem.cfg):
define di_wakeupLight DOIF ( [+:15] or [wakeupLight:?offset] or [Sonos_Schlafzimmer:?AlarmList] )
    ( set wakeupLight alarm {(sonosWakeupTime("Sonos_Schlafzimmer"))} )
DOELSEIF ( [twilight:twilight_weather] >= 50 and [wakeupLight:active] eq 'active' )
    ( set wakeupLight active deactivated )
DOELSEIF ( [twilight:twilight_weather] < 50 and [wakeupLight:active] eq 'deactivated' )
    ( set wakeupLight active active )
DOELSEIF ( [wakeupLight:active] eq 'active' and [wakeupLight:light-begin-dimm] ne "0" and [[wakeupLight:light-begin-dimm]] )
    ( set og_sz_licht 100 5400 {([wakeupLight:offset]*60)} )
attr di_wakeupLight do always 


Und ein readingsProxy zur Visualisierung in FHEM sowie zum Einstellen des Offsets damit das Licht ein paar Minuten vor dem Alarm langsam hochgedimmt wird (Ebenfalls über die Weboberfläche eintragen, ist nicht für copy/paste in die fhem.cfg gedacht):
define wakeupLight readingsProxy wakeupLight
attr wakeupLight event-on-change-reading .*
attr wakeupLight setFn {
    readingsBeginUpdate($defs{$DEVICE});
    if($CMD eq 'alarm') {
        if ($ARGS ne 'off') {
            readingsBulkUpdate($defs{$DEVICE}, $CMD, time_sec2hms($ARGS));
            my $lightBeginTime = ($ARGS - ReadingsVal($DEVICE,'offset',0) * 60);
            $lightBeginTime = 0 if ($lightBeginTime < 0);
            readingsBulkUpdate($defs{$DEVICE}, 'light-begin-dimm', time_sec2hms($lightBeginTime));
        } else {
            readingsBulkUpdate($defs{$DEVICE}, $CMD, $ARGS);
            readingsBulkUpdate($defs{$DEVICE}, 'light-begin-dimm', 0);
        }
    }
    else {
        readingsBulkUpdate($defs{$DEVICE}, $CMD, $ARGS);
    }
    readingsEndUpdate($defs{$DEVICE}, 1);
    return undef
}
attr wakeupLight setList active:active,deactivated alarm light-begin-dimm offset:slider,0,1,15
attr wakeupLight stateFormat { return "light-begin-dimm: ".(ReadingsVal('wakeupLight','light-begin-dimm','N/A') ? ReadingsVal('wakeupLight','light-begin-dimm','N/A') : 'off')." - alarm: ".ReadingsVal('wakeupLight','alarm','N/A') }
attr wakeupLight webCmd active:offset


Evtl. lassen sich hier zwar noch paar Sachen optimieren, das ganze läuft allerdings schon seit Beginn der dunklen Jahreszeit zuverlässig bei mir ;)
Die Namen meiner Lampe "og_sz_licht", meines twilight devices "twilight", sowie des Sonosplayers "Sonos_Schlafzimmer" musst du natürlich noch an allen Stellen entsprechend anpassen.
Die Dimmfunktion wird denke ich auch nur bei Homematic Aktoren funktionieren, und muss evtl. auch auf deine Hardware angepasst werden.

Gruß
  Claudiu

Reinerlein

Hi,

@Claudiu: cool :)

@Christian: dabei nicht vergessen, am entsprechenden Player das Attribut "getAlarms" auf 1 zu setzen, sonst werden die Alarme nicht an Fhem übertragen...

Grüße
Reiner

rapster

Hi Reiner,

richtig, das hatte ich vergessen zu erwähnen :)

PS, die obige Reihenfolge könnte für fhem nicht ganz passen, der readingsProxy muss denke ich vor dem DOIF definiert werden, sonst könnte sich das DOIF nicht erstellen lassen.

Gruß
  Claudiu

Gidiano

Hallo Ihr Lieben!

Danke für die detaillierte Info. Ich hatte keine Info bekommen, dass ihr gepostet habt, deshalb jetzt erst meine Reaktion.
Ich werde mich die Tage da mal durcharbeiten und hoffe, dass das klappt. Wecken mit dem Sonos geht schon super und über Floorplan lässt sich das Ein- und Ausschalten :-)
Jetzte "werde es noch Licht" und dann bin ich wieder nen Schritt weiter.
Hier mal ein Screenshot des Floorplan, wie er am Handy zu bedienen ist. Oben auf den Icons wird die Weckszeit aktiviert und deaktiviert:
(http://up.picr.de/23860990mt.jpg)

Grüße,
Christian
Grüße,
Christian

Gidiano

oh,oh,... ich krieg es nicht hin  :-\
Manche Sachen sind mir dann doch wohl zu hoch.

Nochmals aber besten Dank für eure Mühe!

Grüße,
Christian
Grüße,
Christian

rapster

Wir sind doch im Regelfall hier alle sehr hilfsbereit, nicht gleich den Kopf in Sand stecken  ;D

Versuch doch mal zu beschreiben wo es hackt, bzw. stell ein "list" aller betroffenen Geräte zur Verfügung, und reduzier deine myUtils mal auf dieses Feature und häng Sie mit an.
Dann kann man mal guckn wo es hackt.

Gruß
  Claudiu

Gidiano

#7
Dankeschön! Ich versuch's mal.

Hinter den Buttons im FP sind die jeweiligen Funktionen hinterlegt.
Das funktioniert sehr gut: Button drücken, Alarm wird aktiv, wieder drücken und er wird deaktiviert und so auch gestoppt.
Ich stelle mir vor, dass ich damit auch gleich das Einschalten der Lampen kopple, was ich so auch abends mit nem sunset realisiert haben,
Dabei wird mit
set Licht_Wohnbereich off
set Licht_Wohnbereich on

eine structure aus mehreren Lampen geschaltet.
Mein Ansatz wäre, das mit einem "at" bei Alarmaktivierung zu aktivieren, welches aber nur startet, wenn der dazugehörige Alarm aktiv ist und "losbimmelt".
Und den kriege ich nicht abgefragt, grummel.
Im Fhem-Wiki ist alles so genial beschrieben, aber in meinem speziellen Fall kam ich da leider nicht weiter.
http://www.fhemwiki.de/wiki/SONOS#Beispiele

"sonosWakeupTime" habe ich übernommen und habe versucht es in einen Dummy im Floorplan zu schreiben, um zu sehen "was kommt", krieg aber immer nur "alarm off"

Grüße,
Christian
Grüße,
Christian

Reinerlein

Hallo Christian,

das, was Claudiu geschrieben hat, bezieht sich darauf, auf das Alarm-Event im Vorfeld reagieren zu können. Also *bevor* der Sonosplayer aufwacht und den Alarm loslegt.

Wenn du nur darauf reagieren willst, wenn der Sonosplayer den Alarm startet, ist das eher einfach.

Es gibt am Playerdevice ein Reading "transportState", welches dir angibt, ob etwas abgespielt wird, oder nicht.
Das Reading "AlarmRunning" gibt dir an, ob es ein Alarmabspielen ist.

Beide zusammen ergeben also einen aktiven Alarm :)
Das kannst du so schreiben:

define alarmevent DOIF ([Sonosplayer:transportState] eq "PLAYING" and [Sonosplayer:AlarmRunning]) (set Licht_Wohnbereich on) DOELSE (set Licht_Wohnbereich off)
Das schaltet das Licht an, sobald ein Alarm abgespielt wird. Du musst natürlich den Namen "Sonosplayer" durch deinen gewünschten Playerdevicenamen ersetzen.
Wenn der Alarm beendet wird, geht das Licht wieder aus... das kannst du natürlich auch weglassen, wenn es an bleiben soll...

Versuch es erstmal damit...

Grüße
Reiner

Gidiano

Hallo Reiner,

super, danke, das ist so das, was ich mir vorgestellt hatte (bin gerade wieder am Tüfteln).
Ich baue es mal ein und lasse hören, ob es klappt  ;D

Viele Grüße,
Christian
Grüße,
Christian

Gidiano

Soooooo,

jetzt habe ich das mal hinzugefügt:
define LightOnWakeUp DOIF ([Sonos_Schlafzimmer:transportState] eq "PLAYING" and [Sonos_Schlafzimmer:AlarmRunning])\
(set Lampe_Sofa on)\
(set Lampe_Fenster on)\
(set Lampe_Flur on)
attr LightOnWakeUp wait 3,6,30

und klappt super.
Mal sehen, wie sich das im Praxistest verhält  ;D

Besten Dank Euch!
Christian
Grüße,
Christian

DanielGab

Zitat von: rapster am 25 November 2015, 21:32:54

### Returns todays first alarm of a player in seconds after midnight ###

Hi Claudiu,
dieses Alarmauslesen nutze ich nun schon einige Monate. Kennst Du vielleicht auch eine Möglichkeit die "seconds after midnight", die in meinem Dummy erscheinen in einem HH:MM Format anzeigen zu lassen? Dann könnte ich mir die Alarmzeit immer schön vorlesen lassen, dass auch alles geklappt hat :-) (Manchmal liest er den Alarm nicht aus, und das kann fatale Folgen haben :-D)

Viele Grüße,
Daniel

DanielGab

Ich gebe mir die Antwort mal selbst :)
{time_sec2hms(sonosWakeupTime("Sonos_Schlafzimmer"))}

Nun habe ich das DOIF und kann mit stateFormat den Status selbst mit der Alarmzeit belegen

Sonos_Alarmauslesen_Wecker

([Sonos_Schlafzimmer:AlarmList])

attr Sonos_Alarmauslesen_Wecker do always
attr Sonos_Alarmauslesen_Wecker stateFormat {time_sec2hms(sonosWakeupTime("Sonos_Schlafzimmer"))}


als SUBs dienen hier die time_sec2hms und sonosWakeupTime

Das einzige, was ich noch nicht so hinkriege, ist dass ich über das stateFormat den Zustand 00:00 (wenn der Wecker ausgeschaltet ist) auf aus ändere.

Hatte es so probiert, aber das klappt nicht:
stateFormat {if ({time_sec2hms(sonosWakeupTime("Sonos_Schlafzimmer"))}="00:00")) {"aus"} else {time_sec2hms(sonosWakeupTime("Sonos_Schlafzimmer"))}}

Aber so kann ich auch damit leben und habe mir doch tatsächlich 2 Dummies und ein zusätzliches DOIF gespart. Vielen Dank an alle :)