Skip to content

Instantly share code, notes, and snippets.

@667bdrm
Created April 30, 2015 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 667bdrm/33989e7fe9d751dd3968 to your computer and use it in GitHub Desktop.
Save 667bdrm/33989e7fe9d751dd3968 to your computer and use it in GitHub Desktop.
car-online.ru vehicle tracking service data to gpx converter / openstreetmap uploader
#!/usr/bin/perl
#
# caronline.pl
#
# car-online.ru data to gpx converter / openstreetmap uploader
#
# (c) 2009, https://gist.github.com/667bdrm
#
use Getopt::Long;
use Pod::Usage;
use HTTP::Request::Common;
use LWP::UserAgent;
use XML::LibXML;
my $cfgFile = "";
my $cfgUser = "";
my $cfgPass = "";
my $cfgHost = "";
my $cfgPort = "";
my $cfgTplName = "";
my $cfgGPXfile = "";
my $cfgXslFile = "";
my $cfgOutputFile = "";
my $coAPIUrl = "http://export.car-online.ru";
my $coAPIPattern = 189;
my $coAPIKey = "";
my $osmAPIUrl = "http://www.openstreetmap.org";
my $osmAPILogin = "";
my $osmAPIPass = "";
my $updateOSM = 0;
my $dataSource = "gpx";
my $gpxFile = 'test.gpx';
my $man = 0;
my $help = 0;
my $result = GetOptions (
"help|h" => \$help,
"outputfile|of|o=s" => \$gpxFile,
"apikey|a=s" => \$coAPIKey,
"copattern|p=s" => \$coAPIPattern,
"courl=s" => \$coAPIUrl,
"osmurl=s" => \$osmAPIUrl,
"updateosm" => \$updateOSM,
"osmuser|ou=s" => \$osmAPILogin,
"osmpass|op=s" => \$osmAPIPass,
"datasource|ds=s" => \$dataSource,
"costartdate=s" => \$coStartDate,
"coenddate=s" => \$coEndDate,
);
pod2usage(1) if ($help);
if ($updateOSM and !($osmAPILogin and $osmAPIPass)) {
print STDERR "You must set OpenStreetMap.org login and password!\n";
exit(0);
}
$ua = LWP::UserAgent->new;
$ua->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)');
$ua->env_proxy;
if ($coStartDate) {
$coStartDate =~ /(\d+)\.(\d+)\.(\d{4})(\s+(\d{1-2}):(\d{1-2})(:(\d{1-2}))?)?/;
$hour = 0;
$hour = $5 if ($5);
$min = 0;
$min = $6 if ($6);
$sec = 0;
$sec = $8 if ($8);
$coStartDate = sprintf("%02d%02d%04d_%02d%02d%02d", $1, $2, $3, $hour, $min, $sec);
print STDERR "Start Date: $coStartDate\n";
}
if ($coEndDate) {
$coEndDate =~ /(\d+)\.(\d+)\.(\d{4})(\s+(\d{1-2}):(\d{1-2})(:(\d{1-2}))?)?/;
$hour = 23;
$hour = $5 if ($5);
$min = 59;
$min = $6 if ($6);
$sec = 59;
$sec = $8 if ($8);
$coEndDate = sprintf("%02d%02d%04d_%02d%02d%02d", $1, $2, $3, $hour, $min, $sec);
print STDERR "End Date: $coEndDate\n";
}
my $lastDate = '';
$gpxUrl = $coAPIUrl . "/do?data=gpsPoints&skey=$coAPIKey&content=xml";
if ($coAPIPattern) {
$gpxUrl .= "&pattern=$coAPIPattern";
}
if ($coStartDate) {
$gpxUrl .= "&begin=$coStartDate";
}
if ($coEndDate) {
$gpxUrl .= "&end=$coEndDate";
}
print STDERR "Dumping car-online data...\n";
my $response = $ua->get($gpxUrl);
if ($response->code==200) {
#my $doc = $parser->parsefile($gpxUrl);
my $doc = XML::LibXML->load_xml(string => $response->content);
my @points = $doc->getElementsByTagName('gps');
my $totalPoints = $#points + 1;
print STDERR "Points: " . sprintf("%d", $totalPoints) . "\n";
if ($totalPoints > 0) {
my $gpx = XML::LibXML::Document->new();
print STDERR "Creating gpx-doc...\n";
my $gpxDoc = $gpx->createElement('gpx');
$gpxDoc->setAttribute('version', '1.0');
$gpxDoc->setAttribute('creator', 'caronline.pl');
$gpxDoc->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$gpxDoc->setAttribute('xmlns', 'http://www.topografix.com/GPX/1/0');
$gpxDoc->setAttribute('xsi:schemaLocation', 'http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd');
my $track = $gpx->createElement('trk');
open(OUT, ">$gpxFile");
my $trkseg = $gpx->createElement('trkseg');
my $ptCount = 0;
foreach my $gps (@points) {
my $trackPoint = $gpx->createElement('trkpt');
$trackPoint->setAttribute('lat', $gps->getAttribute('lat'));
$trackPoint->setAttribute('lon', $gps->getAttribute('lon'));
my $speed = $gpx->createElement('speed');
$speed->appendChild($gpx->createTextNode($gps->getAttribute('speed')));
$trackPoint->appendChild($speed);
my $hdop = $gpx->createElement('hdop');
$hdop->appendChild($gpx->createTextNode($gps->getAttribute('hdop')));
$trackPoint->appendChild($hdop);
my $course = $gpx->createElement('course');
$course->appendChild($gpx->createTextNode($gps->getAttribute('course')));
$trackPoint->appendChild($course);
my $coDateTime = $gps->getAttribute('date');
$coDateTime =~ /(\d{2})(\d{2})(\d{4})_(\d{2})(\d{2})(\d{2})/;
my ($day,$mon,$year,$hour,$min,$sec) = ($1,$2,$3,$4,$5,$6);
my $datetime = "$year-$mon-$day"."T$hour:$min:$sec+03:00";
$lastDate = $datetime;
my $time = $gpx->createElement('time');
$time->appendChild($gpx->createTextNode($datetime));
$trackPoint->appendChild($time);
# Adding raw NMEA string for reference
my $nmea = $gps->getAttribute('nmea');
if ($nmea) {
my $gpxExt = $gpx->createElement('extensions');
my $nmeaExt = $gpx->createElement('nmea');
$nmeaExt->appendChild($gpx->createTextNode($nmea));
$gpxExt->appendChild($nmeaExt);
$trackPoint->appendChild($gpxExt);
}
$trkseg->appendChild($trackPoint);
$ptCount++;
}
$track->appendChild($trkseg);
my $name = $gpx->createElement('name');
$name->appendChild($gpx->createTextNode("Track $lastDate"));
$track->appendChild($name);
$gpxDoc->appendChild($track);
my $gpxData = $gpxDoc->toString();
print STDERR "Writing gpx-file...\n";
print OUT $gpxData;
close(OUT);
if ($updateOSM and $ptCount > 0) {
$ua = LWP::UserAgent->new;
$ua->credentials('www.openstreetmap.org:80','Web Password',$osmAPILogin, $osmAPIPass);
print STDERR "Uploading to OSM...\n";
$response=$ua->request(POST 'http://www.openstreetmap.org/api/0.6/gpx/create',
Content_Type => 'form-data',
Content => [
file =>[$gpxFile],
description=> "Track $lastDate",
tags => "",
visibility =>"private" ]
);
if ($response->code==200) {
print STDERR "GPX uploaded\n";
} else {
print STDERR "GPX upload failed!\n";
}
}
}
} else {
print "Error getting track data: $!\n";
exit(0);
}
1;
__END__
=head1 NAME
./caronline.pl - utility for working with caronline data
=head1 SYNOPSIS
./caronline.pl [options] [<gpx file>]
=head1 OPTIONS
=over 8
=item B<-help>
Print a brief help message and exits.
=item B<-of>
Path to output file filename.
=item B<-apikey>
car-online.ru API key, providede by car-online.ru
=item B<-copattern>
car-online.ru pattern, used for getting more detalized gpx data
=item B<-courl>
car-online.ru API url, default http://export.car-online.ru
=item B<-osmurl>
openstreetmap.org upload url, default http://www.openstreetmap.org
=item B<-updateosm>
Upload track to www.openstreetmap.org
=item B<-osmuser>
openstreetmap.org user login
=item B<-osmpass>
openstreetmap.org user password
=item B<-datasource>
Data source: gpx = gpxfile, caronline = caronline.ru
=item B<-costartdate>
car-online.ru track start date and time
=item B<-coenddate>
car-online.ru track end date and time
=back
=head1 DESCRIPTION
B<This program> will upload track to openstreetmap.org.
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment