0,0 → 1,445 |
#!/usr/bin/perl |
#!/usr/bin/perl -d:ptkdb |
|
############################################################################### |
# |
# logging.pl - CSV, KLM, GPS Logging |
# |
# Copyright (C) 2009 Rainer Walther (rainerwalther-mail@web.de) |
# |
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa) |
# |
# Es ist Ihnen gestattet: |
# * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen |
# * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen |
# |
# Zu den folgenden Bedingungen: |
# * Namensnennung. |
# Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen. |
# * Keine kommerzielle Nutzung. |
# Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden. |
# * Weitergabe unter gleichen Bedingungen. |
# Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten, |
# verändern oder als Grundlage für einen anderen Inhalt verwenden, |
# dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen |
# weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind. |
# |
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses |
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden. |
# |
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung |
# des Rechteinhabers dazu erhalten. |
# |
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt. |
# |
# Weitere Details zur Lizenzbestimmung gibt es hier: |
# Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/ |
# Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode |
# |
############################################################################### |
# |
# 2009-02-23 0.0.1 rw created |
# 2009-04-01 0.1.0 rw RC1 |
# 2009-05-01 0.1.1 rw configurable logging interval |
# 2009-05-17 0.1.7 rw _Timestamp timeout von 2s auf 10s erhoeht |
# 2009-09-30 0.1.8 rw SignalHandler removed |
# 2010-01-23 0.1.9 rw kosmetics |
# no logging, if simulator is active |
# 2010-06-24 0.5.0 rw GPX logging match MK format |
# |
############################################################################### |
|
$Version{'logging.pl'} = "0.5.0 - 2010-06-24"; |
|
# |
# Parameter |
# |
|
my $LoopTime = $Cfg->{'logging'}->{'Intervall'} || 1; # in s |
$LoopTime *= 1000000; # in us |
|
# Packages |
use threads; # http://search.cpan.org/~jdhedden/threads-1.72/threads.pm |
# http://perldoc.perl.org/threads.html |
use threads::shared; # http://search.cpan.org/~jdhedden/threads-shared-1.28/shared.pm |
use Thread::Queue; # http://search.cpan.org/dist/Thread-Queue-2.11/lib/Thread/Queue.pm |
use Time::HiRes qw(usleep); |
|
require "mkcomm.pl"; # MK communication |
require "geserver.pl"; # Google Earth Server |
require "translate.pl"; # Übersetzungstable |
|
# Queue for receiving commands |
$LogQueue = Thread::Queue->new(); |
|
my $LogState = "LOG"; # LOG, OFF |
my $LogCsvIsOpen = 0; |
my $LogKmlIsOpen = 0; |
my $LogGpxIsOpen = 0; |
my $GeServerIsRunning = 0; |
|
# |
# CSV |
# |
|
# Open CSV logfile |
sub LogCsvOpen() |
{ |
if ( ! $LogCsvIsOpen ) |
{ |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); |
my $Filename = sprintf ("mk-%04d%02d%02d-%02d%02d%02d.csv", $year+1900, $mon+1, $mday, $hour, $min, $sec); |
open LOGCSV, ">$Cfg->{'logging'}->{'CsvLogDir'}/$Filename"; |
|
# print labes at first line |
|
# wait for hash labels |
while ( $MkOsd{'_Timestamp'} eq "" or $MkNcDebug{'_Timestamp'} eq "" ) |
{ |
sleep 1; |
} |
|
# NC OSD |
my $Sep = ""; |
foreach $Label (sort keys %MkOsd) |
{ |
if ( $Translate{$Label} ne "" ) |
{ |
$Label = $Translate{$Label}; |
} |
print LOGCSV "$Sep" . "$Label"; |
$Sep = ","; |
} |
|
# NC Debug |
foreach $Label (sort keys %MkNcDebug) |
{ |
if ( $Translate{$Label} ne "" ) |
{ |
$Label = $Translate{$Label}; |
} |
print LOGCSV "$Sep" . "$Label"; |
} |
print LOGCSV "\n"; |
|
$LogCsvIsOpen = 1; |
} |
|
return 0; |
} |
|
|
# Close CSV |
sub LogCsvClose() |
{ |
if ( $LogCsvIsOpen ) |
{ |
close LOGCSV; |
$LogCsvIsOpen = 0; |
} |
|
return 0; |
} |
|
# Log CSV |
sub LogCsv() |
{ |
lock %MkOsd; # until end of Block |
lock %MkNcDebug; # until end of Block |
|
if ( $MkOsd{'_Timestamp'} >= time-10 ) |
{ |
# active connection to MK |
&LogCsvOpen(); |
|
# NC OSD |
my $Sep = ""; |
foreach $Label (sort keys %MkOsd) |
{ |
print LOGCSV "$Sep" . "$MkOsd{$Label}"; |
$Sep = ","; |
} |
|
# NC Debug |
foreach $Label (sort keys %MkNcDebug) |
{ |
print LOGCSV "$Sep" . "$MkNcDebug{$Label}"; |
} |
print LOGCSV "\n"; |
} |
else |
{ |
# connection to MK lost, close Logfile |
&LogCsvClose(); |
} |
|
return 0; |
} |
|
|
# |
# GPX |
# http://www.topografix.com/gpx_manual.asp |
# |
|
# Open GPX logfile |
sub LogGpxOpen() |
{ |
if ( ! $LogGpxIsOpen ) |
{ |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); |
my $TimeStamp = sprintf ("%04d%02d%02d-%02d%02d%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); |
my $Filename = "mk-" . $TimeStamp . ".gpx"; |
open LOGGPX, ">$Cfg->{'logging'}->{'GpxLogDir'}/$Filename"; |
$LogGpxIsOpen = 1; |
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time); |
my $UtcTimeStamp = sprintf ("%04d-%02d-%02dT%02d:%02d:%02dZ", $year+1900, $mon+1, $mday, $hour, $min, $sec); |
|
# print GPX-Header |
print LOGGPX <<EOF; |
<?xml version="1.0" encoding="UTF-8"?> |
<gpx |
version="1.0" |
creator="MK Mission Cockpit" |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
xmlns="http://www.topografix.com/GPX/1/0" |
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd"> |
<time>${UtcTimeStamp}</time> |
<trk> |
<name>Mission Cockpit GPS logging</name> |
<desc>Flight ${TimeStamp}</desc> |
<trkseg> |
EOF |
} |
|
return 0; |
} |
|
|
# Close GPX |
sub LogGpxClose() |
{ |
if ( $LogGpxIsOpen ) |
{ |
# print GPX-Trailer |
print LOGGPX <<EOF; |
</trkseg> |
</trk> |
</gpx> |
EOF |
close LOGGPX; |
$LogGpxIsOpen = 0; |
} |
|
return 0; |
} |
|
|
# Log GPX |
sub LogGpx() |
{ |
lock %MkOsd; # until end of Block |
|
if ( $MkOsd{'_Timestamp'} >= time-10 and |
$MkOsd{'MKFlags'} & 0x02 and $MkOsd{'CurPos_Stat'} == 1 ) |
{ |
# active connection to MK, MK is flying, valid GPS |
&LogGpxOpen(); |
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time); |
my $UtcTimeStamp = sprintf ("%04d-%02d-%02dT%02d:%02d:%02dZ", $year+1900, $mon+1, $mday, $hour, $min, $sec); |
|
my $Speed = $MkOsd{'GroundSpeed'} / 100; # m/s |
my $Elevation = &Altitude(); |
|
printf LOGGPX <<EOF; |
<trkpt lat="$MkOsd{'CurPos_Lat'}" lon="$MkOsd{'CurPos_Lon'}"> |
<ele>$Elevation</ele> |
<time>${UtcTimeStamp}</time> |
<sat>$MkOsd{'SatsInUse'}</sat> |
<course>$MkOsd{'CompassHeading'}</course> |
<speed>$Speed</speed> |
<extensions> |
<Altimeter>$MkOsd{'Altimeter'}</Altimeter> |
<Variometer>$MkOsd{'Variometer'}</Variometer> |
<Course>$MkOsd{'Heading'}</Course> |
<GroundSpeed>$MkOsd{'GroundSpeed'}</GroundSpeed> |
<VerticalSpeed>$MkOsd{'TopSpeed'}</VerticalSpeed> |
<FlightTime>$MkOsd{'FlyingTime'}</FlightTime> |
<Voltage>$MkOsd{'UBat'}</Voltage> |
<Current>$MkOsd{'Current'}</Current> |
<Capacity>$MkOsd{'UsedCapacity'}</Capacity> |
<RCQuality>$MkOsd{'RC_Quality'}</RCQuality> |
<RCRSSI>$MkOsd{'RC_RSSI'}</RCRSSI> |
<Compass>$MkOsd{'CompassHeading'}</Compass> |
<NickAngle>$MkOsd{'AngleNick'}</NickAngle> |
<RollAngle>$MkOsd{'AngleRoll'}</RollAngle> |
<NCFlag>$MkOsd{'NCFlags'}</NCFlag> |
<MKFlag>$MkOsd{'MKFlags'}</MKFlag> |
<ErrorCode>$MkOsd{'ErrorCode'}</ErrorCode> |
<TargetLat>$MkOsd{'TargetPos_Lat'}</TargetLat> |
<TargetLon>$MkOsd{'TargetPos_Lon'}</TargetLon> |
<TargetAlt>$MkOsd{'TargetPos_Alt'}</TargetAlt> |
<TargetBearing>$MkOsd{'TargetPosDev_Bearing'}</TargetBearing> |
<TargetDistance>$MkOsd{'TargetPosDev_Dist'}</TargetDistance> |
<Waypoint>$MkOsd{'WaypointIndex'} / $MkOsd{'WaypointNumber'}</Waypoint> |
<RCSticks>0, 0, 0</RCSticks> |
<GPSSticks>0, 0, 0</GPSSticks> |
</extensions> |
</trkpt> |
EOF |
} |
else |
{ |
&LogGpxClose(); |
} |
} |
|
# |
# KML |
# http://code.google.com/intl/de-DE/apis/kml/documentation/kml_tut.html |
# |
|
# Open KML logfile |
sub LogKmlOpen() |
{ |
if ( ! $LogKmlIsOpen ) |
{ |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); |
my $TimeStamp = sprintf ("%04d%02d%02d-%02d%02d%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); |
my $Filename = "mk-" . $TimeStamp . ".kml"; |
open LOGKML, ">$Cfg->{'logging'}->{'KmlLogDir'}/$Filename"; |
$LogKmlIsOpen = 1; |
|
# print KML-Header |
print LOGKML <<EOF; |
<?xml version="1.0" encoding="UTF-8"?> |
<kml xmlns="http://earth.google.com/kml/2.2"> |
<Document> |
<name>Mission Cockpit GPS logging</name> |
<Style id="MK_gps-style"> |
<LineStyle> |
<color>ff0000ff</color> |
<width>2</width> |
</LineStyle> |
</Style> |
<Placemark> |
<name>Flight ${TimeStamp}</name> |
<styleUrl>MK_gps-style</styleUrl> |
<LineString> |
<tessellate>1</tessellate> |
<altitudeMode>relativeToGround</altitudeMode> |
<coordinates> |
EOF |
} |
|
return 0; |
} |
|
|
# Close KML |
sub LogKmlClose() |
{ |
if ( $LogKmlIsOpen ) |
{ |
# print KML-Trailer |
print LOGKML <<EOF; |
</coordinates> |
</LineString> |
</Placemark> |
</Document> |
</kml> |
EOF |
close LOGKML; |
$LogKmlIsOpen = 0; |
} |
|
return 0; |
} |
|
|
# Log KML |
sub LogKml() |
{ |
lock %MkOsd; # until end of Block |
|
if ( $MkOsd{'_Timestamp'} >= time-10 and |
$MkOsd{'MKFlags'} & 0x02 and $MkOsd{'CurPos_Stat'} == 1 ) |
{ |
# active connection to MK, MK is flying, valid GPS |
&LogKmlOpen(); |
|
my $Alt = &Altitude(); |
if ( $Alt < 0 ) { $Alt = 0; } |
printf LOGKML " %f, %f, %f\n", $MkOsd{'CurPos_Lon'}, $MkOsd{'CurPos_Lat'}, $Alt; |
} |
else |
{ |
&LogKmlClose(); |
} |
} |
|
|
# Send Coords to GoogleEarth server |
sub Send2GeServer() |
{ |
lock %MkOsd; # until end of Block |
|
if ( $MkOsd{'_Timestamp'} >= time-10 and |
$MkOsd{'MKFlags'} & 0x02 and $MkOsd{'CurPos_Stat'} == 1 ) |
{ |
# active connection to MK, MK is flying, valid GPS |
|
my $AltRel = $MkOsd{'CurPos_Alt'} - $MkOsd{'HomePos_Alt'}; |
if ( $AltRel < 0 ) { $AltRel = 0; } |
|
push @GeCoords, sprintf "%f, %f, %f", $MkOsd{'CurPos_Lon'}, $MkOsd{'CurPos_Lat'}, $AltRel; |
} |
} |
|
|
sub MkLogLoop() |
{ |
while (1) |
{ |
|
# check commnd queue |
if ( $LogQueue->pending() > 0 ) |
{ |
$LogState = $LogQueue->dequeue(1); |
} |
|
if ( $LogState eq "LOG" ) |
{ |
&LogCsv(); |
&LogKml(); |
&LogGpx(); |
} |
|
&Send2GeServer(); # Google Earth |
|
# kurz schlafen legen |
usleep $LoopTime; |
} |
} |
|
# |
# Hauptprgramm |
# |
|
if ( $0 =~ /logging.pl$/i ) |
{ |
# Program wurde direkt aufgerufen |
|
# Kommunikation zum MK herstellen |
$mk_thr = threads->create (\&MkCommLoop) -> detach(); |
|
&MkLogLoop(); |
|
# should never exit |
} |
|
1; |
|
__END__ |