feat: tracker location based on multiple location providers #5

Merged
localhorst merged 19 commits from feature/ttn-location-algo into main 2025-01-02 14:57:34 +01:00
Owner
No description provided.
localhorst added the
Kind/Feature
label 2024-12-31 13:20:06 +01:00
localhorst added 5 commits 2024-12-31 13:20:06 +01:00
localhorst requested review from Pheanox 2024-12-31 13:20:10 +01:00
localhorst added 1 commit 2024-12-31 14:00:35 +01:00
localhorst added 1 commit 2024-12-31 14:18:51 +01:00
Pheanox requested changes 2024-12-31 16:18:22 +01:00
@ -12,0 +18,4 @@
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;
Collaborator

Das ! kann weg.

Das ! kann weg.
Collaborator

Bzw. kann alles weg, wird nicht verwendet

Bzw. kann alles weg, wird nicht verwendet
localhorst marked this conversation as resolved
@ -12,0 +22,4 @@
if (!event.ttnGateways || event.ttnGateways.length === 0) {
console.log("No TTN Gateway location received!")
} else {
Collaborator

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
Author
Owner

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"
Collaborator

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.

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.
localhorst marked this conversation as resolved
localhorst added 1 commit 2024-12-31 16:57:40 +01:00
localhorst added 1 commit 2025-01-01 18:41:02 +01:00
localhorst added 1 commit 2025-01-01 19:14:25 +01:00
localhorst added 1 commit 2025-01-01 20:25:31 +01:00
localhorst added 1 commit 2025-01-01 21:39:39 +01:00
localhorst added 1 commit 2025-01-01 21:53:40 +01:00
localhorst added 1 commit 2025-01-01 21:56:27 +01:00
Pheanox reviewed 2025-01-01 22:27:46 +01:00
@ -12,0 +63,4 @@
const apiResponse = await getLocationForWifiMemoized(wifi.mac);
if ((apiResponse != undefined) && (apiResponse?.totalResults > 0)) {
// Create new WiFi Scan entry if wigle.net reported location
const newWifiScan = wifiScanService.createWifiScan({
Collaborator

await wifiScanService.createWifiScan

await wifiScanService.createWifiScan
localhorst marked this conversation as resolved
Pheanox requested changes 2025-01-01 22:52:09 +01:00
@ -12,0 +58,4 @@
let weightedLongitude = 0;
// Process Wi-Fi data to compute weighted location
await Promise.all(
Collaborator

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,
  };`
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, };`
localhorst marked this conversation as resolved
@ -12,0 +72,4 @@
})
// Calculate weight based on RSSI (higher signal strength gives more weight)
const weight = 1 / Math.abs((await newWifiScan).rssi);
Collaborator

await kann weg

await kann weg
localhorst marked this conversation as resolved
@ -12,0 +77,4 @@
// Accumulate weighted latitude and longitude
weightedLatitude += (await newWifiScan).latitude * weight;
weightedLongitude += (await newWifiScan).longitude * weight;
Collaborator

await kann weg

await kann weg
localhorst marked this conversation as resolved
Pheanox requested changes 2025-01-01 23:04:39 +01:00
@ -13,1 +13,4 @@
}[];
gnssLocation: {
latitude: number | undefined;
longitude: number | undefined;
Collaborator

Hier habe ich Mist erzählt statt:

latitude: number | undefined; longitude: number | undefined;

geht auch einfach

latitude?: number; longitude?: number;

Hier habe ich Mist erzählt statt: `latitude: number | undefined; longitude: number | undefined;` geht auch einfach `latitude?: number; longitude?: number;`
localhorst marked this conversation as resolved
localhorst added 1 commit 2025-01-02 10:38:11 +01:00
localhorst added 1 commit 2025-01-02 11:38:31 +01:00
localhorst changed title from feat: tracker location based on TTTN Gateway location to feat: tracker location based on multiple location providers 2025-01-02 14:39:42 +01:00
localhorst added 1 commit 2025-01-02 14:40:17 +01:00
localhorst added 1 commit 2025-01-02 14:45:03 +01:00
localhorst added 1 commit 2025-01-02 14:56:04 +01:00
localhorst merged commit fc8e4ca486 into main 2025-01-02 14:57:34 +01:00
localhorst deleted branch feature/ttn-location-algo 2025-01-02 14:57:34 +01:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: localhorst/LocationHub#5
No description provided.