diff --git a/src/device/controllers/device.controller.ts b/src/device/controllers/device.controller.ts index ffedef3..936b8e1 100644 --- a/src/device/controllers/device.controller.ts +++ b/src/device/controllers/device.controller.ts @@ -7,15 +7,18 @@ import { UseGuards, Query, Param, - Put, - Delete, } from '@nestjs/common'; import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard'; -import { AddDeviceDto } from '../dtos/add.device.dto'; -import { GetDeviceDto } from '../dtos/get.device.dto'; +import { + AddDeviceInGroupDto, + AddDeviceInRoomDto, +} from '../dtos/add.device.dto'; +import { + GetDeviceByGroupIdDto, + GetDeviceByRoomIdDto, +} from '../dtos/get.device.dto'; import { ControlDeviceDto } from '../dtos/control.device.dto'; -import { RenameDeviceDto } from '../dtos/rename.device.dto copy'; @ApiTags('Device Module') @Controller({ @@ -25,12 +28,28 @@ import { RenameDeviceDto } from '../dtos/rename.device.dto copy'; export class DeviceController { constructor(private readonly deviceService: DeviceService) {} - // @ApiBearerAuth() - // @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) @Get('room') - async getDevicesByRoomId(@Query() getDevicesDto: GetDeviceDto) { + async getDevicesByRoomId( + @Query() getDeviceByRoomIdDto: GetDeviceByRoomIdDto, + ) { try { - return await this.deviceService.getDevicesByRoomId(getDevicesDto); + return await this.deviceService.getDevicesByRoomId(getDeviceByRoomIdDto); + } catch (err) { + throw new Error(err); + } + } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Get('group') + async getDevicesByGroupId( + @Query() getDeviceByGroupIdDto: GetDeviceByGroupIdDto, + ) { + try { + return await this.deviceService.getDevicesByGroupId( + getDeviceByGroupIdDto, + ); } catch (err) { throw new Error(err); } @@ -38,7 +57,7 @@ export class DeviceController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get(':deviceId') - async getDevicesByDeviceId(@Param('deviceId') deviceId: number) { + async getDevicesByDeviceId(@Param('deviceId') deviceId: string) { try { return await this.deviceService.getDevicesByDeviceId(deviceId); } catch (err) { @@ -47,15 +66,44 @@ export class DeviceController { } @ApiBearerAuth() @UseGuards(JwtAuthGuard) - @Post() - async addDevice(@Body() addDeviceDto: AddDeviceDto) { + @Get(':deviceId/functions') + async getDevicesInstructionByDeviceId(@Param('deviceId') deviceId: string) { try { - return await this.deviceService.addDevice(addDeviceDto); + return await this.deviceService.getDevicesInstructionByDeviceId(deviceId); + } catch (err) { + throw new Error(err); + } + } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Get(':deviceId/functions/status') + async getDevicesInstructionStatus(@Param('deviceId') deviceId: string) { + try { + return await this.deviceService.getDevicesInstructionStatus(deviceId); + } catch (err) { + throw new Error(err); + } + } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Post('room') + async addDeviceInRoom(@Body() addDeviceInRoomDto: AddDeviceInRoomDto) { + try { + return await this.deviceService.addDeviceInRoom(addDeviceInRoomDto); + } catch (err) { + throw new Error(err); + } + } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Post('group') + async addDeviceInGroup(@Body() addDeviceInGroupDto: AddDeviceInGroupDto) { + try { + return await this.deviceService.addDeviceInGroup(addDeviceInGroupDto); } catch (err) { throw new Error(err); } } - @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Post('control') @@ -66,26 +114,4 @@ export class DeviceController { throw new Error(err); } } - - @ApiBearerAuth() - @UseGuards(JwtAuthGuard) - @Put('rename') - async renameDevice(@Body() renameDeviceDto: RenameDeviceDto) { - try { - return await this.deviceService.renameDevice(renameDeviceDto); - } catch (err) { - throw new Error(err); - } - } - - @ApiBearerAuth() - @UseGuards(JwtAuthGuard) - @Delete(':deviceId') - async deleteDevice(@Param('deviceId') deviceId: number) { - try { - return await this.deviceService.deleteDevice(deviceId); - } catch (err) { - throw new Error(err); - } - } } diff --git a/src/device/dtos/add.device.dto.ts b/src/device/dtos/add.device.dto.ts index bdb7eb6..8b1dfe5 100644 --- a/src/device/dtos/add.device.dto.ts +++ b/src/device/dtos/add.device.dto.ts @@ -1,14 +1,31 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsString, IsNumberString } from 'class-validator'; -export class AddDeviceDto { +export class AddDeviceInRoomDto { @ApiProperty({ - description: 'deviceName', + description: 'deviceId', required: true, }) @IsString() @IsNotEmpty() - public deviceName: string; + public deviceId: string; + + @ApiProperty({ + description: 'roomId', + required: true, + }) + @IsNumberString() + @IsNotEmpty() + public roomId: string; +} +export class AddDeviceInGroupDto { + @ApiProperty({ + description: 'deviceId', + required: true, + }) + @IsString() + @IsNotEmpty() + public deviceId: string; @ApiProperty({ description: 'homeId', @@ -19,18 +36,10 @@ export class AddDeviceDto { public homeId: string; @ApiProperty({ - description: 'productId', + description: 'groupId', required: true, }) - @IsString() + @IsNumberString() @IsNotEmpty() - public productId: string; - - @ApiProperty({ - description: 'The list of up to 20 device IDs, separated with commas (,)', - required: true, - }) - @IsString() - @IsNotEmpty() - public deviceIds: string; + public groupId: string; } diff --git a/src/device/dtos/control.device.dto.ts b/src/device/dtos/control.device.dto.ts index 1164973..660cdaf 100644 --- a/src/device/dtos/control.device.dto.ts +++ b/src/device/dtos/control.device.dto.ts @@ -1,20 +1,26 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsObject, IsNumberString } from 'class-validator'; +import { IsNotEmpty, IsString } from 'class-validator'; export class ControlDeviceDto { @ApiProperty({ description: 'deviceId', required: true, }) - @IsNumberString() + @IsString() @IsNotEmpty() public deviceId: string; @ApiProperty({ - description: 'example {"switch_1":true,"add_ele":300}', + description: 'code', required: true, }) - @IsObject() + @IsString() @IsNotEmpty() - public properties: object; + public code: string; + @ApiProperty({ + description: 'value', + required: true, + }) + @IsNotEmpty() + public value: any; } diff --git a/src/device/dtos/get.device.dto.ts b/src/device/dtos/get.device.dto.ts index 217ab46..d49a714 100644 --- a/src/device/dtos/get.device.dto.ts +++ b/src/device/dtos/get.device.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsNumberString } from 'class-validator'; -export class GetDeviceDto { +export class GetDeviceByRoomIdDto { @ApiProperty({ description: 'roomId', required: true, @@ -18,3 +18,27 @@ export class GetDeviceDto { @IsNotEmpty() public pageSize: number; } +export class GetDeviceByGroupIdDto { + @ApiProperty({ + description: 'groupId', + required: true, + }) + @IsNumberString() + @IsNotEmpty() + public groupId: string; + + @ApiProperty({ + description: 'pageSize', + required: true, + }) + @IsNumberString() + @IsNotEmpty() + public pageSize: number; + @ApiProperty({ + description: 'pageNo', + required: true, + }) + @IsNumberString() + @IsNotEmpty() + public pageNo: number; +} diff --git a/src/device/dtos/index.ts b/src/device/dtos/index.ts index 3409fea..1a0b6b3 100644 --- a/src/device/dtos/index.ts +++ b/src/device/dtos/index.ts @@ -1,4 +1,3 @@ export * from './add.device.dto'; export * from './control.device.dto'; export * from './get.device.dto'; -export * from './rename.device.dto copy'; diff --git a/src/device/dtos/rename.device.dto copy.ts b/src/device/dtos/rename.device.dto copy.ts deleted file mode 100644 index e32a6bb..0000000 --- a/src/device/dtos/rename.device.dto copy.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsString, IsNumberString } from 'class-validator'; - -export class RenameDeviceDto { - @ApiProperty({ - description: 'deviceId', - required: true, - }) - @IsNumberString() - @IsNotEmpty() - public deviceId: string; - - @ApiProperty({ - description: 'deviceName', - required: true, - }) - @IsString() - @IsNotEmpty() - public deviceName: string; -} diff --git a/src/device/interfaces/get.device.interface.ts b/src/device/interfaces/get.device.interface.ts index 75a2145..e6f1361 100644 --- a/src/device/interfaces/get.device.interface.ts +++ b/src/device/interfaces/get.device.interface.ts @@ -1,25 +1,44 @@ export class GetDeviceDetailsInterface { - result: { - id: string; - name: string; - }; + result: object; + success: boolean; + msg: string; } -export class GetDevicesInterface { +export class GetDevicesByRoomIdInterface { success: boolean; msg: string; result: []; } -export class addDeviceInterface { +export class GetDevicesByGroupIdInterface { success: boolean; msg: string; result: { - id: string; + count: number; + data_list: []; }; } +export class addDeviceInRoomInterface { + success: boolean; + msg: string; + result: boolean; +} + export class controlDeviceInterface { success: boolean; result: boolean; msg: string; } +export class GetDeviceDetailsFunctionsInterface { + result: { + category: string; + functions: []; + }; + success: boolean; + msg: string; +} +export class GetDeviceDetailsFunctionsStatusInterface { + result: [{ id: string; status: [] }]; + success: boolean; + msg: string; +} diff --git a/src/device/services/device.service.ts b/src/device/services/device.service.ts index 9a80bfb..ce13b30 100644 --- a/src/device/services/device.service.ts +++ b/src/device/services/device.service.ts @@ -1,16 +1,24 @@ import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; import { TuyaContext } from '@tuya/tuya-connector-nodejs'; import { ConfigService } from '@nestjs/config'; -import { AddDeviceDto } from '../dtos/add.device.dto'; import { + AddDeviceInGroupDto, + AddDeviceInRoomDto, +} from '../dtos/add.device.dto'; +import { + GetDeviceDetailsFunctionsInterface, + GetDeviceDetailsFunctionsStatusInterface, GetDeviceDetailsInterface, - GetDevicesInterface, - addDeviceInterface, + GetDevicesByGroupIdInterface, + GetDevicesByRoomIdInterface, + addDeviceInRoomInterface, controlDeviceInterface, } from '../interfaces/get.device.interface'; -import { GetDeviceDto } from '../dtos/get.device.dto'; +import { + GetDeviceByGroupIdDto, + GetDeviceByRoomIdDto, +} from '../dtos/get.device.dto'; import { ControlDeviceDto } from '../dtos/control.device.dto'; -import { RenameDeviceDto } from '../dtos/rename.device.dto copy'; @Injectable() export class DeviceService { @@ -26,9 +34,9 @@ export class DeviceService { }); } - async getDevicesByRoomId(getDeviceDto: GetDeviceDto) { + async getDevicesByRoomId(getDeviceByRoomIdDto: GetDeviceByRoomIdDto) { try { - const response = await this.getDevicesTuya(getDeviceDto); + const response = await this.getDevicesByRoomIdTuya(getDeviceByRoomIdDto); return { success: response.success, @@ -43,20 +51,62 @@ export class DeviceService { } } - async getDevicesTuya( - getDeviceDto: GetDeviceDto, - ): Promise { + async getDevicesByRoomIdTuya( + getDeviceByRoomIdDto: GetDeviceByRoomIdDto, + ): Promise { try { const path = `/v2.0/cloud/thing/space/device`; const response = await this.tuya.request({ method: 'GET', path, query: { - space_ids: getDeviceDto.roomId, - page_size: getDeviceDto.pageSize, + space_ids: getDeviceByRoomIdDto.roomId, + page_size: getDeviceByRoomIdDto.pageSize, }, }); - return response as unknown as GetDevicesInterface; + return response as GetDevicesByRoomIdInterface; + } catch (error) { + throw new HttpException( + 'Error fetching devices ', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async getDevicesByGroupId(getDeviceByGroupIdDto: GetDeviceByGroupIdDto) { + try { + const response = await this.getDevicesByGroupIdTuya( + getDeviceByGroupIdDto, + ); + + return { + success: response.success, + devices: response.result.data_list, + count: response.result.count, + msg: response.msg, + }; + } catch (error) { + throw new HttpException( + 'Error fetching devices', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async getDevicesByGroupIdTuya( + getDeviceByGroupIdDto: GetDeviceByGroupIdDto, + ): Promise { + try { + const path = `/v2.0/cloud/thing/group`; + const response = await this.tuya.request({ + method: 'GET', + path, + query: { + space_id: getDeviceByGroupIdDto.groupId, + page_size: getDeviceByGroupIdDto.pageSize, + page_no: getDeviceByGroupIdDto.pageNo, + }, + }); + return response as GetDevicesByGroupIdInterface; } catch (error) { throw new HttpException( 'Error fetching devices ', @@ -65,13 +115,14 @@ export class DeviceService { } } - async addDevice(addDeviceDto: AddDeviceDto) { - const response = await this.addDeviceTuya(addDeviceDto); + async addDeviceInRoom(addDeviceInRoomDto: AddDeviceInRoomDto) { + const response = await this.addDeviceInRoomTuya(addDeviceInRoomDto); if (response.success) { return { - success: true, - deviceId: response.result.id, + success: response.success, + result: response.result, + msg: response.msg, }; } else { throw new HttpException( @@ -80,21 +131,58 @@ export class DeviceService { ); } } - async addDeviceTuya(addDeviceDto: AddDeviceDto): Promise { + async addDeviceInRoomTuya( + addDeviceInRoomDto: AddDeviceInRoomDto, + ): Promise { try { - const path = `/v2.0/cloud/thing/device`; + const path = `/v2.0/cloud/thing/${addDeviceInRoomDto.deviceId}/transfer`; const response = await this.tuya.request({ method: 'POST', path, body: { - space_id: addDeviceDto.homeId, - name: addDeviceDto.deviceName, - product_id: addDeviceDto.productId, - device_ids: addDeviceDto.deviceIds, + space_id: addDeviceInRoomDto.roomId, }, }); - return response as addDeviceInterface; + return response as addDeviceInRoomInterface; + } catch (error) { + throw new HttpException( + 'Error adding device', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async addDeviceInGroup(addDeviceInGroupDto: AddDeviceInGroupDto) { + const response = await this.addDeviceInGroupTuya(addDeviceInGroupDto); + + if (response.success) { + return { + success: response.success, + result: response.result, + msg: response.msg, + }; + } else { + throw new HttpException( + response.msg || 'Unknown error', + HttpStatus.BAD_REQUEST, + ); + } + } + async addDeviceInGroupTuya( + addDeviceInGroupDto: AddDeviceInGroupDto, + ): Promise { + try { + const path = `/v2.0/cloud/thing/group/${addDeviceInGroupDto.groupId}/device`; + const response = await this.tuya.request({ + method: 'PUT', + path, + body: { + space_id: addDeviceInGroupDto.homeId, + device_ids: addDeviceInGroupDto.deviceId, + }, + }); + + return response as addDeviceInRoomInterface; } catch (error) { throw new HttpException( 'Error adding device', @@ -119,13 +207,14 @@ export class DeviceService { controlDeviceDto: ControlDeviceDto, ): Promise { try { - const path = `/v2.0/cloud/thing/device/properties`; + const path = `/v1.0/iot-03/devices/${controlDeviceDto.deviceId}/commands`; const response = await this.tuya.request({ method: 'POST', path, body: { - device_id: controlDeviceDto.deviceId, - properties: controlDeviceDto.properties, + commands: [ + { code: controlDeviceDto.code, value: controlDeviceDto.value }, + ], }, }); @@ -138,81 +227,14 @@ export class DeviceService { } } - async renameDevice(renameDeviceDto: RenameDeviceDto) { - const response = await this.renameDeviceTuya(renameDeviceDto); - - if (response.success) { - return { - success: response.success, - result: response.result, - msg: response.msg, - }; - } else { - throw new HttpException( - response.msg || 'Unknown error', - HttpStatus.BAD_REQUEST, - ); - } - } - async renameDeviceTuya( - renameDeviceDto: RenameDeviceDto, - ): Promise { - try { - const path = `/v2.0/cloud/thing/device/${renameDeviceDto.deviceId}/${renameDeviceDto.deviceName}`; - const response = await this.tuya.request({ - method: 'PUT', - path, - }); - - return response as controlDeviceInterface; - } catch (error) { - throw new HttpException( - 'Error rename device', - HttpStatus.INTERNAL_SERVER_ERROR, - ); - } - } - - async deleteDevice(deviceId: number) { - const response = await this.deleteDeviceTuya(deviceId); - - if (response.success) { - return { - success: response.success, - result: response.result, - msg: response.msg, - }; - } else { - throw new HttpException( - response.msg || 'Unknown error', - HttpStatus.BAD_REQUEST, - ); - } - } - async deleteDeviceTuya(deviceId: number): Promise { - try { - const path = `/v2.0/cloud/thing/device/${deviceId}`; - const response = await this.tuya.request({ - method: 'DELETE', - path, - }); - - return response as controlDeviceInterface; - } catch (error) { - throw new HttpException( - 'Error delete device', - HttpStatus.INTERNAL_SERVER_ERROR, - ); - } - } - - async getDevicesByDeviceId(deviceId: number) { + async getDevicesByDeviceId(deviceId: string) { try { const response = await this.getDevicesByDeviceIdTuya(deviceId); return { - deviceId: response.result.id, - deviceName: response.result.name, + success: response.success, + result: response.result, + msg: response.msg, }; } catch (error) { throw new HttpException( @@ -223,10 +245,10 @@ export class DeviceService { } async getDevicesByDeviceIdTuya( - deviceId: number, + deviceId: string, ): Promise { try { - const path = `/v2.0/cloud/thing/device/${deviceId}`; + const path = `/v1.1/iot-03/devices/${deviceId}`; const response = await this.tuya.request({ method: 'GET', path, @@ -239,4 +261,78 @@ export class DeviceService { ); } } + async getDevicesInstructionByDeviceId(deviceId: string) { + try { + const response = await this.getDevicesInstructionByDeviceIdTuya(deviceId); + + return { + success: response.success, + result: { + category: response.result.category, + function: response.result.functions, + }, + msg: response.msg, + }; + } catch (error) { + throw new HttpException( + 'Error fetching device functions', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async getDevicesInstructionByDeviceIdTuya( + deviceId: string, + ): Promise { + try { + const path = `/v1.0/iot-03/devices/${deviceId}/functions`; + const response = await this.tuya.request({ + method: 'GET', + path, + }); + return response as GetDeviceDetailsFunctionsInterface; + } catch (error) { + throw new HttpException( + 'Error fetching device functions', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async getDevicesInstructionStatus(deviceId: string) { + try { + const response = await this.getDevicesInstructionStatusTuya(deviceId); + + return { + result: response.result, + success: response.success, + msg: response.msg, + }; + } catch (error) { + throw new HttpException( + 'Error fetching device functions', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async getDevicesInstructionStatusTuya( + deviceId: string, + ): Promise { + try { + const path = `/v1.0/iot-03/devices/status`; + const response = await this.tuya.request({ + method: 'GET', + path, + query: { + device_ids: deviceId, + }, + }); + return response as unknown as GetDeviceDetailsFunctionsStatusInterface; + } catch (error) { + throw new HttpException( + 'Error fetching device functions', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } }