| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- # $Id: 37_NotifyAndroidTV.pm 16138 2018-02-09 20:36:36Z justme1968 $
- package main;
- use strict;
- use warnings;
- use HttpUtils;
- use vars qw($FW_icondir);
- use Data::Dumper;
- my $options = { position => { 'bottom-right' => 0,
- 'bottom-left' => 1,
- 'top-right' => 2,
- 'top-left' => 3,
- 'center' => 4,
- },
- width => { 'default' => 0,
- 'narrow' => 1,
- 'small' => 2,
- 'wide' => 3,
- 'extrawide' => 4,
- },
- transparency => { 'default' => 0,
- '0%' => 1,
- '25%' => 2,
- '50%' => 3,
- '75%' => 4,
- '100%' => 5,
- },
- interrupt => { 'true' => 1,
- 'false' => 0,
- },
- bkgcolor => { 'grey' => '#607d8b',
- 'black' => '#000000',
- 'indigo' => '#303F9F',
- 'green' => '#4CAF50',
- 'red' => '#F44336',
- 'cyan' => '#00BCD4',
- 'teal' => '#009688',
- 'amber' => '#FFC107',
- 'pink' => '#E91E63',
- },
- type => { 'complete' => 0,
- 'titleonly' => 1,
- 'nameonly' => 2,
- 'icononly' => 3,
- 'noimage' => 4,
- 'short' => 5,
- },
- duration => undef,
- offset => undef,
- offsety => undef,
- icon => undef,
- image => undef,
- title => undef,
- imageurl => undef,
- };
- sub
- NotifyAndroidTV_Initialize($)
- {
- my ($hash) = @_;
- $hash->{DefFn} = "NotifyAndroidTV_Define";
- $hash->{UndefFn} = "NotifyAndroidTV_Undefine";
- $hash->{SetFn} = "NotifyAndroidTV_Set";
- $hash->{AttrFn} = "NotifyAndroidTV_Attr";
- #$hash->{AttrList} = "defaultIcon";
- foreach my $option (keys %{$options}) {
- $hash->{AttrList} .= ' ' if( $hash->{AttrList} );
- #$hash->{AttrList} .= "NotifyAndroidTV#$option";
- $hash->{AttrList} .= "default". ucfirst $option;
- if( $options->{$option} ) {
- $hash->{AttrList} .= ":select,". join( ',', sort keys %{$options->{$option}} )
- }
- }
- #delete $hash->{AttrList};
- }
- #####################################
- sub
- NotifyAndroidTV_Define($$)
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- return "Usage: define <name> NotifyAndroidTV <host>" if(@a != 3);
- my $name = $a[0];
- my $host = $a[2];
- $hash->{NAME} = $name;
- $hash->{host} = $host;
- $hash->{STATE} = 'INITIALIZED';
- return undef;
- }
- sub
- NotifyAndroidTV_Undefine($$)
- {
- my ($hash, $arg) = @_;
- return undef;
- }
- sub
- NotifyAndroidTV_addFormField($$;$)
- {
- my ($name,$data,$extra) = @_;
- return "--boundary\r\n".
- "Content-Disposition: form-data; name=\"$name\"\r\n".
- ($extra?"$extra\r\n":"").
- "\r\n".
- $data."\r\n"
- }
- sub
- NotifyAndroidTV_parseHttpAnswer($$$)
- {
- my ($param, $err, $data) = @_;
- my $hash = $param->{hash};
- my $name = $hash->{NAME};
- if( $err ) {
- Log3 $name, 2, "NotifyAndroidTV ($name) - got error while sending notificaton $err";
- readingsSingleUpdate($hash,"lastError", $err, 1);
- if( $param->{cl} && $param->{cl}{canAsyncOutput} ) {
- asyncOutput( $param->{cl}, "got error while sending notification $err\n" );
- }
- return;
- }
- }
- sub
- NotifyAndroidTV_Set($$@)
- {
- my ($hash, $name, $cmd, @params) = @_;
- $hash->{".triggerUsed"} = 1;
- my $list = 'msg';
- if( $cmd && ($cmd eq 'msg' || $cmd eq 'notify') ) {
- my ($param_a, $param_h) = parseParams(\@params);
- my $txt = join( ' ', @{$param_a} );
- $txt =~ s/\n/<br>/g;
- my $error;
- foreach my $option (keys %{$param_h}) {
- if( $options->{$option} ) {
- if( defined( $options->{$option}{$param_h->{$option}}) ) {
- $param_h->{$option} = $options->{$option}{$param_h->{$option}};
- } elsif( grep {$_==$param_h->{$option}} values %{$options->{$option}} ) {
- $param_h->{$option} = $param_h->{$option};
- } else {
- $param_h->{$option} = undef;
- }
- if( !defined($param_h->{$option}) ) {
- $error .= "\n";
- $error .= "$option value must be one of: ". join( ' ', sort keys %{$options->{$option}} );
- }
- }
- }
- return "error: $error" if( $error );
- foreach my $option (keys %{$options}) {
- if( !defined($param_h->{$option}) ) {
- if( my $default = AttrVal($name, "default". ucfirst $option, undef) ) {
- $param_h->{$option} = $default;
- }
- }
- }
- $param_h->{offset} = 0 if( !$param_h->{offset} );
- $param_h->{offsety} = 0 if( !$param_h->{offsety} );
- $param_h->{transparency} = 0 if( !$param_h->{transparency} );
- if( $param_h->{duration} && $param_h->{duration} eq 'unlimited' ) {
- $param_h->{duration} = 15;
- $param_h->{interrupt} = 1;
- }
- if( $txt && $txt eq '?' ) {
- my $usage = "usage: set $name msg";
- foreach my $option (sort keys %{$options}) {
- if( $options->{$option} ) {
- $usage .= " [$option=". join( '|', sort keys %{$options->{$option}} ). "]";
- } else {
- $usage .= " [$option=<$option>]";
- }
- }
- $usage .= " <message>";
- return $usage;
- }
- $param_h->{icon} = 'fhemicon.png' if( !$param_h->{icon} );
- $param_h->{icon} .= ".png" if( $param_h->{icon} !~ '\.' );
- $param_h->{icon} = "$FW_icondir/default/$param_h->{icon}" if( $param_h->{icon} !~ '^/' );
- Log3 $name, 5, "$name: using icon $param_h->{icon}";
- my $icon;
- local( *FH ) ;
- if( open( FH, $param_h->{icon} ) ) {
- $icon = do { local( $/ ) ; <FH> } ;
- close( FH );
- }
- return "icon not found: $param_h->{icon}" if( !$icon );
- delete $param_h->{icon};
- my $image;
- if( $param_h->{image} && $param_h->{image} =~ m/^{.*}$/ ) {
- $image = eval $param_h->{image};
- if( $@ ) {
- Log3 $name, 5, "$name: $@";
- return $@;
- }
- return "empty image returned from perl code" if(!$image);
- } elsif( $param_h->{image} ) {
- #$param_h->{image} .= ".jpg" if( $param_h->{image} !~ '\.' );
- #$param_h->{image} = "$FW_icondir/default/$param_h->{image}" if( $param_h->{image} !~ '^/' );
- Log3 $name, 5, "$name: using image $param_h->{image}";
- local( *FH ) ;
- if( open( FH, $param_h->{image} ) ) {
- $image = do { local( $/ ) ; <FH> } ;
- close(FH);
- }
- return "image not found: $param_h->{image}" if( !$image );
- delete $param_h->{image};
- }
- my $param;
- $param->{url} = "http://$hash->{host}:7676/";
- $param->{callback} = \&NotifyAndroidTV_parseHttpAnswer;
- $param->{hash} = $hash;
- $param->{cl} = $hash->{CL} if( ref($hash->{CL}) eq 'HASH' );
- $param->{noshutdown} = 1;
- $param->{timeout} = 5;
- $param->{loglevel} = 5;
- $param->{method} = "POST";
- $param->{header} = "Content-Type: multipart/form-data; boundary=boundary";
- $param->{data} .= NotifyAndroidTV_addFormField('msg', $txt);
- foreach my $option (keys %{$param_h}) {
- $param->{data} .= NotifyAndroidTV_addFormField($option, $param_h->{$option})
- }
- Log3 $name, 5, $param->{data};
- $param->{data} .= NotifyAndroidTV_addFormField('filename', $icon, "filename=\"fhemicon.png\"\r\nContent-Type: application/octet-stream");
- $param->{data} .= NotifyAndroidTV_addFormField('filename2', $image, "filename=\"image.png\"\r\nContent-Type: application/octet-stream") if( $image );
- $param->{data} .= "--boundary--";
- Log3 $name, 4, "NotifyAndroidTV ($name) - send notification ";
- #Log3 $name, 5, $param->{data};
- my ($err, undef) = HttpUtils_NonblockingGet($param);
- Log3 $name, 5, "NotifyAndroidTV ($name) - received http response code ".$param->{code} if(exists($param->{code}));
- if ($err) {
- Log3 $name, 3, "NotifyAndroidTV ($name) - got error while sending notificaton $err";
- return "got error while sending notification $err";
- }
- return;
- }
- $list =~ s/ $//;
- return "Unknown argument $cmd, choose one of $list";
- }
- sub
- NotifyAndroidTV_Get($$@)
- {
- my ($hash, $name, $cmd, @params) = @_;
- my $list = '';
- $list =~ s/ $//;
- return "Unknown argument $cmd, choose one of $list";
- }
- sub
- NotifyAndroidTV_Attr($$$)
- {
- my ($cmd, $name, $attrName, $attrVal) = @_;
- my $orig = $attrVal;
- $attrVal = int($attrVal) if($attrName eq "interval");
- my $hash = $defs{$name};
- if( $attrName eq 'disable' ) {
- }
- if( $cmd eq "set" ) {
- if( $attrName =~ m/default(.*)/ ) {
- my $option = lcfirst $1;
- if($options->{$option} && !defined($options->{$option}{$attrVal})) {
- return "$attrName value must be one of: ". join( ' ', sort keys %{$options->{$option}} );
- }
- }
- }
- return;
- }
- 1;
- =pod
- =item summary Notifications for Android TV/Fire TV module
- =item summary_DE Notifications for Android TV/Fire TV Modul
- =begin html
- <a name="NotifyAndroidTV"></a>
- <h3>NotifyAndroidTV</h3>
- <ul>
- This module allows you to send notifications to the
- <a href ='https://play.google.com/store/apps/details?id=de.cyberdream.androidtv.notifications.google'>
- Notifications for Android TV</a> and
- <a href ='https://www.amazon.de/Christian-Fees-Notifications-for-Fire/dp/B00OESCXEK'>
- Notifications for Fire TV</a> apps.
- <br><br>
- <code>set <name> msg bkgcolor=amber interrupt=true position=top-left transparency=0% duration=2 offset=10 icon=fhemicon title="der titel" das ist ein test</code>
- <br><br>
- <a name="NotifyAndroidTV_Define"></a>
- <b>Define</b>
- <ul>
- <code>define <name> NotifyAndroidTV <host></code>
- <br><br>
- </ul>
- <a name="NotifyAndroidTV_Set"></a>
- <b>Set</b>
- <ul>
- <li>msg [options] <message><br>
- possible options are: bkgcolor, interrupt, position, transparency, duration, offset, offsety, width, type, icon, image, title, imageurl. use <code>set <name> notify</code> to see valid values.<br>
- <code>set nb msg ?</code> shows a help text<br>
- it is better to use imageurl instad of image as it is non blocking!<br>
- image can be given as <code>image={<perlCode>}</code></li>
- </ul><br>
- <a name="NotifyAndroidTV_Get"></a>
- <b>Get</b>
- <ul>none
- </ul><br>
- <a name="NotifyAndroidTV_Attr"></a>
- <b>Attr</b>
- <ul>none
- </ul>
- </ul><br>
- =end html
- =cut
|