Merge pull request #33 from SyncrowIOT/SP-197-be-retrieve-devices-in-the-gateway

get getway devices
This commit is contained in:
faris Aljohari
2024-06-11 12:25:43 +03:00
committed by GitHub
4 changed files with 161 additions and 25 deletions

View File

@ -0,0 +1,8 @@
export enum ProductType {
AC = 'AC',
GW = 'GW',
CPS = 'CPS',
DL = 'DL',
WPS = 'WPS',
TH_G = '3G',
}

View File

@ -179,4 +179,36 @@ export class DeviceController {
);
}
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Post(':deviceUuid/firmware/:firmwareVersion')
async updateDeviceFirmware(
@Param('deviceUuid') deviceUuid: string,
@Param('firmwareVersion') firmwareVersion: number,
) {
try {
return await this.deviceService.updateDeviceFirmware(
deviceUuid,
firmwareVersion,
);
} catch (error) {
throw new HttpException(
error.message || 'Internal server error',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Get('getaway/:gatewayUuid/devices')
async getDevicesInGetaway(@Param('gatewayUuid') gatewayUuid: string) {
try {
return await this.deviceService.getDevicesInGetaway(gatewayUuid);
} catch (error) {
throw new HttpException(
error.message || 'Internal server error',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}

View File

@ -59,3 +59,8 @@ export interface DeviceInstructionResponse {
dataType: string;
}[];
}
export interface updateDeviceFirmwareInterface {
success: boolean;
result: boolean;
msg: string;
}

View File

@ -4,6 +4,7 @@ import {
HttpException,
HttpStatus,
NotFoundException,
BadRequestException,
} from '@nestjs/common';
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
import { ConfigService } from '@nestjs/config';
@ -14,6 +15,7 @@ import {
GetDeviceDetailsFunctionsStatusInterface,
GetDeviceDetailsInterface,
controlDeviceInterface,
updateDeviceFirmwareInterface,
} from '../interfaces/get.device.interface';
import { GetDeviceByRoomUuidDto } from '../dtos/get.device.dto';
import { ControlDeviceDto } from '../dtos/control.device.dto';
@ -21,6 +23,7 @@ import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
import { DeviceRepository } from '@app/common/modules/device/repositories';
import { PermissionType } from '@app/common/constants/permission-type.enum';
import { In } from 'typeorm';
import { ProductType } from '@app/common/constants/product-type.enum';
@Injectable()
export class DeviceService {
@ -38,7 +41,17 @@ export class DeviceService {
secretKey,
});
}
private async getDeviceByDeviceUuid(
deviceUuid: string,
withProductDevice: boolean = true,
) {
return await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
},
...(withProductDevice && { relations: ['productDevice'] }),
});
}
async addDeviceUser(addDeviceDto: AddDeviceDto) {
try {
const device = await this.getDeviceDetailsByDeviceIdTuya(
@ -189,11 +202,7 @@ export class DeviceService {
async controlDevice(controlDeviceDto: ControlDeviceDto, deviceUuid: string) {
try {
const deviceDetails = await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
},
});
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid, false);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
throw new NotFoundException('Device Not Found');
@ -250,12 +259,7 @@ export class DeviceService {
deviceUuid,
);
const deviceDetails = await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
},
relations: ['productDevice'],
});
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails) {
throw new NotFoundException('Device Not Found');
@ -298,7 +302,7 @@ export class DeviceService {
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { productName, productId, ...rest } = camelCaseResponse.result;
const { productName, productId, id, ...rest } = camelCaseResponse.result;
return {
...rest,
@ -316,12 +320,7 @@ export class DeviceService {
deviceUuid: string,
): Promise<DeviceInstructionResponse> {
try {
const deviceDetails = await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
},
relations: ['productDevice'],
});
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails) {
throw new NotFoundException('Device Not Found');
@ -366,12 +365,7 @@ export class DeviceService {
}
async getDevicesInstructionStatus(deviceUuid: string) {
try {
const deviceDetails = await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
},
relations: ['productDevice'],
});
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails) {
throw new NotFoundException('Device Not Found');
@ -417,9 +411,106 @@ export class DeviceService {
const device = await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
permission: {
userUuid: userUuid,
},
},
relations: ['permission', 'permission.permissionType'],
});
return device.permission[0].permissionType.type;
}
async getDevicesInGetaway(gatewayUuid: string) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(gatewayUuid);
if (!deviceDetails) {
throw new NotFoundException('Device Not Found');
} else if (deviceDetails.productDevice.prodType !== ProductType.GW) {
throw new BadRequestException('This is not a gateway device');
}
const response = await this.getDevicesInGetawayTuya(
deviceDetails.deviceTuyaUuid,
);
return {
uuid: deviceDetails.uuid,
productUuid: deviceDetails.productDevice.uuid,
productType: deviceDetails.productDevice.prodType,
device: response,
};
} catch (error) {
throw new HttpException(
error.message || 'Device Not Found',
HttpStatus.NOT_FOUND,
);
}
}
async getDevicesInGetawayTuya(
deviceId: string,
): Promise<GetDeviceDetailsInterface[]> {
try {
const path = `/v1.0/devices/${deviceId}/sub-devices`;
const response: any = await this.tuya.request({
method: 'GET',
path,
});
const camelCaseResponse = response.result.map((device: any) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { product_id, category, id, ...rest } = device;
const camelCaseDevice = convertKeysToCamelCase({ ...rest });
return camelCaseDevice as GetDeviceDetailsInterface[];
});
return camelCaseResponse;
} catch (error) {
throw new HttpException(
'Error fetching device details from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async updateDeviceFirmware(deviceUuid: string, firmwareVersion: number) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid, false);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
throw new NotFoundException('Device Not Found');
}
const response = await this.updateDeviceFirmwareTuya(
deviceDetails.deviceTuyaUuid,
firmwareVersion,
);
if (response.success) {
return response;
} else {
throw new HttpException(
response.msg || 'Unknown error',
HttpStatus.BAD_REQUEST,
);
}
} catch (error) {
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
}
}
async updateDeviceFirmwareTuya(
deviceUuid: string,
firmwareVersion: number,
): Promise<updateDeviceFirmwareInterface> {
try {
const path = `/v2.0/cloud/thing/${deviceUuid}/firmware/${firmwareVersion}`;
const response = await this.tuya.request({
method: 'POST',
path,
});
return response as updateDeviceFirmwareInterface;
} catch (error) {
throw new HttpException(
'Error updating device firmware from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}