phpvms/app/Console/Commands/AcarsReplay.php

264 lines
7.1 KiB
PHP
Raw Normal View History

<?php
namespace App\Console\Commands;
use App\Console\Command;
use App\Facades\Utils;
2018-02-21 12:33:09 +08:00
use GuzzleHttp\Client;
use Illuminate\Database\Eloquent\Collection;
/**
* Class AcarsReplay
*/
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
2018-08-27 00:40:04 +08:00
*
* @var string
*/
protected $apiKey = 'testadminapikey';
/**
* For automatic updates, how many seconds to sleep between updates
2018-08-27 00:40:04 +08:00
*
* @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,
2018-08-27 00:40:04 +08:00
],
]);
}
/**
* Make a request to start a PIREP
2018-08-27 00:40:04 +08:00
*
* @param \stdClass $flight
2018-08-27 00:40:04 +08:00
*
* @throws \RuntimeException
2018-08-27 00:40:04 +08:00
*
* @return string
*/
2017-12-26 09:23:58 +08:00
protected function startPirep($flight): string
{
2018-08-27 00:40:04 +08:00
// 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);
2017-12-29 04:35:28 +08:00
$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,
2018-08-27 00:40:04 +08:00
],
]);
$body = \json_decode($response->getBody()->getContents());
return $body->id;
}
2017-12-27 04:54:28 +08:00
/**
* Mark the PIREP as filed
2018-08-27 00:40:04 +08:00
*
2017-12-27 04:54:28 +08:00
* @param $pirep_id
2018-08-27 00:40:04 +08:00
*
* @throws \RuntimeException
2018-08-27 00:40:04 +08:00
*
* @return mixed
2017-12-27 04:54:28 +08:00
*/
protected function filePirep($pirep_id)
{
2017-12-29 04:35:28 +08:00
$response = $this->httpClient->post('/api/pireps/'.$pirep_id.'/file', [
2018-08-27 00:40:04 +08:00
'json' => [],
2017-12-27 04:54:28 +08:00
]);
$body = \json_decode($response->getBody()->getContents());
2017-12-27 04:54:28 +08:00
return $body;
}
2017-12-26 09:23:58 +08:00
/**
* @param $pirep_id
* @param $data
2018-08-27 00:40:04 +08:00
*
* @throws \RuntimeException
2018-08-27 00:40:04 +08:00
*
* @return array
2017-12-26 09:23:58 +08:00
*/
protected function postUpdate($pirep_id, $data)
{
$uri = '/api/pireps/'.$pirep_id.'/acars/position';
2018-01-20 05:12:08 +08:00
$position = [
'log' => '',
'lat' => $data->latitude,
'lon' => $data->longitude,
'heading' => $data->heading,
'altitude' => $data->altitude,
'gs' => $data->groundspeed,
2018-01-20 05:12:08 +08:00
'transponder' => $data->transponder,
];
2017-12-26 09:23:58 +08:00
$upd = [
2018-01-20 05:12:08 +08:00
'positions' => [
2018-08-27 00:40:04 +08:00
$position,
],
2017-12-26 09:23:58 +08:00
];
2018-01-20 05:12:08 +08:00
$this->info("Update: $data->callsign, $position[lat] x $position[lon] \t\t"
."hdg: $position[heading]\t\talt: $position[altitude]\t\tgs: $position[gs]");
2017-12-26 09:23:58 +08:00
$response = $this->httpClient->post($uri, [
2018-08-27 00:40:04 +08:00
'json' => $upd,
2017-12-26 09:23:58 +08:00
]);
$body = \json_decode($response->getBody()->getContents());
2017-12-26 09:23:58 +08:00
return [
$data->callsign,
2018-01-20 05:12:08 +08:00
$position['lat'],
$position['lon'],
$position['heading'],
$position['altitude'],
2018-08-27 00:40:04 +08:00
$position['gs'],
2017-12-26 09:23:58 +08:00
];
}
/**
* Parse this file and run the updates
2018-08-27 00:40:04 +08:00
*
* @param array $files
2018-08-27 00:40:04 +08:00
*
* @throws \RuntimeException
*/
2017-12-28 10:52:37 +08:00
protected function updatesFromFile(array $files)
{
/**
* @var $flights Collection
*/
$flights = collect($files)->transform(function ($f) {
$file = storage_path('/replay/'.$f.'.json');
if (file_exists($file)) {
$this->info('Loading '.$file);
$contents = file_get_contents($file);
$contents = \json_decode($contents);
return collect($contents->updates);
}
2018-08-27 00:40:04 +08:00
$this->error($file.' not found, skipping');
return false;
})
2018-08-27 00:40:04 +08:00
// remove any of errored file entries
->filter(function ($value, $key) {
return $value !== false;
});
$this->info('Starting playback');
2018-08-27 00:40:04 +08:00
/*
* 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);
});
2018-08-27 00:40:04 +08:00
/*
* 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) {
2017-12-27 04:54:28 +08:00
$flights = $flights->each(function ($updates, $idx) {
$update = $updates->shift();
2017-12-26 09:23:58 +08:00
$pirep_id = $this->pirepList[$update->callsign];
2017-12-27 04:54:28 +08:00
$this->postUpdate($pirep_id, $update);
2018-08-27 00:40:04 +08:00
// we're done and don't put the "no-submit" option
if ($updates->count() === 0 && !$this->option('no-submit')) {
2017-12-27 04:54:28 +08:00
$this->filePirep($pirep_id);
}
})->filter(function ($updates, $idx) {
return $updates->count() > 0;
});
2017-12-26 09:23:58 +08:00
if (!$this->option('write-all')) {
2017-12-27 04:54:28 +08:00
if (!$this->option('manual')) {
sleep($this->sleepTime);
} else {
$this->confirm('Send next batch of updates?', true);
}
2017-12-26 09:23:58 +08:00
}
}
}
/**
* Execute the console command.
2018-08-27 00:40:04 +08:00
*
* @throws \RuntimeException
2018-08-27 00:40:04 +08:00
*
* @return mixed
*/
2018-08-27 02:50:08 +08:00
public function handle(): void
{
$files = $this->argument('files');
$manual_mode = $this->option('manual');
2017-12-27 04:54:28 +08:00
if ($this->option('write-all')) {
$this->info('In "dump-all" mode, just writing it all in');
} else {
2018-08-27 02:51:47 +08:00
/* @noinspection NestedPositiveIfStatementsInspection */
2017-12-27 04:54:28 +08:00
if (!$manual_mode) {
$this->info('Going to send updates every 10s');
} else {
$this->info('In "manual advance" mode');
}
}
2017-12-28 10:52:37 +08:00
$this->updatesFromFile(explode(',', $files));
$this->info('Done!');
}
}