|
|
|
import m from 'mithril';
|
|
|
|
|
|
|
|
export interface Status {
|
|
|
|
batteryVoltage: number; // in Volts
|
|
|
|
motorCurrent: number; // in Amperes
|
|
|
|
speed: number; // in meters per second
|
|
|
|
tripDistance: number; // in meters
|
|
|
|
tripTotalTime: number; // in seconds
|
|
|
|
tripMovingTime: number; // in seconds
|
|
|
|
tripAscendingElevation: number; // in meters
|
|
|
|
tripMotorEnergy: number; // in Watt-hour
|
|
|
|
temperature: number; // in Celcius degrees
|
|
|
|
altitude: number; // in meters above sea level
|
|
|
|
};
|
|
|
|
|
|
|
|
interface ApiStatus {
|
|
|
|
v: number; // voltage (mV)
|
|
|
|
c: number; // current (mA)
|
|
|
|
s: number; // speed (mm/s)
|
|
|
|
td: number; // trip distance (m)
|
|
|
|
ttt: number; // trip total time (s)
|
|
|
|
tmt: number; // trip moving time (s)
|
|
|
|
tae: number; // trip ascending elevation (m)
|
|
|
|
tme: number; // trip motor energy (Wh)
|
|
|
|
temp: number; // temperature (tenth of °C)
|
|
|
|
alt: number; // altitude (mm)
|
|
|
|
}
|
|
|
|
|
|
|
|
export class MonitorApi {
|
|
|
|
private mockServer: boolean;
|
|
|
|
private lastStatus: Status = null;
|
|
|
|
private static api: MonitorApi = null;
|
|
|
|
|
|
|
|
private lastFetchTime = 0;
|
|
|
|
private lastFetchAltitude = -100000;
|
|
|
|
|
|
|
|
private mockedTripDistance = 0;
|
|
|
|
private mockedTripTotalTime = 0;
|
|
|
|
private mockedTripMovingTime = 0;
|
|
|
|
private mockedTripAscendingElevation = 0;
|
|
|
|
private mockedTripMotorEnergy = 0;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.mockServer = window.location.protocol == "file:";
|
|
|
|
}
|
|
|
|
|
|
|
|
static get() {
|
|
|
|
if(MonitorApi.api == null)
|
|
|
|
MonitorApi.api = new MonitorApi();
|
|
|
|
return MonitorApi.api;
|
|
|
|
}
|
|
|
|
|
|
|
|
getStatus() { return this.lastStatus; }
|
|
|
|
|
|
|
|
async fetchStatus(): Promise<Status> {
|
|
|
|
let apiStatus: ApiStatus;
|
|
|
|
|
|
|
|
if(this.mockServer) {
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
|
|
|
|
let t = Date.now() / 1000.0;
|
|
|
|
if(this.lastFetchTime == 0) this.lastFetchTime = t;
|
|
|
|
let dt = t - this.lastFetchTime;
|
|
|
|
this.lastFetchTime = t;
|
|
|
|
|
|
|
|
let speed = (Math.cos(t*0.3)+1.0)*0.5 * 14; // in meters per second
|
|
|
|
if(speed < 0.25) speed = 0;
|
|
|
|
|
|
|
|
this.mockedTripDistance += speed * dt;
|
|
|
|
this.mockedTripTotalTime += dt;
|
|
|
|
if(speed > 0)
|
|
|
|
this.mockedTripMovingTime += dt;
|
|
|
|
|
|
|
|
let altitude = (Math.cos(t*0.0001)+1.0)*0.5 * 4500 - 200 + (Math.cos(t*0.03))*0.5 * 60; // in meters
|
|
|
|
if(this.lastFetchAltitude == -100000) this.lastFetchAltitude = altitude;
|
|
|
|
let altitudeChange = altitude - this.lastFetchAltitude;
|
|
|
|
this.lastFetchAltitude = altitude;
|
|
|
|
|
|
|
|
if(altitudeChange > 0)
|
|
|
|
this.mockedTripAscendingElevation += altitudeChange;
|
|
|
|
|
|
|
|
let voltage = (Math.cos(t*0.4)+1.0)*0.5 * 6 + 36;
|
|
|
|
let current = (Math.cos(t*0.7)+1.0)*0.5 * 30;
|
|
|
|
let newEnergy = voltage * current * dt / 3600;
|
|
|
|
this.mockedTripMotorEnergy += newEnergy;
|
|
|
|
|
|
|
|
apiStatus = {
|
|
|
|
v: Math.round(voltage * 1000),
|
|
|
|
c: Math.round(current * 1000),
|
|
|
|
s: Math.round(speed * 1000),
|
|
|
|
td: Math.round(this.mockedTripDistance),
|
|
|
|
ttt: Math.round(this.mockedTripTotalTime),
|
|
|
|
tmt: Math.round(this.mockedTripMovingTime),
|
|
|
|
tae: Math.round(this.mockedTripAscendingElevation*10.0),
|
|
|
|
tme: Math.round(this.mockedTripMotorEnergy*10.0),
|
|
|
|
temp: Math.round((Math.cos(t*0.2)+1.0)*0.5 * 400 - 100),
|
|
|
|
alt: Math.round(altitude * 1000)
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
apiStatus = await new Promise<ApiStatus>((resolve, error) => {
|
|
|
|
let request = new XMLHttpRequest();
|
|
|
|
request.onreadystatechange = () => {
|
|
|
|
if(request.readyState == 4) {
|
|
|
|
if(request.status == 200) {
|
|
|
|
resolve(JSON.parse(request.response));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
error();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
request.open('GET', '/api/status', true);
|
|
|
|
request.send();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.lastStatus = {
|
|
|
|
batteryVoltage: apiStatus.v / 1000,
|
|
|
|
motorCurrent: apiStatus.c / 1000,
|
|
|
|
speed: apiStatus.s / 1000,
|
|
|
|
tripDistance: apiStatus.td,
|
|
|
|
tripTotalTime: apiStatus.ttt,
|
|
|
|
tripMovingTime: apiStatus.tmt,
|
|
|
|
tripAscendingElevation: apiStatus.tae / 10,
|
|
|
|
tripMotorEnergy: apiStatus.tme / 10,
|
|
|
|
temperature: apiStatus.temp / 10,
|
|
|
|
altitude: apiStatus.alt / 1000
|
|
|
|
};
|
|
|
|
|
|
|
|
return this.lastStatus;
|
|
|
|
}
|
|
|
|
}
|