From dd100ef7cbd0808a58a44cdb177998c76341032b Mon Sep 17 00:00:00 2001 From: tobiasfaust <> Date: Thu, 8 May 2014 06:15:58 +0000 Subject: [PATCH] - feature: DbLog: (thanks to betateilchen) * added new global modules function $hash->{DbLog_splitFn} to let split the generated events by the own module into readingsname, value and unit * added SVG_sampleDataFn * added FW_detailFn - added: new module contrib/97_SprinkleControl.pm (tobiasfaust) - added: new module contrib/98_Sprinkle.pm (tobiasfaust) both modules helps to control the sprinkles in your garden --> take a look to the Wiki-Article http://www.fhemwiki.de/wiki/Bew%C3%A4sserungssteuerung git-svn-id: https://svn.fhem.de/fhem/trunk@5782 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 11 + fhem/FHEM/93_DbLog.pm | 119 ++++- fhem/FHEM/98_Text2Speech.pm | 2 +- fhem/HISTORY | 7 + fhem/contrib/91_DbLog.pm | 173 ------- fhem/contrib/97_SprinkleControl.pm | 616 ++++++++++++++++++++++++ fhem/contrib/98_Sprinkle.pm | 737 +++++++++++++++++++++++++++++ 7 files changed, 1469 insertions(+), 196 deletions(-) delete mode 100755 fhem/contrib/91_DbLog.pm create mode 100644 fhem/contrib/97_SprinkleControl.pm create mode 100644 fhem/contrib/98_Sprinkle.pm diff --git a/fhem/CHANGED b/fhem/CHANGED index 60d960b60..a4a636449 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,16 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: DbLog: (thanks to betateilchen) + * added new global modules function $hash->{DbLog_splitFn} + to let split the generated events by the own module + into readingsname, value and unit + * added SVG_sampleDataFn + * added FW_detailFn + - added: new module contrib/97_SprinkleControl.pm (tobiasfaust) + - added: new module contrib/98_Sprinkle.pm (tobiasfaust) + both modules helps to control the sprinkles in your garden + --> take a look to the Wiki-Article + http://www.fhemwiki.de/wiki/Bew%C3%A4sserungssteuerung - feature: FB_CALLMONITOR: new reading "missed_call_line" indicating the line number which received the missed call - feature: YAMAHA_AVR current* readings will be erased in case they diff --git a/fhem/FHEM/93_DbLog.pm b/fhem/FHEM/93_DbLog.pm index 76a026910..99da0c826 100644 --- a/fhem/FHEM/93_DbLog.pm +++ b/fhem/FHEM/93_DbLog.pm @@ -44,6 +44,10 @@ sub DbLog_Initialize($) "shutdownWait"; addToAttrList("DbLogExclude"); + + $hash->{FW_detailFn} = "DbLog_fhemwebFn"; + $hash->{SVG_sampleDataFn} = "DbLog_sampleDataFn"; + } ############################################################### @@ -135,6 +139,18 @@ sub DbLog_ParseEvent($$$) my $value; my $unit; + my $dtype = $defs{$device}{TYPE}; + if($modules{$dtype}{DbLog_splitFn}) { + # let the module do the job! + Log 4,"DbLog_ParseEvent calling external DbLog_splitFn for type: $dtype"; + no strict "refs"; + ($reading,$value,$unit) = + &{$modules{$dtype}{DbLog_splitFn}}($event); + use strict "refs"; + @result= ($reading,$value,$unit); + return @result; + } + # split the event into reading, value and unit # "day-temp: 22.0 (Celsius)" -> "day-temp", "22.0 (Celsius)" my @parts = split(/: /,$event); @@ -585,30 +601,14 @@ sub _DbLog_readCfg($){ my $name = $hash->{NAME}; my $configfilename= $hash->{CONFIGURATION}; - my @config; my %dbconfig; my $ret; - - if(configDBUsed()) { - # Verwendung der configDB anstatt fhem.cfg - my $c = _cfgDB_Readfile($configfilename); - if(! $c) { - $ret = "Cannot read configuration file $configfilename from configDB."; - Log3 $hash->{NAME}, 1, $ret; - return $ret; - } - @config = $c; - } else { - if(!open(CONFIG, $configfilename)) { - $ret = "Cannot open database configuration file $configfilename."; - Log3 $hash->{NAME}, 1, $ret; - return $ret; - } - @config=; - close(CONFIG); - } - eval join("", @config); +# use generic fileRead to get configuration data + my ($err, @config) = FileRead($configfilename); + return $err if($err); + + eval join("\n", @config); $hash->{dbconn} = $dbconfig{connection}; $hash->{dbuser} = $dbconfig{user}; @@ -1444,8 +1444,83 @@ sub chartQuery($@) { return $jsonstring; } +######################### +sub +DbLog_fhemwebFn($$$$) +{ + my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn. + + my $ret; + my $newIdx=1; + while($defs{"SVG_${d}_$newIdx"}) { + $newIdx++; + } + my $name = "SVG_${d}_$newIdx"; + $ret .= FW_pH("cmd=define $name SVG $d:templateDB:HISTORY;". + "set $name copyGplotFile&detail=$name", + "
Create SVG plot from DbLog
", 0, "dval", 1); + + return $ret; + +} + +sub +DbLog_sampleDataFn($$$$$) +{ + my ($dlName, $dlog, $max, $conf, $wName) = @_; + my $desc = "Device:Reading"; + my @htmlArr; + my @example; + my @colregs; + my $counter; + + my $currentPresent = AttrVal($dlName,'DbLogType','Current'); + if($currentPresent =~ m/Current/) { + # Table Current present, use it for sample data + + my $dbhf = $defs{$dlName}{DBHF}; + my $query = "select device,reading,value from current where device <> '' group by device,reading order by device,reading"; + my $sth = $dbhf->prepare( $query ); + $sth->execute(); + while (my @line = $sth->fetchrow_array()) { + $counter++; + push (@example, join (" ",@line)) if($counter <= 8); # show max 8 examples + push (@colregs, "$line[0]:$line[1]"); # push all eventTypes to selection list + } + my $cols = join(",", sort @colregs); + + $max = 8 if($max > 8); + for(my $r=0; $r < $max; $r++) { + my @f = split(":", ($dlog->[$r] ? $dlog->[$r] : ":::"), 4); + my $ret = ""; + $ret .= SVG_sel("par_${r}_0", $cols, "$f[0]:$f[1]"); +# $ret .= SVG_txt("par_${r}_2", "", $f[2], 1); # Default not yet implemented +# $ret .= SVG_txt("par_${r}_3", "", $f[3], 3); # Function +# $ret .= SVG_txt("par_${r}_4", "", $f[4], 3); # RegExp + push @htmlArr, $ret; + } + + } else { + # Table Current not present, so create an empty input field + push @example, "No sample data due to missing table 'Current'"; + + $max = 8 if($max > 8); + for(my $r=0; $r < $max; $r++) { + my @f = split(":", ($dlog->[$r] ? $dlog->[$r] : ":::"), 4); + my $ret = ""; + $ret .= SVG_txt("par_${r}_0", "", "$f[0]:$f[1]:$f[2]:$f[3]:$f[4]", 20); +# $ret .= SVG_txt("par_${r}_2", "", $f[2], 1); # Default not yet implemented +# $ret .= SVG_txt("par_${r}_3", "", $f[3], 3); # Function +# $ret .= SVG_txt("par_${r}_4", "", $f[4], 3); # RegExp + push @htmlArr, $ret; + } + + } + + return ($desc, \@htmlArr, join("
", @example)); +} + # -# provide new functions: # get ReadingsVal # get ReadingsTimestamp # diff --git a/fhem/FHEM/98_Text2Speech.pm b/fhem/FHEM/98_Text2Speech.pm index 72d83b1cd..846a0b7f2 100644 --- a/fhem/FHEM/98_Text2Speech.pm +++ b/fhem/FHEM/98_Text2Speech.pm @@ -674,7 +674,7 @@ sub Text2Speech_WriteStats($$$$){ last; } } - return undef if($defs{$DbLogDev}{STATE} ne "active"); # muss active sein! + return undef if($defs{$DbLogDev}{STATE} !~ m/(active|connected)/); # muss active sein! # den letzten Value von "Usage" ermitteln um dann die Staistik um 1 zu erhoehen. my @LastValue = DbLog_Get($defs{$DbLogDev}, "", "current", "array", "-", "-", $hash->{NAME} ."|". $file.":Usage"); diff --git a/fhem/HISTORY b/fhem/HISTORY index bad9de095..631eae936 100644 --- a/fhem/HISTORY +++ b/fhem/HISTORY @@ -568,3 +568,10 @@ - Sun Apr 24 2014 (kaihs) - added new module 02_FRAMEBUFFER.pm - added new module 51_TSL2561.pm + +- Thu May 08 2014 (tobiasfaust) + - added new global modules function $hash->{DbLog_splitFn} + to let split the generated events by the own module + into readingsname, value and unit + - added new module contrib/97_SprinkleControl.pm + - added new module contrib/98_Sprinkle.pm diff --git a/fhem/contrib/91_DbLog.pm b/fhem/contrib/91_DbLog.pm deleted file mode 100755 index 738f46d66..000000000 --- a/fhem/contrib/91_DbLog.pm +++ /dev/null @@ -1,173 +0,0 @@ -############################################## -# Example for logging KS300 data into a DB. -# -# Prerequisites: -# - The DBI and the DBD:: modules must be installed. -# - a Database is created/configured -# - a db table: create table FHZLOG (TIMESTAMP varchar(20), TEMP varchar(5), -# HUM varchar(3), WIND varchar(4), RAIN varchar(8)); -# - Change the content of the dbconn variable below -# - extend your FHEM config file with -# notify .*H:.* {DbLog("@","%")} -# - copy this file into the /FHEM and restart fhem.pl -# -# If you want to change this setup, your starting point is the DbLog function - -my $dbconn = "Oracle:DBNAME:user:password"; - -package main; -use strict; -use warnings; -use DBI; - -my $dbh; - -sub DbDo($); -sub DbConnect(); - - -################################################################ -sub -DbLog_Initialize($) -{ - my ($hash) = @_; - - # Lets connect here, so we see the error at startup - DbConnect(); -} - -################################################################ -sub -DbLog($$) -{ - my ($a1, $a2) = @_; - - # a2 is like "T: 21.2 H: 37 W: 0.0 R: 0.0 IR: no" - my @a = split(" ", $a2); - my $tm = TimeNow(); - - DbDo("insert into FHZLOG (TIMESTAMP, TEMP, HUM, WIND, RAIN) values " . - "('$tm', '$a[1]', '$a[3]', '$a[5]', '$a[7]')"); -} - - -################################################################ -sub -DbConnect() -{ - return 1 if($dbh); - Log 5, "Connecting to database $dbconn"; - my @a = split(":", $dbconn); - $dbh = DBI->connect("dbi:$a[0]:$a[1]", $a[2], $a[3]); - if(!$dbh) { - Log 1, "Can't connect to $a[1]: $DBI::errstr"; - return 0; - } - Log 5, "Connection to db $a[1] established"; - return 1; -} - -################################################################ -sub -DbDo($) -{ - my $str = shift; - - return 0 if(!DbConnect()); - Log 5, "Executing $str"; - my $sth = $dbh->do($str); - if(!$sth) { - Log 2, "DB: " . $DBI::errstr; - $dbh->disconnect; - $dbh = 0; - return 0 if(!DbConnect()); -#retry - $sth = $dbh->do($str); - if($sth) - { - Log 2, "Retry ok: $str"; - return 1; - } -# - return 0; - } - return 1; -} - -1; - -=pod -=begin html - - -

