2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

75_MSG: add support for parseParams

git-svn-id: https://svn.fhem.de/fhem/trunk@13798 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
jpawlowski 2017-03-25 18:31:27 +00:00
parent 1aa16f2d3c
commit aa77dc8640
2 changed files with 176 additions and 69 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # 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. # Do not insert empty lines here, update check depends on it.
- feature: 75_MSG: add support for parseParams
- feature: 10_RESIDENTS: add new durTimer* readings, similar to - feature: 10_RESIDENTS: add new durTimer* readings, similar to
ROOMMATE/GUEST ROOMMATE/GUEST
- update: 49_SSCAM new version 1.42, minor fixes - update: 49_SSCAM new version 1.42, minor fixes

View File

@ -23,6 +23,13 @@
# along with fhem. If not, see <http://www.gnu.org/licenses/>. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
#
#TODO
# - advanced options as attribute in JSON or parseParams format
# - allow ? to recipients to soft-fail if they are not configured or not
# reachable via msg
# - implement default messages in RESIDENTS using msg command
#
package main; package main;
use strict; use strict;
@ -30,8 +37,6 @@ use warnings;
use Time::HiRes qw(time); use Time::HiRes qw(time);
use Data::Dumper; use Data::Dumper;
no if $] >= 5.017011, warnings => 'experimental';
sub CommandMsg($$;$$); sub CommandMsg($$;$$);
######################################## ########################################
@ -77,37 +82,37 @@ sub CommandMsg($$;$$) {
# default settings # default settings
my $cmdSchema = msgSchema::get(); my $cmdSchema = msgSchema::get();
my $settings = { my $settings = {
'audio' => { audio => {
'typeEscalation' => { typeEscalation => {
'gwUnavailable' => 'text', gwUnavailable => 'text',
'emergency' => 'text', emergency => 'text',
'residentGone' => 'text', residentGone => 'text',
'residentAbsent' => 'text', residentAbsent => 'text',
}, },
}, },
'light' => { light => {
'typeEscalation' => { typeEscalation => {
'gwUnavailable' => 'audio', gwUnavailable => 'audio',
'emergency' => 'audio', emergency => 'audio',
'residentGone' => 'audio', residentGone => 'audio',
'residentAbsent' => 'audio', residentAbsent => 'audio',
}, },
}, },
'push' => { push => {
'typeEscalation' => { typeEscalation => {
'gwUnavailable' => 'mail', gwUnavailable => 'mail',
'emergency' => 'mail', emergency => 'mail',
}, },
}, },
'screen' => { screen => {
'typeEscalation' => { typeEscalation => {
'gwUnavailable' => 'light', gwUnavailable => 'light',
'emergency' => 'light', emergency => 'light',
'residentGone' => 'light', residentGone => 'light',
'residentAbsent' => 'light', residentAbsent => 'light',
}, },
}, },
}; };
@ -116,16 +121,47 @@ sub CommandMsg($$;$$) {
### extract message details ### extract message details
### ###
my ( $msgA, $params ) = parseParams($msg);
# only use output from parseParams when
# parameters where found
if ( ref($params) eq "HASH" && keys %$params ) {
if ( scalar @$msgA > 0 ) {
$msg = join( " ", @$msgA );
}
else {
$msg = "";
}
}
if ( defined( $params->{msgText} ) ) {
Log3 $globalDevName, 5,
"msg: Adding message text from given user parameters";
$msg .= " " unless ( $msg eq "" );
$msg .= $params->{msgText};
delete $params->{msgText};
}
return $return
. "Usage: msg [<type>] [<\@device>|<e-mail address>] [<priority>] [|<title>|] <message>"
if ( $msg =~ m/^[\s\t\n ]*$/ );
Log3 $globalDevName, 5, "msg: Extracted user parameters\n" . Dumper($params)
if ( ref($params) eq "HASH" && keys %$params );
my $types = ""; my $types = "";
my $recipients = ""; my $recipients = "";
my $priority = ""; my $priority = "";
my $title = "-"; my $title = "-";
my $advanced = "";
my $priorityCat = ""; my $priorityCat = "";
# check for message types # check for message types
if ( $msg =~ if ( $params->{msgType} ) {
Log3 $globalDevName, 5, "msg: given types=$params->{msgType}";
$types = $params->{msgType};
delete $params->{msgType};
}
elsif ( $msg =~
s/^[\s\t]*([a-z,]*!?(screen|light|audio|text|push|mail)[a-z,!|]*)[\s\t]+// s/^[\s\t]*([a-z,]*!?(screen|light|audio|text|push|mail)[a-z,!|]*)[\s\t]+//
) )
{ {
@ -135,7 +171,13 @@ s/^[\s\t]*([a-z,]*!?(screen|light|audio|text|push|mail)[a-z,!|]*)[\s\t]+//
# programatic exception: # programatic exception:
# e.g. recipients were given automatically from empty readings # e.g. recipients were given automatically from empty readings
if ( $msg =~ s/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([,\-:|]+)))[\s\t]+// ) { if (
$msg =~ s/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([,\-:|]+)))[\s\t]+//
|| ( $params->{msgRcpt}
&& $params->{msgRcpt} =~
m/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([,\-:|]+)))[\s\t]+/ )
)
{
Log3 $globalDevName, 4, Log3 $globalDevName, 4,
"msg: message won't be sent - recipient '$1' contains special" "msg: message won't be sent - recipient '$1' contains special"
. " characters like ',-:|' or behind the @ character is simply" . " characters like ',-:|' or behind the @ character is simply"
@ -147,7 +189,12 @@ s/^[\s\t]*([a-z,]*!?(screen|light|audio|text|push|mail)[a-z,!|]*)[\s\t]+//
} }
# check for given recipients # check for given recipients
if ( $msg =~ if ( $params->{msgRcpt} ) {
Log3 $globalDevName, 5, "msg: given recipient=$params->{msgRcpt}";
$recipients = $params->{msgRcpt};
delete $params->{msgRcpt};
}
elsif ( $msg =~
s/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([%+a-z0-9A-Z.-]+))[\w,@.!|:]*)[\s\t]+// s/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([%+a-z0-9A-Z.-]+))[\w,@.!|:]*)[\s\t]+//
) )
{ {
@ -156,18 +203,28 @@ s/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([%+a-z0-9A-Z.-]+))[\w,@.!|:]*)[\s\t]+//
} }
# check for given priority # check for given priority
if ( $msg =~ s/^[\s\t]*([-+]{0,1}\d+[.\d]*)[\s\t]*// ) { if ( defined( $params->{msgPrio} ) ) {
Log3 $globalDevName, 5, "msg: given priority=$params->{msgPrio}";
$priority = $params->{msgPrio};
delete $params->{msgPrio};
}
elsif ( $msg =~ s/^[\s\t]*([-+]{0,1}\d+[.\d]*)[\s\t]*// ) {
Log3 $globalDevName, 5, "msg: found priority=$1"; Log3 $globalDevName, 5, "msg: found priority=$1";
$priority = $1; $priority = $1;
} }
# check for given message title # check for given message title
if ( $msg =~ s/^[\s\t]*\|(.*?)\|[\s\t]*// ) { if ( defined( $params->{msgTitle} ) ) {
Log3 $globalDevName, 5, "msg: given title=$params->{msgTitle}";
$title = $params->{msgTitle};
delete $params->{msgTitle};
}
elsif ( $msg =~ s/^[\s\t]*\|(.*?)\|[\s\t]*// ) {
Log3 $globalDevName, 5, "msg: found title=$1"; Log3 $globalDevName, 5, "msg: found title=$1";
$title = $1; $title = $1;
} }
# check for advanced options # check for user parameters (DEPRECATED / legacy compatibility only)
if ( $msg =~ s/[\s\t]*O(\[\{.*\}\])[\s\t]*$// ) { if ( $msg =~ s/[\s\t]*O(\[\{.*\}\])[\s\t]*$// ) {
Log3 $globalDevName, 5, "msg: found options=$1"; Log3 $globalDevName, 5, "msg: found options=$1";
@ -177,21 +234,33 @@ s/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([%+a-z0-9A-Z.-]+))[\w,@.!|:]*)[\s\t]+//
require JSON; require JSON;
import JSON qw( decode_json ); import JSON qw( decode_json );
}; };
if ( !$@ ) { if ($@) {
eval '$advanced = decode_json( Encode::encode_utf8($1) ); 1';
if ( !$@ ) {
Log3 $globalDevName, 5,
"msg: Decoded advanced options\n" . Dumper($advanced);
}
else {
Log3 $globalDevName, 5,
"msg: Error decoding JSON for advanced options";
$advanced = "";
}
}
else {
Log3 $globalDevName, 3, Log3 $globalDevName, 3,
"msg: To use advanced options, please install Perl JSON."; "msg: To use user parameters in message text, please install Perl JSON.";
}
else {
my $o;
eval '$o = decode_json( Encode::encode_utf8($1) ); 1';
if ($@) {
Log3 $globalDevName, 5,
"msg: Error decoding JSON for user parameters: $@";
}
elsif ( ref($o) eq "ARRAY" ) {
for my $item (@$o) {
next unless ( ref($item) eq "HASH" );
for my $key ( keys(%$item) ) {
next if ( ref( $item->{$key} ) );
my $val = $item->{$key};
$params->{$key} = $item->{$key}
unless ( $params->{$key} );
}
}
Log3 $globalDevName, 5,
"msg: Decoded user parameters\n" . Dumper($params)
if ($params);
}
} }
} }
@ -243,7 +312,7 @@ s/^[\s\t]*([!]?(([A-Za-z0-9%+._-])*@([%+a-z0-9A-Z.-]+))[\w,@.!|:]*)[\s\t]+//
# check for correct type # check for correct type
my @msgCmds = my @msgCmds =
( "screen", "light", "audio", "text", "push", "mail" ); ( "screen", "light", "audio", "text", "push", "mail" );
if ( !( $type[$i] ~~ @msgCmds ) ) { if ( !grep { $type[$i] eq $_ } @msgCmds ) {
$return .= "Unknown message type $type[$i]\n"; $return .= "Unknown message type $type[$i]\n";
next; next;
} }
@ -988,8 +1057,8 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$forwarded .= "," $forwarded .= ","
if ( $forwarded ne "" ); if ( $forwarded ne "" );
$forwarded .= "text>push+mail"; $forwarded .= "text>push+mail";
push @type, "push" if !( "push" ~~ @type ); push @type, "push" if !grep { "push" eq $_ } @type;
push @type, "mail" if !( "mail" ~~ @type ); push @type, "mail" if !grep { "mail" eq $_ } @type;
} }
elsif ($loopPriority >= $prioThresTextEmg elsif ($loopPriority >= $prioThresTextEmg
&& $routes{push} == 1 && $routes{push} == 1
@ -1000,7 +1069,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$forwarded .= "," $forwarded .= ","
if ( $forwarded ne "" ); if ( $forwarded ne "" );
$forwarded .= "text>push"; $forwarded .= "text>push";
push @type, "push" if !( "push" ~~ @type ); push @type, "push" if !grep { "push" eq $_ } @type;
} }
elsif ($loopPriority >= $prioThresTextEmg elsif ($loopPriority >= $prioThresTextEmg
&& $routes{push} == 0 && $routes{push} == 0
@ -1011,7 +1080,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$forwarded .= "," $forwarded .= ","
if ( $forwarded ne "" ); if ( $forwarded ne "" );
$forwarded .= "text>mail"; $forwarded .= "text>mail";
push @type, "mail" if !( "mail" ~~ @type ); push @type, "mail" if !grep { "mail" eq $_ } @type;
} }
elsif ($loopPriority >= $prioThresTextNormal elsif ($loopPriority >= $prioThresTextNormal
&& $routes{push} == 1 ) && $routes{push} == 1 )
@ -1021,7 +1090,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$forwarded .= "," $forwarded .= ","
if ( $forwarded ne "" ); if ( $forwarded ne "" );
$forwarded .= "text>push"; $forwarded .= "text>push";
push @type, "push" if !( "push" ~~ @type ); push @type, "push" if !grep { "push" eq $_ } @type;
} }
elsif ($loopPriority >= $prioThresTextNormal elsif ($loopPriority >= $prioThresTextNormal
&& $routes{mail} == 1 ) && $routes{mail} == 1 )
@ -1031,7 +1100,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$forwarded .= "," $forwarded .= ","
if ( $forwarded ne "" ); if ( $forwarded ne "" );
$forwarded .= "text>mail"; $forwarded .= "text>mail";
push @type, "mail" if !( "mail" ~~ @type ); push @type, "mail" if !grep { "mail" eq $_ } @type;
} }
elsif ( $routes{mail} == 1 ) { elsif ( $routes{mail} == 1 ) {
Log3 $logDevice, 4, Log3 $logDevice, 4,
@ -1039,7 +1108,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$forwarded .= "," $forwarded .= ","
if ( $forwarded ne "" ); if ( $forwarded ne "" );
$forwarded .= "text>mail"; $forwarded .= "text>mail";
push @type, "mail" if !( "mail" ~~ @type ); push @type, "mail" if !grep { "mail" eq $_ } @type;
} }
elsif ( $routes{push} == 1 ) { elsif ( $routes{push} == 1 ) {
Log3 $logDevice, 4, Log3 $logDevice, 4,
@ -1047,7 +1116,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$forwarded .= "," $forwarded .= ","
if ( $forwarded ne "" ); if ( $forwarded ne "" );
$forwarded .= "text>push"; $forwarded .= "text>push";
push @type, "push" if !( "push" ~~ @type ); push @type, "push" if !grep { "push" eq $_ } @type;
} }
# FATAL ERROR: routing decision failed # FATAL ERROR: routing decision failed
@ -1961,17 +2030,19 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
$cmd =~ s/%TERMINAL%/$termRecipient/gi $cmd =~ s/%TERMINAL%/$termRecipient/gi
if ( $termRecipient ne "" ); if ( $termRecipient ne "" );
# advanced options from message # user parameters from message
if ( ref($advanced) eq "ARRAY" ) { if ( ref($params) eq "HASH" ) {
for my $item (@$advanced) { for my $key ( keys %$params ) {
for my $key ( keys(%$item) ) { next if ( ref( $params->{$key} ) );
my $val = $item->{$key}; my $val = $params->{$key};
$cmd =~ s/%$key%/$val/gi; $cmd =~ s/%$key%/$val/gi;
} $cmd =~ s/\$$key/$val/g;
Log3 $logDevice, 5,
"msg $device: User parameters: replacing %$key% and \$$key by '$val'";
} }
} }
# advanced options from command schema hash # user parameters from command schema hash
if ( if (
$priorityCat ne "" $priorityCat ne ""
&& defined( && defined(
@ -1988,6 +2059,9 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
for my $key ( keys(%$item) ) { for my $key ( keys(%$item) ) {
my $val = $item->{$key}; my $val = $item->{$key};
$cmd =~ s/%$key%/$val/gi; $cmd =~ s/%$key%/$val/gi;
$cmd =~ s/\$$key/$val/g;
Log3 $logDevice, 5,
"msg $device: msgSchema: replacing %$key% and \$$key by '$val'";
} }
} }
@ -2008,6 +2082,9 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
for my $key ( keys(%$item) ) { for my $key ( keys(%$item) ) {
my $val = $item->{$key}; my $val = $item->{$key};
$cmd =~ s/%$key%/$val/gi; $cmd =~ s/%$key%/$val/gi;
$cmd =~ s/\$$key/$val/g;
Log3 $logDevice, 5,
"msg $device: msgSchema: replacing %$key% and \$$key by '$val'";
} }
} }
@ -2032,6 +2109,35 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
unless ($err); unless ($err);
} }
# add user parameters
# if gateway supports parseParams
my $gatewayDevType =
defined( $defs{$gatewayDev}{TYPE} )
? $defs{$gatewayDev}{TYPE}
: undef;
if (
ref($params) eq "HASH"
&& (
$modules{$gatewayDevType}->{parseParams}
|| $modules{$gatewayDevType}
->{'.msgParams'}{parseParams} )
)
{
Log3 $logDevice, 5,
"msg $device: parseParams support: Handing over user parameters to other device";
my ( $a, $h ) = parseParams($cmd);
while ( ( my $key, my $value ) =
each %$params )
{
$key =~ s/^$gatewayDevType\_//;
$cmd .= " $key='$value'"
if ( !defined( $h->{$key} )
|| $h->{$key} =~ m/^[\s\t\n ]*$/ );
}
}
# run command # run command
if ($replaceError) { if ($replaceError) {
$error = 2; $error = 2;
@ -2343,7 +2449,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
# if no gateway device for this type was available # if no gateway device for this type was available
if ( $msgSentDev == 0 if ( $msgSentDev == 0
&& $fw_gwUnavailable ne "" && $fw_gwUnavailable ne ""
&& !( $fw_gwUnavailable ~~ @type ) && !grep { $fw_gwUnavailable eq $_ } @type
&& $routes{$fw_gwUnavailable} == 1 ) && $routes{$fw_gwUnavailable} == 1 )
{ {
Log3 $logDevice, 4, Log3 $logDevice, 4,
@ -2361,7 +2467,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
# if emergency priority # if emergency priority
if ( $loopPriority >= $msgFwPrioEmergency if ( $loopPriority >= $msgFwPrioEmergency
&& $fw_emergency ne "" && $fw_emergency ne ""
&& !( $fw_emergency ~~ @type ) && !grep { $fw_emergency eq $_ } @type
&& $routes{$fw_emergency} == 1 ) && $routes{$fw_emergency} == 1 )
{ {
Log3 $logDevice, 4, Log3 $logDevice, 4,
@ -2380,7 +2486,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
if ( $residentDevPresence eq "absent" if ( $residentDevPresence eq "absent"
&& $loopPriority >= $msgFwPrioGone && $loopPriority >= $msgFwPrioGone
&& $fw_residentGone ne "" && $fw_residentGone ne ""
&& !( $fw_residentGone ~~ @type ) && !grep { $fw_residentGone eq $_ } @type
&& $routes{$fw_residentGone} == 1 ) && $routes{$fw_residentGone} == 1 )
{ {
Log3 $logDevice, 4, Log3 $logDevice, 4,
@ -2400,7 +2506,7 @@ m/^(absent|disappeared|unauthorized|disconnected|unreachable)$/i
if ( $residentDevState eq "absent" if ( $residentDevState eq "absent"
&& $loopPriority >= $msgFwPrioAbsent && $loopPriority >= $msgFwPrioAbsent
&& $fw_residentAbsent ne "" && $fw_residentAbsent ne ""
&& !( $fw_residentAbsent ~~ @type ) && !grep { $fw_residentAbsent eq $_ } @type
&& $routes{$fw_residentAbsent} == 1 ) && $routes{$fw_residentAbsent} == 1 )
{ {
Log3 $logDevice, 4, Log3 $logDevice, 4,