Wetter vorlesen lassen

Aus FHEMWiki
Wechseln zu: Navigation, Suche


Dieser Code-Fragment ermöglicht die aktuellen Temperatur/Luftfeuchte und die Wettervorherssage mit Hilfe von Text2Speech-Modul vorlesen zu lassen.

FHEM-Devices

Es werden einige FHEM-Geräte benötigt:

  1. Das Text2Speak-Device (mit dem Namen 'tts')
  2. Der Temperatur/Feuchte-Sensor ('thSensor')
  3. Das Weather-Modul ('Wetter')
(Die Namen können im Code anpasst werden.)


Code

Der Code muss in irgendein Modul hineingeschrieben werden. Z.B. 99_myUtils.pm

Konstanten

Die Konstanten legen die Geräte-Namen fest.

use constant {
  DEVICE_NAME_TTS    => "tts",
  DEVICE_NAME_TH      => "thSensor",
  DEVICE_NAME_WEATHER => "Wetter",
};

Hauptmethoden

Die zwei Methoden, die die eigentliche Sprachausgabe auslösen: speakWetterDaten(;$) und speakWetterVorhersage(;$). Zum Testen kann man sie (wenn alles fertig eingetragen ist) direkt in der FHEM-Console (oder eben in der Commandline des Webinterfaces) eingeben:

{speakWetterDaten()}

und

{speakWetterVorhersage()}

Beide haben optionale Parameter, diese sind im Quellcode beschrieben.

###############################################################################
# Sagt Wetterdaten an
#  Param: Art: Variante der Aussage:
#         0: Kurzansage, 1: Normal
###############################################################################
sub speakWetterDaten(;$) {
	my($art)=@_;
	if(!defined($art)){$art=1;}
	# TODO: Sauber / Abstraktionslayer erstellen
	my $temp = prepareNumToSpeak(rundeZahl0(ReadingsVal(+DEVICE_NAME_TH,"temperature","unbekannt")));
	my $humi = prepareNumToSpeak(rundeZahl0(ReadingsVal(+DEVICE_NAME_TH,"humidity","unbekannt")));
	if($art==0) {
    #speak("Aussentemperatur ".$temp." Grad. Feuchtigkeit ".$humi." Prozent.",0);
    speak($temp." Grad. Feuchtigkeit ".$humi." Prozent.",0);
  }
  if($art==1) {
    #speak("Die Aussentemperatur betraegt ".$temp." Grad. Die Luftfeuchtigkeit liegt bei ".$humi." Prozent.",0);
    speak("Temperatur ".$temp." Grad. Luftfeuchtigkeit ".$humi." Prozent.",0);
  }
}

###############################################################################
# Sagt Wettervorhersage an.
#  Parameter: Tag: Zahl 1-5 (1-heute, 2-morgen,...) Defaul=2
###############################################################################
sub speakWetterVorhersage(;$) {
	my ($day) = @_;
	if(!defined($day)) {$day=2;}
	
	# TODO: Sauber / Abstraktionslayer erstellen
	my $t1= ReadingsVal(+DEVICE_NAME_WEATHER,"fc".$day."_condition",undef);
	my $t2= ReadingsVal(+DEVICE_NAME_WEATHER,"fc".$day."_low_c",undef);
	my $t3= ReadingsVal(+DEVICE_NAME_WEATHER,"fc".$day."_high_c",undef);
	
	my $text = "";
	if($day==1) {
		#$text = "Wetter heute ";
		$text = "Heute ";
	}
	if($day==2) {
		$text = "Morgen ";
	}
	if($day==3) {
		$text = "Uebermorgen ";
	}
	if($day>3) {
		$text = "Wetter in ".($day-1)." Tagen ";
	}	
	if(defined($t1) && defined($t2) && defined($t3)) {
	  $text.=$t1.". ";
	  $text.="Temperatur von ".$t2." bis ".$t3." Grad.";
	  if($day==1) {
	  	# gefuehlte Temperatur
	  	my $tg= ReadingsVal(+DEVICE_NAME_WEATHER,"wind_chill",undef);
	  	#$text.="Gefuehlte Temperatur aktuell ".$tg." Grad.";
	  	$text.="Gefuehlte ".$tg." Grad.";
	  	my $tw= ReadingsVal(+DEVICE_NAME_WEATHER,"wind_speed",undef);
	  	#$text.="Windgeschwindigkeit ".$tw." Kilometer pro Stunde.";
	  	$text.="Wind ".$tw." Kilometer pro Stunde.";
	  }
	} else {
		$text="Leider keine Vorhersage verfuegbar.";
	}
	
	speak($text,0);
}

