|
|
|
import m from 'mithril';
|
|
|
|
import { Page } from 'components/page';
|
|
|
|
import { MonitorApi, Status } from 'monitor-api';
|
|
|
|
import { Pipe } from 'utilities/pipe';
|
|
|
|
|
|
|
|
import { Clock } from 'components/widgets/clock';
|
|
|
|
import { NumericValue } from 'components/widgets/numeric-value';
|
|
|
|
import { GaugeLinear } from 'components/widgets/gauge-linear';
|
|
|
|
import { GaugeCircular } from 'components/widgets/gauge-circular';
|
|
|
|
import { GaugeBattery } from 'components/widgets/gauge-battery';
|
|
|
|
|
|
|
|
require('./dashboard-page.css');
|
|
|
|
|
|
|
|
export class DashboardPage extends Page {
|
|
|
|
status: Status = null;
|
|
|
|
autoRefresh = true;
|
|
|
|
|
|
|
|
private power = new Pipe(0.0);
|
|
|
|
private battery = new Pipe(0.0);
|
|
|
|
private speed = new Pipe(0.0);
|
|
|
|
|
|
|
|
private tripDistance = new Pipe(0.0);
|
|
|
|
private tripAverageSpeed = new Pipe(0.0);
|
|
|
|
private tripEnergy = new Pipe(0.0);
|
|
|
|
private tripAverageConsumption = new Pipe(0.0);
|
|
|
|
private tripAscendingElevation = new Pipe(0.0);
|
|
|
|
|
|
|
|
private altitude = new Pipe(0.0);
|
|
|
|
private temperature = new Pipe(0.0);
|
|
|
|
|
|
|
|
oninit() {
|
|
|
|
this.status = MonitorApi.get().getStatus();
|
|
|
|
this.refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
onbeforeremove(vnode: m.Vnode<{}, {}>) {
|
|
|
|
this.autoRefresh = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
async refresh() {
|
|
|
|
let newStatus = await MonitorApi.get().fetchStatus();
|
|
|
|
if(this.status == null)
|
|
|
|
m.redraw();
|
|
|
|
this.status = newStatus;
|
|
|
|
|
|
|
|
let power = Math.max(0.0, this.status.batteryVoltage * this.status.motorCurrent);
|
|
|
|
this.power.set(power);
|
|
|
|
|
|
|
|
const minVoltage = 36.0;
|
|
|
|
const maxVoltage = 42.0;
|
|
|
|
let batteryRatio = Math.max(0.0, (this.status.batteryVoltage - minVoltage) / (maxVoltage - minVoltage));
|
|
|
|
this.battery.set(batteryRatio * batteryRatio * 100.0); // TODO: find a better formula to estimate remaining energy from battery voltage and power
|
|
|
|
|
|
|
|
this.speed.set(this.status.speed * 3.6); // convert m/s to km/h
|
|
|
|
|
|
|
|
this.tripDistance.set(this.status.tripDistance/1000);
|
|
|
|
this.tripAverageSpeed.set(this.status.tripDistance/1000 / (Math.max(1.0, this.status.tripMovingTime)/3600));
|
|
|
|
this.tripEnergy.set(this.status.tripMotorEnergy);
|
|
|
|
this.tripAverageConsumption.set(this.status.tripMotorEnergy / Math.max(0.1, this.status.tripDistance/1000));
|
|
|
|
this.tripAscendingElevation.set(this.status.tripAscendingElevation);
|
|
|
|
|
|
|
|
this.temperature.set(this.status.temperature);
|
|
|
|
this.altitude.set(this.status.altitude);
|
|
|
|
|
|
|
|
if(this.autoRefresh)
|
|
|
|
setTimeout(() => { if(this.autoRefresh) this.refresh(); }, 150);
|
|
|
|
}
|
|
|
|
|
|
|
|
view() {
|
|
|
|
return this.status
|
|
|
|
? <div class="dashboard-page">
|
|
|
|
<div class="widgets-row">
|
|
|
|
<Clock/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="widgets-row" style="height: 40%">
|
|
|
|
<GaugeLinear widgetWidth={0.2} value={this.power} minValue={0} maxValue={999.0} bottomWidth={0.4} unit="W" />
|
|
|
|
<GaugeCircular widgetWidth={0.6} value={this.speed} minValue={0} maxValue={50.0} decimals={1} unit="km/h" />
|
|
|
|
<GaugeBattery widgetWidth={0.2} value={this.battery} minValue={0} maxValue={100.0} unit="%" />
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="widgets-row">
|
|
|
|
<NumericValue widgetWidth={0.5} value={this.tripDistance} decimals={1} unit="km" />
|
|
|
|
</div>
|
|
|
|
<div class="widgets-row">
|
|
|
|
<NumericValue widgetWidth={0.5} value={this.tripAverageSpeed} decimals={1} unit="km/h" />
|
|
|
|
<NumericValue widgetWidth={0.5} value={this.tripAscendingElevation} decimals={1} unit="m" />
|
|
|
|
</div>
|
|
|
|
<div class="widgets-row">
|
|
|
|
<NumericValue widgetWidth={0.5} value={this.tripAverageConsumption} decimals={1} unit="Wh/km" />
|
|
|
|
<NumericValue widgetWidth={0.5} value={this.tripEnergy} decimals={1} unit="Wh" />
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="widgets-row">
|
|
|
|
<NumericValue widgetWidth={0.5} value={this.temperature} decimals={1} unit="°C" />
|
|
|
|
<NumericValue widgetWidth={0.5} value={this.altitude} decimals={1} unit="m" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
: <p>Chargement...</p>;
|
|
|
|
}
|
|
|
|
}
|