GT2/Ejectable/GT2.tsx

396 lines
12 KiB
TypeScript
Raw Permalink Normal View History

2021-08-25 02:25:04 +00:00
import React, { useState, useEffect, Component } from 'react';
2021-08-24 00:02:21 +00:00
import * as Location from 'expo-location';
2021-08-20 11:24:38 +00:00
import { Text, View } from './components/Themed';
2021-08-24 15:43:25 +00:00
import { StyleSheet } from 'react-native';
2021-08-25 02:25:04 +00:00
import * as geolib from 'geolib';
2021-08-24 00:02:21 +00:00
2021-08-29 00:11:00 +00:00
export const ver:string = "2.0.7"
2021-08-26 03:46:39 +00:00
var debug:number = 0;
2021-08-28 16:33:29 +00:00
var endIsNigh:boolean = false;
2021-08-25 02:25:04 +00:00
var testCount = 0;
var bgEnabled:boolean = false;
2021-08-24 00:02:21 +00:00
var expoGeoState:any = null;
export var locEnabled:boolean = false;
const heartbeat:number = 500;
2021-08-26 03:46:39 +00:00
const displayBeat:number = 3;
2021-08-29 00:47:37 +00:00
const ticksPerDS = 10;
2021-08-26 03:46:39 +00:00
const geoLibAccuracy:number = 0.1;
2021-08-28 20:57:24 +00:00
const minExpoAccuracy:number = 5;
2021-08-20 11:24:38 +00:00
2021-08-28 16:33:29 +00:00
export function getEndIsLast() : boolean { return endIsNigh; }
export function setEndIsLast(value:boolean) { endIsNigh = value; }
2021-08-20 11:24:38 +00:00
const styles = StyleSheet.create({
tripText: {
marginHorizontal: -10,
marginVertical: 60,
2021-08-23 06:34:16 +00:00
textAlign: 'left',
2021-08-20 11:24:38 +00:00
width: "80%",
fontSize: 12,
fontWeight: 'bold',
}});
2021-08-25 02:25:04 +00:00
interface expoGeoObj {
coords: [
altitude:number,
altitudeAccuracy:number,
latitude:number,
accuracy:number,
longitude:number,
heading:number,
speed:number,
timestamp:number
]
}
2021-08-20 11:24:38 +00:00
2021-08-25 07:59:02 +00:00
2021-08-25 02:25:04 +00:00
class Coordinate {
2021-08-22 04:30:04 +00:00
2021-08-25 02:25:04 +00:00
public mLatitude:number = 0.0;
public mLongitude:number = 0.0;
public glCoords:any = {};
2021-08-25 07:59:02 +00:00
constructor (latitude:number, longitude:number ) {
2021-08-25 02:25:04 +00:00
this.mLongitude = longitude;
this.mLatitude = latitude;
2021-08-25 07:59:02 +00:00
this.get_glcoords();
}
public set(lat:number,lon:number) {
this.mLatitude = lat;
this.mLongitude = lon;
this.get_glcoords();
2021-08-25 02:25:04 +00:00
}
public get_glcoords() {
2021-08-28 02:34:15 +00:00
this.glCoords['lat'] = this.mLatitude;
this.glCoords['lon'] = this.mLongitude;
2021-08-25 02:25:04 +00:00
}
2021-08-28 02:34:15 +00:00
public set_glcoords(lat:number,lon:number) {
this.glCoords['lat'] = lat;
this.glCoords['lon'] = lon;
}
public roundTo(precision:number) {
var lat = this.mLatitude * Math.pow(10,precision);
var lon = this.mLongitude * Math.pow(10,precision);
lat = (Math.round(lat)) / Math.pow(10,precision);
lon = (Math.round(lon)) / Math.pow(10, precision);
this.set_glcoords(lat,lon);
}
2021-08-25 02:25:04 +00:00
public distanceTo(otherPoint:Coordinate) : number {
2021-08-28 02:34:15 +00:00
this.roundTo(Trips.sensitivity)
otherPoint.roundTo(Trips.sensitivity);
2021-08-25 07:59:02 +00:00
return geolib.getPreciseDistance(this.glCoords,otherPoint.glCoords,geoLibAccuracy);
2021-08-25 02:25:04 +00:00
}
}
2021-08-25 07:59:02 +00:00
2021-08-25 02:25:04 +00:00
async function startTracking(client:any){
if (debug > 5) console.log('Starting tracking')
if(!client.location){
client.location = await Location.watchPositionAsync({
accuracy: Location.Accuracy.Highest,
distanceInterval: 3,
timeInterval: (heartbeat / 2),
}, (loc) => {
Trips.deltaLoc(loc)
});
}
}
async function stopTracking(client:any){
if (debug > 5) console.log('Remove tracking')
await client.location.remove();
}
2021-08-24 00:02:21 +00:00
class Trip {
2021-08-20 11:24:38 +00:00
2021-08-25 07:59:02 +00:00
public elapsed:string = "00.00.00";
ticks:number = 0;
2021-08-24 00:02:21 +00:00
interval:any;
2021-08-29 00:47:37 +00:00
minTripDone:boolean = false;
2021-08-25 07:59:02 +00:00
segments:number = 1;
ds:number = 0;
CO2:number = 0.0;
location:any = null;
lastDSFixTick = 0;
lastFix:Coordinate = new Coordinate(0.0,0.0);
loc:Coordinate = new Coordinate(0.0,0.0);
2021-08-24 00:02:21 +00:00
2021-08-26 03:46:39 +00:00
tick() {let hours:number = 0, minutes:number = 0, seconds:number = 0, totals:number = 0;
this.ticks++;
totals = this.ticks * ( heartbeat / 1000 ) ;
hours = totals < 3600 ? 0 : (totals / 3600);
minutes = totals < 60 ? 0 : (totals - (hours * 3600)) / 60;
seconds = totals % 60;
2021-08-25 07:59:02 +00:00
this.elapsed = hours.toFixed(0) + ":" + minutes.toFixed(0) + ":" + seconds.toFixed(0);
}
2021-08-25 02:25:04 +00:00
public start() { this.interval = setInterval(() => this.tick(), heartbeat);
if (!bgEnabled) startTracking(this);
}
2021-08-25 07:59:02 +00:00
2021-08-25 02:25:04 +00:00
public resume() { this.lastFix.mLatitude = 0.0;
2021-08-24 00:02:21 +00:00
this.segments++;
this.interval = setInterval(() => this.tick(), heartbeat); }
2021-08-25 07:59:02 +00:00
2021-08-25 02:25:04 +00:00
public stop() { Trips.distance += this.ds;
this.ds = 0.0;
2021-08-24 00:02:21 +00:00
clearInterval(this.interval);
2021-08-25 02:25:04 +00:00
if (!bgEnabled) stopTracking(this);
2021-08-24 00:02:21 +00:00
}
}
2021-08-20 11:24:38 +00:00
export class GT2 {
2021-08-24 00:02:21 +00:00
trip:Trip = new Trip();
endPoint:Coordinate = new Coordinate(0.0,0.0);
startPoint:Coordinate = new Coordinate(0.0,0.0);
2021-08-21 07:45:27 +00:00
2021-08-23 06:34:16 +00:00
displayInterval:number = displayBeat * heartbeat;
2021-08-28 22:36:13 +00:00
arc:number = 0.0;
2021-08-23 06:34:16 +00:00
public distance:number = 0.0;
2021-08-24 00:02:21 +00:00
co2Rate:number = 250.0;
2021-08-28 02:34:15 +00:00
sensitivity:number = 3;
2021-08-23 06:34:16 +00:00
z:number = 0.0;
2021-08-24 00:02:21 +00:00
public v:number = 0.0;
2021-08-23 06:34:16 +00:00
public inProgress:boolean = false;
public paused:boolean = false;
public elapsed:number = 0.0;
elevation:number = 0.0;
2021-08-24 00:02:21 +00:00
public units:string = "km";
public CO2Effect:string = "carbon burden";
2021-08-23 06:34:16 +00:00
nTrips:number = 0;
2021-08-24 00:02:21 +00:00
n:number = 0.0;
m:number = 0.0;
2021-08-23 06:34:16 +00:00
public deltaLoc(lastFix:any) {
2021-08-26 03:46:39 +00:00
2021-08-28 02:34:15 +00:00
var t:number = 0.0;
var lat:number = 0.0;
var lon:number = 0.0;
2021-08-25 07:59:02 +00:00
lastFix = JSON.stringify(lastFix);
2021-08-24 00:02:21 +00:00
let expoFix:expoGeoObj = JSON.parse(lastFix);
2021-08-23 06:34:16 +00:00
2021-08-26 03:46:39 +00:00
if (debug > 10) {
console.log("lat " + expoFix.coords['latitude'] + " lon " + expoFix.coords['longitude']);
console.log("heading " + expoFix.coords['heading']);
console.log("accuracy " + expoFix.coords['accuracy']);
console.log("speed " + expoFix.coords['speed']);
}
2021-08-28 02:34:15 +00:00
lat = expoFix.coords['latitude']; lon = expoFix.coords['longitude'];
this.trip.loc.set(lat,lon);
2021-08-26 03:46:39 +00:00
2021-08-29 00:11:00 +00:00
if (Trips.startPoint.mLatitude == 0.0) Trips.startPoint.set(lat,lon);
2021-08-26 03:46:39 +00:00
2021-08-29 00:11:00 +00:00
if (this.trip.lastFix.mLatitude == 0.0)
this.trip.lastFix.set(lat,lon);
2021-08-25 07:59:02 +00:00
else
2021-08-29 00:11:00 +00:00
if ((this.trip.ticks % ticksPerDS) == 0) {
t = expoFix.coords['accuracy']; if (t < minExpoAccuracy ) return;
this.trip.ds += this.trip.lastFix.distanceTo(this.trip.loc);
2021-08-29 00:47:37 +00:00
if (this.trip.ds > 250 && !this.trip.minTripDone) {
2021-08-29 06:38:53 +00:00
this.trip.ds -= 250;
2021-08-29 00:47:37 +00:00
this.trip.minTripDone = true;
}
2021-08-28 02:34:15 +00:00
this.trip.lastFix.set(lat,lon);
2021-08-26 03:46:39 +00:00
if (debug > 10) console.log('delta ' + this.trip.ds);
2021-08-25 02:25:04 +00:00
}
2021-08-20 11:24:38 +00:00
}
public end() {
2021-08-25 07:59:02 +00:00
2021-08-24 00:02:21 +00:00
this.trip.stop();
2021-08-20 11:24:38 +00:00
this.inProgress = false;
2021-08-28 22:36:13 +00:00
this.arc = this.startPoint.distanceTo(this.trip.loc);
2021-08-25 07:59:02 +00:00
this.trip.CO2 = ( this.distance / 1000 ) * this.co2Rate;
2021-08-23 06:34:16 +00:00
this.nTrips++;
2021-08-24 00:02:21 +00:00
2021-08-20 11:24:38 +00:00
}
2021-08-28 16:33:29 +00:00
public from(last:GT2) {
this.startPoint = last.startPoint;
this.trip.loc = last.trip.loc;
this.elapsed = last.elapsed;
2021-08-29 11:16:05 +00:00
this.trip.elapsed= last.trip.elapsed;
2021-08-28 16:33:29 +00:00
this.endPoint = last.endPoint;
this.CO2Effect = last.CO2Effect;
this.co2Rate = last.co2Rate;
this.units = last.units;
this.sensitivity = last.sensitivity;
2021-08-28 22:36:13 +00:00
this.arc = last.arc;
2021-08-28 16:33:29 +00:00
}
2021-08-24 00:02:21 +00:00
public setLocEnabled(value:boolean) { locEnabled = value}
2021-08-20 11:24:38 +00:00
public pause() {
2021-08-23 06:34:16 +00:00
if (!this.paused) {
2021-08-24 00:02:21 +00:00
this.trip.stop();
2021-08-23 06:34:16 +00:00
this.paused = true;
} else {
2021-08-24 00:02:21 +00:00
this.trip.resume();
2021-08-23 06:34:16 +00:00
this.paused = false;
}
2021-08-20 11:24:38 +00:00
}
2021-08-24 00:02:21 +00:00
public reset() {
this.distance = 0.0;
2021-08-28 22:36:13 +00:00
this.arc = 0.0;
2021-08-24 00:02:21 +00:00
this.endPoint = new Coordinate(0,0);
this.startPoint = new Coordinate(0,0);
this.v = 0;
this.inProgress = false;
this.paused = false;
this.elapsed = 0.0;
}
2021-08-20 11:24:38 +00:00
public start() {
2021-08-23 06:34:16 +00:00
this.reset();
2021-08-24 00:02:21 +00:00
this.trip = new Trip();
this.trip.start();
2021-08-20 11:24:38 +00:00
this.inProgress = true;
2021-08-24 00:02:21 +00:00
2021-08-20 11:24:38 +00:00
}
2021-08-24 00:02:21 +00:00
lt:number = 0.0;
public getTripSummary() : string {
2021-08-25 02:25:04 +00:00
var preferredUnits:number = ((this.units == 'km') ? (this.distance / 1000)
: (this.distance / 1609.34));
2021-08-28 22:36:13 +00:00
var preferredUnitsArc:number = ((this.units == 'km') ? (this.arc / 1000)
: (this.arc / 1609.34));
2021-08-25 02:25:04 +00:00
2021-08-24 00:02:21 +00:00
return (
'Elapsed - ' + this.trip.elapsed + '\n' +
2021-08-28 16:33:29 +00:00
'Origin: ' + 'lat: ' + this.startPoint.mLatitude.toFixed(8) +
' long: ' + this.startPoint.mLongitude.toFixed(8) + '\n' +
2021-08-24 00:02:21 +00:00
'Destination: ' + 'lat: ' + this.trip.loc.mLatitude.toFixed(8) +
2021-08-25 02:25:04 +00:00
' long: ' + this.trip.loc.mLongitude.toFixed(8) + '\n' +
2021-08-25 07:59:02 +00:00
'CO2: ' + this.trip.CO2.toFixed(1) + ' grams ' + this.CO2Effect + '\n\n' +
2021-08-28 02:34:15 +00:00
'CO2 Rate / Sensitivity: ' + this.co2Rate + " / " + this.sensitivity + '\n' +
2021-08-28 22:36:13 +00:00
'Arc distance from origin to destination: ' + preferredUnitsArc.toFixed(2) + this.units + '\n' +
'Path distance while consuming fuel: ' + preferredUnits.toFixed(2) + ' ' + this.units );
2021-08-24 00:02:21 +00:00
}
2021-08-23 06:34:16 +00:00
public getTripPanel() : string {
2021-08-25 02:25:04 +00:00
var bigDS:number = this.distance + this.trip.ds;
2021-08-25 07:59:02 +00:00
var seconds:number = this.trip.ticks;
2021-08-25 02:25:04 +00:00
2021-08-24 00:02:21 +00:00
if (this.inProgress) {
2021-08-25 07:59:02 +00:00
this.v = this.trip.ds / seconds;
2021-08-24 00:02:21 +00:00
return (
'Elapsed - ' + this.trip.elapsed + '\n' +
'Geo: ' + 'lat: ' + this.trip.loc.mLatitude.toFixed(8) +
' long: ' + this.trip.loc.mLongitude.toFixed(8) + '\n' +
2021-08-25 07:59:02 +00:00
'Vector: ' + 'distance: ' + bigDS.toFixed(2) + ' meters, velocity: ' + this.v.toFixed(1) + ' m/s \n' +
2021-08-23 06:34:16 +00:00
'Altitude: ' + this.elevation + '\n');
2021-08-24 00:02:21 +00:00
}
else return("No trip in progress. " + this.nTrips + " trip(s) completed.");
2021-08-23 06:34:16 +00:00
}
}
export class TripDisplay extends React.Component {
constructor(props:any) {
super(props);
this.state = { seconds: 0 };
}
interval:any;
tick() {
this.setState(state => ({
seconds: 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), Trips.displayInterval);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
2021-08-20 11:24:38 +00:00
2021-08-25 02:25:04 +00:00
if (debug > 10)
2021-08-24 00:02:21 +00:00
return(
<View>
<Text style={styles.tripText}>
{Trips.getTripPanel() }
</Text>
</View> );
2021-08-29 00:11:00 +00:00
else
2021-08-24 00:02:21 +00:00
return(
<View>
2021-08-22 04:30:04 +00:00
<Text style={styles.tripText}>
2021-08-23 06:34:16 +00:00
{Trips.getTripPanel() }
2021-08-22 04:30:04 +00:00
</Text>
2021-08-24 00:02:21 +00:00
<Text>{expoGeoState}</Text>
</View> );
2021-08-20 11:24:38 +00:00
}
}
2021-08-24 00:02:21 +00:00
export class TripSummary extends React.Component {
2021-08-24 15:43:25 +00:00
handleRefresh = () => {
// by calling this method react re-renders the component
this.setState({});
};
2021-08-24 00:02:21 +00:00
render() {
2021-08-28 16:33:29 +00:00
if (endIsNigh) {
setEndIsLast(false);
return(
<View>
<Text style={styles.tripText}>
{LastTrip.getTripSummary() }
</Text>
</View> );
} else
2021-08-24 00:02:21 +00:00
return(
<View>
<Text style={styles.tripText}>
{Trips.getTripSummary() }
</Text>
</View> );
}
}
2021-08-28 16:33:29 +00:00
export var Trips:GT2 = new GT2();
export var LastTrip:GT2 = new GT2();