diff --git a/fhem/contrib/99_gcmsend.pm b/fhem/contrib/99_gcmsend.pm new file mode 100644 index 000000000..c35c48e00 --- /dev/null +++ b/fhem/contrib/99_gcmsend.pm @@ -0,0 +1,230 @@ +package main; + +use HTTP::Request; +use LWP::UserAgent; +use IO::Socket::SSL; +use utf8; + +my @gets = ('dummy'); + +sub +gcmsend_Initialize($) +{ + my ($hash) = @_; + $hash->{DefFn} = "gcmsend_Define"; + $hash->{NotifyFn} = "gcmsend_notify"; + $hash->{SetFn} = "gcmsend_set"; + $hash->{AttrList} = "loglevel:0,1,2,3,4,5 regIds apiKey stateFilter"; +} + +sub +gcmsend_set { + my ($hash, @a) = @_; + my $v = @a[1]; + Log 3, $v; + if ($v eq "delete_saved_states") { + Log 3, $hash->{STATES}{'mat_halogen'}; + $hash->{STATES} = {}; + return "deleted"; + } else { + return "unknown set value, choose one of delete_saved_states"; + } +} + +sub +gcmsend_Define($$) +{ + my ($hash, $def) = @_; + + my @args = split("[ \t]+", $def); + + if (int(@args) < 1) + { + return "gcmsend_Define: too many arguments. Usage:\n" . + "define gcmsend"; + } + return "Invalid arguments. Usage: \n define gcmsend" if(int(@a) != 0); + + $hash->{STATE} = 'Initialized'; + + return undef; +} + +sub gcmsend_array_to_json(@) { + my (@array) = @_; + my $ret = ""; + + for (my $i = 0; $i < int(@array); $i++) { + if ($i != 0) { + $ret .= ","; + } + my $value = @array[$i]; + $ret .= ("\"" . $value . "\""); + } + + return "[" . $ret . "]"; +} + +sub gcmsend_message($$$) { + my ($hash, $deviceName, $changes) = @_; + my $name = $hash->{NAME}; + my $client = LWP::UserAgent->new(); + my $regIdsText = AttrVal($name, "regIds", ""); + my $apikey = AttrVal($name, "apiKey", ""); + my @registrationIds = split(/\|/, $regIdsText); + my $unixTtimestamp = time*1000; + + my $data = + "{" . + "\"registration_ids\":" . gcmsend_array_to_json(@registrationIds) . "," . + "\"data\": {" . + "\"deviceName\": \"$deviceName\"," . + "\"changes\":\"$changes\"" . + "\"source\":\"gcmsend_fhem\"" . + "}". + "}"; + + my $req = HTTP::Request->new(POST => "https://android.googleapis.com/gcm/send"); + $req->header(Authorization => 'key='.$apikey); + $req->header('Content-Type' => 'application/json; charset=UTF-8'); + $req->content($data); + + my $response = $client->request($req); + if (! $response->is_success) { + Log 3, "error during request: " . $response->status_line; + $hash->{STATE} = $response->status_line; + } elsif ($hash->{STATE} != "OK") { + $hash->{STATE} = "OK"; + } +} + +sub gcmsend_notify($$) +{ + my ($ntfy, $dev) = @_; + + my $name = $dev->{NAME}; + + return if(!$dev->{CHANGED}); # Some previous notify deleted the array. + + my $val = ""; + my $max = int(@{$dev->{CHANGED}}); + + my $key; + my $value; + + if (! $dev->{STATES}) { + $dev->{STATES} = {}; + } + + my $stateFilter = AttrVal($name, "stateFilter", ""); + + my $states = $ntfy->{STATES}; + if (!$states->{$name}) { + $states->{$name} = {}; + } + + my $deviceStates = $states->{$name}; + + my $count = 0; + for (my $i = 0; $i < $max; $i++) { + my @keyValue = split(":", $dev->{CHANGED}[$i]); + my $length = int($keyValue); + + + if ($length == 0) { + $key = "state"; + $value = $keyValue[0]; + } else { + $key = @keyValue[0]; + $value = @keyValue[1]; + } + + if ( + ($stateFilter != "" && $value =~ m/$stateFilter/) && + (! $deviceStates->{$key} || !($deviceStates->{$key} eq $value)) + ) { + $deviceStates->{$key} = $value; + if ($count != 0) { + $val .= "<|>"; + } + $count += 1; + $val .= "$key:$value"; + } + } + + if ($count > 0) { + gcmsend_message($ntfy, $name, $val); + } +} + +1; + +=pod +=begin html + + +

GCMSend

+ + +=end html +=cut + +