#!/usr/bin/perl # # SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (c) Rainer Gümpelein, TeilRad GmbH # # #sudo su www-data -c "./src/scripts/Ilockit_cloud.pl shareedms-fr01 get_events 95" # #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 $owner = 183; my $todo = $ARGV[1]; my $groupId = $ARGV[2] || ""; my $deviceId = $ARGV[3] || ""; open(FILE,">>$varenv{logdir}/Ilockit_cloud.log"); print FILE "\n\n*** $now_dt\n"; #2022-11-08 looping and rest changed to groupId and limit (max 10000) #get Ilockit events by groupId my $endpoint = "https://tracking.ilockit.bike/api/reports/events"; my $rest = "groupId=$groupId\&limit=100"; my $ret_json = fetch_ilockit_cloud("","$endpoint",$rest); my $response_in = {}; $response_in = decode_json($ret_json); print FILE "Ilockit $todo response_in:" . Dumper($response_in); #main #loop operators DB while (my ($key, $value) = each %{ $dbt->{operator} }) { if($value->{database}->{dbname} && $value->{hwtype} ne "sigo"){ print FILE "\nON----------$value->{database}->{dbname}---$now_dt | $todo\n"; my $rows = 0; my $sharee_operator = $value->{database}->{dbname}; my $dbh = ""; $dbh = $dbt->dbconnect_extern($sharee_operator); #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($dbh) if($todo eq "get_devices"); #sudo su www-data -c "./src/scripts/Ilockit_cloud.pl shareedms-fr01 get_events 95" #in cronjob disabled &get_events($dbh,$response_in) if($todo eq "get_events"); #sudo su www-data -c "./src/scripts/Ilockit_cloud.pl shareedms-fr01 get_positions 6572" &get_positions($dbh) if($todo eq "get_positions"); } } #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; # #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 -= 2*60*60;# -2 std (Sommerzeit) $utc_epoch -= 1*60*60;# -1 std (Winterzeit) $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 $dbh = shift; my $serialnr = shift || ""; my $pref = { table => "content", fetch => "all", keyfield => "int13", template_id => "205", int13 => ">::0", }; $pref->{txt22} = "ilike::$serialnr%" if($serialnr); my $record = $dbt->fetch_record($dbh,$pref); return $record; } #get last (end_time) device locally in contenttranspos to get end_time of last state sub get_devicesONcontenttranspos { my $dbh = shift; my $deviceId = shift; my $pref = { table => "contenttranspos", fetch => "one", order => "end_time", int13 => "$deviceId", }; my $record = $dbt->fetch_tablerecord($dbh,$pref); return $record; } #get one device localy sub get_devicesONcontent { my $dbh = shift; 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 $dbh = shift; 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; } sub get_devices { my $dbh = shift; my $endpoint = "https://tracking.ilockit.bike/api/devices"; my $rest = ""; my $ret_json = fetch_ilockit_cloud("","$endpoint",$rest); my $response_in = {}; $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 get_devices #get_events sub get_events { my $dbh = shift; $response_in = shift; #1. select all devices on content print FILE "ilockit get_events get_devicesONcontent_all\n"; my $record_cc = get_devicesONcontent_all($dbh,""); 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 content to get deviceId foreach my $id (sort { $record_cc->{$a}->{barcode} <=> $record_cc->{$b}->{barcode} } keys (%$record_cc)){ #get Ilockit events by deviceId #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 = { c_id => 0 }; $theft_record = get_devicesONcontenttheftpos($dbh,"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"; #insert theft alarm if no theft alarm with theft id 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 theft_record:" . Dumper($insert); } } } } }#end get_events sub get_positions { my $dbh = shift; my $record_cc = get_devicesONcontent_all($dbh,"C2-04"); my $endpoint = "https://tracking.ilockit.bike/api/positions"; 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 $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 = { c_id => 0 }; $ctpos = get_devicesONcontenttranspos($dbh,$record_cc->{$id}->{int13}); if($ctpos->{int20} == 1){#if locked then get position in range of end_time to now print FILE "get_position deviceId: $ctpos->{int13} --> lock_state:$ctpos->{int20}| last rental 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/; my $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); my $response_in = {}; $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($dbh,"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 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);