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
3 changed files with 30 additions and 45 deletions
Showing only changes of commit 393eab2b45 - Show all commits
+1 -1
View File
@@ -10,7 +10,7 @@ TODO
### Database
**Change name of database and credentials as you like!**
- Create new database: `CREATE DATABASE locationhub;`
- Create new database: `CREATE DATABASE dev_locationhub;`
- Create new user for database: `GRANT ALL PRIVILEGES ON dev_locationhub.* TO 'dbuser'@'localhost' IDENTIFIED BY '1234';`
- Import tables: `/usr/bin/mariadb -u dbuser -p1234 dev_locationhub < server/sql/tables.sql`
@@ -8,6 +8,34 @@ domainEventEmitter.on(
TtnMessageReceivedEventName,
async (event: TtnMessageReceivedEvent) => {
console.log(event);
// TODO Hendrik 🚀
if (!event.ttnGateways || event.ttnGateways.length === 0) {
console.log("No TTN Gateway location received!")
} else {
let totalWeight = 0;
let weightedLatitude = 0;
let weightedLongitude = 0;
event.ttnGateways.forEach(gw => {
const weight = 1 / Math.abs(gw.rssi); // Higher RSSI (closer to 0) gives more weight
totalWeight += weight;
localhorst marked this conversation as resolved Outdated
Outdated
Review

Das ! kann weg.

Das ! kann weg.
Outdated
Review

Bzw. kann alles weg, wird nicht verwendet

Bzw. kann alles weg, wird nicht verwendet
weightedLatitude += gw.latitude * weight;
weightedLongitude += gw.longitude * weight;
});
localhorst marked this conversation as resolved Outdated
Outdated
Review

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
Outdated
Review

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"
Outdated
Review

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.
// Calculate the weighted average to get the virtual location
const virtualLocation = {
latitude: weightedLatitude / totalWeight,
longitude: weightedLongitude / totalWeight
};
console.log("Tracker location based on TTN Gateway location:", virtualLocation);
}
}
);
-43
View File
@@ -10,38 +10,6 @@ import ttnRoutes from "./controller/ttnController";
import ttnGatewayReceptionRoutes from "./controller/ttnGatewayReceptionController";
import wifiScanRoutes from "./controller/wifiScanController";
interface LocationData {
rssi: number;
latitude: number;
longitude: number;
}
function calculateTtnGatewayLocation(dataList: LocationData[]): { latitude: number, longitude: number } {
if (!dataList || dataList.length === 0) {
throw new Error("The data list is empty or undefined.");
}
let totalWeight = 0;
let weightedLatitude = 0;
let weightedLongitude = 0;
// Loop through the dataList and calculate weighted sums based on RSSI
dataList.forEach(point => {
const weight = 1 / Math.abs(point.rssi); // Higher RSSI (closer to 0) gives more weight
totalWeight += weight;
weightedLatitude += point.latitude * weight;
weightedLongitude += point.longitude * weight;
});
// Calculate the weighted average to get the virtual location
const virtualLocation = {
latitude: weightedLatitude / totalWeight,
longitude: weightedLongitude / totalWeight
};
return virtualLocation;
}
dotenv.config();
const app = express();
@@ -56,17 +24,6 @@ app.use("/api/ttn-gateway-receptions", ttnGatewayReceptionRoutes);
app.use("/api/locations", locationRoutes);
app.use("/api/ttn", ttnRoutes);
const dataList: LocationData[] = [
//sensecap_exporter_2024-10-18_12-52-30.json
{ rssi: -108, latitude: 51.875759063444335, longitude: 4.448537528514863 },
{ rssi: -114, latitude: 51.8875851, longitude: 4.4919652 },
{ rssi: -106, latitude: 51.9102795122954, longitude: 4.48074765239573 },
{ rssi: -103, latitude: 51.9111671447754, longitude: 4.46313190460205 }
];
const virtualLocation = calculateTtnGatewayLocation(dataList);
console.log("TTN Gateway location:", virtualLocation);
app.listen(PORT, () => {
console.log(`🚀 Server runs here: http://localhost:${PORT}`);
});