diff --git a/CHANGED b/CHANGED index 03a0d3562..d3f8d7101 100644 --- a/CHANGED +++ b/CHANGED @@ -1,4 +1,5 @@ - SVN + - feature: new Modules 75_MSG.pm, 76_MSGFile.pm and 76_MSGMail.pm (by Rüdiger) - feature: new Module 59_Twilight.pm to calculate current daylight - feature: internal NotifyOrderPrefix: 98_average.pm is more straightforward - feature: the usb command tries to flash unflashed CULs on linux diff --git a/FHEM/75_MSG.pm b/FHEM/75_MSG.pm new file mode 100644 index 000000000..b742f1345 --- /dev/null +++ b/FHEM/75_MSG.pm @@ -0,0 +1,198 @@ +############################################## +# $Id: 75_MSG.pm 2012-06-20 18:29:00 rbente +############################################## +package main; + +use strict; +use warnings; +use Switch; +use MIME::Lite; +use Net::SMTP::SSL; +my %sets = ( + "send" => "MSG", + "write" => "MSG", +); +########################################################### +## Initialize Function +## +############################################################ +sub +MSG_Initialize($) +{ + my ($hash) = @_; + + $hash->{SetFn} = "MSG_Set"; + $hash->{DefFn} = "MSG_Define"; + $hash->{AttrList} = "loglevel:0,1,2,3,4,5,6"; +} + +########################################################### +## Set Function +## +############################################################ +sub +MSG_Set($@) +{ + my ($hash, @a) = @_; + return "Unknown argument $a[1], choose one of -> " . join(" ", sort keys %sets) + if(!defined($sets{$a[1]})); + + my $name = shift @a; + + return "no set value specified" if(int(@a) < 1); + + return "Unknown argument ?" if($a[0] eq "?"); +########## Check, if we have send or wait as parameter + if(($a[0] eq "send") || ($a[0] eq "write")) + { +########## Check if the device is defined that we like to use as frontend + return "Please define $a[1] first" if(!defined($defs{$a[1]})); +########## switch based on the device type +########## valid device types are: +########## MSGFile = write to a file +########## MSGMail = send an email + if(!defined($defs{$a[1]}{TYPE})) + { + return "TYPE for $defs{$a[1]} not defined"; + } + +#################################################################################################### +## +## M S G F i l e +## +#################################################################################################### + elsif($defs{$a[1]}{TYPE} eq "MSGFile") + { + + return "No filename specified, use attr filename $a[1] $defs{$a[1]}{TYPE}" if (!AttrVal($a[1],"filename","")); + +########## open the file, new = delete file before create it +########## append = add lines to the existing file contents + if(AttrVal($a[1],"filemode","") eq "new") + { + open(FHEMMSGFILE, ">" . AttrVal($a[1],"filename","")) || return "Can not open the file: $!"; + } + else + { + open(FHEMMSGFILE, ">>" . AttrVal($a[1],"filename","")) || return "Can not open the file: $!"; + } +########## loop thru the stored lines and write them to the file +########## number of lines are in the Readings / msgcount + my $i; + if(ReadingsVal($a[1],"msgcount",0) > 0) + { + for($i=0;$i write to File: " . AttrVal($a[1],"filename",""); + } # END MSGFile + +#################################################################################################### +## +## M S G M a i l +## +## We use MAIL::Lite to compose the message, because it works very well at this and +## we use Net::SMTP::SSL to connect to the smtp host and manage the authenification, +## because MAIL:Lite is not very easy to manage with SSL connections +#################################################################################################### + + elsif($defs{$a[1]}{TYPE} eq "MSGMail") + { + +########## check all the needed data + my $from = AttrVal($a[1],"from",""); + return "No address specified, use attr $a[1] from " if (!$from); + my $to = AttrVal($a[1],"to",""); + return "No address specified, use attr $a[1] to " if (!$to); + my $subject = AttrVal($a[1],"subject",""); + return "No specified, use attr $a[1] subject " if (!$subject); + my $authfile = AttrVal($a[1],"authfile",""); + return "No specified, use attr $a[1] authfile " if (!$authfile); + my $smtphost = AttrVal($a[1],"smtphost",""); + return "No name specified, use attr $a[1] sntphost " if (!$smtphost); + my $smtpport = AttrVal($a[1],"smtpport","465"); # 465 is the default port + my $cc = AttrVal($a[1],"cc",""); # Carbon Copy + open(FHEMAUTHFILE, "<" . $authfile) || return "Can not open authfile $authfile: $!";; + my @auth = ; + close(FHEMAUTHFILE); + chomp(@auth); +# Log 1, "MSG User = <" . @auth[0] . "> Passwort = <" . @auth[1] . ">"; + + + +########## compose message + my $i; + my $mess = ""; + for($i=0;$inew( + From => $from, + To => $to, + Subject => $subject, + Type => 'text/plain', + Data => $mess + ); + +########## login to the SMTP Host using SSL and send the message + my $smtp; + my $smtperrmsg = "SMTP Error: "; + $smtp = Net::SMTP::SSL->new($smtphost, Port=>$smtpport) or return $smtperrmsg . " Can't connect to host $smtphost"; + $smtp->auth(@auth[0], @auth[1]) or return $smtperrmsg . " Can't authenticate: " . $smtp->message(); + $smtp->mail($from) or return $smtperrmsg . $smtp->message(); + $smtp->to($to) or return $smtperrmsg . $smtp->message(); + if($cc ne '') + { + Log 1,"CC = $cc"; + $smtp->cc($cc) or return $smtperrmsg . $smtp->message(); + } + $smtp->data() or return $smtperrmsg . $smtp->message(); + $smtp->datasend($mailmsg->as_string) or return $smtperrmsg .$smtp->message(); + $smtp->dataend() or return $smtperrmsg . $smtp->message(); + $smtp->quit() or return $smtperrmsg . $smtp->message(); + + Log 1, " send EMail: <$subject>"; + + } ###> END MSGMail + else + { + return "MSG Filetype $defs{$a[1]}{TYPE} unknown"; + } + } ###> END if(($a[0] eq "send") || ($a[0] eq "write")) + my $v = join(" ", @a); + Log GetLogLevel($name,2), "MSG set $name $v"; +########## update stats + $hash->{CHANGED}[0] = $v; + $hash->{STATE} = $v; + $hash->{READINGS}{state}{TIME} = TimeNow(); + $hash->{READINGS}{state}{VAL} = $v; + return undef; +} + +########################################################### +## Define Function +## +############################################################ + +sub +MSG_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $errMSG_ = "wrong syntax: define MSG"; + + return $errMSG_ if(@a != 2); + + $hash->{STATE} = "ready"; + $hash->{TYPE} = "MSG"; + return undef; +} + + +1; diff --git a/FHEM/76_MSGFile.pm b/FHEM/76_MSGFile.pm new file mode 100644 index 000000000..22d02dfdc --- /dev/null +++ b/FHEM/76_MSGFile.pm @@ -0,0 +1,154 @@ +############################################## +# $Id: 76_MSGFile.pm 2012-06-20 18:29:00 rbente +############################################## +package main; + +use strict; +use warnings; +use Switch; +my %sets = ( + "add" => "MSGFile", + "clear" => "MSGFile", + "list" => "MSGFile" +); +############################################## +# Initialize Function +# Attributes are: +# filename the name of the file +# filemode new = file will be created from scratch +# append = add the new lines to the end of the existing data +# CR 0 = no CR added to the end of the line +# 1 = CR added to the end of the line +############################################## +sub +MSGFile_Initialize($) +{ + my ($hash) = @_; + + $hash->{SetFn} = "MSGFile_Set"; + $hash->{DefFn} = "MSGFile_Define"; + $hash->{UndefFn} = "MSGFile_Undef"; + $hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 filename filemode:new,append CR:0,1"; +} + +############################################## +# Set Function +# all the data are stored in the global array @data +# as counter we use a READING named msgcount +############################################## +sub +MSGFile_Set($@) +{ + my ($hash, @a) = @_; + return "Unknown argument $a[1], choose one of -> " . join(" ", sort keys %sets) + if(!defined($sets{$a[1]})); + + + my $name = shift @a; + + return "no set value specified" if(int(@a) < 1); + return "Unknown argument ?" if($a[0] eq "?"); + my $v = join(" ", @a); + +##### we like to add another line of data + if($a[0] eq "add") + { +##### split the line in command and data + my $mx = shift @a; + my $my = join(" ",@a); +##### check if we like to have and CR at the end of the line + if(AttrVal($name, "CR", "0") eq "1") + { + $my = $my . "\n"; + } +##### get the highest number of lines, store the line in @data and increase +##### the counter, at the end set the status + my $count = $hash->{READINGS}{msgcount}{VAL}; + $data{$name}{$count} = $my; + $hash->{READINGS}{msgcount}{TIME} = TimeNow(); + $hash->{READINGS}{msgcount}{VAL} = $count + 1; + $hash->{STATE} = "addmsg"; + + } + +##### we like to clear our buffer, first clear all lines of @data +##### and then set the counter to 0 and the status to clear + if($a[0] eq "clear") + { + my $i; + for($i=0;$i{READINGS}{msgcount}{TIME} = TimeNow(); + $hash->{READINGS}{msgcount}{VAL} = 0; + $hash->{STATE} = "clear"; + + } + +##### we like to see the buffer + + if($a[0] eq "list") + { + my $i; + my $mess = "---- Lines of data for $name ----\n"; + for($i=0;$i{CHANGED}[0] = $v; + $hash->{READINGS}{state}{TIME} = TimeNow(); + $hash->{READINGS}{state}{VAL} = $v; + return undef; +} + +############################################## +# Define Function +# set the counter to 0 +# and filemode to "new" +############################################## +sub +MSGFile_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $errmsg = "wrong syntax: define MSGFile filename"; + my $name = $hash->{NAME}; + + return $errmsg if(@a != 3); + $attr{$name}{filename} = $a[2]; + $attr{$name}{filemode} = "new"; + $attr{$name}{CR} = "1"; + + + $hash->{STATE} = "ready"; + $hash->{TYPE} = "MSGFile"; + $hash->{READINGS}{msgcount}{TIME} = TimeNow(); + $hash->{READINGS}{msgcount}{VAL} = 0; + return undef; +} +############################################## +# Undefine Function +# flush all lines of data +############################################## +sub +MSGFile_Undef($$) +{ + my ($hash, $name) = @_; + my $i; +############ flush the data + for($i=0;$i{CODE}}) if($hash && $hash->{CODE}); + return undef; +} +1; diff --git a/FHEM/76_MSGMail.pm b/FHEM/76_MSGMail.pm new file mode 100644 index 000000000..6b7af5c3e --- /dev/null +++ b/FHEM/76_MSGMail.pm @@ -0,0 +1,158 @@ +############################################## +# $Id: 76_MSGFile.pm 2012-06-20 18:29:00 rbente +############################################## +package main; + +use strict; +use warnings; +use Switch; +my %sets = ( + "add" => "MSGMail", + "clear" => "MSGMail", + "list" => "MSGMail" +); +############################################## +# Initialize Function +# Attributes are: +# authfile the name of the file which contains userid and password +# smtphost the smtp server hostname +# smtpport the port of the smtp host +# subject subject of the email +# from from mailaddress (sender) +# to to mailaddress (receipent) +# cc carbon copy address(es) (delimiter is comma) +# CR 0 = no CR added to the end of the line +# 1 = CR added to the end of the line +############################################## +sub +MSGMail_Initialize($) +{ + my ($hash) = @_; + + $hash->{SetFn} = "MSGMail_Set"; + $hash->{DefFn} = "MSGMail_Define"; + $hash->{UndefFn} = "MSGMail_Undef"; + $hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 authfile smtphost smtpport subject from to cc CR:0,1"; +} + +############################################## +# Set Function +# all the data are stored in the global array @data +# as counter we use a READING named msgcount +############################################## +sub +MSGMail_Set($@) +{ + my ($hash, @a) = @_; + return "Unknown argument $a[1], choose one of -> " . join(" ", sort keys %sets) + if(!defined($sets{$a[1]})); + my $name = shift @a; + + return "no set value specified" if(int(@a) < 1); +# return "Unknown argument ?" if($a[0] eq "?"); + my $v = join(" ", @a); +##### we like to add another line of data + if($a[0] eq "add") + { +##### split the line in command and data + my $mx = shift @a; + my $my = join(" ",@a); +##### check if we like to have and CR at the end of the line + if(AttrVal($name, "CR", "0") eq "1") + { + $my = $my . "\n"; + } +##### get the highest number of lines, stored the line in @data and increase +##### the counter, at the end set the status + my $count = $hash->{READINGS}{msgcount}{VAL}; + $data{$name}{$count} = $my; + $hash->{READINGS}{msgcount}{TIME} = TimeNow(); + $hash->{READINGS}{msgcount}{VAL} = $count + 1; + $hash->{STATE} = "addmsg"; + + } +##### we like to clear our buffer, first clear all lines of @data +##### and then set the counter to 0 and the status to clear + + if($a[0] eq "clear") + { + my $i; + for($i=0;$i{READINGS}{msgcount}{TIME} = TimeNow(); + $hash->{READINGS}{msgcount}{VAL} = 0; + $hash->{STATE} = "clear"; + + } + +##### we like to see the buffer + + if($a[0] eq "list") + { + my $i; + my $mess = "---- Lines of data for $name ----\n"; + for($i=0;$i{CHANGED}[0] = $v; + $hash->{READINGS}{state}{TIME} = TimeNow(); + $hash->{READINGS}{state}{VAL} = $v; + return undef; +} + +############################################## +# Define Function +# set the counter to 0 +############################################## +sub +MSGMail_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $errmsg = "wrong syntax: define MSGMail from to smtphost authfile"; + my $name = $hash->{NAME}; + + return $errmsg if(@a != 6); +##### set all the Attributes + $attr{$name}{from} = $a[2]; + $attr{$name}{to} = $a[3]; + $attr{$name}{smtphost} = $a[4]; + $attr{$name}{authfile} = $a[5]; + $attr{$name}{subject} = "FHEM "; + $attr{$name}{CR} = "1"; + + + $hash->{STATE} = "ready"; + $hash->{TYPE} = "MSGMail"; + $hash->{READINGS}{msgcount}{TIME} = TimeNow(); + $hash->{READINGS}{msgcount}{VAL} = 0; + return undef; +} +############################################## +# Undefine Function +# flush all lines of data +############################################## +sub +MSGMail_Undef($$) +{ + my ($hash, $name) = @_; + my $i; +############ flush the data + for($i=0;$i{CODE}}) if($hash && $hash->{CODE}); + return undef; +} + +1; diff --git a/docs/commandref.html b/docs/commandref.html index 5f965e2f4..93da072a7 100644 --- a/docs/commandref.html +++ b/docs/commandref.html @@ -107,6 +107,9 @@ M232   M232Counter   M232Voltage   + MSG   + MSGFile   + MSGMail   NetIO230B   OREGON   OWFS   @@ -4426,6 +4429,223 @@ A line ending with \ will be concatenated with the next one, so long lines + +