DbLog

-
    -
    - - - Define -
      - define <name> DbLog <configfilename> <regexp> -

      - - Log events to a database. The database connection is defined in - <configfilename> (see sample configuration file - db.conf). The configuration is stored in a separate file - to avoid storing the password in the main configuration file and to have it - visible in the output of the list command. -

      - - You must have 93_DbLog.pm in the FHEM subdirectory - to make this work. Additionally, the modules DBI and - DBD::<dbtype> need to be installed (use - cpan -i <module> if your distribution does not have it). -

      - <regexp> is the same as in FileLog. -

      - Sample code to create a MySQL database is in fhemdb_create.sql. - The database contains two tables: current and - history. The latter contains all events whereas the former only - contains the last event for any given reading and device. - The columns have the following meaning: -
        -
      1. TIMESTAMP: timestamp of event, e.g. 2007-12-30 21:45:22
      2. -
      3. DEVICE: device name, e.g. Wetterstation
      4. -
      5. TYPE: device type, e.g. KS300
      6. -
      7. EVENT: event specification as full string, - e.g. humidity: 71 (%)
      8. -
      9. READING: name of reading extracted from event, - e.g. humidity
      10. -
      11. VALUE: actual reading extracted from event, - e.g. 71
      12. -
      13. UNIT: unit extracted from event, e.g. %
      14. -
      - The content of VALUE is optimized for automated post-processing, e.g. - yes is translated to 1. -

      - The current values can be retrieved by means of the perl script - fhemdb_get.pl. Its output is adapted to what a - Cacti data input method expects. - Call fhemdb_get.pl without parameters to see the usage - information. -

      - Examples: -
        - # log everything to database
        - define logdb DbLog /etc/fhem/db.conf .*:.* -
      -
    - - - - Set
      N/A

    - - - Get
      N/A

    - - - Attributes
      N/A

    - -
