mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 08:54:54 +00:00
Merge pull request #33 from SyncrowIOT/SP-197-be-retrieve-devices-in-the-gateway
get getway devices
This commit is contained in:
8
libs/common/src/constants/product-type.enum.ts
Normal file
8
libs/common/src/constants/product-type.enum.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export enum ProductType {
|
||||||
|
AC = 'AC',
|
||||||
|
GW = 'GW',
|
||||||
|
CPS = 'CPS',
|
||||||
|
DL = 'DL',
|
||||||
|
WPS = 'WPS',
|
||||||
|
TH_G = '3G',
|
||||||
|
}
|
||||||
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,3 +59,8 @@ export interface DeviceInstructionResponse {
|
|||||||
dataType: string;
|
dataType: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
export interface updateDeviceFirmwareInterface {
|
||||||
|
success: boolean;
|
||||||
|
result: boolean;
|
||||||
|
msg: string;
|
||||||
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
HttpException,
|
HttpException,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
|
BadRequestException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
@ -14,6 +15,7 @@ import {
|
|||||||
GetDeviceDetailsFunctionsStatusInterface,
|
GetDeviceDetailsFunctionsStatusInterface,
|
||||||
GetDeviceDetailsInterface,
|
GetDeviceDetailsInterface,
|
||||||
controlDeviceInterface,
|
controlDeviceInterface,
|
||||||
|
updateDeviceFirmwareInterface,
|
||||||
} from '../interfaces/get.device.interface';
|
} from '../interfaces/get.device.interface';
|
||||||
import { GetDeviceByRoomUuidDto } from '../dtos/get.device.dto';
|
import { GetDeviceByRoomUuidDto } from '../dtos/get.device.dto';
|
||||||
import { ControlDeviceDto } from '../dtos/control.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 { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
||||||
import { In } from 'typeorm';
|
import { In } from 'typeorm';
|
||||||
|
import { ProductType } from '@app/common/constants/product-type.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeviceService {
|
export class DeviceService {
|
||||||
@ -38,7 +41,17 @@ export class DeviceService {
|
|||||||
secretKey,
|
secretKey,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private async getDeviceByDeviceUuid(
|
||||||
|
deviceUuid: string,
|
||||||
|
withProductDevice: boolean = true,
|
||||||
|
) {
|
||||||
|
return await this.deviceRepository.findOne({
|
||||||
|
where: {
|
||||||
|
uuid: deviceUuid,
|
||||||
|
},
|
||||||
|
...(withProductDevice && { relations: ['productDevice'] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
async addDeviceUser(addDeviceDto: AddDeviceDto) {
|
async addDeviceUser(addDeviceDto: AddDeviceDto) {
|
||||||
try {
|
try {
|
||||||
const device = await this.getDeviceDetailsByDeviceIdTuya(
|
const device = await this.getDeviceDetailsByDeviceIdTuya(
|
||||||
@ -189,11 +202,7 @@ export class DeviceService {
|
|||||||
|
|
||||||
async controlDevice(controlDeviceDto: ControlDeviceDto, deviceUuid: string) {
|
async controlDevice(controlDeviceDto: ControlDeviceDto, deviceUuid: string) {
|
||||||
try {
|
try {
|
||||||
const deviceDetails = await this.deviceRepository.findOne({
|
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid, false);
|
||||||
where: {
|
|
||||||
uuid: deviceUuid,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
|
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
|
||||||
throw new NotFoundException('Device Not Found');
|
throw new NotFoundException('Device Not Found');
|
||||||
@ -250,12 +259,7 @@ export class DeviceService {
|
|||||||
deviceUuid,
|
deviceUuid,
|
||||||
);
|
);
|
||||||
|
|
||||||
const deviceDetails = await this.deviceRepository.findOne({
|
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
|
||||||
where: {
|
|
||||||
uuid: deviceUuid,
|
|
||||||
},
|
|
||||||
relations: ['productDevice'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!deviceDetails) {
|
if (!deviceDetails) {
|
||||||
throw new NotFoundException('Device Not Found');
|
throw new NotFoundException('Device Not Found');
|
||||||
@ -298,7 +302,7 @@ export class DeviceService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const { productName, productId, ...rest } = camelCaseResponse.result;
|
const { productName, productId, id, ...rest } = camelCaseResponse.result;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...rest,
|
...rest,
|
||||||
@ -316,12 +320,7 @@ export class DeviceService {
|
|||||||
deviceUuid: string,
|
deviceUuid: string,
|
||||||
): Promise<DeviceInstructionResponse> {
|
): Promise<DeviceInstructionResponse> {
|
||||||
try {
|
try {
|
||||||
const deviceDetails = await this.deviceRepository.findOne({
|
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
|
||||||
where: {
|
|
||||||
uuid: deviceUuid,
|
|
||||||
},
|
|
||||||
relations: ['productDevice'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!deviceDetails) {
|
if (!deviceDetails) {
|
||||||
throw new NotFoundException('Device Not Found');
|
throw new NotFoundException('Device Not Found');
|
||||||
@ -366,12 +365,7 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
async getDevicesInstructionStatus(deviceUuid: string) {
|
async getDevicesInstructionStatus(deviceUuid: string) {
|
||||||
try {
|
try {
|
||||||
const deviceDetails = await this.deviceRepository.findOne({
|
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
|
||||||
where: {
|
|
||||||
uuid: deviceUuid,
|
|
||||||
},
|
|
||||||
relations: ['productDevice'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!deviceDetails) {
|
if (!deviceDetails) {
|
||||||
throw new NotFoundException('Device Not Found');
|
throw new NotFoundException('Device Not Found');
|
||||||
@ -417,9 +411,106 @@ export class DeviceService {
|
|||||||
const device = await this.deviceRepository.findOne({
|
const device = await this.deviceRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
uuid: deviceUuid,
|
uuid: deviceUuid,
|
||||||
|
permission: {
|
||||||
|
userUuid: userUuid,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
relations: ['permission', 'permission.permissionType'],
|
relations: ['permission', 'permission.permissionType'],
|
||||||
});
|
});
|
||||||
return device.permission[0].permissionType.type;
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user