MSG

+
    +The MSG device is the backend device for all the message handling (I/O-engine). +Under normal conditions only one MSG device is needed to serve multiple frontend +message devices like file or email. +

    + +Define +
      +define <name> MSG

      +Specifies the MSG device. A single MSG device could serve multiple MSG frontends. +But, for special conditions there could be defined more than one MSG device. +
    +
    + +Set +
      +set <name> send|write <devicename>

      +
    +Notes: +
      +To send the data, both send or write could be used.
      + The devicename is the name of a frontenddevice previously + defined. Based on the type of the frontend device, the MSG device + will send out the lines of data. +
      + Frontend devices are available for:
      + + For details about this devices, please review the device-definitions.
      + After sending/writing the data, the data stills exists with the + frontend device, MSG do not delete/purge any data, this must be done + by the frontend device. +

      + Examples: +
        + define myMsg MSG +
      +
    + +Attributes + +
+

+ +

MSGFile

+
    + The MSGFile device is a frontend device for message handling. + With a MSGFile device data is written to disk (or other media). + Multiple MSGFile devices could be defined. + To write the data to disk, a MSG device is necessary. + A MSGFile device needs the operating systems rights to write to the filesystem. + To set the rights for a directory, please use OS related commands. +

    + + Define +

      + define <name> MSGFile <filename>

      + Specifies the MSGFile device. At definition the message counter is set to 0. + A filename must be specified at definition. +
    +
    + Examples: +
      + define myFile MSGFile +

    + +Set
    +
      set <name> add|clear|list [text]
      + Set is used to manipulate the message buffer of the device. The message + buffer is an array of lines of data, stored serial based on the incoming + time into the buffer. Lines of data inside the buffer could not be deleted + anymore, except of flashing the whole buffer.
      +
        add
        to add lines of data to the message buffer. All data behind + "add" will be interpreted as text message. To add a carriage return to the data, + please use the CR attribute. +
      +
        clear
        to flash the message buffer and set the line counter to 0. + All the lines of data are deleted and the buffer is flushed.
      +
        list
        to list the message buffer.

      +

    + Examples: +
      + set myFile add Dies ist Textzeile 1
      + set myFile add Dies ist Textzeile 2
      + set myFile clear

      + Full working example to write two lines of data to a file:
      + define myMsg MSG
      + define myFile MSGFile /tmp/fhemtest.txt
      + attr myFile filemode append
      + set myFile add Textzeile 1
      + set myFile add Textzeile 2
      + set myMsg write myFile
      + set myFile clear
      +

    + +Attributes +
      +
    • filename
      + sets the filename, must be a fully qualified filename. + FHEM must have the rights to write this file to the directory
    • +
    • filemode
      + sets the filemode, valid are "new" or "append"
      + new creates a new, empty file and writes the data to this file. Existing files are cleared, the data is lost!
      + append uses, if available, an existing file and writes the + buffer data to the end of the file. If the file do not exist, it will + be created
    • +
    • CR
      + set the option to write a carriage return at the end of the line. + CR could be set to 0 or 1, 1 enables this feature
    • +
    • loglevel
    • +
    +