Hilfsroutinen

Diese halten bestimmte (in den Hauptmethoden benötigte) Services bereit.

###############################################################################
# Bereitet Zahlen zur Ansage auf.
# Ersetzt Kommas und Punkte durch das Wort 'Komma'.
###############################################################################
sub prepareNumToSpeak($) {
	my($text) = @_;
	$text =~ s/\./Komma/g;
  $text =~ s/,/Komma/g;
	return $text;
}

# Rundet eine Zahl ohne Nachkommastellen
sub rundeZahl0($) {
	my($val)=@_;
	# Prüfen, ob numerisch
	if(int($val)>0) {
		$val = int($val+0.5);
	}
	return $val;
}

# Rundet eine Zahl mit 1-er Nachkommastelle
sub rundeZahl1($) {
	my($val)=@_;
	# Prüfen, ob numerisch
	if(int($val)>0) {
		$val = int(10*$val+0.5)/10;
	}
	return $val;
}

###############################################################################
# Bereitet Texte zur Ansage auf.
# Ersetzt Umlaute (ä=ae etc.)
###############################################################################
sub prepareTextToSpeak($) {
	my($text) = @_;
	# TODO: Ist halt noch nicht fertig geworden ;)
	return $text;
}

ja, und dann noch die Methode, die den TTS-Modul anspricht. Die Lautstärke wird je nach Tageszeit geändert (also Nachts leiser etc.)

######################################################
# Sprachausgabe ueber Text2Speak Modul
#  Parameter:
#   - text: Auszugebender Text
#   - volume (optional) - Lautstaerke
#     (wenn nicht vorhaneden: wird aktuell gesetzte 
#      Lautstaerke benutzt,
#      wenn 1 oder groesser: dieser Wert wird benutzt,
#      wenn 0: adaptiv gesetzt je nach Fageszeit 
#              (also Nachts wesentlich leiser)
#       (ggf. spaeter adaptiv durch ermitteln der Zimmerlautstaerke)
######################################################
sub speak($;$) {
	my($text,$volume)=@_;
	if(defined ($volume)) {
		if(int($volume) >=1) {
      fhem("set ".+DEVICE_NAME_TTS." volume ".$volume);
    } else {
    	if(int($volume) == 0) {
    	# Adaptiv 
    	my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime;
    	# 5 - sehr leise
    	# 10 - ok
    	# 50 - gut hoerbar
    	# 100 - default / gut laut
    	#
    	# 20:00 - 22:00 => 10
    	# 22:00 - 05:00 =>  5
    	# 05:00 - 07:00 => 10
    	# 07:00 - 08:00 => 50
    	# 08:00 - 20:00 => 100
    	if ($hour>=20 && $hour<22) {$volume=18}
    	if ($hour>=22 || $hour<5)  {$volume=8}
    	if ($hour>=5  && $hour<7)  {$volume=15}
    	if ($hour>=7  && $hour<8)  {$volume=40}
    	if ($hour>=8  && $hour<20)  {$volume=100}
    	
    	fhem("set ".+DEVICE_NAME_TTS." volume ".$volume);
      }
    }
  }
	fhem("set ".+DEVICE_NAME_TTS." tts ".prepareTextToSpeak($text));
}


Verwendung

Wie kann man das Ganze sinnvoll einsetzen? Na zum Beispiel indem man die Methoden auf ein Funkbutton oder ein Bewegungsmelder legt und sich so jeden Morgen nach dem Aufstehen auf die Welt da draußen vorbereiten lässt  ;D

Was braucht man an Hardware? Außer Wettersensoren werden aktive Boxen o.ä. benötigt, die an den Line-Out Ausgang des Rechners angeschlossen werden. Und natürlich etwas zum Aktivieren der Ansage. (Ich nutze einen in der Wand installierten Lautsprecher (Link, für die Sprachausgabe ausreichend, lässt sich in einer tiefen UP-Dose installieren) der über eine kleine 3Watt Verstärkerplatine an meinen Cubietruck angeschlossen ist.)

Links