diff --git a/src/app.module.ts b/src/app.module.ts index b890f1a..1da5880 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -6,6 +6,7 @@ import { AuthenticationController } from './auth/controllers/authentication.cont import { UserModule } from './users/user.module'; import { HomeModule } from './home/home.module'; import { RoomModule } from './room/room.module'; +import { GroupModule } from './group/group.module'; @Module({ imports: [ ConfigModule.forRoot({ @@ -15,6 +16,7 @@ import { RoomModule } from './room/room.module'; UserModule, HomeModule, RoomModule, + GroupModule, ], controllers: [AuthenticationController], }) diff --git a/src/group/controllers/group.controller.ts b/src/group/controllers/group.controller.ts new file mode 100644 index 0000000..4cdb617 --- /dev/null +++ b/src/group/controllers/group.controller.ts @@ -0,0 +1,48 @@ +import { GroupService } from '../services/group.service'; +import { + Body, + Controller, + Get, + Post, + UseGuards, + Query, + Param, +} from '@nestjs/common'; +import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; +import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard'; +import { AddGroupDto } from '../dtos/add.group.dto'; +import { GetGroupDto } from '../dtos/get.group.dto'; + +@ApiTags('Group Module') +@Controller({ + version: '1', + path: 'group', +}) +export class GroupController { + constructor(private readonly groupService: GroupService) {} + + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Get(':homeId') + async userList( + @Param('homeId') homeId: string, + @Query() getGroupsDto: GetGroupDto, + ) { + try { + return await this.groupService.getGroupsByHomeId(homeId, getGroupsDto); + } catch (err) { + throw new Error(err); + } + } + + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Post() + async addGroup(@Body() addGroupDto: AddGroupDto) { + try { + return await this.groupService.addGroup(addGroupDto); + } catch (err) { + throw new Error(err); + } + } +} diff --git a/src/group/controllers/index.ts b/src/group/controllers/index.ts new file mode 100644 index 0000000..daf2953 --- /dev/null +++ b/src/group/controllers/index.ts @@ -0,0 +1 @@ +export * from './group.controller'; diff --git a/src/group/dtos/add.group.dto.ts b/src/group/dtos/add.group.dto.ts new file mode 100644 index 0000000..b91f793 --- /dev/null +++ b/src/group/dtos/add.group.dto.ts @@ -0,0 +1,36 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString, IsNumberString } from 'class-validator'; + +export class AddGroupDto { + @ApiProperty({ + description: 'groupName', + required: true, + }) + @IsString() + @IsNotEmpty() + public groupName: string; + + @ApiProperty({ + description: 'homeId', + required: true, + }) + @IsNumberString() + @IsNotEmpty() + public homeId: string; + + @ApiProperty({ + description: 'productId', + required: true, + }) + @IsString() + @IsNotEmpty() + public productId: string; + + @ApiProperty({ + description: 'The list of up to 20 device IDs, separated with commas (,)', + required: true, + }) + @IsString() + @IsNotEmpty() + public deviceIds: string; +} diff --git a/src/group/dtos/get.group.dto.ts b/src/group/dtos/get.group.dto.ts new file mode 100644 index 0000000..16f8236 --- /dev/null +++ b/src/group/dtos/get.group.dto.ts @@ -0,0 +1,20 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsNumberString } from 'class-validator'; + +export class GetGroupDto { + @ApiProperty({ + description: 'pageSize', + required: true, + }) + @IsNumberString() + @IsNotEmpty() + public pageSize: number; + + @ApiProperty({ + description: 'pageNo', + required: true, + }) + @IsNumberString() + @IsNotEmpty() + public pageNo: number; +} diff --git a/src/group/dtos/index.ts b/src/group/dtos/index.ts new file mode 100644 index 0000000..61cffa2 --- /dev/null +++ b/src/group/dtos/index.ts @@ -0,0 +1 @@ +export * from './add.group.dto'; diff --git a/src/group/group.module.ts b/src/group/group.module.ts new file mode 100644 index 0000000..3969d39 --- /dev/null +++ b/src/group/group.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { GroupService } from './services/group.service'; +import { GroupController } from './controllers/group.controller'; +import { ConfigModule } from '@nestjs/config'; +@Module({ + imports: [ConfigModule], + controllers: [GroupController], + providers: [GroupService], + exports: [GroupService], +}) +export class GroupModule {} diff --git a/src/group/interfaces/get.group.interface.ts b/src/group/interfaces/get.group.interface.ts new file mode 100644 index 0000000..3e93b95 --- /dev/null +++ b/src/group/interfaces/get.group.interface.ts @@ -0,0 +1,20 @@ +export class GetRoomDetailsInterface { + result: { + id: string; + name: string; + }; +} +export class GetGroupsInterface { + result: { + count: number; + data_list: []; + }; +} + +export class addGroupInterface { + success: boolean; + msg: string; + result: { + id: string; + }; +} diff --git a/src/group/services/group.service.ts b/src/group/services/group.service.ts new file mode 100644 index 0000000..f05dc10 --- /dev/null +++ b/src/group/services/group.service.ts @@ -0,0 +1,124 @@ +import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; +import { TuyaContext } from '@tuya/tuya-connector-nodejs'; +import { ConfigService } from '@nestjs/config'; +import { AddGroupDto } from '../dtos'; +import { + GetGroupsInterface, + GetRoomDetailsInterface, + addGroupInterface, +} from '../interfaces/get.group.interface'; +import { GetGroupDto } from '../dtos/get.group.dto'; + +@Injectable() +export class GroupService { + private tuya: TuyaContext; + constructor(private readonly configService: ConfigService) { + const accessKey = this.configService.get('auth-config.ACCESS_KEY'); + const secretKey = this.configService.get('auth-config.SECRET_KEY'); + // const clientId = this.configService.get('auth-config.CLIENT_ID'); + this.tuya = new TuyaContext({ + baseUrl: 'https://openapi.tuyaeu.com', + accessKey, + secretKey, + }); + } + + async getGroupsByHomeId(homeId: string, getGroupDto: GetGroupDto) { + try { + const response = await this.getGroupsTuya(homeId, getGroupDto); + + const groups = response.result.data_list.map((group: any) => ({ + groupId: group.id, + groupName: group.name, + })); + + return { + count: response.result.count, + groups: groups, + }; + } catch (error) { + throw new HttpException( + 'Error fetching groups', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async getGroupsTuya( + homeId: string, + getGroupDto: GetGroupDto, + ): Promise { + try { + const path = `/v2.0/cloud/thing/group`; + const response = await this.tuya.request({ + method: 'GET', + path, + query: { + space_id: homeId, + page_size: getGroupDto.pageSize, + page_no: getGroupDto.pageNo, + }, + }); + return response as unknown as GetGroupsInterface; + } catch (error) { + throw new HttpException( + 'Error fetching groups ', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async getRoomDetails(roomId: string): Promise { + // Added return type + try { + const path = `/v2.0/cloud/space/${roomId}`; + const response = await this.tuya.request({ + method: 'GET', + path, + }); + + return response as GetRoomDetailsInterface; // Cast response to RoomData + } catch (error) { + throw new HttpException( + 'Error fetching rooms details', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async addGroup(addGroupDto: AddGroupDto) { + const response = await this.addGroupTuya(addGroupDto); + + if (response.success) { + return { + success: true, + groupId: response.result.id, + }; + } else { + throw new HttpException( + response.msg || 'Unknown error', + HttpStatus.BAD_REQUEST, + ); + } + } + async addGroupTuya(addGroupDto: AddGroupDto): Promise { + try { + const path = `/v2.0/cloud/thing/group`; + const response = await this.tuya.request({ + method: 'POST', + path, + body: { + space_id: addGroupDto.homeId, + name: addGroupDto.groupName, + product_id: addGroupDto.productId, + device_ids: addGroupDto.deviceIds, + }, + }); + + return response as addGroupInterface; + } catch (error) { + throw new HttpException( + 'Error adding group', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } +} diff --git a/src/group/services/index.ts b/src/group/services/index.ts new file mode 100644 index 0000000..ee9dd3f --- /dev/null +++ b/src/group/services/index.ts @@ -0,0 +1 @@ +export * from './group.service';