Added battery info to frontend

This commit is contained in:
Fabio Manganiello 2025-03-30 22:10:01 +02:00
parent aca1aeead4
commit 3eaf721ffd
Signed by: blacklight
GPG key ID: D90FBA7F76362774
3 changed files with 65 additions and 3 deletions

View file

@ -55,7 +55,7 @@
{{ device.name }}
</p>
<p class="battery" :style="{ color: batteryColor }" v-if="point.battery">
<p class="battery" :style="{ color: batteryColor ?? 'initial' }" v-if="point.battery">
<font-awesome-icon :icon="batteryIconClass" />
<span>{{ point.battery }}%</span>
</p>

View file

@ -21,6 +21,13 @@
:title="(showMetrics.speed ? 'Hide' : 'Show') + ' speed'">
<font-awesome-icon icon="tachometer-alt" />
</button>
<button @click="toggleMetric('battery')"
:class="{ selected: showMetrics.battery }"
:title="(showMetrics.battery ? 'Hide' : 'Show') + ' battery level'"
v-if="hasBatteryInfo">
<font-awesome-icon icon="battery-full" />
</button>
</div>
<div class="page-button-container">
@ -128,12 +135,25 @@ export default {
})
},
hasBatteryInfo(): boolean {
return this.points.some((point: GPSPoint) => point.battery != null)
},
battery(): (number | null)[] {
return this.points
.map((point: GPSPoint) => point.battery ?? null)
},
speed(): number[] {
if (!this.points.length) {
return []
}
return this.points.map((point: GPSPoint, index: number) => {
if (point.speed != null) {
return point.speed
}
if (index === 0) {
return 0
}
@ -185,6 +205,19 @@ export default {
)
}
if (this.showMetrics.battery) {
datasets.push(
{
label: 'Battery (%)',
backgroundColor: '#0989f8',
borderColor: '#5959a8',
fill: false,
data: this.battery,
yAxisID: 'percentage',
}
)
}
return {
labels: this.points.map((point: GPSPoint) => point.timestamp),
datasets: datasets,
@ -242,6 +275,31 @@ export default {
}
}
if (this.showMetrics.battery) {
let position = 'left'
if (yAxes.meters || yAxes.speed) {
position = 'right'
}
yAxes.percentage = {
type: 'linear',
position: position,
display: true,
min: 0,
max: 100,
ticks: {
beginAtZero: true,
},
title: {
display: true,
text: 'Percentage',
},
grid: {
drawOnChartArea: false,
},
}
}
const xTicks = {} as { min?: Date, max?: Date }
if (this.points.length > 1) {
xTicks.min = this.points[0].timestamp

View file

@ -2,13 +2,14 @@ class TimelineMetricsConfiguration {
public altitude: boolean = false;
public distance: boolean = true;
public speed: boolean = false;
public battery: boolean = false;
constructor(data: any | null = null) {
if (!data) {
return;
}
for (const key of ['altitude', 'distance', 'speed']) {
for (const key of ['altitude', 'distance', 'speed', 'battery']) {
const value = String(
data[key] ?? data['show' + key.charAt(0).toUpperCase() + key.slice(1)]
)
@ -39,13 +40,16 @@ class TimelineMetricsConfiguration {
case 'speed':
this.speed = !this.speed;
break;
case 'battery':
this.battery = !this.battery;
break;
default:
throw new TypeError(`Invalid timeline metric: ${metric}`);
}
}
toQuery(): Record<string, string> {
return ['altitude', 'distance', 'speed'].reduce((acc: Record<string, string>, key: string) => {
return ['altitude', 'distance', 'speed', 'battery'].reduce((acc: Record<string, string>, key: string) => {
acc['show' + key.charAt(0).toUpperCase() + key.slice(1)] = String((this as any)[key]);
return acc;
}, {});