+ + +

MSGMail

+
    + The MSGMail device is a frontend device for mail message handling. + With a MSGMaildevice data is fowarded to a mail provider and send to a recipent. + Multiple MSGMail devices could be defined. + MSGMail supports by the moment only mail provider, which uses SSL secured connection + like Googlemail, GMX, Yahoo or 1und1 for example. + To send an email, a MSG device is necessary.
    + MAIL::Lite and Net::SMTP::SSL from CPAN is needed to use MSGMail!! +

    + + Define +

      + define <name> MSGMail <from> <to> <smtphost> <authfile>

      + Specifies the MSGMail device. At definition the message counter is set to 0. + From, To, SMTPHost and the authfile (see attributes below) need to be defined + at definition time. +
    +
    + Examples: +
      + define myMail MSGMail from@address.com to@address.com smtp.provider.host /etc/msgauthfile +

    + +Set
    +
      set <name> add|clear|list [text]
      + Set is used to manipulate the message buffer of the device. The message + buffer is an array of lines of data, stored serial based on the incoming + time into the buffer. Lines of data inside the buffer could not be deleted + anymore, except of flashing the whole buffer.
      +
        add
        to add lines of data to the message buffer. All data behind + "add" will be interpreted as text message. To add a carriage return to the data, + please use the CR attribute. +
      +
        clear
        to flash the message buffer and set the line counter to 0. + All the lines of data are deleted and the buffer is flushed.
      +
        list
        to list the message buffer.

      +
      + Examples: +
        + set myMail add Dies ist Textzeile 1
        + set myMail add Dies ist Textzeile 2
        + set myMail clear

        + Full working example to send two lines of data to a recipent:
        + define myMsg MSG
        + define myMail MSGMail donald.duck@entenhausen.com dagobert.duck@duck-banking.com smtp.entenhausen.net /etc/fhem/msgmailauth
        + attr myMail smtpport 9999
        + attr myMail subject i need more money
        + attr myMail CR 0
        + set myMail add Please send me
        + set myMail add 1.000.000 Taler
        + set myMsg send myMail
        + set myMail clear
        +

      + +Attributes +
        + Almost all of these attributes are not optional, most of them could set at definition.
        +
      • from
        + sets the mail address of the sender
      • +
      • to
        + sets the mail address of the recipent
      • +
      • smtphost
        + sets the name of the smtphost, for example for GMX + you could use mail.gmx.net or for Googlemail the smtphost is + smtp.googlemail.com
      • +
      • smtpport (optional)
        + sets the port of the smtphost, for example for GMX + or for Googlemail the smtport is 465, which is also + the default and do not need to be set
      • +
      • subject (optional)
        + sets the subject of this email. Per default the subject is set to "FHEM"
        +
      • +
      • authfile
        + sets the authfile for the SSL connection to the SMTP host
        + the authfile is a simple textfile with the userid in line 1 and + the password in line 2.
        + Example:
        + 123user45
        + strenggeheim
        + It is a good behaviour to protect this data and put the file, for + example into the /etc directory and set the rights to 440 + (chmod 440 /etc/msgmailauthfile), so that not everyone could see the contents + of the file. FHEM must have access to this file to read the userid and password. +
        +
      • +
      • CR
        + set the option to write a carriage return at the end of the line. + CR could be set to 0 or 1, 1 enables this feature. + Per default this attribute is enabled
      • +
      • loglevel
      • +
      +
    + +

    LUXTRONIK2