From efc8ed53a498feb5879e9880607c893b5d053cb7 Mon Sep 17 00:00:00 2001 From: GPlay97 Date: Fri, 26 Sep 2025 23:29:51 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20calculate=20distance=20within?= =?UTF-8?q?=20logs=20sync?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logs/handler/metadata.ts | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/logs/handler/metadata.ts b/src/logs/handler/metadata.ts index fe889e4..aed7a0c 100644 --- a/src/logs/handler/metadata.ts +++ b/src/logs/handler/metadata.ts @@ -11,6 +11,7 @@ import { STATUS } from '../entities/status.entity'; import { Log } from '../schemas/log.schema'; import { Sync } from '../schemas/sync.schema'; import { TYPE } from '../entities/type.entity'; +import { buffer, distance, lineString, point, pointToLineDistance } from "@turf/turf"; @Injectable() export class MetadataHandler { @@ -93,9 +94,13 @@ export class MetadataHandler { log.history.forEach((entry) => { if (entry.dcBatteryPower != null) { averageKWs.push(entry.dcBatteryPower); - } else if (entry.speed != null) { + } + + if (entry.speed != null) { averageSpeeds.push(entry.speed); - } else if (entry.latitude != null && entry.longitude != null) { + } + + if (entry.latitude != null && entry.longitude != null) { distances.push({ latitude: entry.latitude, longitude: entry.longitude, @@ -114,7 +119,28 @@ export class MetadataHandler { averageSpeeds.reduce((a, b) => a + b, sync.speed) / (averageSpeeds.length + 1); } - // TODO calculate distance + + let totalDistance = 0; + + if (sync.latitude != null && sync.longitude != null) { + distances.push({ + latitude: sync.latitude, + longitude: sync.longitude, + }); + } + + distances.forEach((coord, index) => { + if (index === 0) { + return; + } + + const currentCoord = point([coord.longitude, coord.latitude]); + const previousCoord = point([distances[index - 1].longitude, distances[index - 1].latitude]); + + totalDistance += distance(previousCoord, currentCoord); + }); + + log.distance = parseFloat(totalDistance.toFixed(2)); if (sync.cec != null && log.startCEC) { const amount = parseFloat((sync.cec - log.startCEC).toFixed(1)); From 8ba2ddd933d41b0f45e0fe0c83498bbe4b2a3739 Mon Sep 17 00:00:00 2001 From: GPlay97 Date: Fri, 26 Sep 2025 23:30:07 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=85=20log=20tests=20for=20dischargedK?= =?UTF-8?q?Wh=20and=20distance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logs/logs.controller.spec.ts | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/logs/logs.controller.spec.ts b/src/logs/logs.controller.spec.ts index b0cdbf4..067e703 100644 --- a/src/logs/logs.controller.spec.ts +++ b/src/logs/logs.controller.spec.ts @@ -357,7 +357,10 @@ describe('LogsController', () => { dto.dcBatteryPower = 2; dto.cec = 30069.1; + dto.ced = 30059; dto.socDisplay = 77; + dto.latitude = 32.125; + dto.longitude = 34.112; await controller.syncData(testAccount.akey, dto); @@ -370,7 +373,8 @@ describe('LogsController', () => { expect(response).toHaveProperty('rechargedKWh', 0); expect(response).toHaveProperty('startSOC', 75); expect(response).toHaveProperty('currentSOC', 77); - expect(response).toHaveProperty('dischargedKWh', undefined); + expect(response).toHaveProperty('dischargedKWh', 0); + expect(response).toHaveProperty('distance', 0); }); it('should update rechargedKWh metadata when adding new cec value', async () => { @@ -388,6 +392,37 @@ describe('LogsController', () => { expect(response).toHaveProperty('rechargedKWh', 0.2); }); + it('should update dischargedKWh metadata when adding new ced value', async () => { + const dto = new SyncDto(); + + dto.ced = 30062.4; + + await controller.syncData(testAccount.akey, dto); + + await new Promise((resolve) => setTimeout(resolve, 1000)); + + const response = await controller.findOne(testAccount.akey, chargeLogId); + + expect(response).toBeInstanceOf(LogDto); + expect(response).toHaveProperty('dischargedKWh', 3.4); + }); + + it('should update distance metadata when adding new location', async () => { + const dto = new SyncDto(); + + dto.latitude = 32.135; + dto.longitude = 34.125; + + await controller.syncData(testAccount.akey, dto); + + await new Promise((resolve) => setTimeout(resolve, 1000)); + + const response = await controller.findOne(testAccount.akey, chargeLogId); + + expect(response).toBeInstanceOf(LogDto); + expect(response).toHaveProperty('distance', 1.65); + }); + it('should find current running log', async () => { const response = await controller.findRunning(testAccount.akey);