mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-11 15:48:09 +00:00
get devices
This commit is contained in:
@ -136,6 +136,17 @@ export class ControllerRoute {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static SPACE_DEVICES = class {
|
||||||
|
public static readonly ROUTE =
|
||||||
|
'/communities/:communityUuid/spaces/:spaceUuid/devices';
|
||||||
|
static ACTIONS = class {
|
||||||
|
public static readonly LIST_SPACE_DEVICE_SUMMARY =
|
||||||
|
'List devices in a space';
|
||||||
|
public static readonly LIST_SPACE_DEVICE_DESCRIPTION =
|
||||||
|
'Retrieves a list of all devices associated with a specified space.';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static SUBSPACE = class {
|
static SUBSPACE = class {
|
||||||
public static readonly ROUTE =
|
public static readonly ROUTE =
|
||||||
'/communities/:communityUuid/spaces/:spaceUuid/subspaces';
|
'/communities/:communityUuid/spaces/:spaceUuid/subspaces';
|
||||||
|
@ -35,4 +35,21 @@ export class TuyaService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getDeviceDetails(deviceId: string) {
|
||||||
|
const path = `/v1.1/iot-03/devices/${deviceId}`;
|
||||||
|
const response = await this.tuya.request({
|
||||||
|
method: 'GET',
|
||||||
|
path,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Error fetching device details: ${response.msg}`,
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ export class DeviceEntity extends AbstractEntity<DeviceDto> {
|
|||||||
)
|
)
|
||||||
deviceUserNotification: DeviceNotificationEntity[];
|
deviceUserNotification: DeviceNotificationEntity[];
|
||||||
|
|
||||||
@ManyToOne(() => SpaceEntity, (space) => space.devicesSpaceEntity, {
|
@ManyToOne(() => SpaceEntity, (space) => space.devices, {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
spaceDevice: SpaceEntity;
|
spaceDevice: SpaceEntity;
|
||||||
|
@ -81,7 +81,7 @@ export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
|||||||
() => DeviceEntity,
|
() => DeviceEntity,
|
||||||
(devicesSpaceEntity) => devicesSpaceEntity.spaceDevice,
|
(devicesSpaceEntity) => devicesSpaceEntity.spaceDevice,
|
||||||
)
|
)
|
||||||
devicesSpaceEntity: DeviceEntity[];
|
devices: DeviceEntity[];
|
||||||
|
|
||||||
constructor(partial: Partial<SpaceEntity>) {
|
constructor(partial: Partial<SpaceEntity>) {
|
||||||
super();
|
super();
|
||||||
|
@ -114,10 +114,10 @@ class Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AddAutomationDto {
|
export class AddAutomationDto {
|
||||||
@ApiProperty({ description: 'Unit ID', required: true })
|
@ApiProperty({ description: 'Space ID', required: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public unitUuid: string;
|
public spaceUuid: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Automation name', required: true })
|
@ApiProperty({ description: 'Automation name', required: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -197,10 +197,10 @@ export class UpdateAutomationDto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class UpdateAutomationStatusDto {
|
export class UpdateAutomationStatusDto {
|
||||||
@ApiProperty({ description: 'Unit uuid', required: true })
|
@ApiProperty({ description: 'Space uuid', required: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public unitUuid: string;
|
public spaceUuid: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Is enable', required: true })
|
@ApiProperty({ description: 'Is enable', required: true })
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
|
@ -50,11 +50,15 @@ export class AutomationService {
|
|||||||
try {
|
try {
|
||||||
let unitSpaceTuyaId;
|
let unitSpaceTuyaId;
|
||||||
if (!spaceTuyaId) {
|
if (!spaceTuyaId) {
|
||||||
const unitDetails = await this.getUnitByUuid(addAutomationDto.unitUuid);
|
const unitDetails = await this.getUnitByUuid(
|
||||||
|
addAutomationDto.spaceUuid,
|
||||||
|
);
|
||||||
|
|
||||||
unitSpaceTuyaId = unitDetails.spaceTuyaUuid;
|
unitSpaceTuyaId = unitDetails.spaceTuyaUuid;
|
||||||
if (!unitDetails) {
|
if (!unitDetails) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException(
|
||||||
|
`Invalid space UUID ${addAutomationDto.spaceUuid}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unitSpaceTuyaId = spaceTuyaId;
|
unitSpaceTuyaId = spaceTuyaId;
|
||||||
@ -125,22 +129,23 @@ export class AutomationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getUnitByUuid(unitUuid: string) {
|
async getUnitByUuid(spaceUuid: string) {
|
||||||
try {
|
try {
|
||||||
const unit = await this.spaceRepository.findOne({
|
const space = await this.spaceRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
uuid: unitUuid,
|
uuid: spaceUuid,
|
||||||
},
|
},
|
||||||
|
relations: ['community'],
|
||||||
});
|
});
|
||||||
if (!unit) {
|
if (!space) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
uuid: unit.uuid,
|
uuid: space.uuid,
|
||||||
createdAt: unit.createdAt,
|
createdAt: space.createdAt,
|
||||||
updatedAt: unit.updatedAt,
|
updatedAt: space.updatedAt,
|
||||||
name: unit.spaceName,
|
name: space.spaceName,
|
||||||
spaceTuyaUuid: unit.spaceTuyaUuid,
|
spaceTuyaUuid: space.community.externalId,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof BadRequestException) {
|
if (err instanceof BadRequestException) {
|
||||||
@ -150,11 +155,11 @@ export class AutomationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getAutomationByUnit(unitUuid: string) {
|
async getAutomationByUnit(spaceUuid: string) {
|
||||||
try {
|
try {
|
||||||
const unit = await this.getUnitByUuid(unitUuid);
|
const unit = await this.getUnitByUuid(spaceUuid);
|
||||||
if (!unit.spaceTuyaUuid) {
|
if (!unit.spaceTuyaUuid) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = `/v2.0/cloud/scene/rule?space_id=${unit.spaceTuyaUuid}&type=automation`;
|
const path = `/v2.0/cloud/scene/rule?space_id=${unit.spaceTuyaUuid}&type=automation`;
|
||||||
@ -311,10 +316,10 @@ export class AutomationService {
|
|||||||
const { automationUuid, spaceUuid } = param;
|
const { automationUuid, spaceUuid } = param;
|
||||||
let unitSpaceTuyaId;
|
let unitSpaceTuyaId;
|
||||||
if (!spaceTuyaId) {
|
if (!spaceTuyaId) {
|
||||||
const unitDetails = await this.getUnitByUuid(spaceUuid);
|
const space = await this.getUnitByUuid(spaceUuid);
|
||||||
unitSpaceTuyaId = unitDetails.spaceTuyaUuid;
|
unitSpaceTuyaId = space.spaceTuyaUuid;
|
||||||
if (!unitSpaceTuyaId) {
|
if (!unitSpaceTuyaId) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unitSpaceTuyaId = spaceTuyaId;
|
unitSpaceTuyaId = spaceTuyaId;
|
||||||
@ -357,7 +362,7 @@ export class AutomationService {
|
|||||||
}
|
}
|
||||||
const addAutomation = {
|
const addAutomation = {
|
||||||
...updateAutomationDto,
|
...updateAutomationDto,
|
||||||
unitUuid: null,
|
spaceUuid: null,
|
||||||
};
|
};
|
||||||
const newAutomation = await this.addAutomation(
|
const newAutomation = await this.addAutomation(
|
||||||
addAutomation,
|
addAutomation,
|
||||||
@ -387,14 +392,16 @@ export class AutomationService {
|
|||||||
automationUuid: string,
|
automationUuid: string,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const unitDetails = await this.getUnitByUuid(
|
const space = await this.getUnitByUuid(
|
||||||
updateAutomationStatusDto.unitUuid,
|
updateAutomationStatusDto.spaceUuid,
|
||||||
|
);
|
||||||
|
if (!space.spaceTuyaUuid) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
`Invalid space UUID ${updateAutomationStatusDto.spaceUuid}`,
|
||||||
);
|
);
|
||||||
if (!unitDetails.spaceTuyaUuid) {
|
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = `/v2.0/cloud/scene/rule/state?space_id=${unitDetails.spaceTuyaUuid}`;
|
const path = `/v2.0/cloud/scene/rule/state?space_id=${space.spaceTuyaUuid}`;
|
||||||
const response: DeleteAutomationInterface = await this.tuya.request({
|
const response: DeleteAutomationInterface = await this.tuya.request({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
path,
|
path,
|
||||||
|
@ -792,15 +792,15 @@ export class DeviceService {
|
|||||||
parent: {
|
parent: {
|
||||||
uuid: SpaceUuid,
|
uuid: SpaceUuid,
|
||||||
},
|
},
|
||||||
devicesSpaceEntity: {
|
devices: {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
relations: ['devicesSpaceEntity', 'devicesSpaceEntity.productDevice'],
|
relations: ['devices', 'devices.productDevice'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const devices = spaces.flatMap((space) => {
|
const devices = spaces.flatMap((space) => {
|
||||||
return space.devicesSpaceEntity.map((device) => device);
|
return space.devices.map((device) => device);
|
||||||
});
|
});
|
||||||
|
|
||||||
const devicesData = await Promise.all(
|
const devicesData = await Promise.all(
|
||||||
|
@ -35,13 +35,11 @@ export class GroupService {
|
|||||||
uuid: unitUuid,
|
uuid: unitUuid,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
relations: ['devicesSpaceEntity', 'devicesSpaceEntity.productDevice'],
|
relations: ['devices', 'devices.productDevice'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const groupNames = spaces.flatMap((space) => {
|
const groupNames = spaces.flatMap((space) => {
|
||||||
return space.devicesSpaceEntity.map(
|
return space.devices.map((device) => device.productDevice.prodType);
|
||||||
(device) => device.productDevice.prodType,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const uniqueGroupNames = [...new Set(groupNames)];
|
const uniqueGroupNames = [...new Set(groupNames)];
|
||||||
@ -82,7 +80,7 @@ export class GroupService {
|
|||||||
parent: {
|
parent: {
|
||||||
uuid: unitUuid,
|
uuid: unitUuid,
|
||||||
},
|
},
|
||||||
devicesSpaceEntity: {
|
devices: {
|
||||||
productDevice: {
|
productDevice: {
|
||||||
prodType: groupName,
|
prodType: groupName,
|
||||||
},
|
},
|
||||||
@ -95,18 +93,18 @@ export class GroupService {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
relations: [
|
relations: [
|
||||||
'devicesSpaceEntity',
|
'devices',
|
||||||
'devicesSpaceEntity.productDevice',
|
'devices.productDevice',
|
||||||
'devicesSpaceEntity.spaceDevice',
|
'devices.spaceDevice',
|
||||||
'devicesSpaceEntity.permission',
|
'devices.permission',
|
||||||
'devicesSpaceEntity.permission.permissionType',
|
'devices.permission.permissionType',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const devices = await Promise.all(
|
const devices = await Promise.all(
|
||||||
spaces.flatMap(async (space) => {
|
spaces.flatMap(async (space) => {
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
space.devicesSpaceEntity.map(async (device) => {
|
space.devices.map(async (device) => {
|
||||||
const deviceDetails = await this.getDeviceDetailsByDeviceIdTuya(
|
const deviceDetails = await this.getDeviceDetailsByDeviceIdTuya(
|
||||||
device.deviceTuyaUuid,
|
device.deviceTuyaUuid,
|
||||||
);
|
);
|
||||||
|
@ -33,13 +33,13 @@ export class CheckUnitTypeGuard implements CanActivate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkFloorIsFloorType(unitUuid: string) {
|
async checkFloorIsFloorType(spaceUuid: string) {
|
||||||
const unitData = await this.spaceRepository.findOne({
|
const space = await this.spaceRepository.findOne({
|
||||||
where: { uuid: unitUuid },
|
where: { uuid: spaceUuid },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!unitData) {
|
if (!space) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,12 +64,12 @@ class Action {
|
|||||||
|
|
||||||
export class AddSceneTapToRunDto {
|
export class AddSceneTapToRunDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Unit UUID',
|
description: 'Space UUID',
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public unitUuid: string;
|
public spaceUuid: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Scene name',
|
description: 'Scene name',
|
||||||
|
@ -48,12 +48,12 @@ export class SceneService {
|
|||||||
try {
|
try {
|
||||||
let unitSpaceTuyaId;
|
let unitSpaceTuyaId;
|
||||||
if (!spaceTuyaId) {
|
if (!spaceTuyaId) {
|
||||||
const unitDetails = await this.getSpaceByUuid(
|
const space = await this.getSpaceByUuid(addSceneTapToRunDto.spaceUuid);
|
||||||
addSceneTapToRunDto.unitUuid,
|
unitSpaceTuyaId = space.spaceTuyaUuid;
|
||||||
|
if (!space) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
`Invalid space UUID ${addSceneTapToRunDto.spaceUuid}`,
|
||||||
);
|
);
|
||||||
unitSpaceTuyaId = unitDetails.spaceTuyaUuid;
|
|
||||||
if (!unitDetails) {
|
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unitSpaceTuyaId = spaceTuyaId;
|
unitSpaceTuyaId = spaceTuyaId;
|
||||||
@ -112,6 +112,7 @@ export class SceneService {
|
|||||||
where: {
|
where: {
|
||||||
uuid: spaceUuid,
|
uuid: spaceUuid,
|
||||||
},
|
},
|
||||||
|
relations: ['community'],
|
||||||
});
|
});
|
||||||
if (!space) {
|
if (!space) {
|
||||||
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
||||||
@ -121,10 +122,11 @@ export class SceneService {
|
|||||||
createdAt: space.createdAt,
|
createdAt: space.createdAt,
|
||||||
updatedAt: space.updatedAt,
|
updatedAt: space.updatedAt,
|
||||||
name: space.spaceName,
|
name: space.spaceName,
|
||||||
spaceTuyaUuid: space.spaceTuyaUuid,
|
spaceTuyaUuid: space.community.externalId,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof BadRequestException) {
|
if (err instanceof BadRequestException) {
|
||||||
|
console.log(err);
|
||||||
throw err; // Re-throw BadRequestException
|
throw err; // Re-throw BadRequestException
|
||||||
} else {
|
} else {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
@ -136,12 +138,12 @@ export class SceneService {
|
|||||||
}
|
}
|
||||||
async getTapToRunSceneByUnit(spaceUuid: string) {
|
async getTapToRunSceneByUnit(spaceUuid: string) {
|
||||||
try {
|
try {
|
||||||
const unit = await this.getSpaceByUuid(spaceUuid);
|
const space = await this.getSpaceByUuid(spaceUuid);
|
||||||
if (!unit.spaceTuyaUuid) {
|
if (!space.spaceTuyaUuid) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = `/v2.0/cloud/scene/rule?space_id=${unit.spaceTuyaUuid}&type=scene`;
|
const path = `/v2.0/cloud/scene/rule?space_id=${space.spaceTuyaUuid}&type=scene`;
|
||||||
const response: GetTapToRunSceneByUnitInterface = await this.tuya.request(
|
const response: GetTapToRunSceneByUnitInterface = await this.tuya.request(
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -177,10 +179,10 @@ export class SceneService {
|
|||||||
try {
|
try {
|
||||||
let unitSpaceTuyaId;
|
let unitSpaceTuyaId;
|
||||||
if (!spaceTuyaId) {
|
if (!spaceTuyaId) {
|
||||||
const unitDetails = await this.getSpaceByUuid(spaceUuid);
|
const space = await this.getSpaceByUuid(spaceUuid);
|
||||||
unitSpaceTuyaId = unitDetails.spaceTuyaUuid;
|
unitSpaceTuyaId = space.spaceTuyaUuid;
|
||||||
if (!unitSpaceTuyaId) {
|
if (!unitSpaceTuyaId) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException(`Invalid space UUID ${spaceUuid}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unitSpaceTuyaId = spaceTuyaId;
|
unitSpaceTuyaId = spaceTuyaId;
|
||||||
@ -331,7 +333,7 @@ export class SceneService {
|
|||||||
}
|
}
|
||||||
const addSceneTapToRunDto: AddSceneTapToRunDto = {
|
const addSceneTapToRunDto: AddSceneTapToRunDto = {
|
||||||
...updateSceneTapToRunDto,
|
...updateSceneTapToRunDto,
|
||||||
unitUuid: null,
|
spaceUuid: null,
|
||||||
};
|
};
|
||||||
const newTapToRunScene = await this.addTapToRunScene(
|
const newTapToRunScene = await this.addTapToRunScene(
|
||||||
addSceneTapToRunDto,
|
addSceneTapToRunDto,
|
||||||
|
30
src/space/controllers/space-device.controller.ts
Normal file
30
src/space/controllers/space-device.controller.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||||
|
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
|
||||||
|
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { SubspaceDeviceService } from '../services/space-device.service';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
import { GetSpaceParam } from '../dtos';
|
||||||
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
|
|
||||||
|
@ApiTags('Space Module')
|
||||||
|
@Controller({
|
||||||
|
version: '1',
|
||||||
|
path: ControllerRoute.SPACE_DEVICES.ROUTE,
|
||||||
|
})
|
||||||
|
export class SubSpaceDeviceController {
|
||||||
|
constructor(private readonly spaceDeviceService: SubspaceDeviceService) {}
|
||||||
|
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
@ApiOperation({
|
||||||
|
summary: ControllerRoute.SPACE_DEVICES.ACTIONS.LIST_SPACE_DEVICE_SUMMARY,
|
||||||
|
description:
|
||||||
|
ControllerRoute.SPACE_DEVICES.ACTIONS.LIST_SPACE_DEVICE_DESCRIPTION,
|
||||||
|
})
|
||||||
|
@Get()
|
||||||
|
async listDevicesInSpace(
|
||||||
|
@Param() params: GetSpaceParam,
|
||||||
|
): Promise<BaseResponseDto> {
|
||||||
|
return await this.spaceDeviceService.listDevicesInSpace(params);
|
||||||
|
}
|
||||||
|
}
|
112
src/space/services/space-device.service.ts
Normal file
112
src/space/services/space-device.service.ts
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import { TuyaService } from '@app/common/integrations/tuya/tuya.service';
|
||||||
|
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||||
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
|
import { GetDeviceDetailsInterface } from 'src/device/interfaces/get.device.interface';
|
||||||
|
import { GetSpaceParam } from '../dtos';
|
||||||
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
|
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||||
|
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
|
||||||
|
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SubspaceDeviceService {
|
||||||
|
constructor(
|
||||||
|
private readonly spaceRepository: SpaceRepository,
|
||||||
|
private readonly tuyaService: TuyaService,
|
||||||
|
private readonly productRepository: ProductRepository,
|
||||||
|
private readonly communityRepository: CommunityRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async listDevicesInSpace(params: GetSpaceParam): Promise<BaseResponseDto> {
|
||||||
|
const { spaceUuid, communityUuid } = params;
|
||||||
|
|
||||||
|
const space = await this.validateCommunityAndSpace(
|
||||||
|
communityUuid,
|
||||||
|
spaceUuid,
|
||||||
|
);
|
||||||
|
|
||||||
|
const detailedDevices = await Promise.all(
|
||||||
|
space.devices.map(async (device) => {
|
||||||
|
const tuyaDetails = await this.getDeviceDetailsByDeviceIdTuya(
|
||||||
|
device.deviceTuyaUuid,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: device.uuid,
|
||||||
|
deviceTuyaUuid: device.deviceTuyaUuid,
|
||||||
|
productUuid: device.productDevice.uuid,
|
||||||
|
productType: device.productDevice.prodType,
|
||||||
|
isActive: device.isActive,
|
||||||
|
createdAt: device.createdAt,
|
||||||
|
updatedAt: device.updatedAt,
|
||||||
|
...tuyaDetails,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return new SuccessResponseDto({
|
||||||
|
data: detailedDevices,
|
||||||
|
message: 'Successfully retrieved list of devices',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async validateCommunityAndSpace(
|
||||||
|
communityUuid: string,
|
||||||
|
spaceUuid: string,
|
||||||
|
) {
|
||||||
|
const community = await this.communityRepository.findOne({
|
||||||
|
where: { uuid: communityUuid },
|
||||||
|
});
|
||||||
|
if (!community) {
|
||||||
|
this.throwNotFound('Community', communityUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
const space = await this.spaceRepository.findOne({
|
||||||
|
where: { uuid: spaceUuid, community: { uuid: communityUuid } },
|
||||||
|
relations: ['devices', 'devices.productDevice'],
|
||||||
|
});
|
||||||
|
if (!space) {
|
||||||
|
this.throwNotFound('Space', spaceUuid);
|
||||||
|
}
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
private throwNotFound(entity: string, uuid: string) {
|
||||||
|
throw new HttpException(
|
||||||
|
`${entity} with ID ${uuid} not found`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getDeviceDetailsByDeviceIdTuya(
|
||||||
|
deviceId: string,
|
||||||
|
): Promise<GetDeviceDetailsInterface> {
|
||||||
|
try {
|
||||||
|
// Fetch details from TuyaService
|
||||||
|
const tuyaDeviceDetails =
|
||||||
|
await this.tuyaService.getDeviceDetails(deviceId);
|
||||||
|
|
||||||
|
// Convert keys to camel case
|
||||||
|
const camelCaseResponse = convertKeysToCamelCase(tuyaDeviceDetails);
|
||||||
|
|
||||||
|
const product = await this.productRepository.findOne({
|
||||||
|
where: {
|
||||||
|
prodId: camelCaseResponse.productId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Exclude specific keys and add `productUuid`
|
||||||
|
const { ...rest } = camelCaseResponse;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
productUuid: product?.uuid,
|
||||||
|
} as GetDeviceDetailsInterface;
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
'Error fetching device details from Tuya',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,10 @@ import {
|
|||||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
import { DeviceSubSpaceParam, GetSubSpaceParam } from '../../dtos';
|
import { DeviceSubSpaceParam, GetSubSpaceParam } from '../../dtos';
|
||||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||||
|
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
|
||||||
|
import { TuyaService } from '@app/common/integrations/tuya/tuya.service';
|
||||||
|
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||||
|
import { GetDeviceDetailsInterface } from '../../../device/interfaces/get.device.interface';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SubspaceDeviceService {
|
export class SubspaceDeviceService {
|
||||||
@ -16,6 +20,8 @@ export class SubspaceDeviceService {
|
|||||||
private readonly communityRepository: CommunityRepository,
|
private readonly communityRepository: CommunityRepository,
|
||||||
private readonly subspaceRepository: SubspaceRepository,
|
private readonly subspaceRepository: SubspaceRepository,
|
||||||
private readonly deviceRepository: DeviceRepository,
|
private readonly deviceRepository: DeviceRepository,
|
||||||
|
private readonly tuyaService: TuyaService,
|
||||||
|
private readonly productRepository: ProductRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async listDevicesInSubspace(
|
async listDevicesInSubspace(
|
||||||
@ -26,12 +32,31 @@ export class SubspaceDeviceService {
|
|||||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||||
|
|
||||||
const subspace = await this.findSubspaceWithDevices(subSpaceUuid);
|
const subspace = await this.findSubspaceWithDevices(subSpaceUuid);
|
||||||
|
|
||||||
|
const detailedDevices = await Promise.all(
|
||||||
|
subspace.devices.map(async (device) => {
|
||||||
|
const tuyaDetails = await this.getDeviceDetailsByDeviceIdTuya(
|
||||||
|
device.deviceTuyaUuid,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: device.uuid,
|
||||||
|
deviceTuyaUuid: device.deviceTuyaUuid,
|
||||||
|
productUuid: device.productDevice.uuid,
|
||||||
|
productType: device.productDevice.prodType,
|
||||||
|
isActive: device.isActive,
|
||||||
|
createdAt: device.createdAt,
|
||||||
|
updatedAt: device.updatedAt,
|
||||||
|
...tuyaDetails,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
data: subspace.devices,
|
data: detailedDevices,
|
||||||
message: 'Successfully retrieved list of devices',
|
message: 'Successfully retrieved list of devices',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async associateDeviceToSubspace(params: DeviceSubSpaceParam) {
|
async associateDeviceToSubspace(params: DeviceSubSpaceParam) {
|
||||||
const { subSpaceUuid, deviceUuid, spaceUuid, communityUuid } = params;
|
const { subSpaceUuid, deviceUuid, spaceUuid, communityUuid } = params;
|
||||||
|
|
||||||
@ -91,7 +116,7 @@ export class SubspaceDeviceService {
|
|||||||
private async findSubspaceWithDevices(subSpaceUuid: string) {
|
private async findSubspaceWithDevices(subSpaceUuid: string) {
|
||||||
const subspace = await this.subspaceRepository.findOne({
|
const subspace = await this.subspaceRepository.findOne({
|
||||||
where: { uuid: subSpaceUuid },
|
where: { uuid: subSpaceUuid },
|
||||||
relations: ['devices'],
|
relations: ['devices', 'devices.productDevice'],
|
||||||
});
|
});
|
||||||
if (!subspace) {
|
if (!subspace) {
|
||||||
this.throwNotFound('Subspace', subSpaceUuid);
|
this.throwNotFound('Subspace', subSpaceUuid);
|
||||||
@ -125,4 +150,35 @@ export class SubspaceDeviceService {
|
|||||||
HttpStatus.NOT_FOUND,
|
HttpStatus.NOT_FOUND,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async getDeviceDetailsByDeviceIdTuya(
|
||||||
|
deviceId: string,
|
||||||
|
): Promise<GetDeviceDetailsInterface> {
|
||||||
|
try {
|
||||||
|
// Fetch details from TuyaService
|
||||||
|
const tuyaDeviceDetails =
|
||||||
|
await this.tuyaService.getDeviceDetails(deviceId);
|
||||||
|
|
||||||
|
// Convert keys to camel case
|
||||||
|
const camelCaseResponse = convertKeysToCamelCase(tuyaDeviceDetails);
|
||||||
|
|
||||||
|
const product = await this.productRepository.findOne({
|
||||||
|
where: {
|
||||||
|
prodId: camelCaseResponse.productId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Exclude specific keys and add `productUuid`
|
||||||
|
const { ...rest } = camelCaseResponse;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
productUuid: product?.uuid,
|
||||||
|
} as GetDeviceDetailsInterface;
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
'Error fetching device details from Tuya',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ import {
|
|||||||
UserSpaceRepository,
|
UserSpaceRepository,
|
||||||
} from '@app/common/modules/user/repositories';
|
} from '@app/common/modules/user/repositories';
|
||||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
|
import { TuyaService } from '@app/common/integrations/tuya/tuya.service';
|
||||||
|
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, SpaceRepositoryModule],
|
imports: [ConfigModule, SpaceRepositoryModule],
|
||||||
@ -34,6 +36,8 @@ import { DeviceRepository } from '@app/common/modules/device/repositories';
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
SpaceService,
|
SpaceService,
|
||||||
|
TuyaService,
|
||||||
|
ProductRepository,
|
||||||
SubSpaceService,
|
SubSpaceService,
|
||||||
SubspaceDeviceService,
|
SubspaceDeviceService,
|
||||||
SpaceRepository,
|
SpaceRepository,
|
||||||
|
Reference in New Issue
Block a user