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]; if ($v eq "delete_saved_states") { $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; } $hash->{STATE} = "OK"; return undef; } 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($ntfy->{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); my $change = $dev->{CHANGED}[$i]; my $position = index($change, ':'); if ($position == -1) { $key = "state"; $value = $keyValue[0]; } else { $key = substr($change, 0, $position); $value = substr($change, $position + 2, length($change)); } if ( ($stateFilter eq "" || $value =~ m/$stateFilter/) && (! $deviceStates->{$key} || !($deviceStates->{$key} eq $value)) && (!($value eq "")) ) { $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