From 050f64530475c68b7156f0a64fa55ac7d5c46738 Mon Sep 17 00:00:00 2001 From: Alex McBean Date: Fri, 12 Aug 2022 17:46:27 +0100 Subject: [PATCH] feat(simbridge): simbridge client (#7378) * Initial Commit * Simbridge client returns objects rather than response * remove Terrain Component - Terrain component added when #7268 merged * fix: added src folder to folder structure --- .gitignore | 1 + .../FlyByWire_A320_Neo/CDU/A320_Neo_CDU.html | 1 + igniter.config.mjs | 3 + package.json | 1 + src/simbridge-client/rollup.config.js | 75 ++++++++++++++++++ src/simbridge-client/src/Coroute/Airport.ts | 4 + src/simbridge-client/src/Coroute/Fix.ts | 16 ++++ src/simbridge-client/src/Coroute/General.ts | 3 + src/simbridge-client/src/Coroute/Navlog.ts | 5 ++ src/simbridge-client/src/Coroute/coroute.ts | 15 ++++ src/simbridge-client/src/common.ts | 3 + .../src/components/Coroute.ts | 40 ++++++++++ src/simbridge-client/src/components/Viewer.ts | 79 +++++++++++++++++++ src/simbridge-client/src/index.ts | 4 + src/simbridge-client/tsconfig.json | 13 +++ 15 files changed, 263 insertions(+) create mode 100644 src/simbridge-client/rollup.config.js create mode 100644 src/simbridge-client/src/Coroute/Airport.ts create mode 100644 src/simbridge-client/src/Coroute/Fix.ts create mode 100644 src/simbridge-client/src/Coroute/General.ts create mode 100644 src/simbridge-client/src/Coroute/Navlog.ts create mode 100644 src/simbridge-client/src/Coroute/coroute.ts create mode 100644 src/simbridge-client/src/common.ts create mode 100644 src/simbridge-client/src/components/Coroute.ts create mode 100644 src/simbridge-client/src/components/Viewer.ts create mode 100644 src/simbridge-client/src/index.ts create mode 100644 src/simbridge-client/tsconfig.json diff --git a/.gitignore b/.gitignore index 1709b8c72c6..ca0ad1fdaea 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ /flybywire-aircraft-a320-neo/html_ui/JS/fmgc/ /flybywire-aircraft-a320-neo/html_ui/JS/sentry-client/ /flybywire-aircraft-a320-neo/html_ui/JS/tcas/ +/flybywire-aircraft-a320-neo/html_ui/JS/simbridge-client/ /flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/A32NX/* !/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/A32NX/PFD /flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/A32NX/PFD/*.js diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU.html b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU.html index 1e533288617..88beca001b1 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU.html +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU.html @@ -29,6 +29,7 @@ + diff --git a/igniter.config.mjs b/igniter.config.mjs index 329b0169a1d..d76ea970860 100644 --- a/igniter.config.mjs +++ b/igniter.config.mjs @@ -37,6 +37,9 @@ export default new TaskOfTasks('a32nx', [ 'src/flypad-backend/build.sh', 'wasm-opt -O1 -o flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel/flypad-backend.wasm flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel/flypad-backend.wasm' ], ['src/flypad-backend', 'flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel/flypad-backend.wasm']), + new TaskOfTasks('simbridge', [ + new ExecTask('client', ['npm run build:simbridge-client'], ['src/simbridge-client', 'flybywire-aircraft-a320-neo/html_ui/JS/simbridge-client']), + ]), new TaskOfTasks('mcdu-server', [ new ExecTask('client', ['npm run build:mcdu-client'], ['src/mcdu-server/client', 'src/mcdu-server/client/build']), new ExecTask('server', ['npm run build:mcdu-server'], ['src/mcdu-server', 'flybywire-aircraft-a320-neo/MCDU SERVER/server.exe']), diff --git a/package.json b/package.json index 0568532db05..384c5e4a3f0 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "build:pfd": "cd src/instruments/src/PFD && rollup -c", "build:mcdu-client": "rollup -c src/mcdu-server/client/rollup.config.js", "build:mcdu-server": "pkg src/mcdu-server/index.js --target node12-win-x64 --no-bytecode --public-packages \"*\" --public --output \"flybywire-aircraft-a320-neo/MCDU SERVER/server.exe\"", + "build:simbridge-client": "rollup -c src/simbridge-client/rollup.config.js", "build:ace": "node --max-old-space-size=8192 node_modules/rollup/dist/bin/rollup -wc .\\src\\instruments\\buildSrc\\aceBuild.mjs" }, "lint-staged": { diff --git a/src/simbridge-client/rollup.config.js b/src/simbridge-client/rollup.config.js new file mode 100644 index 00000000000..e4b7213052b --- /dev/null +++ b/src/simbridge-client/rollup.config.js @@ -0,0 +1,75 @@ +/* + * MIT License + * + * Copyright (c) 2022 FlyByWire Simulations + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +'use strict'; + +const { join } = require('path'); +const babel = require('@rollup/plugin-babel').default; +const { typescriptPaths } = require('rollup-plugin-typescript-paths'); +const dotenv = require('dotenv'); +const commonjs = require('@rollup/plugin-commonjs'); +const nodeResolve = require('@rollup/plugin-node-resolve').default; +const json = require('@rollup/plugin-json'); + +const replace = require('@rollup/plugin-replace'); + +const extensions = ['.js', '.ts']; + +const src = join(__dirname, '..'); +const root = join(__dirname, '..', '..'); + +dotenv.config(); + +process.chdir(src); + +module.exports = { + input: join(__dirname, 'src/index.ts'), + plugins: [ + nodeResolve({ extensions, browser: true }), + commonjs(), + json(), + babel({ + presets: ['@babel/preset-typescript', ['@babel/preset-env', { targets: { browsers: ['safari 11'] } }]], + plugins: [ + '@babel/plugin-proposal-class-properties', + ], + extensions, + }), + typescriptPaths({ + tsConfigPath: join(src, 'tsconfig.json'), + preserveExtensions: true, + }), + replace({ + 'DEBUG': 'false', + 'process.env.NODE_ENV': '"production"', + 'process.env.SENTRY_DSN': JSON.stringify(process.env.SENTRY_DSN), + 'preventAssignment': true, + }), + ], + output: { + file: join(root, 'flybywire-aircraft-a320-neo/html_ui/JS/simbridge-client/simbridge-client.js'), + format: 'umd', + name: 'SimbridgeClient', + }, +}; diff --git a/src/simbridge-client/src/Coroute/Airport.ts b/src/simbridge-client/src/Coroute/Airport.ts new file mode 100644 index 00000000000..f61e1da0dae --- /dev/null +++ b/src/simbridge-client/src/Coroute/Airport.ts @@ -0,0 +1,4 @@ +/* eslint-disable camelcase */ +export interface Airport { + icao_code: String +} diff --git a/src/simbridge-client/src/Coroute/Fix.ts b/src/simbridge-client/src/Coroute/Fix.ts new file mode 100644 index 00000000000..7fb4f938fc5 --- /dev/null +++ b/src/simbridge-client/src/Coroute/Fix.ts @@ -0,0 +1,16 @@ +/* eslint-disable camelcase */ +export interface Fix { + ident: String + + name: String + + type: String + + via_airway: String + + is_sid_star: String + + pos_lat: String + + pos_long: String +} diff --git a/src/simbridge-client/src/Coroute/General.ts b/src/simbridge-client/src/Coroute/General.ts new file mode 100644 index 00000000000..15c0a1a8368 --- /dev/null +++ b/src/simbridge-client/src/Coroute/General.ts @@ -0,0 +1,3 @@ +export interface General { + route: string +} diff --git a/src/simbridge-client/src/Coroute/Navlog.ts b/src/simbridge-client/src/Coroute/Navlog.ts new file mode 100644 index 00000000000..74eba2b356a --- /dev/null +++ b/src/simbridge-client/src/Coroute/Navlog.ts @@ -0,0 +1,5 @@ +import { Fix } from './fix'; + +export class Navlog { + fix: Fix[] = [] +} diff --git a/src/simbridge-client/src/Coroute/coroute.ts b/src/simbridge-client/src/Coroute/coroute.ts new file mode 100644 index 00000000000..bb64d95e225 --- /dev/null +++ b/src/simbridge-client/src/Coroute/coroute.ts @@ -0,0 +1,15 @@ +import { Airport } from './Airport'; +import { General } from './General'; +import { Navlog } from './Navlog'; + +export interface CoRouteDto { + name: String; + + origin: Airport; + + destination: Airport; + + general: General; + + navlog: Navlog +} diff --git a/src/simbridge-client/src/common.ts b/src/simbridge-client/src/common.ts new file mode 100644 index 00000000000..1d37437f61b --- /dev/null +++ b/src/simbridge-client/src/common.ts @@ -0,0 +1,3 @@ +import { NXDataStore } from '@shared/persistence'; + +export const simbridgeUrl: String = `http://localhost:${NXDataStore.get('CONFIG_SIMBRIDGE_PORT', '8380')}`; diff --git a/src/simbridge-client/src/components/Coroute.ts b/src/simbridge-client/src/components/Coroute.ts new file mode 100644 index 00000000000..99f0435f5ff --- /dev/null +++ b/src/simbridge-client/src/components/Coroute.ts @@ -0,0 +1,40 @@ +import { simbridgeUrl } from '../common'; +import { CoRouteDto } from '../Coroute/coroute'; + +/** + * Class responsible for retrieving data related to company routes from SimBridge + */ +export class CompanyRoute { + /** + * Used to retrieve a given company route + * @param route The routename in question + * @returns Returns the CoRoute DTO + */ + public static async getCoRoute(route: String): Promise { + if (route) { + const response = await fetch(`${simbridgeUrl}/api/v1/coroute?rteNum=${route}`); + if (response.status === 200) { + response.json(); + } + throw new Error('Server Error'); + } + throw new Error('No Company route provided'); + } + + /** + * Used to retrieve a list of company routes for a given origin and dest + * @param origin the origin + * @param dest the destination + * @returns Returns a list of CoRoute DTOs + */ + public static async getRouteList(origin: String, dest: String): Promise { + if (origin || dest) { + const response = await fetch(`${simbridgeUrl}/api/v1/coroute/list?origin=${origin}&destination=${dest}`); + if (response.ok) { + response.json(); + } + throw new Error('Server Error'); + } + throw new Error('Origin or Destination missing'); + } +} diff --git a/src/simbridge-client/src/components/Viewer.ts b/src/simbridge-client/src/components/Viewer.ts new file mode 100644 index 00000000000..247fd817a07 --- /dev/null +++ b/src/simbridge-client/src/components/Viewer.ts @@ -0,0 +1,79 @@ +import { simbridgeUrl } from '../common'; + +/** + * Class pertaining to retrieving static files for general viewing from SimBridge + */ +export class Viewer { + /** + * Used to retrieve a streamable image of specified page within a given PDF file + * @param filename required field, filename of the pdf + * @param pageNumber required field, The page of the PDF file + * @returns a Blob + */ + public static async getPDFPage(filename: string, pageNumber: number): Promise { + if (filename || pageNumber) { + const response = await fetch(`${simbridgeUrl}/api/v1/utility/pdf?filename=${filename}&pagenumber=${pageNumber}`); + if (response.ok) { + return response.blob(); + } + throw new Error(`SimBridge Error: ${response.status}`); + } + throw new Error('File name or page number missing'); + } + + /** + * Retrieve the number of pages within a specified PDF file + * @param filename required field, filename of the pdf + * @returns A number + */ + public static async getPDFPageNum(filename: string): Promise { + if (filename) { + const response = await fetch(`${simbridgeUrl}/api/v1/utility/pdf/numpages?filename=${filename}`); + if (response.ok) { + return response.json(); + } + throw new Error(`SimBridge Error: ${response.status}`); + } + throw new Error('File name or page number missing'); + } + + /** + * Used to retrieve a list of filenames within the PDF folder + * @returns an Array of strings + */ + public static async getPDFList(): Promise { + const response = await fetch(`${simbridgeUrl}/api/v1/utility/pdf/list`); + if (response.ok) { + return response.json(); + } + throw new Error(`SimBridge Error: ${response.status}`); + } + + /** + * Used to retrieve a streamable image of a specified image in the images folder + * @param filename required field, filename of the image + * @returns A Blob + */ + public static async getImage(filename: string, pageNumber: number): Promise { + if (filename || pageNumber) { + const response = await fetch(`${simbridgeUrl}/api/v1/utility/image?filename=${filename}`); + if (response.ok) { + return response.blob(); + } + throw new Error(`SimBridge Error: ${response.status}`); + } + throw new Error('File name or page number missing'); + } + + /** + * Used to retrieve a list of filenames within the PDF folder + * @returns an Array of strings + */ + public static async getImageList(): Promise { + const response = await fetch(`${simbridgeUrl}/api/v1/utility/image/list`); + if (response.ok) { + return response.json(); + } + throw new Error(`SimBridge Error: ${response.status}`); + } +} diff --git a/src/simbridge-client/src/index.ts b/src/simbridge-client/src/index.ts new file mode 100644 index 00000000000..f6d10beef48 --- /dev/null +++ b/src/simbridge-client/src/index.ts @@ -0,0 +1,4 @@ +import { CompanyRoute } from './components/Coroute'; +import { Viewer } from './components/Viewer'; + +export { CompanyRoute, Viewer }; diff --git a/src/simbridge-client/tsconfig.json b/src/simbridge-client/tsconfig.json new file mode 100644 index 00000000000..b7d74e18154 --- /dev/null +++ b/src/simbridge-client/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "moduleResolution": "node", + "target": "ESNext", + "noEmit": true, + "typeRoots": ["../../typings"] + }, + "include": [ + "src/**/*", + "../../typings/**/*.d.ts" + ] + }