135 lines
3.2 KiB
PHP

<?php
namespace germanairlinesva_recording;
class Recording
{
private const ident = "VGAR";
private const header_unpack = "Z5ident/Cversion";
private const segment_unpack = "Vtime/Saltitude/Sgroundspeed/elatitude/elongitude";
private string $file_name;
public function __construct(string $file)
{
$this->file_name = $file;
}
/**
* Generates a geoJSON representation
*
* @return string geoJSON representation of path
*/
public function geoJSON(): string
{
$geoJSON = [
"type" => "FeatureCollection",
"features" => [
0 => [
"type" => "Feature",
"properties" => [
"stroke" => "#ff0000",
"stroke-width" => 2,
"stroke-opacity" => 1
],
"geometry" => [
"type" => "LineString",
"coordinates" => []
]
]
]
];
$segments = $this->read();
$geoJSON["features"][0]["geometry"]["coordinates"] = array_map(function ($segment) {
return array($segment["longitude"], $segment["latitude"]);
}, $segments);
return json_encode($geoJSON);
}
/**
* Reads recording
*
* @return array Fields:
* int Segment time (number) as time,
* int Altitude as altitude,
* int Ground speed as groundspeed,
* double Latitude as latitude,
* double Longitude as longitude
*/
public function read(): array
{
$file = fopen($this->file_name, "rb");
flock($file, LOCK_SH);
$segments = [];
$version = $this->read_header($file);
if ($version == 1) {
while (($segment = $this->read_segment_1($file)) != false) {
array_push($segments, $segment);
}
}
flock($file, LOCK_UN);
fclose($file);
return $segments;
}
/**
* Reads one segment entry
*
* @param resource $file File handle
*
* @return array if not EOF with fields:
* int Segment time (number) as time,
* int Altitude as altitude,
* int Ground speed as groundspeed,
* double Latitude as latitude,
* double Longitude as longitude
*
* @return false if EOF
*
* @throws InvalidArgumentException If file is not a resource
*/
private function read_segment_1($file): array | false
{
if (false === is_resource($file)) {
throw new \InvalidArgumentException(sprintf('Argument must be a valid resource type. %s given.', gettype($file)));
}
$data = fread($file, 24);
if ($data) {
return unpack(Recording::segment_unpack, $data);
}
return false;
}
/**
* Reads the file header
*
* @param resource $file File handle
*
* @return string File version
*
* @throws InvalidArgumentException If file is not a resource
* @throws UnexpectedValueException If ident mismatches
*/
private function read_header($file): string
{
if (false === is_resource($file)) {
throw new \InvalidArgumentException(sprintf('Argument must be a valid resource type. %s given.', gettype($file)));
}
$header = unpack(Recording::header_unpack, fread($file, 6));
if ($header["ident"] !== Recording::ident) {
throw
new \UnexpectedValueException(sprintf("Ident mismatch. Got %s, expected %s", $header["ident"], Recording::ident));
}
return $header["version"];
}
}