Files
backend/src/schedule/services/schedule.service.ts
2024-10-02 03:21:13 -05:00

374 lines
12 KiB
TypeScript

import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
import { ConfigService } from '@nestjs/config';
import {
AddScheduleDto,
EnableScheduleDto,
UpdateScheduleDto,
} from '../dtos/schedule.dto';
import {
addScheduleDeviceInterface,
getDeviceScheduleInterface,
} from '../interfaces/get.schedule.interface';
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
import { DeviceRepository } from '@app/common/modules/device/repositories';
import { ProductType } from '@app/common/constants/product-type.enum';
import { convertTimestampToDubaiTime } from '@app/common/helper/convertTimestampToDubaiTime';
import {
getEnabledDays,
getScheduleStatus,
} from '@app/common/helper/getScheduleStatus';
@Injectable()
export class ScheduleService {
private tuya: TuyaContext;
constructor(
private readonly configService: ConfigService,
private readonly deviceRepository: DeviceRepository,
) {
const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY');
const secretKey = this.configService.get<string>('auth-config.SECRET_KEY');
const tuyaEuUrl = this.configService.get<string>('tuya-config.TUYA_EU_URL');
this.tuya = new TuyaContext({
baseUrl: tuyaEuUrl,
accessKey,
secretKey,
});
}
async enableDeviceSchedule(
deviceUuid: string,
enableScheduleDto: EnableScheduleDto,
) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
}
// Corrected condition for supported device types
if (
deviceDetails.productDevice.prodType !== ProductType.THREE_G &&
deviceDetails.productDevice.prodType !== ProductType.ONE_G &&
deviceDetails.productDevice.prodType !== ProductType.TWO_G &&
deviceDetails.productDevice.prodType !== ProductType.WH &&
deviceDetails.productDevice.prodType !== ProductType.ONE_1TG &&
deviceDetails.productDevice.prodType !== ProductType.TWO_2TG &&
deviceDetails.productDevice.prodType !== ProductType.THREE_3TG
) {
throw new HttpException(
'This device is not supported for schedule',
HttpStatus.BAD_REQUEST,
);
}
return await this.enableScheduleDeviceInTuya(
deviceDetails.deviceTuyaUuid,
enableScheduleDto,
);
} catch (error) {
throw new HttpException(
error.message || 'Error While Updating Schedule',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async enableScheduleDeviceInTuya(
deviceId: string,
enableScheduleDto: EnableScheduleDto,
): Promise<addScheduleDeviceInterface> {
try {
const path = `/v2.0/cloud/timer/device/${deviceId}/state`;
const response = await this.tuya.request({
method: 'PUT',
path,
body: {
enable: enableScheduleDto.enable,
timer_id: enableScheduleDto.scheduleId,
},
});
return response as addScheduleDeviceInterface;
} catch (error) {
throw new HttpException(
'Error while updating schedule from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async deleteDeviceSchedule(deviceUuid: string, scheduleId: string) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
}
// Corrected condition for supported device types
if (
deviceDetails.productDevice.prodType !== ProductType.THREE_G &&
deviceDetails.productDevice.prodType !== ProductType.ONE_G &&
deviceDetails.productDevice.prodType !== ProductType.TWO_G &&
deviceDetails.productDevice.prodType !== ProductType.WH &&
deviceDetails.productDevice.prodType !== ProductType.ONE_1TG &&
deviceDetails.productDevice.prodType !== ProductType.TWO_2TG &&
deviceDetails.productDevice.prodType !== ProductType.THREE_3TG
) {
throw new HttpException(
'This device is not supported for schedule',
HttpStatus.BAD_REQUEST,
);
}
return await this.deleteScheduleDeviceInTuya(
deviceDetails.deviceTuyaUuid,
scheduleId,
);
} catch (error) {
throw new HttpException(
error.message || 'Error While Deleting Schedule',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async deleteScheduleDeviceInTuya(
deviceId: string,
scheduleId: string,
): Promise<addScheduleDeviceInterface> {
try {
const path = `/v2.0/cloud/timer/device/${deviceId}/batch?timer_ids=${scheduleId}`;
const response = await this.tuya.request({
method: 'DELETE',
path,
});
return response as addScheduleDeviceInterface;
} catch (error) {
throw new HttpException(
'Error while deleting schedule from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async addDeviceSchedule(deviceUuid: string, addScheduleDto: AddScheduleDto) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
}
// Corrected condition for supported device types
if (
deviceDetails.productDevice.prodType !== ProductType.THREE_G &&
deviceDetails.productDevice.prodType !== ProductType.ONE_G &&
deviceDetails.productDevice.prodType !== ProductType.TWO_G &&
deviceDetails.productDevice.prodType !== ProductType.WH &&
deviceDetails.productDevice.prodType !== ProductType.ONE_1TG &&
deviceDetails.productDevice.prodType !== ProductType.TWO_2TG &&
deviceDetails.productDevice.prodType !== ProductType.THREE_3TG
) {
throw new HttpException(
'This device is not supported for schedule',
HttpStatus.BAD_REQUEST,
);
}
await this.addScheduleDeviceInTuya(
deviceDetails.deviceTuyaUuid,
addScheduleDto,
);
} catch (error) {
throw new HttpException(
error.message || 'Error While Adding Schedule',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async addScheduleDeviceInTuya(
deviceId: string,
addScheduleDto: AddScheduleDto,
): Promise<addScheduleDeviceInterface> {
try {
const convertedTime = convertTimestampToDubaiTime(addScheduleDto.time);
const loops = getScheduleStatus(addScheduleDto.days);
const path = `/v2.0/cloud/timer/device/${deviceId}`;
const response = await this.tuya.request({
method: 'POST',
path,
body: {
time: convertedTime.time,
timezone_id: 'Asia/Dubai',
loops: `${loops}`,
functions: [
{
code: addScheduleDto.function.code,
value: addScheduleDto.function.value,
},
],
category: `category_${addScheduleDto.category}`,
},
});
return response as addScheduleDeviceInterface;
} catch (error) {
throw new HttpException(
'Error adding schedule from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getDeviceScheduleByCategory(deviceUuid: string, category: string) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
}
// Corrected condition for supported device types
if (
deviceDetails.productDevice.prodType !== ProductType.THREE_G &&
deviceDetails.productDevice.prodType !== ProductType.ONE_G &&
deviceDetails.productDevice.prodType !== ProductType.TWO_G &&
deviceDetails.productDevice.prodType !== ProductType.WH &&
deviceDetails.productDevice.prodType !== ProductType.ONE_1TG &&
deviceDetails.productDevice.prodType !== ProductType.TWO_2TG &&
deviceDetails.productDevice.prodType !== ProductType.THREE_3TG
) {
throw new HttpException(
'This device is not supported for schedule',
HttpStatus.BAD_REQUEST,
);
}
const schedules = await this.getScheduleDeviceInTuya(
deviceDetails.deviceTuyaUuid,
category,
);
const result = schedules.result.map((schedule: any) => {
return {
category: schedule.category.replace('category_', ''),
enable: schedule.enable,
function: {
code: schedule.functions[0].code,
value: schedule.functions[0].value,
},
time: schedule.time,
schedule_id: schedule.timer_id,
timezone_id: schedule.timezone_id,
days: getEnabledDays(schedule.loops),
};
});
return convertKeysToCamelCase(result);
} catch (error) {
throw new HttpException(
error.message || 'Error While Adding Schedule',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getScheduleDeviceInTuya(
deviceId: string,
category: string,
): Promise<getDeviceScheduleInterface> {
try {
const path = `/v2.0/cloud/timer/device/${deviceId}?category=category_${category}`;
const response = await this.tuya.request({
method: 'GET',
path,
});
return response as getDeviceScheduleInterface;
} catch (error) {
console.error('Error fetching device schedule from Tuya:', error);
throw new HttpException(
'Error fetching device schedule from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getDeviceByDeviceUuid(
deviceUuid: string,
withProductDevice: boolean = true,
) {
return await this.deviceRepository.findOne({
where: {
uuid: deviceUuid,
},
...(withProductDevice && { relations: ['productDevice'] }),
});
}
async updateDeviceSchedule(
deviceUuid: string,
updateScheduleDto: UpdateScheduleDto,
) {
try {
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
}
// Corrected condition for supported device types
if (
deviceDetails.productDevice.prodType !== ProductType.THREE_G &&
deviceDetails.productDevice.prodType !== ProductType.ONE_G &&
deviceDetails.productDevice.prodType !== ProductType.TWO_G &&
deviceDetails.productDevice.prodType !== ProductType.WH &&
deviceDetails.productDevice.prodType !== ProductType.ONE_1TG &&
deviceDetails.productDevice.prodType !== ProductType.TWO_2TG &&
deviceDetails.productDevice.prodType !== ProductType.THREE_3TG
) {
throw new HttpException(
'This device is not supported for schedule',
HttpStatus.BAD_REQUEST,
);
}
await this.updateScheduleDeviceInTuya(
deviceDetails.deviceTuyaUuid,
updateScheduleDto,
);
} catch (error) {
throw new HttpException(
error.message || 'Error While Updating Schedule',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async updateScheduleDeviceInTuya(
deviceId: string,
updateScheduleDto: UpdateScheduleDto,
): Promise<addScheduleDeviceInterface> {
try {
const convertedTime = convertTimestampToDubaiTime(updateScheduleDto.time);
const loops = getScheduleStatus(updateScheduleDto.days);
const path = `/v2.0/cloud/timer/device/${deviceId}`;
const response = await this.tuya.request({
method: 'PUT',
path,
body: {
timer_id: updateScheduleDto.scheduleId,
time: convertedTime.time,
timezone_id: 'Asia/Dubai',
loops: `${loops}`,
functions: [
{
code: updateScheduleDto.function.code,
value: updateScheduleDto.function.value,
},
],
category: `category_${updateScheduleDto.category}`,
},
});
return response as addScheduleDeviceInterface;
} catch (error) {
throw new HttpException(
'Error updating schedule from Tuya',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}