diff --git a/libs/common/src/integrations/tuya/tuya.service.ts b/libs/common/src/integrations/tuya/tuya.service.ts index 59efe6f..e37ab4d 100644 --- a/libs/common/src/integrations/tuya/tuya.service.ts +++ b/libs/common/src/integrations/tuya/tuya.service.ts @@ -52,4 +52,38 @@ export class TuyaService { return response.result; } + + async deleteSceneRule(sceneId: string, spaceId: string) { + const path = `/v2.0/cloud/scene/rule?ids=${sceneId}&space_id=${spaceId}`; + const response = await this.tuya.request({ + method: 'DELETE', + path, + }); + + if (response.success) { + return response; + } else { + throw new HttpException( + `Error deleting scene rule: ${response.msg}`, + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async getSceneRule(sceneId: string) { + const path = `/v2.0/cloud/scene/rule/${sceneId}`; + const response = await this.tuya.request({ + method: 'GET', + path, + }); + + if (response.success) { + return response; + } else { + throw new HttpException( + `Error fetching scene rule: ${response.msg}`, + HttpStatus.BAD_REQUEST, + ); + } + } } diff --git a/src/scene/controllers/scene.controller.ts b/src/scene/controllers/scene.controller.ts index f83f9a2..bb729f8 100644 --- a/src/scene/controllers/scene.controller.ts +++ b/src/scene/controllers/scene.controller.ts @@ -60,14 +60,15 @@ export class SceneController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) - @Delete('tap-to-run/:unitUuid/:sceneUuid') + @Delete('tap-to-run/:spaceUuid/:sceneUuid') async deleteTapToRunScene(@Param() param: DeleteSceneParamDto) { - await this.sceneService.deleteTapToRunScene(param); + await this.sceneService.deleteScene(param); return { statusCode: HttpStatus.OK, message: 'Scene Deleted Successfully', }; } + @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('tap-to-run/trigger/:sceneUuid') diff --git a/src/scene/scene.module.ts b/src/scene/scene.module.ts index cdbf2d4..5649f2a 100644 --- a/src/scene/scene.module.ts +++ b/src/scene/scene.module.ts @@ -12,6 +12,7 @@ import { SceneIconRepository, SceneRepository, } from '@app/common/modules/scene/repositories'; +import { TuyaService } from '@app/common/integrations/tuya/tuya.service'; @Module({ imports: [ConfigModule, SpaceRepositoryModule, DeviceStatusFirebaseModule], @@ -20,6 +21,7 @@ import { SceneService, SpaceRepository, DeviceService, + TuyaService, DeviceRepository, ProductRepository, SceneIconRepository, diff --git a/src/scene/services/scene.service.ts b/src/scene/services/scene.service.ts index 8fcfe5e..f279fd7 100644 --- a/src/scene/services/scene.service.ts +++ b/src/scene/services/scene.service.ts @@ -3,7 +3,6 @@ import { HttpException, HttpStatus, BadRequestException, - HttpCode, } from '@nestjs/common'; import { SpaceRepository } from '@app/common/modules/space/repositories'; import { @@ -29,6 +28,8 @@ import { SceneRepository, } from '@app/common/modules/scene/repositories'; import { SceneIconType } from '@app/common/constants/secne-icon-type.enum'; +import { SceneEntity } from '@app/common/modules/scene/entities'; +import { TuyaService } from '@app/common/integrations/tuya/tuya.service'; @Injectable() export class SceneService { @@ -39,6 +40,7 @@ export class SceneService { private readonly sceneIconRepository: SceneIconRepository, private readonly sceneRepository: SceneRepository, private readonly deviceService: DeviceService, + private readonly tuyaService: TuyaService, ) { const accessKey = this.configService.get('auth-config.ACCESS_KEY'); const secretKey = this.configService.get('auth-config.SECRET_KEY'); @@ -121,6 +123,7 @@ export class SceneService { id: response.result.id, }; } catch (err) { + console.log(err); if (err instanceof BadRequestException) { throw err; // Re-throw BadRequestException } else { @@ -131,6 +134,7 @@ export class SceneService { } } } + async getSpaceByUuid(spaceUuid: string) { try { const space = await this.spaceRepository.findOne({ @@ -221,6 +225,8 @@ export class SceneService { path, }); + console.log(path); + if (!response.success) { throw new HttpException('Scene not found', HttpStatus.NOT_FOUND); } else { @@ -229,6 +235,7 @@ export class SceneService { return response; } catch (err) { + console.log(err); if (err instanceof BadRequestException) { throw err; // Re-throw BadRequestException } else { @@ -262,6 +269,7 @@ export class SceneService { } } } + async getTapToRunSceneDetails(sceneId: string, withSpaceId = false) { const scene = await this.sceneRepository.findOne({ where: { uuid: sceneId }, @@ -372,24 +380,35 @@ export class SceneService { } } } + async updateTapToRunScene( updateSceneTapToRunDto: UpdateSceneTapToRunDto, sceneUuid: string, ) { + const scene = await this.sceneRepository.findOne({ + where: { uuid: sceneUuid }, + }); + + if (!scene) { + throw new HttpException( + `Scene with ${sceneUuid} is not found`, + HttpStatus.NOT_FOUND, + ); + } + try { const spaceTuyaId = await this.getTapToRunSceneDetails(sceneUuid, true); + if (!spaceTuyaId.spaceId) { throw new HttpException("Scene doesn't exist", HttpStatus.NOT_FOUND); } + const addSceneTapToRunDto: AddSceneTapToRunDto = { ...updateSceneTapToRunDto, - spaceUuid: null, + spaceUuid: scene.spaceUuid, iconUuid: updateSceneTapToRunDto.iconUuid, showInHomePage: updateSceneTapToRunDto.showInHomePage, }; - const scene = await this.sceneRepository.findOne({ - where: { sceneTuyaUuid: sceneUuid }, - }); const newTapToRunScene = await this.addTapToRunScene( addSceneTapToRunDto, @@ -398,12 +417,14 @@ export class SceneService { ); const param: DeleteSceneParamDto = { - spaceUuid: spaceTuyaId.spaceId, - sceneUuid, + spaceUuid: scene.spaceUuid, + sceneUuid: scene.sceneTuyaUuid, }; + console.log(param); + if (newTapToRunScene.id) { - await this.deleteTapToRunScene(null, param); + await this.deleteTapToRunScene(param, spaceTuyaId.spaceId); await this.sceneRepository.update( { sceneTuyaUuid: sceneUuid }, @@ -419,6 +440,7 @@ export class SceneService { return newTapToRunScene; } } catch (err) { + console.log(err); if (err instanceof BadRequestException) { throw err; // Re-throw BadRequestException } else { @@ -429,6 +451,7 @@ export class SceneService { } } } + async addSceneIcon(addSceneIconDto: AddSceneIconDto) { try { const icon = await this.sceneIconRepository.save({ @@ -463,4 +486,67 @@ export class SceneService { ); } } + + async deleteScene(params: DeleteSceneParamDto) { + try { + const { sceneUuid, spaceUuid } = params; + const scene = await this.findScene(sceneUuid); + const space = await this.getSpaceByUuid(spaceUuid); + if (!space.spaceTuyaUuid) { + throw new HttpException( + `Invalid space UUID: ${spaceUuid}`, + HttpStatus.BAD_REQUEST, + ); + } + const response = await this.delete( + scene.sceneTuyaUuid, + space.spaceTuyaUuid, + ); + return response; + } catch (err) { + if (err instanceof HttpException) { + throw err; // Re-throw existing HttpException + } else { + throw new HttpException( + err.message || `Scene not found for id ${params.sceneUuid}`, + err.status || HttpStatus.NOT_FOUND, + ); + } + } + } + + async findScene(sceneUuid: string): Promise { + const scene = await this.sceneRepository.findOne({ + where: { + uuid: sceneUuid, + }, + }); + + if (!scene) { + throw new HttpException( + `Invalid scene with id ${sceneUuid}`, + HttpStatus.NOT_FOUND, + ); + } + return scene; + } + + async delete(tuyaSceneId: string, tuyaSpaceId: string) { + try { + const response = (await this.tuyaService.deleteSceneRule( + tuyaSceneId, + tuyaSpaceId, + )) as DeleteTapToRunSceneInterface; + return response; + } catch (error) { + if (error instanceof HttpException) { + throw error; + } else { + throw new HttpException( + 'Failed to delete scene rule in Tuya', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + } }