Internetbudget der Kinder per FHEM regeln

Begonnen von Clyde, 09 Dezember 2018, 14:19:46

Vorheriges Thema - Nächstes Thema

tomster

Ganz unten im Fritzbox Device userticket01


Clyde

Ja genau den meine ich. Das eröffnet Möglichkeiten...
Proxmox auf MINIX-Z100, LXC: FHEM, FS20, FHT, HM, Tradfri, Alexa, Anker Solix Solarbank 2

Mundus

Hallo,

leider habe ich erst jetzt Zeit mein Konstrukt (evtl. umständlich) darzustellen. Mein Wunsch war, dass unser Fernseher nach einer bestimmten Zeit (Budget) ausgeht. Das Budget sollte zwischengespeichert werden und erhöht als auch reduziert werden können.

Zunächst habe ich den Fernseher in FHEM eingebunden und mittels presence überwacht, welchen Zustand er hat. Sobald Presence einen neuen Status vom Fernseher empfängt, wird ein Notify ausgelöst
Zitatdefmod nt_SamsungTV notify pr_SamsungTV:.* {\
   my $prSamsung = Value('pr_SamsungTV');;\
   my $readTimerTV = ReadingsVal("dTimerTV","TV","off");;\
   if ($prSamsung eq "present") {\
      fhem "setstate SamsungTV POWERON";;\
      if ($readTimerTV eq "off"){\
         fhem "setreading dTimerTV TV on";;\
      }\
   } else {\
      fhem "setstate SamsungTV POWEROFF";;\
      if ($readTimerTV eq "on") {\
         fhem "setreading dTimerTV TV off";;\
      }\
   }\
}
attr nt_SamsungTV group Helfer
attr nt_SamsungTV room Wohnzimmer
attr nt_SamsungTV verbose 0

Hinweis: Die Wenn-Dann-Abfragen $readTimerTV eq "on" bzw. "off" habe ich eingebaut, da das Presence-Modul zwischenzeitlich neue Status meldet, obgleich diese nicht eingetreten sind.

Dieses o.g. Notify schreibt in den Dummy "dTimerTV" den Status des Fernsehers. Das Dummy speichert zusätzlich das Zeitbudget und hat einen Ein- und Ausschalter.
Hier das list von dem Dummy
ZitatInternals:
   NAME       dTimerTV
   NR         98
   STATE      off
   TYPE       dummy
   READINGS:
     2018-12-16 11:11:35   TV              off
     2018-12-16 05:00:00   ZeitBudgetTV    00:30:00
     2018-12-16 05:01:00   state           off
Attributes:
   devStateIcon off:ios-off:on on:ios-on-for-timer-green:off
   group      TimerTV
   room       Wohnzimmer
   setList    state:on,off

Der Dummy wird von zwei Notifys überwacht. Erstens wenn der Fernseher eingeschaltet wird
Zitat
Internals:
   DEF        dTimerTV:TV:.* {
   my $Timer = "dTimerTV";
   Log3 $Timer,3,"Event lautet $EVENT";
   Log3 $Timer,3,"EventPart1 lautet $EVTPART1";
   my $DevAnAus = "SamsungTV";
   my $tempValue = Value("$Timer");
   if ($tempValue eq "on"){
      if ($EVTPART1 eq "on"){
         timerAnlegen($Timer,$DevAnAus);
         }
      }
   if ($EVTPART1 eq "off") {
         timerAusschalten ($Timer);
      }
}
   NAME       nt_TV_AnAus_Timer
   NOTIFYDEV  dTimerTV
   NR         99
   NTFY_ORDER 50-nt_TV_AnAus_Timer
   REGEXP     dTimerTV:TV:.*
   STATE      2018-12-16 11:11:35
   TYPE       notify
   READINGS:
     2018-08-13 23:27:36   state           active
Attributes:
   group      TimerTV
   room       Wohnzimmer
und zweitens, wenn der Timer Ein-/bzw. Ausgeschaltet wird
Zitat
Internals:
   DEF        dTimerTV.* {
   my $Timer = "dTimerTV";
   my $DevAnAus = "SamsungTV";
   my $readTimer = ReadingsVal("$Timer","TV","on");
   
   #if ($valueDevAnAus eq "on"){
   if ($readTimer eq "on"){
      if ($EVENT eq "on"){
         timerAnlegen($Timer,$DevAnAus)
         }
   }
   if ($EVENT eq "off") {
         timerAusschalten ($Timer)
         }
}
   NAME       nt_TV_Timer_AnAus
   NOTIFYDEV  dTimerTV.*
   NR         102
   NTFY_ORDER 50-nt_TV_Timer_AnAus
   REGEXP     dTimerTV.*
   STATE      2018-12-16 11:11:35
   TYPE       notify
   READINGS:
     2018-08-13 23:27:36   state           active
Attributes:
   group      TimerTV
   room       Wohnzimmer

Hinweis: Diese beiden Notifys können sicherlich zusammengefasst werden, das war mir aber zu unübersichtlich

Die beiden Notifys rufen ein Script auf, in dem die weitere Abhandlung stattfindet. Das Skript folgt hier
Zitatpackage main;
use strict;
use warnings;
use POSIX;

my $nameValTimer = "ZeitBudgetTV";
######################################################################################
sub
timerUtil_Initialize($$)
{
  my ($hash) = @_;
}
###################################################################################
#################Funktion zum Anlegen eines Timers
sub
timerAnlegen($$){
   #Übergabe dummy_Timers (u.a. ist hier BugetZeit gespeichert) und des zu schaltenden Device
   my ($deviceTimer,$deviceAnAus) = @_;
   
   #at Name wird festgelegt
   my $atTimer = "at_$deviceTimer.timer";
   #Werte aus dummy_Timer auslesen (BudgetZeit, Attribute)
   my $ausschaltzeit = ReadingsVal("$deviceTimer","$nameValTimer","00:00:00");
   my $attrRoom = AttrVal($deviceTimer,"room","");
   my $attrGroup = AttrVal($deviceTimer,"group","");
   
   #at anlegen
   fhem "define $atTimer at +$ausschaltzeit set $deviceAnAus POWEROFF;;setreading $deviceTimer $nameValTimer 00:00:00";
   fhem "attr $atTimer room $attrRoom";
   fhem "attr $atTimer group $attrGroup";
}
sub
timerAusschalten($){
   #Übergabe dummy_Timers (u.a. ist hier BudgetZeit gespeichert)
   my ($deviceTimer) = @_;
   #at Name wird festgelegt
   my $atTimer = "at_$deviceTimer.timer";
   
   #prüfen ob at erstellt wurde
   if (Value($atTimer)ne ""){
      #errechnen des neuen BudgetWertes (Min = 0)
      my $currentOffTime = InternalVal("$atTimer","TRIGGERTIME",0)-time;
      $currentOffTime =~ s/\.\d+//;
      if ($currentOffTime < 0){
         $currentOffTime = 0;
         }         
      my $umgerechneterWert = sek2hhmmss($currentOffTime);
      #zurückschreiben des neuen BudgetWertes
      fhem "setreading $deviceTimer $nameValTimer $umgerechneterWert";
      #löschen des at
      fhem "delete $atTimer";
      #Return Wert
      return "on";
   }
}
sub
timerPlusMinus($$$){
#Übergabe dummy_Timers (u.a. ist hier BugetZeit gespeichert), des zu schaltenden Device und + bzw -
my ($deviceTimer,$deviceAnAus,$plusMinus) = @_;
my $timeValue = 600;

#alten Timer Ausschalten (wenn an, dann $var = on)
my $timerExists = timerAusschalten($deviceTimer);
my $tTimer = hhmmss2sek(ReadingsVal($deviceTimer,$nameValTimer,"00:00:00"));

#Bei Plus wird Zeit addiert; bei Minus subtrahiert, Min Wert ist 0!
if ($plusMinus eq "plus") {
   $timeValue=sek2hhmmss($tTimer + $timeValue);
} elsif ($plusMinus eq "minus") {
   $timeValue=$tTimer - $timeValue;
   if ($timeValue < 0) {
      $timeValue = 0;
   }
   $timeValue=sek2hhmmss($timeValue);
}   

#neue Zeit zurückschreiben
fhem "setreading $deviceTimer $nameValTimer $timeValue";
#Timer aktivieren, sofern Dev und Timer on
if ($timerExists eq "on") {
   timerAnlegen($deviceTimer,$deviceAnAus);
   }
}
1;

Hinweis: Für das formatieren der Zeiten habe ich ein zweites Skript
Zitat
package main;
use strict;
use warnings;
use POSIX;
######################################################################################
sub
myTimeUtil_Initialize($$)
{
  my ($hash) = @_;
}
###################################################################################
# Funktion zur Berechnung von Sekunden in das Format hh:mm:ss

sub
sek2hhmmss($) {
   
   my ($sektime) = @_;
   
   my $m = int $sektime/60;
   my $s = $sektime - ($m * 60);
   my $h = int $m / 60;
   $m = $m - ($h *60);
   
   my $umgerechneterWert = sprintf("%02d:%02d:%02d",$h,$m,$s);
   return $umgerechneterWert;
}
sub hhmmss2sek($) {
   my ($hhmmsstime) = @_;
   my @time = split (/:/,$hhmmsstime);
   my $h = shift @time;
   my $m = shift @time;
   my $s = shift @time;
   
   my $umgerechneterWert = $h * 3600 + $m * 60 + $s;
   return $umgerechneterWert;
}
1;

So, damit sind wir schon fast am Ende meines Konstruktes. Es fehlt lediglich das Erhöhen und reduzieren des Zeitbudgets. In dem o.g. Skript ist bereits eine Funktion abgebildet, die die tatsächliche Berechnung durchführt. Auf FHEM habe ich dafür dann noch einen Dummy und ein Notify angelegt.
ZitatInternals:
   NAME       dTimerTV_p_m
   NR         100
   STATE      plus
   TYPE       dummy
   READINGS:
     2018-10-11 07:41:49   state           plus
Attributes:
   devStateIcon plus:control_plus@green minus:control_minus@red
   group      TimerTV
   room       Wohnzimmer
   setList    state:plus,minus
   webCmd     plus:minus
Und das Notify
ZitatInternals:
   DEF        dTimerTV_p_m.* {
   my $Timer = "dTimerTV";
   my $DevAnAus = "SamsungTV";
   my $dTimerOn = Value("$Timer");

   timerPlusMinus($Timer,$DevAnAus,$EVENT);
}
   NAME       nt_TV_Timer_p_m
   NOTIFYDEV  dTimerTV_p_m.*
   NR         101
   NTFY_ORDER 50-nt_TV_Timer_p_m
   REGEXP     dTimerTV_p_m.*
   STATE      2018-10-11 07:41:49
   TYPE       notify
   READINGS:
     2018-08-13 23:27:36   state           active
Attributes:
   group      TimerTV
   room       Wohnzimmer

So und damit ist es schon fertig.

Evtl. hilft dir dies weiter und du kannst meine Lösung für dein Problem modifizieren und nutzen.

Gruß

Mundus