261 lines
7.0 KiB
PHP
261 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Console\Command;
|
|
use App\Facades\Utils;
|
|
use GuzzleHttp\Client;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
|
|
class AcarsReplay extends Command
|
|
{
|
|
protected $signature = 'phpvms:replay {files} {--manual} {--write-all} {--no-submit}';
|
|
protected $description = 'Replay an ACARS file';
|
|
|
|
/**
|
|
* API Key to post as
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $apiKey = 'testadminapikey';
|
|
|
|
/**
|
|
* For automatic updates, how many seconds to sleep between updates
|
|
*
|
|
* @var int
|
|
*/
|
|
protected $sleepTime = 10;
|
|
|
|
/**
|
|
* @var array key == update[callsign]
|
|
* value == PIREP ID
|
|
*/
|
|
protected $pirepList = [];
|
|
|
|
/**
|
|
* @var Client
|
|
*/
|
|
protected $httpClient;
|
|
|
|
/**
|
|
* Return an instance of an HTTP client all ready to post
|
|
*/
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
|
|
$this->httpClient = new Client([
|
|
'base_uri' => config('app.url'),
|
|
'headers' => [
|
|
'Authorization' => $this->apiKey,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Make a request to start a PIREP
|
|
*
|
|
* @param \stdClass $flight
|
|
*
|
|
* @throws \RuntimeException
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function startPirep($flight): string
|
|
{
|
|
// convert the planned flight time to be completely in minutes
|
|
$pft = Utils::hoursToMinutes(
|
|
$flight->planned_hrsenroute,
|
|
$flight->planned_minenroute
|
|
);
|
|
|
|
$flight_number = substr($flight->callsign, 3);
|
|
|
|
$response = $this->httpClient->post('/api/pireps/prefile', [
|
|
'json' => [
|
|
'airline_id' => 1,
|
|
'flight_number' => $flight_number,
|
|
'aircraft_id' => 1,
|
|
'dpt_airport_id' => $flight->planned_depairport,
|
|
'arr_airport_id' => $flight->planned_destairport,
|
|
'level' => $flight->planned_altitude,
|
|
'planned_flight_time' => $pft,
|
|
'route' => $flight->planned_route,
|
|
],
|
|
]);
|
|
|
|
$body = \json_decode($response->getBody()->getContents());
|
|
|
|
return $body->id;
|
|
}
|
|
|
|
/**
|
|
* Mark the PIREP as filed
|
|
*
|
|
* @param $pirep_id
|
|
*
|
|
* @throws \RuntimeException
|
|
*
|
|
* @return mixed
|
|
*/
|
|
protected function filePirep($pirep_id)
|
|
{
|
|
$response = $this->httpClient->post('/api/pireps/'.$pirep_id.'/file', [
|
|
'json' => [],
|
|
]);
|
|
|
|
$body = \json_decode($response->getBody()->getContents());
|
|
|
|
return $body;
|
|
}
|
|
|
|
/**
|
|
* @param $pirep_id
|
|
* @param $data
|
|
*
|
|
* @throws \RuntimeException
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function postUpdate($pirep_id, $data)
|
|
{
|
|
$uri = '/api/pireps/'.$pirep_id.'/acars/position';
|
|
|
|
$position = [
|
|
'log' => '',
|
|
'lat' => $data->latitude,
|
|
'lon' => $data->longitude,
|
|
'heading' => $data->heading,
|
|
'altitude' => $data->altitude,
|
|
'gs' => $data->groundspeed,
|
|
'transponder' => $data->transponder,
|
|
];
|
|
|
|
$upd = [
|
|
'positions' => [
|
|
$position,
|
|
],
|
|
];
|
|
|
|
$this->info("Update: $data->callsign, $position[lat] x $position[lon] \t\t"
|
|
."hdg: $position[heading]\t\talt: $position[altitude]\t\tgs: $position[gs]");
|
|
|
|
$response = $this->httpClient->post($uri, [
|
|
'json' => $upd,
|
|
]);
|
|
|
|
$body = \json_decode($response->getBody()->getContents());
|
|
|
|
return [
|
|
$data->callsign,
|
|
$position['lat'],
|
|
$position['lon'],
|
|
$position['heading'],
|
|
$position['altitude'],
|
|
$position['gs'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Parse this file and run the updates
|
|
*
|
|
* @param array $files
|
|
*
|
|
* @throws \RuntimeException
|
|
*/
|
|
protected function updatesFromFile(array $files)
|
|
{
|
|
/**
|
|
* @var $flights Collection
|
|
*/
|
|
$flights = collect($files)->transform(function ($f) {
|
|
$file = $f;
|
|
if (file_exists($file)) {
|
|
$this->info('Loading '.$file);
|
|
$contents = file_get_contents($file);
|
|
$contents = \json_decode($contents);
|
|
|
|
return collect($contents->updates);
|
|
}
|
|
$this->error($file.' not found, skipping');
|
|
|
|
return false;
|
|
})
|
|
// remove any of errored file entries
|
|
->filter(function ($value, $key) {
|
|
return $value !== false;
|
|
});
|
|
|
|
$this->info('Starting playback');
|
|
|
|
/*
|
|
* File the initial pirep to get a "preflight" status
|
|
*/
|
|
$flights->each(function ($updates, $idx) {
|
|
$update = $updates->first();
|
|
$pirep_id = $this->startPirep($update);
|
|
$this->pirepList[$update->callsign] = $pirep_id;
|
|
$this->info('Prefiled '.$update->callsign.', ID: '.$pirep_id);
|
|
});
|
|
|
|
/*
|
|
* Iterate through all of the flights, retrieving the updates
|
|
* from each individual flight. Remove the update. Continue through
|
|
* until there are no updates left, at which point we remove the flight
|
|
* and updates.
|
|
*
|
|
* Continue until we have no more flights and updates left
|
|
*/
|
|
while ($flights->count() > 0) {
|
|
$flights = $flights->each(function ($updates, $idx) {
|
|
$update = $updates->shift();
|
|
$pirep_id = $this->pirepList[$update->callsign];
|
|
|
|
$this->postUpdate($pirep_id, $update);
|
|
|
|
// we're done and don't put the "no-submit" option
|
|
if ($updates->count() === 0 && !$this->option('no-submit')) {
|
|
$this->filePirep($pirep_id);
|
|
}
|
|
})->filter(function ($updates, $idx) {
|
|
return $updates->count() > 0;
|
|
});
|
|
|
|
if (!$this->option('write-all')) {
|
|
if (!$this->option('manual')) {
|
|
sleep($this->sleepTime);
|
|
} else {
|
|
$this->confirm('Send next batch of updates?', true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute the console command.
|
|
*
|
|
* @throws \RuntimeException
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function handle(): void
|
|
{
|
|
$files = $this->argument('files');
|
|
$manual_mode = $this->option('manual');
|
|
|
|
if ($this->option('write-all')) {
|
|
$this->info('In "dump-all" mode, just writing it all in');
|
|
} else {
|
|
/* @noinspection NestedPositiveIfStatementsInspection */
|
|
if (!$manual_mode) {
|
|
$this->info('Going to send updates every 10s');
|
|
} else {
|
|
$this->info('In "manual advance" mode');
|
|
}
|
|
}
|
|
|
|
$this->updatesFromFile(explode(',', $files));
|
|
$this->info('Done!');
|
|
}
|
|
}
|