Browse Source

Added menu with two pages (RawDataPage and DashboardPage)

Added temperature and altitude display in RawDataPage
master
Youen Toupin 3 years ago
parent
commit
f5ea6054da
  1. 5
      WebApp/package.json
  2. 12
      WebApp/src/app.ts
  3. 29
      WebApp/src/dashboard-page.tsx
  4. 1
      WebApp/src/index.html
  5. 3
      WebApp/src/layout.css
  6. 33
      WebApp/src/layout.tsx
  7. 3
      WebApp/src/main-page.css
  8. 21
      WebApp/src/monitor-api.ts
  9. 3
      WebApp/src/raw-data-page.css
  10. 10
      WebApp/src/raw-data-page.tsx

5
WebApp/package.json

@ -10,7 +10,6 @@
"author": "Youen Toupin", "author": "Youen Toupin",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"mithril": "^2.0.4"
}, },
"devDependencies": { "devDependencies": {
"@types/mithril": "^2.0.9", "@types/mithril": "^2.0.9",
@ -20,6 +19,8 @@
"ts-loader": "^9.2.8", "ts-loader": "^9.2.8",
"typescript": "^4.6.2", "typescript": "^4.6.2",
"webpack": "^5.70.0", "webpack": "^5.70.0",
"webpack-cli": "^4.9.2" "webpack-cli": "^4.9.2",
"bulma": "^0.9.3",
"mithril": "^2.0.4"
} }
} }

12
WebApp/src/app.ts

@ -1,4 +1,12 @@
import m from 'mithril'; import m from 'mithril';
import MainPage from './main-page';
m.mount(document.body, MainPage); import Layout from './layout';
import RawDataPage from './raw-data-page';
import DashboardPage from './dashboard-page';
require('../node_modules/bulma/css/bulma.css');
m.route(document.body, "/raw", {
"/dashboard": { render: () => m(Layout, m(DashboardPage)) },
"/raw": { render: () => m(Layout, m(RawDataPage)) },
});

29
WebApp/src/dashboard-page.tsx

@ -0,0 +1,29 @@
import m from 'mithril';
import { MonitorApi, Status } from './monitor-api';
export default class DashboardPage {
api = new MonitorApi();
status?: Status;
autoRefresh = true;
oninit() {
this.refresh();
}
onbeforeremove() {
this.autoRefresh = false;
}
async refresh() {
this.status = await this.api.getStatus();
if(this.autoRefresh)
setTimeout(() => { if(this.autoRefresh) this.refresh(); }, 500);
}
view() {
return this.status
? <div class="dashboard-page">
</div>
: <p>Chargement...</p>;
}
}

1
WebApp/src/index.html

@ -1,6 +1,7 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Ordinateur de bord</title> <title>Ordinateur de bord</title>
</head> </head>
<body> <body>

3
WebApp/src/layout.css

@ -0,0 +1,3 @@
/*html body {
font-size: 3rem;
}*/

33
WebApp/src/layout.tsx

@ -0,0 +1,33 @@
import m from 'mithril';
require("./layout.css");
export default class Layout {
private menuActive = false;
view(vnode: m.Vnode) {
return [
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href='#!/dashboard'>Tableau de bord</a>
<a role="button" class={'navbar-burger ' + (this.menuActive ? 'is-active' : '')} onclick={() => this.menuActive = !this.menuActive} aria-label="menu" aria-expanded="false" data-target="mainMenu">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="mainMenu" class={'navbar-menu ' + (this.menuActive ? 'is-active' : '')}>
<div class="navbar-start" onclick={() => { this.menuActive = false; return true; }}>
<a class="navbar-item" href='#!/raw'>Données brutes</a>
</div>
</div>
</nav>,
<section>
{vnode.children}
</section>
];
}
}

3
WebApp/src/main-page.css

@ -1,3 +0,0 @@
.main-page p {
font-size: 4rem;
}

21
WebApp/src/monitor-api.ts

@ -1,19 +1,26 @@
import m from 'mithril'; import m from 'mithril';
export interface Status { export interface Status {
batteryVoltage: number; batteryVoltage: number; // in Volts
motorCurrent: number; motorCurrent: number; // in Amperes
speed: number; // in meters per second speed: number; // in meters per second
temperature: number; // in Celcius degrees
altitude: number; // in meters above sea level
}; };
interface ApiStatus { interface ApiStatus {
v: number; v: number;
c: number; c: number;
s: number; s: number;
t: number;
alt: number;
} }
export class MonitorApi { export class MonitorApi {
constructor(private mockServer: boolean) { private mockServer: boolean;
constructor() {
this.mockServer = window.location.protocol == "file:";
} }
async getStatus(): Promise<Status> { async getStatus(): Promise<Status> {
@ -24,7 +31,9 @@ export class MonitorApi {
apiStatus = { apiStatus = {
v: Math.random() * 20000 + 20000, v: Math.random() * 20000 + 20000,
c: Math.random() * 30000, c: Math.random() * 30000,
s: Math.random() * 14000 s: Math.random() * 14000,
t: Math.random() * 400 - 100,
alt: Math.random() * 4500000 - 200000
} }
setTimeout(() => m.redraw(), 0); setTimeout(() => m.redraw(), 0);
} else { } else {
@ -37,7 +46,9 @@ export class MonitorApi {
return { return {
batteryVoltage: apiStatus.v / 1000, batteryVoltage: apiStatus.v / 1000,
motorCurrent: apiStatus.c / 1000, motorCurrent: apiStatus.c / 1000,
speed: apiStatus.s / 1000 speed: apiStatus.s / 1000,
temperature: apiStatus.t / 10,
altitude: apiStatus.alt / 1000
}; };
} }
} }

3
WebApp/src/raw-data-page.css

@ -0,0 +1,3 @@
.raw-data-page p {
font-size: 2rem;
}

10
WebApp/src/main-page.tsx → WebApp/src/raw-data-page.tsx

@ -1,10 +1,10 @@
import m from 'mithril'; import m from 'mithril';
import { MonitorApi, Status } from './monitor-api'; import { MonitorApi, Status } from './monitor-api';
require("./main-page.css"); require("./raw-data-page.css");
export default class MainPage { export default class RawDataPage {
api = new MonitorApi(false); api = new MonitorApi();
status?: Status; status?: Status;
autoRefresh = true; autoRefresh = true;
@ -24,11 +24,13 @@ export default class MainPage {
view() { view() {
return this.status return this.status
? <div class="main-page"> ? <div class="raw-data-page">
<p>Tension batterie : {this.status.batteryVoltage.toFixed(3)}V</p> <p>Tension batterie : {this.status.batteryVoltage.toFixed(3)}V</p>
<p>Courant : {this.status.motorCurrent.toFixed(3)}A</p> <p>Courant : {this.status.motorCurrent.toFixed(3)}A</p>
<p>Puissance : {(this.status.batteryVoltage * this.status.motorCurrent).toFixed(1)}W</p> <p>Puissance : {(this.status.batteryVoltage * this.status.motorCurrent).toFixed(1)}W</p>
<p>Vitesse : {(this.status.speed * 3.6).toFixed(1)}km/h</p> <p>Vitesse : {(this.status.speed * 3.6).toFixed(1)}km/h</p>
<p>Temperature : {this.status.temperature.toFixed(1)}°C</p>
<p>Altitude : {this.status.altitude.toFixed(1)}m</p>
</div> </div>
: <p>Chargement...</p>; : <p>Chargement...</p>;
} }
Loading…
Cancel
Save