Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | import { MqttMessageHandler } from './mqttHandler';
import { ThingyController } from '../api/controllers/thingyController';
import { TagController } from '../api/controllers/tagController';
import { DeviceController } from '../api/controllers/deviceController';
import { processMultilaterationData } from './utils/multilaterateService';
export class DataService {
private loggingInterval: NodeJS.Timeout | null = null;
private trilaterationInterval: NodeJS.Timeout | null = null;
private thingyController: ThingyController = new ThingyController();
private tagController: TagController = new TagController();
private deviceController: DeviceController = new DeviceController();
private mqttHandler: MqttMessageHandler;
constructor(mqttHandler: MqttMessageHandler) {
this.mqttHandler = mqttHandler;
}
public startLoggingAirSensingData(): void {
Iif (this.loggingInterval) {
clearInterval(this.loggingInterval);
}
this.loggingInterval = setInterval(() => {
const lastData = this.mqttHandler.getAllAirSensingData();
console.log('[MQTT] Logged air sensing data:', lastData);
const thingyDataArray = this.constructThingyDataArray(lastData);
const { mockRequest, mockResponse } = this.createMockExpressObjects(thingyDataArray);
this.thingyController.createThingyData(mockRequest, mockResponse).catch((err) => {
console.error('[MQTT] Failed to save air sensing data:', err);
});
}, 5000);
}
public startTrilaterationProcessing(): void {
Iif (this.trilaterationInterval) {
clearInterval(this.trilaterationInterval);
}
this.trilaterationInterval = setInterval(async () => {
const tagData = this.mqttHandler.getAllTagData();
console.log('[MQTT] Collected tag data for trilateration:', tagData);
for (const [macAddress, data] of Object.entries(tagData)) {
await this.processTagData(macAddress, data);
}
}, 1000);
}
private async processTagData(macAddress: string, data: any): Promise<void> {
try {
const trilaterationResult = await processMultilaterationData({
tag: parseInt(macAddress, 16),
beacons: data.beacons,
});
if (trilaterationResult) {
//save tag data to tag collection
console.log(`[MQTT] Trilateration result for tag ${macAddress}:`, trilaterationResult);
const tagDataToSave = this.constructTagDataToSave(macAddress, data, trilaterationResult);
this.mqttHandler.sendMessage(`smartclassroom/multilateration/${macAddress}/location`, JSON.stringify(trilaterationResult));
const { mockRequest, mockResponse } = this.createMockExpressObjects(tagDataToSave);
await this.tagController.createTagData(mockRequest, mockResponse);
//setup request and response data structures
const getDeviceRequest = { query: { macAddress } }; // Use query, not body
let deviceId: string | null = null;
const getDeviceResponse = {
status: (_: number) => ({
json: (data: any) => {
Iif (Array.isArray(data) && data.length > 0) {
deviceId = data[0]._id;
}
},
}),
};
//pull device ID from database using macAddress
await this.deviceController.getDevices(getDeviceRequest as any, getDeviceResponse as any);
//update device location if device exists
if (deviceId) {
const deviceDataToSave = this.constructDeviceDataToSave(deviceId, trilaterationResult);
const { mockRequest: updateRequest, mockResponse: updateResponse } = this.createMockExpressObjects(deviceDataToSave);
await this.deviceController.updateDevice(updateRequest, updateResponse);
console.log(`[MQTT] Updated device location for tag ${macAddress}`);
} else {
//update failed - device not found, create new device
console.warn(`[MQTT] Device with macAddress ${macAddress} not found for location update, creating new device.`);
const newDeviceData = {
macAddress,
location: {
floor_id: trilaterationResult.floor_id,
x: trilaterationResult.x,
y: trilaterationResult.y,
},
};
const { mockRequest: createRequest, mockResponse: createResponse } = this.createMockExpressObjects(newDeviceData);
await this.deviceController.createDevice(createRequest, createResponse);
console.log(`[MQTT] Created new device for tag ${macAddress}`);
}
}
else {
console.warn(`[MQTT] Trilateration failed for tag ${macAddress}`);
}
} catch (error) {
console.error(`[MQTT] Error during trilateration for tag ${macAddress}:`, error);
}
}
private constructTagDataToSave(macAddress: string, data: any, trilaterationResult: any): any {
// Ensure the first beacon exists and has a valid floor_id
const floorId = trilaterationResult.floor_id || "Unknown_Floor"; // Use floor_id from trilateration result
return {
macAddress: macAddress,
timestamp: new Date(),
beacon: data.beacons
.filter((beacon: any) => beacon && beacon.id && beacon.floor_id) // Ensure beacon, id, and floor_id exist
.map((beacon: any) => ({
macAddress: beacon.id.toString(), // Convert id to string
rssi: beacon.rssi,
floor_id: beacon.floor_id, // Use floor_id directly
})),
location: {
x: trilaterationResult.x,
y: trilaterationResult.y,
floor_id: floorId, // Use floor_id from trilateration result
},
};
}
private constructDeviceDataToSave(id: string, updateLocation: any): any {
return {
_id: id,
location: {
floor_id: updateLocation.floor_id,
x: updateLocation.x,
y: updateLocation.y,
},
};
}
private constructThingyDataArray(lastData: Record<string, any>): any[] {
return Object.entries(lastData).map(([macAddress, data]) => ({
macAddress: macAddress.toUpperCase(),
temperature: data.temperature || null,
humidity: data.humidity || null,
co2: data.co2 || null,
pm_1: data.pm1_0,
pm_2_5: data.pm2_5,
pm_10: data.pm10,
timestamp: data.timestamp || null,
}));
}
private createMockExpressObjects(body: any): { mockRequest: any; mockResponse: any } {
const mockRequest = { body };
const mockResponse = {
status: (code: number) => ({
json: (data: any) => console.log(`[MQTT] Mock Response: ${code}`, data),
}),
};
return { mockRequest, mockResponse };
}
} |