This commit is contained in:
hannathkadher
2025-02-26 15:39:31 +04:00
4 changed files with 110 additions and 37 deletions
@@ -10,7 +10,13 @@ import { GetDeviceDetailsFunctionsStatusInterface } from 'src/device/interfaces/
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
import { ConfigService } from '@nestjs/config';
import { firebaseDataBase } from '../../firebase.config';
import { Database, DataSnapshot, get, ref, set } from 'firebase/database';
import {
Database,
DataSnapshot,
get,
ref,
runTransaction,
} from 'firebase/database';
import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories';
@Injectable()
export class DeviceStatusFirebaseService {
@@ -154,39 +160,48 @@ export class DeviceStatusFirebaseService {
this.firebaseDb,
`device-status/${addDeviceStatusDto.deviceUuid}`,
);
const snapshot: DataSnapshot = await get(dataRef);
const existingData = snapshot.val() || {};
// Assign default values if fields are not present
if (!existingData.deviceTuyaUuid) {
existingData.deviceTuyaUuid = addDeviceStatusDto.deviceTuyaUuid;
}
if (!existingData.productUuid) {
existingData.productUuid = addDeviceStatusDto.productUuid;
}
if (!existingData.productType) {
existingData.productType = addDeviceStatusDto.productType;
}
if (!existingData.status) {
existingData.status = [];
}
// Use a transaction to handle concurrent updates
await runTransaction(dataRef, (existingData) => {
if (!existingData) {
existingData = {};
}
// Create a map to track existing status codes
const statusMap = new Map(
existingData.status.map((item) => [item.code, item.value]),
);
// Assign default values if fields are not present
if (!existingData.deviceTuyaUuid) {
existingData.deviceTuyaUuid = addDeviceStatusDto.deviceTuyaUuid;
}
if (!existingData.productUuid) {
existingData.productUuid = addDeviceStatusDto.productUuid;
}
if (!existingData.productType) {
existingData.productType = addDeviceStatusDto.productType;
}
if (!existingData.status) {
existingData.status = [];
}
// Update or add status codes
// Create a map to track existing status codes
const statusMap = new Map(
existingData.status.map((item) => [item.code, item.value]),
);
for (const statusItem of addDeviceStatusDto.status) {
statusMap.set(statusItem.code, statusItem.value);
}
// Update or add status codes
// Convert the map back to an array format
existingData.status = Array.from(statusMap, ([code, value]) => ({
code,
value,
}));
for (const statusItem of addDeviceStatusDto.status) {
statusMap.set(statusItem.code, statusItem.value);
}
// Convert the map back to an array format
existingData.status = Array.from(statusMap, ([code, value]) => ({
code,
value,
}));
return existingData;
});
// Save logs to your repository
const newLogs = addDeviceStatusDto.log.properties.map((property) => {
return this.deviceStatusLogRepository.create({
deviceId: addDeviceStatusDto.deviceUuid,
@@ -200,10 +215,9 @@ export class DeviceStatusFirebaseService {
});
});
await this.deviceStatusLogRepository.save(newLogs);
// Save the updated data to Firebase
await set(dataRef, existingData);
// Return the updated data
return existingData;
const snapshot: DataSnapshot = await get(dataRef);
return snapshot.val();
}
}
+33 -2
View File
@@ -1021,10 +1021,13 @@ export class DeviceService {
}
}
const spaceHierarchy = await this.getFullSpaceHierarchy(
const spaceHierarchy = await this.getParentHierarchy(
device?.spaceDevice,
);
const orderedHierarchy = spaceHierarchy.reverse();
const orderedHierarchy = [
device?.spaceDevice,
...spaceHierarchy.reverse(),
];
return {
spaces: orderedHierarchy.map((space) => ({
@@ -1515,4 +1518,32 @@ export class DeviceService {
}
return project;
}
async getParentHierarchy(
space: SpaceEntity,
): Promise<{ uuid: string; spaceName: string }[]> {
try {
const targetSpace = await this.spaceRepository.findOne({
where: { uuid: space.uuid },
relations: ['parent'],
});
if (!targetSpace) {
throw new HttpException('Space not found', HttpStatus.NOT_FOUND);
}
const ancestors = await this.fetchAncestors(targetSpace);
return ancestors.map((parentSpace) => ({
uuid: parentSpace.uuid,
spaceName: parentSpace.spaceName,
}));
} catch (error) {
console.error('Error fetching parent hierarchy:', error.message);
throw new HttpException(
'Error fetching parent hierarchy',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}
+3 -3
View File
@@ -32,10 +32,10 @@ export class SpaceDeviceService {
);
}
// Fetch space hierarchy **once** and reverse it to get an ordered hierarchy
const spaceHierarchy =
await this.validationService.getFullSpaceHierarchy(space);
const orderedHierarchy = spaceHierarchy.reverse();
await this.validationService.getParentHierarchy(space);
const orderedHierarchy = [space, ...spaceHierarchy.reverse()];
// Fetch Tuya details for each device in parallel using Promise.allSettled
const deviceDetailsPromises = space.devices.map((device) =>
@@ -222,4 +222,32 @@ export class ValidationService {
return descendants;
}
async getParentHierarchy(
space: SpaceEntity,
): Promise<{ uuid: string; spaceName: string }[]> {
try {
const targetSpace = await this.spaceRepository.findOne({
where: { uuid: space.uuid },
relations: ['parent'],
});
if (!targetSpace) {
throw new HttpException('Space not found', HttpStatus.NOT_FOUND);
}
const ancestors = await this.fetchAncestors(targetSpace);
return ancestors.map((parentSpace) => ({
uuid: parentSpace.uuid,
spaceName: parentSpace.spaceName,
}));
} catch (error) {
console.error('Error fetching parent hierarchy:', error.message);
throw new HttpException(
'Error fetching parent hierarchy',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}