- -=end html -=cut diff --git a/fhem/contrib/97_SprinkleControl.pm b/fhem/contrib/97_SprinkleControl.pm new file mode 100644 index 000000000..528819f73 --- /dev/null +++ b/fhem/contrib/97_SprinkleControl.pm @@ -0,0 +1,616 @@ + +############################################## +# $Id$ +# +# 97_SprinkleControl.pm +# +# written by Tobias Faust 2013-10-23 +# e-mail: tobias dot faust at online dot de +# +############################################## + +package main; +use strict; +use warnings; +use Data::Dumper; + +use vars qw(%gets %sets %defs %attr); + +sub SprinkleControl_AllocateNewThread($@); +sub SprinkleControl_DeallocateThread($@); +sub UpdateSprinkleControlList($$); + +# SetParamName -> Anzahl Paramter +my %sets = ( + "MaxParallel" => "1" +); + +# These we may get on request +my %gets = ( + "Threads" => "0" +); + +########################## +sub SprinkleControl_Initialize($) +{ + my ($hash) = @_; + + require "$main::attr{global}{modpath}/FHEM/98_Sprinkle.pm"; + + $hash->{DefFn} = "SprinkleControl_Define"; + $hash->{SetFn} = "SprinkleControl_Set"; + $hash->{UndefFn} = "SprinkleControl_Undefine"; + $hash->{AttrFn} = "SprinkleControl_Attr"; + $hash->{AttrList} = "disable:0,1". + " SprinkleControl_MaxParallel". + " ".$readingFnAttributes; +} + + +########################## +# Define SprinkleControl +########################## +sub SprinkleControl_Define($$) +{ + my ($hash, $def) = @_; + my $me = $hash->{NAME}; + my @a = split("[ \t]+", $def); + + #$a[0]: Name + #$a[1]: Type/Alias -> SprinkleControl + + if(int(@a) > 2) { + my $msg = "wrong syntax: define SprinkleControl"; + Log3 $hash, 2, $msg; + return $msg; + } + + if(!$attr{$me}) { + #Attribute vorbelegen! Nur beim Define, kein Modify + #$attr{$me}{webCmd} = "Auto:An:Aus:Toggle:Disable"; + $attr{$me}{SprinkleControl_MaxParallel} = 2; + } + + UpdateSprinkleControlList($hash, "add"); + + $hash->{MaxParallel} = $attr{$me}{SprinkleControl_MaxParallel}; + readingsSingleUpdate($hash, "state", "0/".$attr{$me}{SprinkleControl_MaxParallel}, 1); + readingsSingleUpdate($hash, "CountThreads", 0, 1); + + return undef; +} + +##################################### +sub SprinkleControl_Undefine($$) +{ + my ($hash, $arg) = @_; + + UpdateSprinkleControlList($hash, "del"); + return undef; +} + +################################### +# +################################### +sub SprinkleControl_Attr(@) { + my @a = @_; + my $do = 0; + my $hash = $defs{$a[1]}; + my $command = $a[0]; + my $setter = $a[2]; + my $value = $a[3]; + + my $threads = ReadingsVal($hash->{NAME}, "CountThreads",0); + + if($setter eq "SprinkleControl_MaxParallel" && $command ne "del") { + return "Max Parallel Threads isn´t numeric or not > 0" if ($value !~ m/^(\d+)$/ || $value < 0); + $hash->{MaxParallel} = $value; + readingsSingleUpdate($hash, "state", $threads."/".$value, 1); + + } elsif($setter eq "disable"){ + # 1=disable; 2=enable + if($command eq "set") { + $do = (!defined($value) || $value) ? 1 : 2; + } + $do = 2 if($command eq "del"); + readingsSingleUpdate($hash, "state", ($do == 1 ? "disabled" : $threads."/".$hash->{MaxParallel}), 1); + } + + return undef; + +} + +########################################################################### + +sub SprinkleControl_Set($@) +{ + my ($hash, @a) = @_; + my $me = $hash->{NAME}; + + return "no set argument specified" if(int(@a) < 2); + + my $cmd = $a[1]; # DevName + my $value = $a[2]; + + if(!defined($sets{$cmd})) { + my $r = "Unknown argument $cmd, choose one of ".join(" ",sort keys %sets); + return $r; + } + + # Abbruch falls Disabled + #return undef if(IsDisabled($hash->{NAME})); + +# return "$cmd needs $sets{$cmd} parameter(s)" if(@a-$sets{$cmd} != 0); + my $threads = ReadingsVal($me, "CountThreads",0); + + if($cmd eq "Disable" && !IsDisabled($me)) { + $attr{$me}{disable}=1; + readingsSingleUpdate($hash, "state", "disabled", 1); # Deaktivieren + return undef; + } elsif($cmd eq "Disable" && IsDisabled($me)) { + $attr{$me}{disable}=0; + my $threads = ReadingsVal($hash->{NAME}, "CountThreads",0); + readingsSingleUpdate($hash, "state", $threads."/".$hash->{MaxParallel}, 1); + return undef; + } elsif (IsDisabled($me)) { # mache nix da disabled + return undef; + } elsif($cmd eq "MaxParallel") { + $hash->{MaxParallel} = $value; + readingsSingleUpdate($hash, "state", $threads."/".$value, 1); + } + + return undef; +} + +########################################################## +# Allokiert einen neuen Thread +# param1 : SprinkleControlDevice +# param2 : anforderndes Device +# param3 : Command +# param4 : Priorität +# 1->Ausführung sofort ->ToDo +# 2->Ausführung als nächstes, Anfang der Queue +# 3->Einreihung an das Ende der Queue +########################################################## +sub SprinkleControl_AllocateNewThread($@) { + my ($me, $dev, $cmd, $prio) = @_; + my $hash = $defs{$me}; + + return 1 if(IsDisabled($me)); + + my $threads = ReadingsVal($me, "CountThreads",0); + my $max = $hash->{MaxParallel}; + $prio = 3 if(!defined($prio)); + + my $present=0; + $present = 1 if(defined($hash->{helper}{Queue}{$dev})); + + if($present == 0) { + # noch nciht in der queue vorhanden + $hash->{helper}{Queue}{$dev}{priority} = $prio; + $hash->{helper}{Queue}{$dev}{command} = $cmd; + } + + if($present == 0 || ($present == 1 && $hash->{helper}{Queue}{$dev}{active} == 0)) { + # schon in der Queue vorhanden aber in Wartestellung + if($threads < $max) { + $threads += 1; + $hash->{helper}{Queue}{$dev}{active} = 1; + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, "CountThreads", $threads); + readingsBulkUpdate($hash, "state", $threads."/".$max); + readingsEndUpdate($hash, 1); + + return $threads; # Rückgabe der Threadnummer + + } else { + # abgelehnt da MAX erreicht, in queue gelegt + $hash->{helper}{Queue}{$dev}{active} = 0; + return undef ; + } + } else { + # Device ist bereits in der Queue vorhanden + return undef; + } + +} + + +############################################ +# Gibt einen Thread frei +# param1 : SprinkleControlDevice +# param2 : abgebendes Device +############################################ +sub SprinkleControl_DeallocateThread($@) { + my ($me, $dev) = @_; + my $hash = $defs{$me}; + + my $threads = ReadingsVal($me, "CountThreads",0); + my $max = $hash->{MaxParallel}; + + if(defined($hash->{helper}{Queue}{$dev})) { + $threads -= 1; + $threads = 0 if($threads<0); + delete $hash->{helper}{Queue}{$dev}; + } + + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, "CountThreads", $threads); + readingsBulkUpdate($hash, "state", ($threads)."/".$max); + readingsEndUpdate($hash, 1); + + # den nächsten wartenden Thread aus der Queue starten + #my %queue = %{$hash->{helper}{Queue}}; + my @queue = sort keys %{$hash->{helper}{Queue}}; +#Log3 $hash, 3, "Queue: \n".Dumper(@queue); + for(my $i=0; $i < @queue; $i++) { + my $d = $queue[$i]; +#Log3 $hash,3, "Device: $d"; + if($hash->{helper}{Queue}{$d}{active} == 0) { +#Log3 $hash, 3, "DoIt: $d -> ".$hash->{helper}{Queue}{$d}{command}; + Sprinkle_DoIt($defs{$d}, $hash->{helper}{Queue}{$d}{command}); + last; + } + } + + return 1; +} + +############################################ +# Updatet die AttrListe im SprinkleModul +############################################ +sub UpdateSprinkleControlList($$) { + my ($hash, $cmd) = @_; + + #List verfuegbarer SprinkleControls in den SprinkleModulen aktualisieren + my $attrlist = $modules{Sprinkle}{AttrList}; +#Log3 $hash,3,"1. AttrList: ".$attrlist; + #my $newlist = "SprinkleControl:"; + my @newlist; + my $newlist1 = ""; + + foreach my $d (sort keys %defs) { + if($defs{$d}{TYPE} eq "SprinkleControl") { + push(@newlist, $d) unless(defined($hash) && ($d eq $hash->{NAME}) && ($cmd eq "del")) + } + } + + if(@newlist > 0) { + $newlist1 = "SprinkleControl:" . join(",", @newlist); + } + + #if($attrlist) { + #$attrlist =~ s/(SprinkleControl\:[^\ ]+)/$newlist1/i; + $attrlist =~ s/SprinkleControl\:[^\ ]+/$newlist1/i; +#Log3 $hash,3,"2. AttrList: ".$attrlist; + $attrlist .= " ".$newlist1 if($attrlist !~ m/SprinkleControl/); +#Log3 $hash,3,"3. AttrList: ".$attrlist; + $modules{Sprinkle}{AttrList} = $attrlist; + #} + +#Log3 $hash,3,"4. AttrList: ".$attrlist; +} + +1; + +=pod +=begin html + + +

Sprinkle

+
    +
    + + Define +
      + Local : define <name> Sprinkle <alsadevice>
      + Remote: define <name> Sprinkle <host>[:<portnr>][:SSL] [portpassword] +

      + This module converts any text into speech with serveral possible providers. The Device can be defined as locally + or remote device. +

      + +
    • + Local Device
      +
        + The output will be send to any connected audiodevice. For example external speakers connected per jack + or with bluetooth speakers - connected per bluetooth dongle. Its important to install mplayer.
        + apt-get install mplayer
        + The given alsadevice has to be configured in /etc/asound.conf +

        + Special AlsaDevice: none
        + The internal mplayer command will be without any audio directive if the given alsadevice is none. + In this case mplayer is using the standard audiodevice. +

        +

        + Example:
        + define MyTTS Sprinkle hw=0.0
        + define MyTTS Sprinkle none +

        +
      +
    • + +
    • + Remote Device
      +
        + This module can configured as remote-device for client-server Environments. The Client has to be configured + as local device.
        + Notice: the Name of the locally instance has to be the same! +
          +
        • Host: setting up IP-adress
        • +
        • PortNr: setting up TelnetPort of FHEM; default: 7072
        • +
        • SSL: setting up if connect over SSL; default: no SSL
        • +
        • PortPassword: setting up the configured target telnet passwort
        • +
        +

        + Example:
        + define MyTTS Sprinkle 192.168.178.10:7072 fhempasswd + define MyTTS Sprinkle 192.168.178.10 +

        +
      +
    • + +
    +
+ + +Set +
    +
  • tts:
    + Giving a text to translate into audio. +
  • +
  • volume:
    + Setting up the volume audio response.
    + Notice: Only available in locally instances! +
  • +

+ + +Get +
    N/A

+ + +Attributes +
    +
  • TTS_Delemiter
    + optional: By using the google engine, its not possible to convert more than 100 characters in a single audio brick. + With a delemiter the audio brick will be split at this character. A delemiter must be a single character.!
    + By default, ech audio brick will be split at sentence end. Is a single sentence longer than 100 characters, + the sentence will be split additionally at comma, semicolon and the word and.
    + Notice: Only available in locally instances with Google engine! +
  • + +
  • TTS_Ressource
    + optional: Selection of the Translator Engine
    + Notice: Only available in locally instances! +
      +
    • Google
      + Using the Google Engine. It´s nessessary to have internet access. This engine is the recommend engine + because the quality is fantastic. This engine is using by default. +
    • +
    • ESpeak
      + Using the ESpeak Engine. Installation of the espeak sourcen is required.
      + apt-get install espeak +
    • +
    +
  • + +
  • TTS_CacheFileDir
    + optional: The downloaded Goole audio bricks are saved in this folder for reusing. + No automatically implemented deleting are available.
    + Default: cache/
    + Notice: Only available in locally instances! +
  • + +
  • TTS_UseMP3Wrap
    + optional: To become a liquid audio response its recommend to use the tool mp3wrap. + Each downloaded audio bricks are concatinated to a single audio file to play with mplayer.
    + Installtion of the mp3wrap source is required.
    + apt-get install mp3wrap
    + Notice: Only available in locally instances! +
  • + +
  • TTS_MplayerCall
    + optional: Setting up the Mplayer system call. The following example is default.
    + Example: sudo /usr/bin/mplayer +
  • + +
  • TTS_SentenceAppendix
    + Optional: Definition of one mp3-file to append each time of audio response.
    + Using of Mp3Wrap is required. The audio bricks has to be downloaded before into CacheFileDir. + Example: silence.mp3 +
  • + +
  • TTS_FileMapping
    + Definition of mp3files with a custom templatedefinition. Separated by space. + All templatedefinitions can used in audiobricks by i>tts. + The definition must begin and end with e colon. + The mp3files must saved in the given directory by TTS_FIleTemplateDir.
    + attr myTTS TTS_FileMapping ring:ringtone.mp3 beep:MyBeep.mp3
    + set MyTTS tts Attention: This is my ringtone :ring: Its loud? +
  • + +
  • TTS_FileTemplateDir
    + Directory to save all mp3-files are defined in TTS_FileMapping und TTS_SentenceAppendix
    + Optional, Default: cache/templates +
  • + +
  • readingFnAttributes

  • + +
  • disable
    + If this attribute is activated, the soundoutput will be disabled.
    + Possible values: 0 => not disabled , 1 => disabled
    + Default Value is 0 (not disabled)

    +
  • + +
  • verbose
    + 4: each step will be logged
    + 5: Additionally the individual debug informations from mplayer and mp3wrap will be logged +
  • + +
+ +=end html +=begin html_DE + + +

Sprinkle

+
    +
    + + Define +
      + Local : define <name> Sprinkle <alsadevice>
      + Remote: define <name> Sprinkle <host>[:<portnr>][:SSL] [portpassword] +

      + Das Modul wandelt Text mittels verschiedener Provider/Ressourcen in Sprache um. Dabei kann das Device als + Remote oder Lokales Device konfiguriert werden. +

      + +
    • + Local Device
      +
        + Die Ausgabe erfolgt auf angeschlossenen Audiodevices, zb. Lautsprecher direkt am Gerät oder per + Bluetooth-Lautsprecher per Mplayer. Dazu ist Mplayer zu installieren.
        + apt-get install mplayer
        + Das angegebene Alsadevice ist in der /etc/asound.conf zu konfigurieren. +

        + Special AlsaDevice: none
        + Ist als Alsa-Device none angegeben, so wird mplayer ohne eine Audiodevice Angabe aufgerufen. + Dementsprechend verwendet mplayer das Standard Audio Ausgabedevice. +

        +

        + Beispiel:
        + define MyTTS Sprinkle hw=0.0
        + define MyTTS Sprinkle none +

        +
      +
    • + +
    • + Remote Device
      +
        + Das Modul ist Client-Server fäas bedeutet, das auf der Haupt-FHEM Installation eine Sprinkle-Instanz + als Remote definiert wird. Auf dem Client wird Sprinkle als Local definiert. Die Sprachausgabe erfolgt auf + der lokalen Instanz.
        + Zu beachten ist, das die Sprinkle Instanz (Definition als local Device) auf dem Zieldevice identisch benannt ist. +
          +
        • Host: Angabe der IP-Adresse
        • +
        • PortNr: Angabe des TelnetPorts von FHEM; default: 7072
        • +
        • SSL: Angabe ob der der Zugriff per SSL erfolgen soll oder nicht; default: kein SSL
        • +
        • PortPassword: Angabe des in der Ziel-FHEM-Installtion angegebene Telnet Portpasswort
        • +
        +

        + Beispiel:
        + define MyTTS Sprinkle 192.168.178.10:7072 fhempasswd + define MyTTS Sprinkle 192.168.178.10 +

        +
      +
    • + +
    +
+ + +Set +
    +
  • tts:
    + Setzen eines Textes zur Sprachausgabe. +
  • +
  • volume:
    + Setzen der Ausgabe Lautstärke.
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
  • +

