====== GPSD Raw Web Stats ====== Used in the `timehatstats` script, perhaps elsewhere in the future? ===== implementation ===== rm /tmp/gpsstats.php wget -q -P /tmp http://127.0.0.1/gpsstats.php FIX=$(sed -n 1p /tmp/gpsstats.php) FIXTYPE=$(sed -n 2p /tmp/gpsstats.php) GPSTIME=$(sed -n 3p /tmp/gpsstats.php) LAT=$(sed -n 4p /tmp/gpsstats.php) LON=$(sed -n 5p /tmp/gpsstats.php) GDOP=$(sed -n 6p /tmp/gpsstats.php) PDOP=$(sed -n 7p /tmp/gpsstats.php) TDOP=$(sed -n 8p /tmp/gpsstats.php) SATS=$(sed -n 9p /tmp/gpsstats.php) SATSUSED=$(sed -n 10p /tmp/gpsstats.php) ===== code ===== 0) && ($port < 65536)) $port = $_GET['port']; if ($testmode){ $sock = @fsockopen($server, $port, $errno, $errstr, 2); @fwrite($sock, "?WATCH={\"enable\":true}\n"); usleep(1000); @fwrite($sock, "?POLL;\n"); usleep(1000); for($tries = 0; $tries < 10; $tries++){ $resp = @fgets($sock, 10000); # SKY can be pretty big if (preg_match('/{"class":"POLL".+}/i', $resp, $m)){ $resp = $m[0]; break; } } @fclose($sock); if (!$resp) $resp = '{"class":"ERROR","message":"no response from GPS daemon"}'; } } # ensure all satellites keys exist, for clean logs. function sat_clean($sat) { $skeys = array('az', 'el', 'gnssid', 'health', 'PRN', 'ss', 'svid', 'used'); foreach($skeys as $key) { if (!array_key_exists($key, $sat)) { $sat[$key] = 'n/a'; } } return $sat; } # format $arr[$field], adding $unit, optionally add $errkey/$errunit # otherwise return 'n/a' or 'n/a' function field_str($arr, $key, $unit, $errkey = '', $errunit = '') { if (!array_key_exists($key, $arr)) { if ($errkey) { return 'n/a '; } else { return 'n/a'; } } if ('' == $errunit) { $errunit = $unit; } $ret = strval($arr[$key]); if ('' != $unit) { $ret .= " " . $unit; if ($errkey) { $ret .= " " ; if (array_key_exists($errkey, $arr)) { $ret .= "±" . strval($arr[$errkey]) . " " . $errunit; } } } return $ret; } if ($op == 'view') gen_image($resp); else if ($op == 'json') write_json($resp); else write_html($resp); exit(0); # compare sats for sort. used at top. function sat_cmp($a, $b) { if ($b['used'] != $a['used']) { # used Y before used N return $b['used'] - $a['used']; } return $a['PRN'] - $b['PRN']; } function write_html($resp) { global $sock, $errstr, $errno, $server, $port, $head, $body, $open; global $blurb, $title, $autorefresh, $showmap, $gmap_key, $footer; global $testmode, $advertise; $GPS = json_decode($resp, true); if ($GPS['class'] != 'POLL'){ die("json_decode error: $resp"); } header("Content-type: text/html; charset=UTF-8"); global $lat, $lon; # make sure some things exist if (!array_key_exists('sky', $GPS)) { $GPS['sky'] = array(); } if (!array_key_exists(0, $GPS['sky'])) { $GPS['sky'][0] = array(); } if (!array_key_exists('satellites', $GPS['sky'][0])) { $GPS['sky'][0]['satellites'] = array(); } if (!array_key_exists('tpv', $GPS)) { $GPS['tpv'] = array(); } if (!array_key_exists(0, $GPS['tpv'])) { $GPS['tpv'][0] = array(); } if (!array_key_exists('lat', $GPS['tpv'][0]) || !array_key_exists('lon', $GPS['tpv'][0])) { $GPS['tpv'][0]['lat'] = 0.0; $GPS['tpv'][0]['lon'] = 0.0; } if (!array_key_exists('mode', $GPS['tpv'][0])) { $GPS['tpv'][0]['mode'] = 0; } if (!array_key_exists('time', $GPS['tpv'][0])) { $GPS['tpv'][0]['time'] = 0; } $lat = (float)$GPS['tpv'][0]['lat']; $lon = (float)$GPS['tpv'][0]['lon']; $x = $server; $y = $port; $imgdata = base64_encode($resp); $server = $x; $port = $y; if ($autorefresh > 0) $autorefresh = ""; else $autorefresh = ''; $map_head = $map_body = $map_code = ''; if ($showmap == 1) { $map_head = gen_gmap_head(); $map_body = 'onload="Load()" onunload="GUnload()"'; $map_code = gen_map_code(); } else if ($showmap == 2) { $map_head = gen_osm_head(); $map_body = ''; $map_code = gen_osmmap_code(); } $part_header = << gpsstats
{$blurb}
EOF; if (!strlen($advertise)) $advertise = $server; if ($testmode && !$sock) $part_sky = ""; else $part_sky = <<

