#!/usr/bin/perl # # SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (c) Rainer Gümpelein, TeilRad GmbH # #get lock event for last 20 minutes #cronjob interval 15 minutes #sudo su www-data -c "./src/scripts/Ilockit_cloud.pl shareedms-fr01 get_events" # #Ilockit GPS cloud # #4. Get a list of positions #fetch_ >> https://tracking.ilockit.bike/api/positions?from=2021-05-31T07:44:10Z&to=2021-06-06T07:44:10Z&deviceId=4272 #5. Get a list of Events #fetch_ >> https://tracking.ilockit.bike/api/reports/events?from=2021-05-31T07:44:10Z&to=2021-06-06T07:44:10Z&deviceId=4272 use vars qw($syshost); BEGIN { $syshost = $ARGV[0] || die; } use lib "/var/www/copri-bike/$syshost/src"; use strict; use warnings; use POSIX; use CGI; use Lib::Config; use JSON; use LWP::UserAgent; use DateTime; use Time::Piece; my $cf = new Config; use Mod::DBtank; use Data::Dumper; my $q = new CGI; my $dbt = new DBtank; my %varenv = $cf->envonline($syshost); my $lang = "de"; my $now_dt = strftime "%Y-%m-%d %H:%M:%S", localtime; my $api_file = "/var/www/copri4/shareeconf/apikeys.cfg"; my $aconf = Config::General->new($api_file); my %apikeyconf = $aconf->getall; #print "---> " . $apikeyconf{Ilockitcloud}->{username} . "\n"; my $ua = LWP::UserAgent->new; $ua->agent("sharee APIclient"); $ua->credentials( 'tracking.ilockit.bike:443', 'api', "$apikeyconf{Ilockitcloud}->{username}", "$apikeyconf{Ilockitcloud}->{passwd}"); my $json = JSON->new->allow_nonref; my $response_in = {}; my $dbh = ""; my $owner = 183; my $todo = $ARGV[1]; my $deviceId = $ARGV[2] || ""; open(FILE,">>$varenv{logdir}/Ilockit_cloud.log"); print FILE "\n\n*** $now_dt\n"; #my $endpoint = "https://tracking.ilockit.bike/api/commands"; #utc to localtime sub localizedtime { my $date = shift; $date =~ s/\..*$//; my $time = Time::Piece->strptime($date, "%Y-%m-%dT%H:%M:%S"); print FILE "localizedtime GMT alias Zulu: " . $time->datetime . "\n";#GMT alias Zulu $time = localtime($time->epoch);#epoch print FILE "localizedtime localized date time: " . $time->datetime . "\n";#localized date time return $time->datetime; } #print localizedtime("2021-06-11T11:58:09.000+0000") . " example\n"; #localtime to utc #my $now = strftime "%Y-%m-%dT%H:%M:%S", localtime; #utctime($now); sub utctime { my $date = shift; my $latency = shift || 0; $date =~ s/\..*$//; $date =~ s/\+\d+$//; print FILE "requested datetime: " . $date . "\n"; my $time = Time::Piece->strptime($date, "%Y-%m-%dT%H:%M:%S"); print FILE "localtime: " . $time->datetime . "\n";#localtime my $utc_epoch = $time->epoch; #$utc_epoch -= 2*60*60;# -2 std # #only -1 hour, because of deviceTime and serverTime differs #'deviceTime' => '2021-10-14T08:19:35.000+0000', #'serverTime' => '2021-10-14T07:19:37.000+0000', $utc_epoch -= 1*60*60;# -1 std $utc_epoch += $latency; $time = gmtime($utc_epoch);#epoch print FILE "utctime: " . $time->datetime . "\n";#utc zulu date time # return $time->datetime; } #get all device localy sub get_devicesONcontent_all { my $deviceId = shift; my $pref = { table => "content", fetch => "all", keyfield => "int13", template_id => "205", int13 => ">::0", }; my $record = $dbt->fetch_record($dbh,$pref); return $record; } #get one device localy in contenttranspos to check if bike is locked sub get_devicesONcontenttranspos { my $deviceId = shift; my $pref = { table => "contenttranspos", fetch => "one", int13 => "$deviceId", #int20 => "1",#locked }; my $record = $dbt->fetch_tablerecord($dbh,$pref); return $record; } #get one device localy sub get_devicesONcontent { my $deviceId = shift; my $pref = { table => "content", fetch => "one", template_id => "205", int13 => "$deviceId", }; my $record = $dbt->fetch_record($dbh,$pref); return $record; } #get and check if theft exist in contenttranspos not older than 1 day sub get_devicesONcontenttheftpos { my $key = shift; my $id = shift; my $pref = { table => "contenttheftpos", fetch => "one", #mtime => ">::(now() - interval '1 day')", $key => "$id", }; my $record = $dbt->fetch_tablerecord($dbh,$pref); return $record; } #per cronjob once a day to get and update content with cloud device id #sudo su www-data -c "./src/scripts/Ilockit_cloud.pl shareedms-fr01 get_devices" &get_devices if($todo eq "get_devices"); sub get_devices { my $endpoint = "https://tracking.ilockit.bike/api/devices"; my $rest = ""; my $ret_json = fetch_ilockit_cloud("","$endpoint",$rest); $response_in = decode_json($ret_json); print FILE "ilockit get_devices response_in:" . Dumper($response_in); #foreach my $result (@{ $response_in }) { # if($result->{id}){ # print $result->{id} . "\n"; # print $result->{name} . "\n"; # } #} my $pref = { table => "content", fetch => "all", keyfield => "barcode", template_id => "205", #int10 => "1",#1 = "available" }; my $record = $dbt->fetch_record($dbh,$pref); my $rows = 0; if(1==1 && ref($response_in) eq "ARRAY"){ foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){ foreach my $resp (@{ $response_in }) { #print "if($resp->{name} eq $record->{$id}->{txt18} && ($resp->{id} && $resp->{id} ne $record->{$id}->{int13}))\n"; if($resp->{name} eq $record->{$id}->{txt18} && ($resp->{id} && $resp->{id} ne $record->{$id}->{int13})){ my $update = { table => "content", mtime => "now()", owner => "$owner", int13 => "$resp->{id}", }; $rows = $dbt->update_record($dbh,$update,$record->{$id}); print FILE "update_record content.int13=$resp->{id}" . $rows . "\n"; } } } } }#end if($todo eq "get_devices"){ #sudo su www-data -c "./src/scripts/Ilockit_cloud.pl shareedms-fr01 get_events 6572 20" &get_events if($todo eq "get_events"); sub get_events { #1. select all devices on content my $record_cc = get_devicesONcontent_all(); my $today = DateTime->now( time_zone => "Europe/Berlin" ); $today .= "Z"; my $from_datetime = DateTime->now( time_zone => "Europe/Berlin" ); $from_datetime->subtract( days => 1 ); $from_datetime .= "Z"; my $endpoint = "https://tracking.ilockit.bike/api/reports/events"; #my $rest = "from=2021-05-31T07:44:10Z\&to=2021-06-06T07:44:10Z\&deviceId=4272"; #my $rest = "from=2021-06-11T07:44:10Z\&to=2021-06-11T12:44:10Z\&deviceId=$deviceId"; # #2. loope cloud foreach my $id (sort { $record_cc->{$a}->{barcode} <=> $record_cc->{$b}->{barcode} } keys (%$record_cc)){ my $rest = "from=$from_datetime\&to=$today\&deviceId=$record_cc->{$id}->{int13}"; my $ret_json = fetch_ilockit_cloud("","$endpoint",$rest); $response_in = decode_json($ret_json); print FILE "ilockit get_events response_in:" . Dumper($response_in); foreach my $resp (@{ $response_in }) { #if($record_cc->{$id}->{int13} eq $resp->{deviceId} && $resp->{type} eq "deviceOnline"){ if($record_cc->{$id}->{int13} && $record_cc->{$id}->{int13} eq $resp->{deviceId} && ref($resp->{attributes}) eq "HASH" && $resp->{attributes}->{statusCode} && $resp->{attributes}->{statusCode} eq "alarm"){ my $theft_record = get_devicesONcontenttheftpos("int01",$resp->{id}); print FILE "id: $resp->{id}\n"; print FILE "deviceId: $resp->{deviceId}\n"; print FILE "type: $resp->{type}\n"; print FILE "statusCode: $resp->{attributes}->{statusCode}\n"; print FILE "serverTime: $resp->{serverTime}\n\n"; if(!$theft_record->{c_id}){ my $serverTime = localizedtime($resp->{serverTime}); my $insert = { table => "contenttheftpos", cc_id => "$record_cc->{$id}->{c_id}", barcode => "$record_cc->{$id}->{barcode}", int04 => "$record_cc->{$id}->{int04}",#end station txt06 => "$record_cc->{$id}->{txt06}",#end gps txt18 => "$record_cc->{$id}->{txt18}", owner => $owner, mtime => "now()", int10 => "7",#theft alarm int01 => "$resp->{id}",#keeps id for event_type int13 => "$resp->{deviceId}", start_time => "$serverTime", end_time => "$serverTime", }; my $c_id = $dbt->insert_contentoid($dbh,$insert); print FILE "insert sub get_events:" . Dumper($insert); } } } } }#end if($todo eq "get_events"){ #sudo su www-data -c "./src/scripts/Ilockit_cloud.pl shareedms-fr01 get_positions 6572" #2021-10-27, cron disabled, unspecific and not only alarm &get_positions if($todo eq "get_positions"); sub get_positions { #1. select all devices on content my $record_cc = get_devicesONcontent_all(); my $today = DateTime->now( time_zone => "Europe/Berlin" ); $today .= "Z"; my $from_datetime = DateTime->now( time_zone => "Europe/Berlin" ); $from_datetime->subtract( days => 1 ); $from_datetime .= "Z"; my $endpoint = "https://tracking.ilockit.bike/api/positions"; #my $rest = "from=2021-06-11T07:44:10Z\&to=2021-06-11T12:44:10Z\&deviceId=$deviceId" if($deviceId); #my $ret_json = fetch_ilockit_cloud("","$endpoint",$rest); #$response_in = decode_json($ret_json); #print Dumper($response_in); #2. loope cloud foreach my $id (sort { $record_cc->{$a}->{barcode} <=> $record_cc->{$b}->{barcode} } keys (%$record_cc)){ my $ctpos = get_devicesONcontenttranspos("$record_cc->{$id}->{int13}"); if($ctpos->{int20} == 1){#if locked then get position in range of end_time to now print FILE "record_pos.int13: $ctpos->{int13} --> lock_state:$ctpos->{int20}| end_time:$ctpos->{end_time}\n"; #get only positions until smartlock end_time is locked if($ctpos->{int13} && $ctpos->{end_time} =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/){ $ctpos->{end_time} =~ s/\..*$//; my $end_time = $ctpos->{end_time}; $end_time =~ s/\s/T/; $from_datetime = utctime($end_time,"0"); $from_datetime .= "Z"; #keep in mind, api-from maybe deviceTime (end_time-1) and position timestamp is serverTime+2 my $rest = "from=$from_datetime\&to=$today\&deviceId=$record_cc->{$id}->{int13}"; my $ret_json = fetch_ilockit_cloud("","$endpoint",$rest); $response_in = decode_json($ret_json); print FILE "ilockit get_positions response_in:" . Dumper($response_in); foreach my $resp (@{ $response_in }) { if($record_cc->{$id}->{int13} eq $resp->{deviceId}){ my $theft_record = get_devicesONcontenttheftpos("int02",$resp->{id}); print FILE "id: $resp->{id}\n"; print FILE "deviceId: $resp->{deviceId}\n"; print FILE "serverTime: $resp->{serverTime}\n\n"; if(!$theft_record->{c_id}){ my $serverTime = localizedtime($resp->{serverTime}); my $insert = { table => "contenttheftpos", cc_id => "$record_cc->{$id}->{c_id}", barcode => "$record_cc->{$id}->{barcode}", txt06 => "$resp->{latitude}, $resp->{longitude}", owner => $owner, mtime => "now()", int10 => "8",#gps position int02 => "$resp->{id}",#keeps id for event_type int07 => "$resp->{speed}", int08 => "$resp->{attributes}->{distance}", int09 => "$resp->{attributes}->{totalDistance}", int13 => "$resp->{deviceId}", start_time => "$serverTime", end_time => "$serverTime", }; my $c_id = $dbt->insert_contentoid($dbh,$insert); print FILE "insert sub get_positions:" . Dumper($insert); } } } } } } }#end if($todo eq "get_positions"){ #ilockit http request sub fetch_ilockit_cloud { my $self = shift; my $ilockitserver = shift || ""; my $rest = shift || ""; my $ilockit_request = "$ilockitserver?$rest"; print FILE "fetch_ >> " . $ilockit_request . "\n"; my $req = HTTP::Request->new(GET => "$ilockit_request"); #$req->content_type('application/x-www-form-urlencoded'); $req->content_type('application/json'); $req->content($rest); my $res = $ua->request($req); if ($res->is_success) { #print $res->content; return $res->content; print $res->status_line, "\n"; }else { print $res->status_line, "\n"; } } close(FILE);