+ + +Get +
    N/A

+ + +Attribute +
    +
  • TTS_Delemiter
    + Optional: Wird ein Delemiter angegeben, so wird der Sprachbaustein an dieser Stelle geteilt. + Als Delemiter ist nur ein einzelnes Zeichen zulässig. + Hintergrund ist die Tatsache, das die Google Sprachengine nur 100Zeichen zulässt.
    + Im Standard wird nach jedem Satzende geteilt. Ist ein einzelner Satz länger als 100 Zeichen, + so wird zusätzlich nach Kommata, Semikolon und dem Verbindungswort und geteilt.
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich und nur Nutzung der Google Sprachengine relevant! +
  • + +
  • TTS_Ressource
    + Optional: Auswahl der Sprachengine
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
      +
    • Google
      + Nutzung der GoogleSprachengine. Ein Internetzugriff ist notwendig! Aufgrund der Qualität ist der + Einsatz diese Engine zu empfehlen und der Standard. +
    • +
    • ESpeak
      + Nutzung der ESpeak Offline Sprachengine. Die Qualitä ist schlechter als die Google Engine. + ESpeak ist vor der Nutzung zu installieren.
      + apt-get install espeak +
    • +
    +
  • + +
  • TTS_CacheFileDir
    + Optional: Die per Google geladenen Sprachbausteine werden in diesem Verzeichnis zur Wiedeverwendung abgelegt. + Es findet zurZEit keine automatisierte Löschung statt.
    + Default: cache/
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
  • + +
  • TTS_UseMP3Wrap
    + Optional: Für eine flüssige Sprachausgabe ist es zu empfehlen, die einzelnen vorher per Google + geladenen Sprachbausteine zu einem einzelnen Sprachbaustein zusammenfassen zu lassen bevor dieses per + Mplayer ausgegeben werden. Dazu muss Mp3Wrap installiert werden.
    + apt-get install mp3wrap
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
  • + +
  • TTS_MplayerCall
    + Optional: Angabe der Systemaufrufes zu Mplayer. Das folgende Beispiel ist der Standardaufruf.
    + Beispiel: sudo /usr/bin/mplayer +
  • + +
  • TTS_SentenceAppendix
    + Optional: Angabe einer mp3-Datei die mit jeder Sprachausgabe am Ende ausgegeben wird.
    + Voraussetzung ist die Nutzung von MP3Wrap. Die Sprachbausteine müssen bereits als mp3 im + CacheFileDir vorliegen. + Beispiel: silence.mp3 +
  • + +
  • TTS_FileMapping
    + Angabe von möglichen MP3-Dateien mit deren Templatedefinition. Getrennt duch Leerzeichen. + Die Templatedefinitionen können in den per tts übergebenen Sprachbausteinen verwendet werden + und müssen mit einem beginnenden und endenden Doppelpunkt angegeben werden. + Die Dateien müssen im Verzeichnis TTS_FIleTemplateDir gespeichert sein.
    + attr myTTS TTS_FileMapping ring:ringtone.mp3 beep:MyBeep.mp3
    + set MyTTS tts Achtung: hier kommt mein Klingelton :ring: War der laut? +
  • + +
  • TTS_FileTemplateDir
    + Verzeichnis, in dem die per TTS_FileMapping und TTS_SentenceAppendix definierten + MP3-Dateien gespeichert sind.
    + Optional, Default: cache/templates +
  • + +
  • readingFnAttributes

  • + +
  • disable
    + If this attribute is activated, the soundoutput will be disabled.
    + Possible values: 0 => not disabled , 1 => disabled
    + Default Value is 0 (not disabled)

    +
  • + +
  • verbose
    + 4: Alle Zwischenschritte der Verarbeitung werden ausgegeben
    + 5: Zusätzlich werden auch die Meldungen von Mplayer und Mp3Wrap ausgegeben +
  • + +
