feat: tracker location based on multiple location providers #5
@@ -3,12 +3,23 @@ import {
|
|||||||
TtnMessageReceivedEvent,
|
TtnMessageReceivedEvent,
|
||||||
TtnMessageReceivedEventName,
|
TtnMessageReceivedEventName,
|
||||||
} from "../event/ttnMessageReceivedEvent";
|
} from "../event/ttnMessageReceivedEvent";
|
||||||
|
import { container } from "tsyringe";
|
||||||
|
import { LocationService } from "../services/locationService";
|
||||||
|
|
||||||
|
const locationService = container.resolve(LocationService);
|
||||||
|
|
||||||
domainEventEmitter.on(
|
domainEventEmitter.on(
|
||||||
TtnMessageReceivedEventName,
|
TtnMessageReceivedEventName,
|
||||||
async (event: TtnMessageReceivedEvent) => {
|
async (event: TtnMessageReceivedEvent) => {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
|
|
||||||
|
var wifi_based_latitude!: number;
|
||||||
|
var wifi_based_longitude!: number;
|
||||||
|
var gnss_based_latitude!: number; // Should this be set here?
|
||||||
|
var gnss_based_longitude!: number; // Should this be set here?
|
||||||
|
var ttn_gw_based_latitude!: number;
|
||||||
|
var ttn_gw_based_longitude!: number;
|
||||||
|
localhorst marked this conversation as resolved
Outdated
|
|||||||
|
|
||||||
if (!event.ttnGateways || event.ttnGateways.length === 0) {
|
if (!event.ttnGateways || event.ttnGateways.length === 0) {
|
||||||
console.log("No TTN Gateway location received!")
|
console.log("No TTN Gateway location received!")
|
||||||
} else {
|
} else {
|
||||||
|
localhorst marked this conversation as resolved
Outdated
Pheanox
commented
Ich würde nach dem console.log ein return machen. Dann sparst du dir die else Ich würde nach dem console.log ein return machen. Dann sparst du dir die else
localhorst
commented
ne, dann würdest ja evtl. die Location von GNSS oder Wifi nicht "parsen" ne, dann würdest ja evtl. die Location von GNSS oder Wifi nicht "parsen"
Pheanox
commented
Ich hätte es so aufgebaut Vorschlag:
In der "Hauptfunktion" dann prüfen ob die werte da sind und wenn ja die Funktion aufrufen und die Werte zuweisen:
So werden drei if else zu drei if und man hat weniger Komplexität in einer Funktion. Ich hätte es so aufgebaut Vorschlag:
Für jede Berechnung eine eigene Funktion die die Werte ausrechnet und dann zurück gibt:
`const CalculateTtngatewayLocation = (event: TtnMessageReceivedEvent) => {`
`//... do stuff`
`return {`
`gnss_latitude: virtualLocation.latitude,`
`gnss_longitude: virtualLocation.longitude,`
`};`
`};`
In der "Hauptfunktion" dann prüfen ob die werte da sind und wenn ja die Funktion aufrufen und die Werte zuweisen:
`var location: Partial<Location> = {};`
`// Get location based on TTN Gateways`
`if (event.ttnGateways && event.ttnGateways.length > 0) {`
`// Option 1`
`const virtualLocation = CalculateTtngatewayLocation(event);`
`location.ttn_gw_latitude = virtualLocation.gnss_latitude;`
`location.ttn_gw_longitude = virtualLocation.gnss_latitude;`
`// Option 2`
`const virtualLocation = CalculateTtngatewayLocation(event);`
`location = { ...location, ...virtualLocation };`
`// Option 3 -> fancy :D`
`location = { ...location, ...CalculateTtngatewayLocation(event) };`
`}`
So werden drei if else zu drei if und man hat weniger Komplexität in einer Funktion.
|
|||||||
@@ -30,12 +41,23 @@ domainEventEmitter.on(
|
|||||||
};
|
};
|
||||||
|
|
||||||
console.log("Tracker location based on TTN Gateway location:", virtualLocation);
|
console.log("Tracker location based on TTN Gateway location:", virtualLocation);
|
||||||
|
ttn_gw_based_latitude = virtualLocation.latitude;
|
||||||
|
ttn_gw_based_longitude = virtualLocation.longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// TODO: parse Wifi location here
|
||||||
|
}
|
||||||
|
|
||||||
|
const newLocation = await locationService.createLocation({
|
||||||
|
lp_ttn_end_device_uplinks_id: event.lp_ttn_end_device_uplinks_id,
|
||||||
|
ttn_gw_latitude: ttn_gw_based_latitude,
|
||||||
|
ttn_gw_longitude: ttn_gw_based_longitude,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
console.log(newLocation)
|
||||||
}
|
}
|
||||||
|
localhorst marked this conversation as resolved
Outdated
Pheanox
commented
Der Wifi eintrag wird nur die die Datenbank geschrieben, wenn es eine Location gibt, sollte dieser nicht auch ohne reingeschrieben werden mit latitude und longitude undefined? Ansonsten würde ich es in drei steps unterteilen: Api Call, Datenbank entry erstellen, totalWeight + weightedLatitude + weightedLongitude ausrechnen. Ich glaube das macht es übersichtlicher ist aber vermutlich Geschmackssache. Mein Vorschlag: ` const wifiScans = await Promise.all(
Der Wifi eintrag wird nur die die Datenbank geschrieben, wenn es eine Location gibt, sollte dieser nicht auch ohne reingeschrieben werden mit latitude und longitude undefined? Ansonsten würde ich es in drei steps unterteilen: Api Call, Datenbank entry erstellen, totalWeight + weightedLatitude + weightedLongitude ausrechnen. Ich glaube das macht es übersichtlicher ist aber vermutlich Geschmackssache. Mein Vorschlag:
` const wifiScans = await Promise.all(
event.wifis.map(async (wifi) => {
const apiResponse = await getLocationForWifiMemoized(wifi.mac);
return {
lp_ttn_end_device_uplinks_id: event.lp_ttn_end_device_uplinks_id,
mac: wifi.mac,
rssi: wifi.rssi,
latitude: apiResponse?.results[0]?.trilat,
longitude: apiResponse?.results[0]?.trilong,
};
})
);
await wifiScanService.createWifiScans(wifiScans);
const { totalWeight, weightedLatitude, weightedLongitude } =
wifiScans.reduce(
(acc, { latitude, longitude, rssi }) => {
if (latitude && longitude && rssi !== 0) {
const weight = 1 / Math.abs(rssi);
acc.totalWeight += weight;
acc.weightedLatitude += latitude * weight;
acc.weightedLongitude += longitude * weight;
}
return acc;
},
{
totalWeight: 0,
weightedLatitude: 0,
weightedLongitude: 0,
}
);
const virtualLocation = {
latitude: weightedLatitude / totalWeight,
longitude: weightedLongitude / totalWeight,
};`
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Das ! kann weg.
Bzw. kann alles weg, wird nicht verwendet