EOF; if ($open) $part3 = <<
To get real-time information, connect to telnet://{$advertise}:{$port}/ and type "?POLL;" or "?WATCH={"enable":true,"raw":true}".
Use a different server:
:

EOF; else $part3 = ''; if ($testmode && !$sock) $part_tpv_sky = <<The gpsd instance that this page monitors is not running. EOF; else { $fix = $GPS['tpv'][0]; $sky = $GPS['sky'][0]; $sats = $sky['satellites']; $fixtype = array('Unknown' => 0, 'No Fix' => 1, '2D Fix' => 2, '3D Fix' => 3); $type = array_search($fix['mode'], $fixtype); $nsv = count($sats); $ts = $fix['time']; $sat = ''; # gnssid to gnss abbreviation $gnss = array(0 => 'GP', 1 => 'SB', 2 => 'GA', 3 => 'BD', 4 => 'IM', 5 => 'QZ', 6 => 'GL'); # sort sats usort($sats, "sat_cmp"); $sats_used = 0; foreach($sats as $s) { $s = sat_clean($s); if (array_key_exists($s['gnssid'], $gnss)) { $s['gnssid'] = $gnss[$s['gnssid']]; } else { $s['gnssid'] = ' '; } if ($s['used']) { $sats_used += 1; } if (2 == (int)$s['health']) { $used = $s['used'] ? 'uY ' : 'uN  '; } else { $used = $s['used'] ? ' Y ' : ' N  '; } $sat .= sprintf( "\t%s" . "%d%d %d " . "%d%s\n", $s['gnssid'] . $s['svid'], $s['PRN'], $s['el'], $s['az'], $s['ss'], $used ); }; # ensure all $fix keys exist, for clean logs. $fixkeys = array('lat', 'leapseconds', 'lon'); foreach($fixkeys as $key) { if (!array_key_exists($key, $fix)) { $fix[$key] = 'n/a'; } } # ensure all $sky keys exist, for clean logs. $skykeys = array('gdop', 'hdop', 'pdop','tdop', 'vdop', 'xdop', 'ydop'); foreach($skykeys as $key) { if (!array_key_exists($key, $sky)) { $sky[$key] = 'n/a'; } } $lat = field_str($fix, 'lat', '', '', ''); $lon = field_str($fix, 'lon', '', '', ''); $altHAE = field_str($fix, 'altHAE', 'm', 'epv'); $altMSL = field_str($fix, 'altMSL', 'm'); $geoidSep = field_str($fix, 'geoidSep', 'm'); $speed = field_str($fix, 'speed', 'm/s', 'eps'); $climb = field_str($fix, 'climb', 'm/s', 'epc'); $velN = field_str($fix, 'velN', 'm/s'); $velE = field_str($fix, 'velE', 'm/s'); $velD = field_str($fix, 'velD', 'm/s'); $track = field_str($fix, 'track', '°', 'epd'); $magtrack = field_str($fix, 'magtrack', '°'); $magvar = field_str($fix, 'magvar', '°'); $ecefx = field_str($fix, 'ecefx', 'm'); $ecefy = field_str($fix, 'ecefy', 'm'); $ecefz = field_str($fix, 'ecefz', 'm', 'ecefpAcc'); $ecefvx = field_str($fix, 'ecefvx', 'm/s'); $ecefvy = field_str($fix, 'ecefvy', 'm/s'); $ecefvz = field_str($fix, 'ecefvz', 'm/s', 'ecefvAcc'); $epc = field_str($fix, 'epc', 'm/s'); $eph = field_str($fix, 'eph', 'm'); $eps = field_str($fix, 'eps', 'm/s'); $ept = field_str($fix, 'ept', 's'); $epx = field_str($fix, 'epx', 'm'); $epy = field_str($fix, 'epy', 'm'); $epv = field_str($fix, 'epv', 'm'); $sep = field_str($fix, 'sep', 'm'); $ecefpAcc = field_str($fix, 'ecefpAcc', 'm'); $ecefvAcc = field_str($fix, 'ecefvAcc', 'm'); $sep = field_str($fix, 'sep', 'm'); if (!array_key_exists('status', $fix)) { $fix['status'] = 1; } switch($fix['status']) { case 0: $status = 'None'; break; case 1: $status = 'Normal'; break; case 2: $status = 'DGPS'; break; case 3: $status = 'RTK'; break; case 4: $status = 'RTK Float'; break; case 5: $status = 'Dead Reckoning'; break; case 6: $status = 'GNSS+DR'; break; case 7: $status = 'Surveyed-In'; break; case 8: $status = 'Simulated'; break; default: $status = 'Unknown'; break; } $part_tpv_sky = <<