+ +=end html_DE +=cut diff --git a/fhem/contrib/98_Sprinkle.pm b/fhem/contrib/98_Sprinkle.pm new file mode 100644 index 000000000..1a00e7824 --- /dev/null +++ b/fhem/contrib/98_Sprinkle.pm @@ -0,0 +1,737 @@ + +############################################## +# $Id$ +# +# 98_Sprinkle.pm +# +# written by Tobias Faust 2013-10-23 +# e-mail: tobias dot faust at online dot de +# +############################################## + +package main; +use strict; +use warnings; +use Data::Dumper; + +use vars qw(%gets %sets %defs %attr); + +# SetParamName -> Anzahl Paramter +my %sets = ( + "Auto" => "0", + "An" => "0", + "Aus" => "0", + "Toggle" => "0", + "Disable" => "0" +); + +# These we may get on request +#my %gets = ( +# "alarms" => "0" +#); + +########################## +sub Sprinkle_Initialize($) +{ + my ($hash) = @_; + + require "$main::attr{global}{modpath}/FHEM/97_SprinkleControl.pm"; + + $hash->{DefFn} = "Sprinkle_Define"; + $hash->{NotifyFn} = "Sprinkle_Notify"; + $hash->{SetFn} = "Sprinkle_Set"; + $hash->{UndefFn} = "Sprinkle_Undefine"; + $hash->{AttrFn} = "Sprinkle_Attr"; + $hash->{AttrList} = "disable:0,1". + " Sprinkle_SensorThreshold". # in 0% - 100% + " Sprinkle_OnTimeSec". # =0: On; >0: on-for-timer x + " Sprinkle_DefaultCmd:Auto,An". + " ".$readingFnAttributes; + +} + + +########################## +# Define Sprinkle [] [] +########################## +sub Sprinkle_Define($$) +{ + my ($hash, $def) = @_; + my $me = $hash->{NAME}; + my @a = split("[ \t]+", $def); + + #$a[0]: Name + #$a[1]: Type/Alias -> Sprinkle + my $device = $a[2]; + + my $deviceport; + my $sensor; + my $sensorport; + my $timespec; + + $sensor = $a[3] if($a[3] && length($a[3])>0); + $timespec = $a[4] if($a[4] && length($a[4])>0); + + if(int(@a) < 3) { + my $msg = "wrong syntax: define Sprinkle [] []"; + Log3 $hash, 2, $msg; + return $msg; + } + + my @t; + # Check definition of device + if($device =~ m/:/) { + @t = split(":", $device); + $device = $t[0]; + $deviceport = $t[1] if($t[1]); + } + # check definition of sensor + if($sensor && $sensor =~ m/:/) { + @t = split(":", $sensor); + $sensor = $t[0]; + $sensorport = $t[1] if($t[1]); + } + + return "Given device not exists: $device" if(!$defs{$device}); + return "Given Sensordevice not exists: $sensor" if(defined($sensor) && !$defs{$sensor}); + + return "The specified reading of device not exists: $deviceport" if (defined($deviceport) && !defined(ReadingsVal($device, $deviceport, undef))); + return "The specified reading of sensor not exists: $sensorport" if (defined($sensorport) && !defined(ReadingsVal($sensor, $sensorport, undef))); + + return "Wrong timespec, use \"[+]::\"" if(defined($timespec) && $timespec !~ m/^([\+]?)([\d]{2}):([\d]{2}):([\d]{2})$/); + + #ininitial delete + delete $hash->{Device}; + delete $hash->{DevicePort}; + delete $hash->{Sensor}; + delete $hash->{SensorPort}; + delete $hash->{TimeSpec}; + delete $hash->{NOTIFYDEV}; + + $hash->{Device} = $device; + $hash->{DevicePort} = $deviceport if($deviceport); + $hash->{Sensor} = $sensor if($sensor); + $hash->{SensorPort} = $sensorport if($sensorport); + $hash->{TimeSpec} = $timespec if($timespec); + $hash->{NOTIFYDEV} = $device; + + if(!$attr{$me}) { + #Attribute vorbelegen! Nur beim Define, kein Modify + $attr{$me}{webCmd} = "Auto:An:Aus:Toggle:Disable"; + $attr{$me}{devStateIcon} = "An:general_an Aus:general_aus Auto:time_automatic disabled:remotecontrol/black_btn_POWEROFF2"; + $attr{$me}{Sprinkle_OnTimeSec} = 640; + $attr{$me}{Sprinkle_SensorThreshold} = 50; + $attr{$me}{Sprinkle_DefaultCmd} = "Auto"; + } + + UpdateSprinkleControlList(undef, undef); + + if(defined($timespec) && $sensor && $attr{$me}{Sprinkle_OnTimeSec} && $attr{$me}{Sprinkle_SensorThreshold}) { + readingsSingleUpdate($hash, "state", "Auto", 1); + Sprinkle_InternalTimerDoIt($hash); + } else { + readingsSingleUpdate($hash, "state", "Initialized", 1); + } + + return undef; +} + +##################################### +sub Sprinkle_Undefine($$) +{ + my ($hash, $arg) = @_; + + RemoveInternalTimer($hash); + return undef; +} + +################################### +# +################################### +sub Sprinkle_Attr(@) { + my @a = @_; + my $do = 0; + my $hash = $defs{$a[1]}; + my $command = $a[0]; + my $setter = $a[2]; + my $value = $a[3]; + + if($setter eq "Sprinkle_SensorThreshold" && $command ne "del") { + return "SensorTreshold isn´t numeric or not in range [0..100]" if ($value !~ m/^(\d+)$/ || $value < 0 || $value > 100); + + } elsif($setter eq "Sprinkle_OnTimeSec" && $command ne "del") { + return "OnTimeSec isn´t numeric or not greater than zero" if ($value !~ m/^(\d+)$/ || $value < 0); + + } elsif($setter eq "disable"){ + # 1=disable; 2=enable + if($command eq "set") { + $do = (!defined($value) || $value) ? 1 : 2; + } + $do = 2 if($command eq "del"); + readingsSingleUpdate($hash, "state", ($do == 1 ? "disabled" : "Initialized"), 1); + } + + return undef; + +} + +################################################ +# +# +############################################### +sub Sprinkle_Set($@) +{ + my ($hash, @a) = @_; + my $me = $hash->{NAME}; + + return "no set argument specified" if(int(@a) < 2); + + my $cmd = shift(@a); # Dummy + $cmd = shift(@a); # DevName + + if(!defined($sets{$cmd})) { + my $r = "Unknown argument $cmd, choose one of ".join(" ",sort keys %sets); + return $r; + } + + # Abbruch falls Disabled + #return undef if(IsDisabled($hash->{NAME})); + + #if($cmd ne "tts") { + # return "$cmd needs $sets{$cmd} parameter(s)" if(@a-$sets{$cmd} != 0); + #} + + RemoveInternalTimer($hash); + + if($cmd eq "Disable" && !IsDisabled($me)) { + $attr{$me}{disable}=1; + readingsSingleUpdate($hash, "state", "disabled", 1); # Deaktivieren + return undef; + } elsif($cmd eq "Disable" && IsDisabled($me)) { + $attr{$me}{disable}=0; + readingsSingleUpdate($hash, "state", "Aus", 1); # wieder aktivieren, Startzustand: Aus + return undef; + } elsif (IsDisabled($me)) { # mache nix da disabled + return undef; + } elsif($cmd eq "Toggle") { + my $aktstate = lc(OldValue($me)); + if($aktstate =~ m/^aus/) { + $cmd = "An"; + } else { + $cmd = "Aus"; + } + } elsif($cmd eq "Auto") { + return "automode not possible because no sensor defined" if(!defined($hash->{Sensor})); + return "automode not possible because no sensor threshold (Sprinkle_SensorThreshold) defined or value is 0" if(AttrVal($me, "Sprinkle_SensorThreshold", 0) == 0); + return "automode not possible because no time definition (Sprinkle_OnTimeSec) defined or value is 0" if(AttrVal($me, "Sprinkle_OnTimeSec", 0) == 0); + + if(OldValue($me) !~ m/Auto/) { + readingsSingleUpdate($hash, "state", "Auto", 1); # AutoMode aktivieren, Startzustand: Aus + Sprinkle_InternalTimerDoIt($hash, 0); + return undef; + } + } + + Sprinkle_DoIt($hash, $cmd); + + return undef; +} + +################################################ +# +# +############################################### +sub Sprinkle_Notify($$) { + # Log is my entry, Dev is the entry of the changed device + my ($hash, $dev) = @_; + my $me = $hash->{NAME}; + my $devname = $dev->{NAME}; + return undef if(IsDisabled($me)); + return undef if($hash->{Device} ne $dev->{NAME}); + + my $SprinkleControl = AttrVal($me, "SprinkleControl", undef); + + my $newState; + $newState = "An" if(lc(ReadingsVal($devname, "state", "")) =~ m/(an|on)/); + $newState = "Aus" if(lc(ReadingsVal($devname, "state", "")) =~ m/(aus|off)/); + + if($newState eq "An") { + SprinkleControl_AllocateNewThread($SprinkleControl, $me, "An") if($SprinkleControl); + } elsif($newState eq "Aus") { + SprinkleControl_DeallocateThread($SprinkleControl, $me) if($SprinkleControl); + } + + if(lc(ReadingsVal($me, "state", "")) =~ m/auto/) { + $newState = "Auto(An)" if ($newState eq "An"); + $newState = "Auto" if ($newState eq "Aus"); + } + + readingsSingleUpdate($hash, "state", $newState, 1) if($newState); + + return undef; +} + +################################################ +# +# +############################################### +sub Sprinkle_InternalTimerDoIt(@) { + my ($hash, $DoIt) = @_; + my $me = $hash->{NAME}; + + $DoIt = 1 if(!defined($DoIt)); + + if(defined($hash->{TimeSpec}) && $hash->{TimeSpec} =~ m/^([\+]?)([\d]{2}):([\d]{2}):([\d]{2})$/) { + my ($rel, $hr, $min, $sec) = ($1, $2, $3, $4); + my @lt = localtime(time); + my $nt = time; + $nt -= ($lt[2]*3600+$lt[1]*60+$lt[0]) # Midnight for absolute time + if($rel ne "+"); + $nt += ($hr*3600+$min*60+$sec); # Plus relative time + + @lt = localtime($nt); + my $ntm = sprintf("%02d:%02d:%02d", $lt[2], $lt[1], $lt[0]); + $hash->{NextTime} = $ntm; + $hash->{TriggerTime} = $nt; + + my $DefaultCmd = AttrVal($me, "Sprinkle_DefaultCmd", "Auto"); + RemoveInternalTimer($hash); + Sprinkle_DoIt($hash, $DefaultCmd) if($DoIt == 1); + InternalTimer($nt, "Sprinkle_InternalTimerDoIt", $hash, 0); + } else { + delete $hash->{NextTime}; + delete $hash->{TriggerTime}; + } + +} + + +############################################## +# HauptProzedur zur Bewässerungssteuerung +# +# param1: $hash +# param2: Command, zb: An, Auto, Aus... +############################################## +sub Sprinkle_DoIt($$) { + my ($hash, $cmd) = @_; + my $me = $hash->{NAME}; + return undef if(IsDisabled($me)); + return undef if((lc(ReadingsVal($me, "state", undef)) =~ m/an/) && + (lc($cmd) !~ m/aus/)) ; # Aufruf durch InternalTimer und manuell wurde bereits angeschaltet + + my $SensorTreshold = AttrVal($me, "Sprinkle_SensorThreshold", undef); + my $OnTimeSec = AttrVal($me, "Sprinkle_OnTimeSec", undef); + + my $device = $hash->{Device}; + my $deviceport = $hash->{DevicePort} if(defined($hash->{DevicePort})); + my $sensor = $hash->{Sensor} if(defined($hash->{Sensor})); + my $sensorport = $hash->{SensorPort} if(defined($hash->{SensorPort})); + + my $oldState; + my $sensorvalue; + + # aktuellen Status des Device abfragen + if(defined($deviceport)) { + $oldState = lc(ReadingsVal($device, $deviceport,undef)); + } else { + $oldState = lc(ReadingsVal($device, "state", undef)); + } + return "actual state of given device not accessable, please check definition of $me" if(!$oldState); + + # Status des Sensors abfragen + if (defined($sensor) && defined($sensorport)) { + $sensorvalue = ReadingsVal($sensor, $sensorport, undef); + } + if(defined($sensor) && !defined($sensorport)) { + $sensorvalue = ReadingsVal($sensor, "status", undef); + $sensorvalue = ReadingsVal($sensor, "state", undef) if (!defined($sensorvalue)); + + #Bodenfeuchte ist kein Messwert sondern nur ein on/off Reading + $sensorvalue = 0 if(lc($sensorvalue) =~ m/^(on)/); + $sensorvalue = 999 if(lc($sensorvalue) =~ m/^(off)/); + } + + return "AutoMode not accessable. Please check your Sprinkle attributes and value of Sensor" + if(lc($cmd) eq "auto" && (!defined($OnTimeSec) || $OnTimeSec <= 0 || !defined($sensorvalue) || !defined($SensorTreshold))); + + my $newState; + my $OnCmd; + my $OnCmdAdd = ""; + my $doit = 0; # 0 => mache nichts; 1 => mache; 2 => warte auf Freigabe SprinkleControl + + if(defined($OnTimeSec) && $OnTimeSec > 0 ) { + $OnCmd = "on-for-timer ".$OnTimeSec; + } else { + $OnCmd = "on"; + } + + my $SprinkleControl = AttrVal($me, "SprinkleControl", undef); + + if(defined($deviceport)) { + $OnCmdAdd = "output ".$deviceport; #zb OWSwitch, ev. unterscheiden nach OWSWITCH und OWDEVICE + } + + if(lc($cmd) eq "an") { + $newState = $cmd; + if($oldState ne $newState && (($SprinkleControl && SprinkleControl_AllocateNewThread($SprinkleControl, $me, $cmd)) || !$SprinkleControl)) { + fhem "set $device $OnCmdAdd $OnCmd"; + $doit = 1; + } elsif($oldState ne $newState) { + $newState = "Wait"; + $doit = 2; + } + + } elsif(lc($cmd) eq "aus") { + $newState = $cmd; + if($oldState ne $newState && (($SprinkleControl && SprinkleControl_DeallocateThread($SprinkleControl, $me)) || !$SprinkleControl)) { + fhem "set $device off"; + $doit = 1; + } + + } elsif(lc($cmd) eq "auto") { + if($SensorTreshold >= $sensorvalue) { + $newState = "Auto(An)"; + if($oldState ne "on" && (($SprinkleControl && SprinkleControl_AllocateNewThread($SprinkleControl, $me, $cmd)) || !$SprinkleControl)) { + fhem "set $device $OnCmdAdd $OnCmd"; + $doit = 1; + } elsif ($oldState ne $newState) { + $newState = "Wait"; + $doit = 2; + } + } else { + $newState = "Auto"; + if($oldState ne "off" && (($SprinkleControl && SprinkleControl_DeallocateThread($SprinkleControl, $me)) || !$SprinkleControl)) { + fhem "set $device off"; + $doit = 1; + } + } + } + + readingsSingleUpdate($hash, "state", $newState, 1) if($doit >= 1); + + return $newState; +} + +1; + +=pod +=begin html + + +

Sprinkle

+
    +
    + + Define +
      + Local : define <name> Sprinkle <alsadevice>
      + Remote: define <name> Sprinkle <host>[:<portnr>][:SSL] [portpassword] +

      + This module converts any text into speech with serveral possible providers. The Device can be defined as locally + or remote device. +

      + +
    • + Local Device
      +
        + The output will be send to any connected audiodevice. For example external speakers connected per jack + or with bluetooth speakers - connected per bluetooth dongle. Its important to install mplayer.
        + apt-get install mplayer
        + The given alsadevice has to be configured in /etc/asound.conf +

        + Special AlsaDevice: none
        + The internal mplayer command will be without any audio directive if the given alsadevice is none. + In this case mplayer is using the standard audiodevice. +

        +

        + Example:
        + define MyTTS Sprinkle hw=0.0
        + define MyTTS Sprinkle none +

        +
      +
    • + +
    • + Remote Device
      +
        + This module can configured as remote-device for client-server Environments. The Client has to be configured + as local device.
        + Notice: the Name of the locally instance has to be the same! +
          +
        • Host: setting up IP-adress
        • +
        • PortNr: setting up TelnetPort of FHEM; default: 7072
        • +
        • SSL: setting up if connect over SSL; default: no SSL
        • +
        • PortPassword: setting up the configured target telnet passwort
        • +
        +

        + Example:
        + define MyTTS Sprinkle 192.168.178.10:7072 fhempasswd + define MyTTS Sprinkle 192.168.178.10 +

        +
      +
    • + +
    +
+ + +Set +
    +
  • tts:
    + Giving a text to translate into audio. +
  • +
  • volume:
    + Setting up the volume audio response.
    + Notice: Only available in locally instances! +
  • +

+ + +Get +
    N/A

+ + +Attributes +
    +
  • TTS_Delemiter
    + optional: By using the google engine, its not possible to convert more than 100 characters in a single audio brick. + With a delemiter the audio brick will be split at this character. A delemiter must be a single character.!
    + By default, ech audio brick will be split at sentence end. Is a single sentence longer than 100 characters, + the sentence will be split additionally at comma, semicolon and the word and.
    + Notice: Only available in locally instances with Google engine! +
  • + +
  • TTS_Ressource
    + optional: Selection of the Translator Engine
    + Notice: Only available in locally instances! +
      +
    • Google
      + Using the Google Engine. It´s nessessary to have internet access. This engine is the recommend engine + because the quality is fantastic. This engine is using by default. +
    • +
    • ESpeak
      + Using the ESpeak Engine. Installation of the espeak sourcen is required.
      + apt-get install espeak +
    • +
    +
  • + +
  • TTS_CacheFileDir
    + optional: The downloaded Goole audio bricks are saved in this folder for reusing. + No automatically implemented deleting are available.
    + Default: cache/
    + Notice: Only available in locally instances! +
  • + +
  • TTS_UseMP3Wrap
    + optional: To become a liquid audio response its recommend to use the tool mp3wrap. + Each downloaded audio bricks are concatinated to a single audio file to play with mplayer.
    + Installtion of the mp3wrap source is required.
    + apt-get install mp3wrap
    + Notice: Only available in locally instances! +
  • + +
  • TTS_MplayerCall
    + optional: Setting up the Mplayer system call. The following example is default.
    + Example: sudo /usr/bin/mplayer +
  • + +
  • TTS_SentenceAppendix
    + Optional: Definition of one mp3-file to append each time of audio response.
    + Using of Mp3Wrap is required. The audio bricks has to be downloaded before into CacheFileDir. + Example: silence.mp3 +
  • + +
  • TTS_FileMapping
    + Definition of mp3files with a custom templatedefinition. Separated by space. + All templatedefinitions can used in audiobricks by i>tts. + The definition must begin and end with e colon. + The mp3files must saved in the given directory by TTS_FIleTemplateDir.
    + attr myTTS TTS_FileMapping ring:ringtone.mp3 beep:MyBeep.mp3
    + set MyTTS tts Attention: This is my ringtone :ring: Its loud? +
  • + +
  • TTS_FileTemplateDir
    + Directory to save all mp3-files are defined in TTS_FileMapping und TTS_SentenceAppendix
    + Optional, Default: cache/templates +
  • + +
  • readingFnAttributes

  • + +
  • disable
    + If this attribute is activated, the soundoutput will be disabled.
    + Possible values: 0 => not disabled , 1 => disabled
    + Default Value is 0 (not disabled)

    +
  • + +
  • verbose
    + 4: each step will be logged
    + 5: Additionally the individual debug informations from mplayer and mp3wrap will be logged +
  • + +
