Files
backend/src/group/services/group.service.ts
2024-04-28 09:37:11 +03:00

265 lines
7.2 KiB
TypeScript

import {
Injectable,
HttpException,
HttpStatus,
BadRequestException,
} from '@nestjs/common';
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
import { ConfigService } from '@nestjs/config';
import { AddGroupDto } from '../dtos/add.group.dto';
import {
GetGroupDetailsInterface,
GetGroupsBySpaceUuidInterface,
} from '../interfaces/get.group.interface';
import { ControlGroupDto } from '../dtos/control.group.dto';
import { RenameGroupDto } from '../dtos/rename.group.dto copy';
import { GroupRepository } from '@app/common/modules/group/repositories';
import { GroupDeviceRepository } from '@app/common/modules/group-device/repositories';
import { controlDeviceInterface } from 'src/device/interfaces/get.device.interface';
@Injectable()
export class GroupService {
private tuya: TuyaContext;
constructor(
private readonly configService: ConfigService,
private readonly groupRepository: GroupRepository,
private readonly groupDeviceRepository: GroupDeviceRepository,
) {
const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY');
const secretKey = this.configService.get<string>('auth-config.SECRET_KEY');
// const clientId = this.configService.get<string>('auth-config.CLIENT_ID');
this.tuya = new TuyaContext({
baseUrl: 'https://openapi.tuyaeu.com',
accessKey,
secretKey,
});
}
async getGroupsBySpaceUuid(
spaceUuid: string,
): Promise<GetGroupsBySpaceUuidInterface[]> {
try {
const groupDevices = await this.groupDeviceRepository.find({
relations: ['group', 'device'],
where: {
device: { spaceDevice: { uuid: spaceUuid } },
isActive: true,
},
});
// Extract and return only the group entities
const groups = groupDevices.map((groupDevice) => {
return {
groupUuid: groupDevice.uuid,
groupName: groupDevice.group.groupName,
};
});
if (groups.length > 0) {
return groups;
} else {
throw new HttpException(
'this space has no groups',
HttpStatus.NOT_FOUND,
);
}
} catch (error) {
throw new HttpException(
error.message || 'Error fetching groups',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async addGroup(addGroupDto: AddGroupDto) {
try {
const group = await this.groupRepository.save({
groupName: addGroupDto.groupName,
});
const groupDevicePromises = addGroupDto.deviceUuids.map(
async (deviceUuid) => {
await this.saveGroupDevice(group.uuid, deviceUuid);
},
);
await Promise.all(groupDevicePromises);
return { message: 'Group added successfully' };
} catch (err) {
if (err.code === '23505') {
throw new HttpException(
'User already belongs to this group',
HttpStatus.BAD_REQUEST,
);
}
throw new HttpException(
err.message || 'Internal Server Error',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
private async saveGroupDevice(groupUuid: string, deviceUuid: string) {
try {
await this.groupDeviceRepository.save({
group: {
uuid: groupUuid,
},
device: {
uuid: deviceUuid,
},
});
} catch (error) {
throw error;
}
}
async getDevicesByGroupUuid(groupUuid: string) {
try {
const devices = await this.groupDeviceRepository.find({
relations: ['device'],
where: {
group: {
uuid: groupUuid,
},
isActive: true,
},
});
return devices;
} catch (error) {
throw error;
}
}
async controlDevice(deviceUuid: string, code: string, value: any) {
try {
const response = await this.controlDeviceTuya(deviceUuid, code, value);
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 controlDeviceTuya(
deviceUuid: string,
code: string,
value: any,
): Promise<controlDeviceInterface> {
try {
const path = `/v1.0/iot-03/devices/${deviceUuid}/commands`;
const response = await this.tuya.request({
method: 'POST',
path,
body: {
commands: [{ code, value: value }],
},
});
return response as controlDeviceInterface;
} catch (error) {
throw new HttpException(
'Error control device from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async controlGroup(controlGroupDto: ControlGroupDto) {
const devices = await this.getDevicesByGroupUuid(controlGroupDto.groupUuid);
try {
await Promise.all(
devices.map(async (device) => {
return this.controlDevice(
device.device.deviceTuyaUuid,
controlGroupDto.code,
controlGroupDto.value,
);
}),
);
return { message: 'Group controlled successfully', success: true };
} catch (error) {
throw new HttpException(
'Error controlling devices',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async renameGroupByUuid(
groupUuid: string,
renameGroupDto: RenameGroupDto,
): Promise<GetGroupsBySpaceUuidInterface> {
try {
await this.groupRepository.update(
{ uuid: groupUuid },
{ groupName: renameGroupDto.groupName },
);
// Fetch the updated floor
const updatedGroup = await this.groupRepository.findOneOrFail({
where: { uuid: groupUuid },
});
return {
groupUuid: updatedGroup.uuid,
groupName: updatedGroup.groupName,
};
} catch (error) {
throw new HttpException('Group not found', HttpStatus.NOT_FOUND);
}
}
async deleteGroup(groupUuid: string) {
try {
const group = await this.getGroupsByGroupUuid(groupUuid);
if (!group) {
throw new HttpException('Group not found', HttpStatus.NOT_FOUND);
}
await this.groupRepository.update(
{ uuid: groupUuid },
{ isActive: false },
);
return { message: 'Group deleted successfully' };
} catch (error) {
throw new HttpException(
error.message || 'Error deleting group',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getGroupsByGroupUuid(
groupUuid: string,
): Promise<GetGroupDetailsInterface> {
try {
const group = await this.groupRepository.findOne({
where: {
uuid: groupUuid,
isActive: true,
},
});
if (!group) {
throw new BadRequestException('Invalid group UUID');
}
return {
groupUuid: group.uuid,
groupName: group.groupName,
createdAt: group.createdAt,
updatedAt: group.updatedAt,
};
} catch (err) {
if (err instanceof BadRequestException) {
throw err; // Re-throw BadRequestException
} else {
throw new HttpException('Group not found', HttpStatus.NOT_FOUND);
}
}
}
}