feat: impl. use of new tables

This commit is contained in:
Philipp Schweizer 2025-01-06 15:47:53 +01:00
parent c2e0fe94a4
commit e43cb76e4d
8 changed files with 103 additions and 38 deletions

View File

@ -15,7 +15,6 @@ const ttnGatewayReceptionService = container.resolve(
TtnGatewayReceptionService TtnGatewayReceptionService
); );
const wifiScanService = container.resolve(WifiScanService); const wifiScanService = container.resolve(WifiScanService);
const locationService = container.resolve(LocationService); const locationService = container.resolve(LocationService);
const router = express.Router(); const router = express.Router();
@ -59,8 +58,6 @@ router.post(
rssi: w.rssi, rssi: w.rssi,
})) ?? []; })) ?? [];
console.log(wifiScans);
const ttnGatewayReceptions = message.uplink_message.rx_metadata.map( const ttnGatewayReceptions = message.uplink_message.rx_metadata.map(
(g) => ({ (g) => ({
lp_ttn_end_device_uplinks_id, lp_ttn_end_device_uplinks_id,
@ -83,9 +80,8 @@ router.post(
locationService.createLocationFromTriangulation({ locationService.createLocationFromTriangulation({
lp_ttn_end_device_uplinks_id, lp_ttn_end_device_uplinks_id,
wifi: wifiResults.map(({ latitude, longitude, rssi }) => ({ wifi: wifiResults.map(({ mac, rssi }) => ({
latitude, mac,
longitude,
rssi, rssi,
})), })),
ttn_gw: gatewayResults.map(({ latitude, longitude, rssi }) => ({ ttn_gw: gatewayResults.map(({ latitude, longitude, rssi }) => ({

View File

@ -21,8 +21,8 @@ WifiLocation.init(
allowNull: false, allowNull: false,
}, },
longitude: { longitude: {
type: DataTypes.NUMBER, type: DataTypes.NUMBER,
allowNull: false, allowNull: false,
}, },
created_at_utc: { created_at_utc: {
type: DataTypes.DATE, type: DataTypes.DATE,

View File

@ -27,8 +27,8 @@ WifiLocationHistory.init(
allowNull: false, allowNull: false,
}, },
longitude: { longitude: {
type: DataTypes.NUMBER, type: DataTypes.NUMBER,
allowNull: false, allowNull: false,
}, },
created_at_utc: { created_at_utc: {
type: DataTypes.DATE, type: DataTypes.DATE,
@ -43,8 +43,8 @@ WifiLocationHistory.init(
}, },
{ {
sequelize, sequelize,
modelName: "WifiLocation", modelName: "WifiLocationHistory",
tableName: "wifi_location", tableName: "wifi_location_history",
timestamps: false, timestamps: false,
} }
); );

View File

@ -1,3 +1,4 @@
import { Attributes, FindOptions } from "sequelize";
import { injectable } from "tsyringe"; import { injectable } from "tsyringe";
import { WifiLocationHistory } from "../models/wifiLocationHistory"; import { WifiLocationHistory } from "../models/wifiLocationHistory";
@ -7,6 +8,10 @@ export class WifiLocationHistoryRepository {
return await WifiLocationHistory.findAll(); return await WifiLocationHistory.findAll();
} }
public async findOne(options?: FindOptions<Attributes<WifiLocationHistory>>) {
return await WifiLocationHistory.findOne(options);
}
public async findById(id: string) { public async findById(id: string) {
return await WifiLocationHistory.findByPk(id); return await WifiLocationHistory.findByPk(id);
} }

View File

@ -1,10 +1,11 @@
import { Attributes, FindOptions } from "sequelize";
import { injectable } from "tsyringe"; import { injectable } from "tsyringe";
import { WifiLocation } from "../models/wifiLocation"; import { WifiLocation } from "../models/wifiLocation";
@injectable() @injectable()
export class WifiLocationRepository { export class WifiLocationRepository {
public async findAll() { public async findAll(options?: FindOptions<Attributes<WifiLocation>>) {
return await WifiLocation.findAll(); return await WifiLocation.findAll(options);
} }
public async findById(id: string) { public async findById(id: string) {

View File

@ -1,6 +1,7 @@
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
import { Location } from "../models/location"; import { Location } from "../models/location";
import { LocationRepository } from "../repositories/locationRepository"; import { LocationRepository } from "../repositories/locationRepository";
import { WifiLocationService } from "./wifiLocationService";
interface CreateLocationParams { interface CreateLocationParams {
lp_ttn_end_device_uplinks_id: string; lp_ttn_end_device_uplinks_id: string;
@ -11,7 +12,10 @@ interface CreateLocationParams {
interface CreateLocationTriangulationParams { interface CreateLocationTriangulationParams {
lp_ttn_end_device_uplinks_id: string; lp_ttn_end_device_uplinks_id: string;
wifi: LocationSignal[]; wifi: {
mac: string;
rssi: number;
}[];
ttn_gw: LocationSignal[]; ttn_gw: LocationSignal[];
gnss?: Coordinates; gnss?: Coordinates;
} }
@ -39,7 +43,9 @@ interface UpdateTtnGatewayReceptionParams {
export class LocationService { export class LocationService {
constructor( constructor(
@inject(LocationRepository) @inject(LocationRepository)
private repository: LocationRepository private repository: LocationRepository,
@inject(WifiLocationService)
private wifiLocationService: WifiLocationService
) {} ) {}
public async getAllLocations() { public async getAllLocations() {
@ -65,7 +71,9 @@ export class LocationService {
public async createLocationFromTriangulation( public async createLocationFromTriangulation(
data: CreateLocationTriangulationParams data: CreateLocationTriangulationParams
) { ) {
const wifi_location = this.calculateVirtualLocation(data.wifi); const wifi_location = this.calculateVirtualLocation(
await this.enrichWifiObjectWithLocation(data.wifi)
);
const gateway_location = this.calculateVirtualLocation(data.ttn_gw); const gateway_location = this.calculateVirtualLocation(data.ttn_gw);
return this.createLocation({ return this.createLocation({
@ -84,6 +92,29 @@ export class LocationService {
return this.repository.delete(id); return this.repository.delete(id);
} }
private async enrichWifiObjectWithLocation(
wifis: CreateLocationTriangulationParams["wifi"]
) {
const enrichedWifi = await Promise.all(
wifis.map(async (wifi) => {
const location = await this.wifiLocationService.getWifiLocationByMac(
wifi.mac
);
return location?.latitude !== undefined &&
location.longitude !== undefined
? {
rssi: wifi.rssi,
latitude: location.latitude,
longitude: location.longitude,
}
: null;
})
);
return enrichedWifi.filter((wifi) => wifi !== null);
}
private calculateVirtualLocation(locations: LocationSignal[]) { private calculateVirtualLocation(locations: LocationSignal[]) {
if (locations.length === 0) return undefined; if (locations.length === 0) return undefined;

View File

@ -1,6 +1,4 @@
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
import { WifiScanRepository } from "../repositories/wifiScanRepository";
import { WifiLocationRepository } from "../repositories/wifiLocationRepository";
import { WifiLocationHistoryRepository } from "../repositories/wifiLocationHistoryRepository"; import { WifiLocationHistoryRepository } from "../repositories/wifiLocationHistoryRepository";
interface CreateWifiLocationHistoryParams { interface CreateWifiLocationHistoryParams {
@ -18,7 +16,8 @@ interface UpdateWifiLocationHistoryParams {
@injectable() @injectable()
export class WifiLocationHistoryService { export class WifiLocationHistoryService {
constructor( constructor(
@inject(WifiLocationHistoryRepository) private repository: WifiLocationHistoryRepository @inject(WifiLocationHistoryRepository)
private repository: WifiLocationHistoryRepository
) {} ) {}
public async getAllWifiLocationHistories() { public async getAllWifiLocationHistories() {
@ -29,11 +28,28 @@ export class WifiLocationHistoryService {
return this.repository.findById(id); return this.repository.findById(id);
} }
public async createWifiLocationHistory(data: CreateWifiLocationHistoryParams) { public async createWifiLocationHistory(
return this.repository.create(data); data: CreateWifiLocationHistoryParams
) {
const existingEntry = await this.repository.findOne({
where: {
mac: data.mac,
latitude: data.latitude,
longitude: data.longitude,
},
order: [["updated_at_utc", "DESC"]],
});
if (!existingEntry) {
return await this.repository.create(data);
}
return existingEntry;
} }
public async updateWifiLocationHistory(data: UpdateWifiLocationHistoryParams) { public async updateWifiLocationHistory(
data: UpdateWifiLocationHistoryParams
) {
return this.repository.update(data.mac, data); return this.repository.update(data.mac, data);
} }

View File

@ -1,12 +1,8 @@
import { Op } from "sequelize";
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
import { WifiScanRepository } from "../repositories/wifiScanRepository"; import { getLocationForWifi } from "../proxy/wigle";
import { WifiLocationRepository } from "../repositories/wifiLocationRepository"; import { WifiLocationRepository } from "../repositories/wifiLocationRepository";
import { WifiLocationHistoryService } from "./wifiLocationHistoryService";
interface CreateWifiLocationParams {
mac: string;
latitude: number;
longitude: number;
}
interface UpdateWifiLocationParams { interface UpdateWifiLocationParams {
mac: string; mac: string;
@ -17,23 +13,43 @@ interface UpdateWifiLocationParams {
@injectable() @injectable()
export class WifiLocationService { export class WifiLocationService {
constructor( constructor(
@inject(WifiLocationRepository) private repository: WifiLocationRepository @inject(WifiLocationRepository) private repository: WifiLocationRepository,
@inject(WifiLocationHistoryService)
private wifiLocationHistory: WifiLocationHistoryService
) {} ) {}
public async getAllWifiLocations() { public async getAllWifiLocations() {
return this.repository.findAll(); return this.repository.findAll();
} }
public async getWifiLocationById(id: string) { public async getAllWifiLocationsByAddresses(macAddresses: string[]) {
return this.repository.findById(id); return this.repository.findAll({
where: { mac: { [Op.in]: macAddresses } },
});
} }
public async createWifiLocation(data: CreateWifiLocationParams) { public async getWifiLocationByMac(mac: string) {
return this.repository.create(data); let wifiLocation = await this.repository.findById(mac);
}
public async createWifiLocations(data: CreateWifiLocationParams[]) { if (wifiLocation?.longitude && wifiLocation.latitude) return wifiLocation;
return await this.repository.createMany(data);
const apiLocation = await getLocationForWifi(mac);
if (apiLocation && apiLocation.totalResults >= 0) {
wifiLocation = await this.repository.create({
mac,
latitude: apiLocation.results[0].trilat,
longitude: apiLocation.results[0].trilong,
});
await this.wifiLocationHistory.createWifiLocationHistory(
wifiLocation.dataValues
);
return wifiLocation;
}
return undefined;
} }
public async updateWifiLocation(data: UpdateWifiLocationParams) { public async updateWifiLocation(data: UpdateWifiLocationParams) {