+ +=end html +=begin html_DE + + +

Sprinkle

+
    +
    + + Define +
      + Local : define <name> Sprinkle <alsadevice>
      + Remote: define <name> Sprinkle <host>[:<portnr>][:SSL] [portpassword] +

      + Das Modul wandelt Text mittels verschiedener Provider/Ressourcen in Sprache um. Dabei kann das Device als + Remote oder Lokales Device konfiguriert werden. +

      + +
    • + Local Device
      +
        + Die Ausgabe erfolgt auf angeschlossenen Audiodevices, zb. Lautsprecher direkt am Gerät oder per + Bluetooth-Lautsprecher per Mplayer. Dazu ist Mplayer zu installieren.
        + apt-get install mplayer
        + Das angegebene Alsadevice ist in der /etc/asound.conf zu konfigurieren. +

        + Special AlsaDevice: none
        + Ist als Alsa-Device none angegeben, so wird mplayer ohne eine Audiodevice Angabe aufgerufen. + Dementsprechend verwendet mplayer das Standard Audio Ausgabedevice. +

        +

        + Beispiel:
        + define MyTTS Sprinkle hw=0.0
        + define MyTTS Sprinkle none +

        +
      +
    • + +
    • + Remote Device
      +
        + Das Modul ist Client-Server fäas bedeutet, das auf der Haupt-FHEM Installation eine Sprinkle-Instanz + als Remote definiert wird. Auf dem Client wird Sprinkle als Local definiert. Die Sprachausgabe erfolgt auf + der lokalen Instanz.
        + Zu beachten ist, das die Sprinkle Instanz (Definition als local Device) auf dem Zieldevice identisch benannt ist. +
          +
        • Host: Angabe der IP-Adresse
        • +
        • PortNr: Angabe des TelnetPorts von FHEM; default: 7072
        • +
        • SSL: Angabe ob der der Zugriff per SSL erfolgen soll oder nicht; default: kein SSL
        • +
        • PortPassword: Angabe des in der Ziel-FHEM-Installtion angegebene Telnet Portpasswort
        • +
        +

        + Beispiel:
        + define MyTTS Sprinkle 192.168.178.10:7072 fhempasswd + define MyTTS Sprinkle 192.168.178.10 +

        +
      +
    • + +
    +
+ + +Set +
    +
  • tts:
    + Setzen eines Textes zur Sprachausgabe. +
  • +
  • volume:
    + Setzen der Ausgabe Lautstärke.
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
  • +

+ + +Get +
    N/A

+ + +Attribute +
    +
  • TTS_Delemiter
    + Optional: Wird ein Delemiter angegeben, so wird der Sprachbaustein an dieser Stelle geteilt. + Als Delemiter ist nur ein einzelnes Zeichen zulässig. + Hintergrund ist die Tatsache, das die Google Sprachengine nur 100Zeichen zulässt.
    + Im Standard wird nach jedem Satzende geteilt. Ist ein einzelner Satz länger als 100 Zeichen, + so wird zusätzlich nach Kommata, Semikolon und dem Verbindungswort und geteilt.
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich und nur Nutzung der Google Sprachengine relevant! +
  • + +
  • TTS_Ressource
    + Optional: Auswahl der Sprachengine
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
      +
    • Google
      + Nutzung der GoogleSprachengine. Ein Internetzugriff ist notwendig! Aufgrund der Qualität ist der + Einsatz diese Engine zu empfehlen und der Standard. +
    • +
    • ESpeak
      + Nutzung der ESpeak Offline Sprachengine. Die Qualitä ist schlechter als die Google Engine. + ESpeak ist vor der Nutzung zu installieren.
      + apt-get install espeak +
    • +
    +
  • + +
  • TTS_CacheFileDir
    + Optional: Die per Google geladenen Sprachbausteine werden in diesem Verzeichnis zur Wiedeverwendung abgelegt. + Es findet zurZEit keine automatisierte Löschung statt.
    + Default: cache/
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
  • + +
  • TTS_UseMP3Wrap
    + Optional: Für eine flüssige Sprachausgabe ist es zu empfehlen, die einzelnen vorher per Google + geladenen Sprachbausteine zu einem einzelnen Sprachbaustein zusammenfassen zu lassen bevor dieses per + Mplayer ausgegeben werden. Dazu muss Mp3Wrap installiert werden.
    + apt-get install mp3wrap
    + Achtung: Nur bei einem lokal definierter Sprinkle Instanz möglich! +
  • + +
  • TTS_MplayerCall
    + Optional: Angabe der Systemaufrufes zu Mplayer. Das folgende Beispiel ist der Standardaufruf.
    + Beispiel: sudo /usr/bin/mplayer +
  • + +
  • TTS_SentenceAppendix
    + Optional: Angabe einer mp3-Datei die mit jeder Sprachausgabe am Ende ausgegeben wird.
    + Voraussetzung ist die Nutzung von MP3Wrap. Die Sprachbausteine müssen bereits als mp3 im + CacheFileDir vorliegen. + Beispiel: silence.mp3 +
  • + +
  • TTS_FileMapping
    + Angabe von möglichen MP3-Dateien mit deren Templatedefinition. Getrennt duch Leerzeichen. + Die Templatedefinitionen können in den per tts übergebenen Sprachbausteinen verwendet werden + und müssen mit einem beginnenden und endenden Doppelpunkt angegeben werden. + Die Dateien müssen im Verzeichnis TTS_FIleTemplateDir gespeichert sein.
    + attr myTTS TTS_FileMapping ring:ringtone.mp3 beep:MyBeep.mp3
    + set MyTTS tts Achtung: hier kommt mein Klingelton :ring: War der laut? +
  • + +
  • TTS_FileTemplateDir
    + Verzeichnis, in dem die per TTS_FileMapping und TTS_SentenceAppendix definierten + MP3-Dateien gespeichert sind.
    + Optional, Default: cache/templates +
  • + +
  • readingFnAttributes

  • + +
  • disable
    + If this attribute is activated, the soundoutput will be disabled.
    + Possible values: 0 => not disabled , 1 => disabled
    + Default Value is 0 (not disabled)

    +
  • + +
  • verbose
    + 4: Alle Zwischenschritte der Verarbeitung werden ausgegeben
    + 5: Zusätzlich werden auch die Meldungen von Mplayer und Mp3Wrap ausgegeben +
  • + +
+ +=end html_DE +=cut