From f0666fab82cdb29f7f40927d8882b2ae4f2e451a Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:41:02 -0500 Subject: [PATCH 01/18] finished get power clamp status --- .../common/src/constants/product-type.enum.ts | 1 + src/device/controllers/device.controller.ts | 10 ++++ src/device/interfaces/get.device.interface.ts | 7 +++ src/device/services/device.service.ts | 46 +++++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/libs/common/src/constants/product-type.enum.ts b/libs/common/src/constants/product-type.enum.ts index 6442f87..2f518fb 100644 --- a/libs/common/src/constants/product-type.enum.ts +++ b/libs/common/src/constants/product-type.enum.ts @@ -15,4 +15,5 @@ export enum ProductType { WL = 'WL', GD = 'GD', CUR = 'CUR', + PC = 'PC', } diff --git a/src/device/controllers/device.controller.ts b/src/device/controllers/device.controller.ts index 5f1a7ae..d0ebbc9 100644 --- a/src/device/controllers/device.controller.ts +++ b/src/device/controllers/device.controller.ts @@ -191,4 +191,14 @@ export class DeviceController { batchFactoryResetDevicesDto, ); } + @ApiBearerAuth() + // @UseGuards(JwtAuthGuard) + @Get(':powerClampUuid/power-clamp/status') + async getPowerClampInstructionStatus( + @Param('powerClampUuid') powerClampUuid: string, + ) { + return await this.deviceService.getPowerClampInstructionStatus( + powerClampUuid, + ); + } } diff --git a/src/device/interfaces/get.device.interface.ts b/src/device/interfaces/get.device.interface.ts index 7422ed2..93438b9 100644 --- a/src/device/interfaces/get.device.interface.ts +++ b/src/device/interfaces/get.device.interface.ts @@ -70,3 +70,10 @@ export interface getDeviceLogsInterface { endTime: string; deviceUuid?: string; } +export interface GetPowerClampFunctionsStatusInterface { + result: { + properties: []; + }; + success: boolean; + msg: string; +} diff --git a/src/device/services/device.service.ts b/src/device/services/device.service.ts index 2b37df8..db1cfb4 100644 --- a/src/device/services/device.service.ts +++ b/src/device/services/device.service.ts @@ -14,6 +14,7 @@ import { GetDeviceDetailsFunctionsInterface, GetDeviceDetailsFunctionsStatusInterface, GetDeviceDetailsInterface, + GetPowerClampFunctionsStatusInterface, controlDeviceInterface, getDeviceLogsInterface, updateDeviceFirmwareInterface, @@ -965,4 +966,49 @@ export class DeviceService { ); } } + async getPowerClampInstructionStatus(powerClampUuid: string) { + try { + const deviceDetails = await this.getDeviceByDeviceUuid(powerClampUuid); + if (!deviceDetails) { + throw new NotFoundException('Device Not Found'); + } else if (deviceDetails.productDevice.prodType !== ProductType.PC) { + throw new BadRequestException('This is not a power clamp device'); + } + const deviceStatus = await this.getPowerClampInstructionStatusTuya( + deviceDetails.deviceTuyaUuid, + ); + + return { + productUuid: deviceDetails.productDevice.uuid, + productType: deviceDetails.productDevice.prodType, + status: deviceStatus.result.properties, + }; + } catch (error) { + throw new HttpException( + error.message || 'Error fetching power clamp functions status', + error.status || HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async getPowerClampInstructionStatusTuya( + deviceUuid: string, + ): Promise { + try { + const path = `/v2.0/cloud/thing/${deviceUuid}/shadow/properties`; + const response = await this.tuya.request({ + method: 'GET', + path, + query: { + device_ids: deviceUuid, + }, + }); + const camelCaseResponse = convertKeysToCamelCase(response); + return camelCaseResponse as GetPowerClampFunctionsStatusInterface; + } catch (error) { + throw new HttpException( + 'Error fetching power clamp functions status from Tuya', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } } From 8431ee3660fc45a483281f81bd8d279879f8e92e Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 19 Oct 2024 13:35:24 -0500 Subject: [PATCH 02/18] edit power clamp response --- src/device/services/device.service.ts | 34 ++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/device/services/device.service.ts b/src/device/services/device.service.ts index db1cfb4..96cba90 100644 --- a/src/device/services/device.service.ts +++ b/src/device/services/device.service.ts @@ -977,11 +977,43 @@ export class DeviceService { const deviceStatus = await this.getPowerClampInstructionStatusTuya( deviceDetails.deviceTuyaUuid, ); + const statusList = deviceStatus.result.properties as { + code: string; + value: any; + }[]; + + const groupedStatus = statusList.reduce( + (acc, currentStatus) => { + const { code } = currentStatus; + + if (code.includes('A')) { + acc.phaseA.push(currentStatus); + } else if (code.includes('B')) { + acc.phaseB.push(currentStatus); + } else if (code.includes('C')) { + acc.phaseC.push(currentStatus); + } else { + acc.general.push(currentStatus); + } + return acc; + }, + { + phaseA: [] as { code: string; value: any }[], + phaseB: [] as { code: string; value: any }[], + phaseC: [] as { code: string; value: any }[], + general: [] as { code: string; value: any }[], + }, + ); return { productUuid: deviceDetails.productDevice.uuid, productType: deviceDetails.productDevice.prodType, - status: deviceStatus.result.properties, + status: { + phaseA: groupedStatus.phaseA, + phaseB: groupedStatus.phaseB, + phaseC: groupedStatus.phaseC, + general: groupedStatus.general, + }, }; } catch (error) { throw new HttpException( From d112a3474cfa37eeb2dae681c3b56c645df56b3b Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sat, 19 Oct 2024 13:36:18 -0500 Subject: [PATCH 03/18] add jwt guard --- src/device/controllers/device.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/controllers/device.controller.ts b/src/device/controllers/device.controller.ts index d0ebbc9..7a2543e 100644 --- a/src/device/controllers/device.controller.ts +++ b/src/device/controllers/device.controller.ts @@ -192,7 +192,7 @@ export class DeviceController { ); } @ApiBearerAuth() - // @UseGuards(JwtAuthGuard) + @UseGuards(JwtAuthGuard) @Get(':powerClampUuid/power-clamp/status') async getPowerClampInstructionStatus( @Param('powerClampUuid') powerClampUuid: string, From 07ac955eb030a80529617bf17076c999988d2012 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 20 Oct 2024 16:46:44 +0300 Subject: [PATCH 04/18] added timeseries --- libs/common/src/database/database.module.ts | 2 ++ .../devices-status/devices-status.module.ts | 9 +++++-- .../services/devices-status.service.ts | 11 ++++++++ .../entities/device-status-log.entity.ts | 26 +++++++++++++++++++ .../device-status-log/entities/index.ts | 1 + .../repositories/device-status.repository.ts | 10 +++++++ .../device-status-log/repositories/index.ts | 1 + src/door-lock/door.lock.module.ts | 2 ++ .../visitor-password.module.ts | 2 ++ 9 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts create mode 100644 libs/common/src/modules/device-status-log/entities/index.ts create mode 100644 libs/common/src/modules/device-status-log/repositories/device-status.repository.ts create mode 100644 libs/common/src/modules/device-status-log/repositories/index.ts diff --git a/libs/common/src/database/database.module.ts b/libs/common/src/database/database.module.ts index ae01e55..9de32e9 100644 --- a/libs/common/src/database/database.module.ts +++ b/libs/common/src/database/database.module.ts @@ -19,6 +19,7 @@ import { DeviceNotificationEntity } from '../modules/device/entities'; import { RegionEntity } from '../modules/region/entities'; import { TimeZoneEntity } from '../modules/timezone/entities'; import { VisitorPasswordEntity } from '../modules/visitor-password/entities'; +import { DeviceStatusLogEntity } from '../modules/device-status-log/entities'; @Module({ imports: [ @@ -52,6 +53,7 @@ import { VisitorPasswordEntity } from '../modules/visitor-password/entities'; RegionEntity, TimeZoneEntity, VisitorPasswordEntity, + DeviceStatusLogEntity, ], namingStrategy: new SnakeNamingStrategy(), synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))), diff --git a/libs/common/src/firebase/devices-status/devices-status.module.ts b/libs/common/src/firebase/devices-status/devices-status.module.ts index ad13b29..54d5cfa 100644 --- a/libs/common/src/firebase/devices-status/devices-status.module.ts +++ b/libs/common/src/firebase/devices-status/devices-status.module.ts @@ -2,10 +2,15 @@ import { Module } from '@nestjs/common'; import { DeviceStatusFirebaseController } from './controllers/devices-status.controller'; import { DeviceStatusFirebaseService } from './services/devices-status.service'; import { DeviceRepository } from '@app/common/modules/device/repositories'; +import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories/device-status.repository'; @Module({ - providers: [DeviceStatusFirebaseService, DeviceRepository], + providers: [ + DeviceStatusFirebaseService, + DeviceRepository, + DeviceStatusLogRepository, + ], controllers: [DeviceStatusFirebaseController], - exports: [DeviceStatusFirebaseService], + exports: [DeviceStatusFirebaseService, DeviceStatusLogRepository], }) export class DeviceStatusFirebaseModule {} diff --git a/libs/common/src/firebase/devices-status/services/devices-status.service.ts b/libs/common/src/firebase/devices-status/services/devices-status.service.ts index f075f34..41a3b39 100644 --- a/libs/common/src/firebase/devices-status/services/devices-status.service.ts +++ b/libs/common/src/firebase/devices-status/services/devices-status.service.ts @@ -11,6 +11,7 @@ import { TuyaContext } from '@tuya/tuya-connector-nodejs'; import { ConfigService } from '@nestjs/config'; import { firebaseDataBase } from '../../firebase.config'; import { Database, DataSnapshot, get, ref, set } from 'firebase/database'; +import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories'; @Injectable() export class DeviceStatusFirebaseService { private tuya: TuyaContext; @@ -18,6 +19,7 @@ export class DeviceStatusFirebaseService { constructor( private readonly configService: ConfigService, private readonly deviceRepository: DeviceRepository, + private deviceStatusLogRepository: DeviceStatusLogRepository, ) { const accessKey = this.configService.get('auth-config.ACCESS_KEY'); const secretKey = this.configService.get('auth-config.SECRET_KEY'); @@ -175,6 +177,7 @@ export class DeviceStatusFirebaseService { ); // Update or add status codes + for (const statusItem of addDeviceStatusDto.status) { statusMap.set(statusItem.code, statusItem.value); } @@ -184,7 +187,15 @@ export class DeviceStatusFirebaseService { code, value, })); + const newLog = this.deviceStatusLogRepository.create({ + deviceUuid: addDeviceStatusDto.deviceUuid, + deviceTuyaUuid: addDeviceStatusDto.deviceTuyaUuid, + productUuid: addDeviceStatusDto.productUuid, + productType: addDeviceStatusDto.productType, + status: existingData.status, + }); + await this.deviceStatusLogRepository.save(newLog); // Save the updated data to Firebase await set(dataRef, existingData); diff --git a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts new file mode 100644 index 0000000..d886ae3 --- /dev/null +++ b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts @@ -0,0 +1,26 @@ +import { Entity, Column, PrimaryColumn, Index } from 'typeorm'; + +@Entity('device-status-log') +@Index('logTime_idx', ['logTime']) +export class DeviceStatusLogEntity { + @PrimaryColumn() + id: number; + + @PrimaryColumn({ type: 'timestamptz' }) + logTime: Date; + + @Column({ type: 'text' }) + deviceUuid: string; + + @Column({ type: 'text' }) + deviceTuyaUuid: string; + + @Column({ type: 'text' }) + productUuid: string; + + @Column({ type: 'text' }) + productType: string; + + @Column({ type: 'jsonb' }) + status: any; // JSON array of status codes and values +} diff --git a/libs/common/src/modules/device-status-log/entities/index.ts b/libs/common/src/modules/device-status-log/entities/index.ts new file mode 100644 index 0000000..07b1986 --- /dev/null +++ b/libs/common/src/modules/device-status-log/entities/index.ts @@ -0,0 +1 @@ +export * from './device-status-log.entity'; diff --git a/libs/common/src/modules/device-status-log/repositories/device-status.repository.ts b/libs/common/src/modules/device-status-log/repositories/device-status.repository.ts new file mode 100644 index 0000000..84f3d60 --- /dev/null +++ b/libs/common/src/modules/device-status-log/repositories/device-status.repository.ts @@ -0,0 +1,10 @@ +import { DataSource, Repository } from 'typeorm'; +import { Injectable } from '@nestjs/common'; +import { DeviceStatusLogEntity } from '../entities/device-status-log.entity'; + +@Injectable() +export class DeviceStatusLogRepository extends Repository { + constructor(private dataSource: DataSource) { + super(DeviceStatusLogEntity, dataSource.createEntityManager()); + } +} diff --git a/libs/common/src/modules/device-status-log/repositories/index.ts b/libs/common/src/modules/device-status-log/repositories/index.ts new file mode 100644 index 0000000..02628b5 --- /dev/null +++ b/libs/common/src/modules/device-status-log/repositories/index.ts @@ -0,0 +1 @@ +export * from './device-status.repository'; diff --git a/src/door-lock/door.lock.module.ts b/src/door-lock/door.lock.module.ts index b72fad9..d5f070e 100644 --- a/src/door-lock/door.lock.module.ts +++ b/src/door-lock/door.lock.module.ts @@ -10,6 +10,7 @@ import { DeviceService } from 'src/device/services'; import { ProductRepository } from '@app/common/modules/product/repositories'; import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service'; import { SpaceRepository } from '@app/common/modules/space/repositories'; +import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories'; @Module({ imports: [ConfigModule, DeviceRepositoryModule], controllers: [DoorLockController], @@ -22,6 +23,7 @@ import { SpaceRepository } from '@app/common/modules/space/repositories'; ProductRepository, DeviceStatusFirebaseService, SpaceRepository, + DeviceStatusLogRepository, ], exports: [DoorLockService], }) diff --git a/src/vistor-password/visitor-password.module.ts b/src/vistor-password/visitor-password.module.ts index 19e61ea..990e1e7 100644 --- a/src/vistor-password/visitor-password.module.ts +++ b/src/vistor-password/visitor-password.module.ts @@ -12,6 +12,7 @@ import { ProductRepository } from '@app/common/modules/product/repositories'; import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service'; import { SpaceRepository } from '@app/common/modules/space/repositories'; import { VisitorPasswordRepository } from '@app/common/modules/visitor-password/repositories'; +import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories'; @Module({ imports: [ConfigModule, DeviceRepositoryModule, DoorLockModule], controllers: [VisitorPasswordController], @@ -25,6 +26,7 @@ import { VisitorPasswordRepository } from '@app/common/modules/visitor-password/ SpaceRepository, DeviceRepository, VisitorPasswordRepository, + DeviceStatusLogRepository, ], exports: [VisitorPasswordService], }) From f165e8ce3a029daabb5aebf287458bf8751a76d6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Oct 2024 14:18:31 +0300 Subject: [PATCH 05/18] fixed forgot password --- src/auth/controllers/user-auth.controller.ts | 6 ++++++ src/auth/dtos/user-password.dto.ts | 5 +++++ src/auth/services/user-auth.service.ts | 1 - 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/auth/controllers/user-auth.controller.ts b/src/auth/controllers/user-auth.controller.ts index bc9fc3c..1bf429b 100644 --- a/src/auth/controllers/user-auth.controller.ts +++ b/src/auth/controllers/user-auth.controller.ts @@ -16,6 +16,7 @@ import { ForgetPasswordDto, UserOtpDto, VerifyOtpDto } from '../dtos'; import { RefreshTokenGuard } from '@app/common/guards/jwt-refresh.auth.guard'; import { SuperAdminRoleGuard } from 'src/guards/super.admin.role.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { OtpType } from '@app/common/constants/otp-type.enum'; @Controller({ version: EnableDisableStatusEnum.ENABLED, @@ -74,6 +75,11 @@ export class UserAuthController { @Post('user/forget-password') async forgetPassword(@Body() forgetPasswordDto: ForgetPasswordDto) { + await this.userAuthService.verifyOTP({ + otpCode: forgetPasswordDto.otpCode, + email: forgetPasswordDto.email, + type: OtpType.PASSWORD, + }); await this.userAuthService.forgetPassword(forgetPasswordDto); return { statusCode: HttpStatus.OK, diff --git a/src/auth/dtos/user-password.dto.ts b/src/auth/dtos/user-password.dto.ts index 9a93935..de5eb5b 100644 --- a/src/auth/dtos/user-password.dto.ts +++ b/src/auth/dtos/user-password.dto.ts @@ -22,4 +22,9 @@ export class ForgetPasswordDto { 'password must be at least 8 characters long and include at least one uppercase letter, one lowercase letter, one numeric digit, and one special character.', }) public password: string; + + @ApiProperty() + @IsString() + @IsNotEmpty() + public otpCode: string; } diff --git a/src/auth/services/user-auth.service.ts b/src/auth/services/user-auth.service.ts index 9fd9fe3..c924658 100644 --- a/src/auth/services/user-auth.service.ts +++ b/src/auth/services/user-auth.service.ts @@ -18,7 +18,6 @@ import * as argon2 from 'argon2'; import { differenceInSeconds } from '@app/common/helper/differenceInSeconds'; import { LessThan, MoreThan } from 'typeorm'; import { ConfigService } from '@nestjs/config'; -import { UUID } from 'typeorm/driver/mongodb/bson.typings'; @Injectable() export class UserAuthService { From 1054ac6053c09f843a44081e1adbf80992e13507 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Oct 2024 14:20:31 +0300 Subject: [PATCH 06/18] fixed forgot password --- src/auth/controllers/user-auth.controller.ts | 22 +++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/auth/controllers/user-auth.controller.ts b/src/auth/controllers/user-auth.controller.ts index 1bf429b..92f30bd 100644 --- a/src/auth/controllers/user-auth.controller.ts +++ b/src/auth/controllers/user-auth.controller.ts @@ -1,4 +1,5 @@ import { + BadRequestException, Body, Controller, Get, @@ -75,17 +76,24 @@ export class UserAuthController { @Post('user/forget-password') async forgetPassword(@Body() forgetPasswordDto: ForgetPasswordDto) { - await this.userAuthService.verifyOTP({ + const otpResult = await this.userAuthService.verifyOTP({ otpCode: forgetPasswordDto.otpCode, email: forgetPasswordDto.email, type: OtpType.PASSWORD, }); - await this.userAuthService.forgetPassword(forgetPasswordDto); - return { - statusCode: HttpStatus.OK, - data: {}, - message: 'Password changed successfully', - }; + if (otpResult) { + await this.userAuthService.forgetPassword(forgetPasswordDto); + return { + statusCode: HttpStatus.OK, + data: {}, + message: 'Password changed successfully', + }; + } +throw new BadRequestException({ + statusCode: HttpStatus.BAD_REQUEST, + data: {}, + message: 'Otp is incorrect', +}) } @ApiBearerAuth() From fa35c2c60c7a971b124758caec03880edeb7a213 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Oct 2024 14:44:39 +0300 Subject: [PATCH 07/18] fixed forgot password --- src/auth/controllers/user-auth.controller.ts | 23 +++++++++++--------- src/auth/services/user-auth.service.ts | 9 +++++--- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/auth/controllers/user-auth.controller.ts b/src/auth/controllers/user-auth.controller.ts index 92f30bd..e7074da 100644 --- a/src/auth/controllers/user-auth.controller.ts +++ b/src/auth/controllers/user-auth.controller.ts @@ -76,11 +76,14 @@ export class UserAuthController { @Post('user/forget-password') async forgetPassword(@Body() forgetPasswordDto: ForgetPasswordDto) { - const otpResult = await this.userAuthService.verifyOTP({ - otpCode: forgetPasswordDto.otpCode, - email: forgetPasswordDto.email, - type: OtpType.PASSWORD, - }); + const otpResult = await this.userAuthService.verifyOTP( + { + otpCode: forgetPasswordDto.otpCode, + email: forgetPasswordDto.email, + type: OtpType.PASSWORD, + }, + true, + ); if (otpResult) { await this.userAuthService.forgetPassword(forgetPasswordDto); return { @@ -89,11 +92,11 @@ export class UserAuthController { message: 'Password changed successfully', }; } -throw new BadRequestException({ - statusCode: HttpStatus.BAD_REQUEST, - data: {}, - message: 'Otp is incorrect', -}) + throw new BadRequestException({ + statusCode: HttpStatus.BAD_REQUEST, + data: {}, + message: 'Otp is incorrect', + }); } @ApiBearerAuth() diff --git a/src/auth/services/user-auth.service.ts b/src/auth/services/user-auth.service.ts index c924658..9f9d82d 100644 --- a/src/auth/services/user-auth.service.ts +++ b/src/auth/services/user-auth.service.ts @@ -210,7 +210,7 @@ export class UserAuthService { } const otpCode = Math.floor(100000 + Math.random() * 900000).toString(); const expiryTime = new Date(); - expiryTime.setMinutes(expiryTime.getMinutes() + 1); + expiryTime.setMinutes(expiryTime.getMinutes() + 10); await this.otpRepository.save({ email: data.email, otpCode, @@ -232,7 +232,10 @@ export class UserAuthService { return { otpCode, cooldown }; } - async verifyOTP(data: VerifyOtpDto): Promise { + async verifyOTP( + data: VerifyOtpDto, + fromNewPassword: boolean = false, + ): Promise { const otp = await this.otpRepository.findOne({ where: { email: data.email, type: data.type }, }); @@ -253,7 +256,7 @@ export class UserAuthService { throw new BadRequestException('You entered wrong otp'); } - if (otp.expiryTime < new Date()) { + if (otp.expiryTime < new Date() || fromNewPassword) { await this.otpRepository.delete(otp.uuid); throw new BadRequestException('OTP expired'); } From c2958498e5e99e0e37b452f2ef3f73ad011d4fd3 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Tue, 22 Oct 2024 02:13:53 -0500 Subject: [PATCH 08/18] finished scene icons --- libs/common/src/database/database.module.ts | 3 + libs/common/src/modules/scene/dtos/index.ts | 1 + .../src/modules/scene/dtos/scene.dto.ts | 30 ++++ .../src/modules/scene/entities/index.ts | 1 + .../modules/scene/entities/scene.entity.ts | 57 ++++++++ .../src/modules/scene/repositories/index.ts | 1 + .../scene/repositories/scene.repository.ts | 17 +++ .../modules/scene/scene.repository.module.ts | 11 ++ src/scene/controllers/scene.controller.ts | 38 ++++- src/scene/dtos/scene.dto.ts | 61 +++++++- src/scene/scene.module.ts | 6 + src/scene/services/scene.service.ts | 130 ++++++++++++++---- 12 files changed, 324 insertions(+), 32 deletions(-) create mode 100644 libs/common/src/modules/scene/dtos/index.ts create mode 100644 libs/common/src/modules/scene/dtos/scene.dto.ts create mode 100644 libs/common/src/modules/scene/entities/index.ts create mode 100644 libs/common/src/modules/scene/entities/scene.entity.ts create mode 100644 libs/common/src/modules/scene/repositories/index.ts create mode 100644 libs/common/src/modules/scene/repositories/scene.repository.ts create mode 100644 libs/common/src/modules/scene/scene.repository.module.ts diff --git a/libs/common/src/database/database.module.ts b/libs/common/src/database/database.module.ts index 9de32e9..5d9d7f1 100644 --- a/libs/common/src/database/database.module.ts +++ b/libs/common/src/database/database.module.ts @@ -20,6 +20,7 @@ import { RegionEntity } from '../modules/region/entities'; import { TimeZoneEntity } from '../modules/timezone/entities'; import { VisitorPasswordEntity } from '../modules/visitor-password/entities'; import { DeviceStatusLogEntity } from '../modules/device-status-log/entities'; +import { SceneEntity, SceneIconEntity } from '../modules/scene/entities'; @Module({ imports: [ @@ -54,6 +55,8 @@ import { DeviceStatusLogEntity } from '../modules/device-status-log/entities'; TimeZoneEntity, VisitorPasswordEntity, DeviceStatusLogEntity, + SceneEntity, + SceneIconEntity, ], namingStrategy: new SnakeNamingStrategy(), synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))), diff --git a/libs/common/src/modules/scene/dtos/index.ts b/libs/common/src/modules/scene/dtos/index.ts new file mode 100644 index 0000000..b1ca9c8 --- /dev/null +++ b/libs/common/src/modules/scene/dtos/index.ts @@ -0,0 +1 @@ +export * from './scene.dto'; diff --git a/libs/common/src/modules/scene/dtos/scene.dto.ts b/libs/common/src/modules/scene/dtos/scene.dto.ts new file mode 100644 index 0000000..c128a6a --- /dev/null +++ b/libs/common/src/modules/scene/dtos/scene.dto.ts @@ -0,0 +1,30 @@ +import { IsBoolean, IsNotEmpty, IsString } from 'class-validator'; + +export class SceneDto { + @IsString() + @IsNotEmpty() + public uuid: string; + + @IsString() + @IsNotEmpty() + public sceneTuyaUuid: string; + @IsString() + @IsNotEmpty() + public unitUuid: string; + @IsString() + @IsNotEmpty() + public iconUuid: string; + + @IsBoolean() + @IsNotEmpty() + public inHomePage: boolean; +} +export class SceneIconDto { + @IsString() + @IsNotEmpty() + public uuid: string; + + @IsString() + @IsNotEmpty() + public icon: string; +} diff --git a/libs/common/src/modules/scene/entities/index.ts b/libs/common/src/modules/scene/entities/index.ts new file mode 100644 index 0000000..b7cd2fb --- /dev/null +++ b/libs/common/src/modules/scene/entities/index.ts @@ -0,0 +1 @@ +export * from './scene.entity'; diff --git a/libs/common/src/modules/scene/entities/scene.entity.ts b/libs/common/src/modules/scene/entities/scene.entity.ts new file mode 100644 index 0000000..d94d172 --- /dev/null +++ b/libs/common/src/modules/scene/entities/scene.entity.ts @@ -0,0 +1,57 @@ +import { Column, Entity, ManyToOne, OneToMany } from 'typeorm'; +import { SceneDto, SceneIconDto } from '../dtos'; +import { AbstractEntity } from '../../abstract/entities/abstract.entity'; + +// Define SceneIconEntity before SceneEntity +@Entity({ name: 'scene-icon' }) +export class SceneIconEntity extends AbstractEntity { + @Column({ + nullable: true, + type: 'text', + }) + public icon: string; + + @OneToMany( + () => SceneEntity, + (scenesIconEntity) => scenesIconEntity.sceneIcon, + ) + scenesIconEntity: SceneEntity[]; + + constructor(partial: Partial) { + super(); + Object.assign(this, partial); + } +} + +@Entity({ name: 'scene' }) +export class SceneEntity extends AbstractEntity { + @Column({ + type: 'uuid', + default: () => 'gen_random_uuid()', + nullable: false, + }) + public uuid: string; + + @Column({ + nullable: false, + }) + sceneTuyaUuid: string; + @Column({ + nullable: false, + }) + unitUuid: string; + @Column({ + nullable: false, + }) + showInHomePage: boolean; + + @ManyToOne(() => SceneIconEntity, (icon) => icon.scenesIconEntity, { + nullable: false, + }) + sceneIcon: SceneIconEntity; + + constructor(partial: Partial) { + super(); + Object.assign(this, partial); + } +} diff --git a/libs/common/src/modules/scene/repositories/index.ts b/libs/common/src/modules/scene/repositories/index.ts new file mode 100644 index 0000000..75c83c9 --- /dev/null +++ b/libs/common/src/modules/scene/repositories/index.ts @@ -0,0 +1 @@ +export * from './scene.repository'; diff --git a/libs/common/src/modules/scene/repositories/scene.repository.ts b/libs/common/src/modules/scene/repositories/scene.repository.ts new file mode 100644 index 0000000..d077592 --- /dev/null +++ b/libs/common/src/modules/scene/repositories/scene.repository.ts @@ -0,0 +1,17 @@ +import { DataSource, Repository } from 'typeorm'; +import { Injectable } from '@nestjs/common'; +import { SceneEntity, SceneIconEntity } from '../entities'; + +@Injectable() +export class SceneRepository extends Repository { + constructor(private dataSource: DataSource) { + super(SceneEntity, dataSource.createEntityManager()); + } +} + +@Injectable() +export class SceneIconRepository extends Repository { + constructor(private dataSource: DataSource) { + super(SceneIconEntity, dataSource.createEntityManager()); + } +} diff --git a/libs/common/src/modules/scene/scene.repository.module.ts b/libs/common/src/modules/scene/scene.repository.module.ts new file mode 100644 index 0000000..8bda28a --- /dev/null +++ b/libs/common/src/modules/scene/scene.repository.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { SceneEntity, SceneIconEntity } from './entities'; + +@Module({ + providers: [], + exports: [], + controllers: [], + imports: [TypeOrmModule.forFeature([SceneEntity, SceneIconEntity])], +}) +export class SceneRepositoryModule {} diff --git a/src/scene/controllers/scene.controller.ts b/src/scene/controllers/scene.controller.ts index 1186433..4e986e2 100644 --- a/src/scene/controllers/scene.controller.ts +++ b/src/scene/controllers/scene.controller.ts @@ -8,10 +8,16 @@ import { Param, Post, Put, + Query, UseGuards, } from '@nestjs/common'; import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; -import { AddSceneTapToRunDto, UpdateSceneTapToRunDto } from '../dtos/scene.dto'; +import { + AddSceneIconDto, + AddSceneTapToRunDto, + GetSceneDto, + UpdateSceneTapToRunDto, +} from '../dtos/scene.dto'; import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; @@ -39,9 +45,14 @@ export class SceneController { @ApiBearerAuth() @UseGuards(JwtAuthGuard) @Get('tap-to-run/:unitUuid') - async getTapToRunSceneByUnit(@Param('unitUuid') unitUuid: string) { - const tapToRunScenes = - await this.sceneService.getTapToRunSceneByUnit(unitUuid); + async getTapToRunSceneByUnit( + @Param('unitUuid') unitUuid: string, + @Query() inHomePage: GetSceneDto, + ) { + const tapToRunScenes = await this.sceneService.getTapToRunSceneByUnit( + unitUuid, + inHomePage, + ); return tapToRunScenes; } @ApiBearerAuth() @@ -95,4 +106,23 @@ export class SceneController { data: tapToRunScene, }; } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Post('icon') + async addSceneIcon(@Body() addSceneIconDto: AddSceneIconDto) { + const tapToRunScene = await this.sceneService.addSceneIcon(addSceneIconDto); + return { + statusCode: HttpStatus.CREATED, + success: true, + message: 'Icon added successfully', + data: tapToRunScene, + }; + } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Get('icon') + async getAllIcons() { + const icons = await this.sceneService.getAllIcons(); + return icons; + } } diff --git a/src/scene/dtos/scene.dto.ts b/src/scene/dtos/scene.dto.ts index ca39212..62690bd 100644 --- a/src/scene/dtos/scene.dto.ts +++ b/src/scene/dtos/scene.dto.ts @@ -6,8 +6,10 @@ import { ValidateNested, IsOptional, IsNumber, + IsBoolean, } from 'class-validator'; -import { Type } from 'class-transformer'; +import { Transform, Type } from 'class-transformer'; +import { BooleanValues } from '@app/common/constants/boolean-values.enum'; class ExecutorProperty { @ApiProperty({ @@ -70,7 +72,20 @@ export class AddSceneTapToRunDto { @IsString() @IsNotEmpty() public unitUuid: string; - + @ApiProperty({ + description: 'Icon UUID', + required: true, + }) + @IsString() + @IsNotEmpty() + public iconUuid: string; + @ApiProperty({ + description: 'show in home page', + required: true, + }) + @IsBoolean() + @IsNotEmpty() + public showInHomePage: boolean; @ApiProperty({ description: 'Scene name', required: true, @@ -109,7 +124,20 @@ export class UpdateSceneTapToRunDto { @IsString() @IsNotEmpty() public sceneName: string; - + @ApiProperty({ + description: 'Icon UUID', + required: true, + }) + @IsString() + @IsNotEmpty() + public iconUuid: string; + @ApiProperty({ + description: 'show in home page', + required: true, + }) + @IsBoolean() + @IsNotEmpty() + public showInHomePage: boolean; @ApiProperty({ description: 'Decision expression', required: true, @@ -132,3 +160,30 @@ export class UpdateSceneTapToRunDto { Object.assign(this, dto); } } +export class AddSceneIconDto { + @ApiProperty({ + description: 'Icon', + required: true, + }) + @IsString() + @IsNotEmpty() + public icon: string; + + constructor(dto: Partial) { + Object.assign(this, dto); + } +} +export class GetSceneDto { + @ApiProperty({ + example: true, + description: 'showInHomePage', + required: true, + default: false, + }) + @IsNotEmpty() + @IsBoolean() + @Transform((value) => { + return value.obj.showInHomePage === BooleanValues.TRUE; + }) + public showInHomePage: boolean = false; +} diff --git a/src/scene/scene.module.ts b/src/scene/scene.module.ts index c673748..cdbf2d4 100644 --- a/src/scene/scene.module.ts +++ b/src/scene/scene.module.ts @@ -8,6 +8,10 @@ import { DeviceService } from 'src/device/services'; import { DeviceRepository } from '@app/common/modules/device/repositories'; import { ProductRepository } from '@app/common/modules/product/repositories'; import { DeviceStatusFirebaseModule } from '@app/common/firebase/devices-status/devices-status.module'; +import { + SceneIconRepository, + SceneRepository, +} from '@app/common/modules/scene/repositories'; @Module({ imports: [ConfigModule, SpaceRepositoryModule, DeviceStatusFirebaseModule], @@ -18,6 +22,8 @@ import { DeviceStatusFirebaseModule } from '@app/common/firebase/devices-status/ DeviceService, DeviceRepository, ProductRepository, + SceneIconRepository, + SceneRepository, ], exports: [SceneService], }) diff --git a/src/scene/services/scene.service.ts b/src/scene/services/scene.service.ts index 30e53aa..ba5436b 100644 --- a/src/scene/services/scene.service.ts +++ b/src/scene/services/scene.service.ts @@ -5,7 +5,12 @@ import { BadRequestException, } from '@nestjs/common'; import { SpaceRepository } from '@app/common/modules/space/repositories'; -import { AddSceneTapToRunDto, UpdateSceneTapToRunDto } from '../dtos'; +import { + AddSceneIconDto, + AddSceneTapToRunDto, + GetSceneDto, + UpdateSceneTapToRunDto, +} from '../dtos'; import { GetUnitByUuidInterface } from 'src/unit/interface/unit.interface'; import { ConfigService } from '@nestjs/config'; import { TuyaContext } from '@tuya/tuya-connector-nodejs'; @@ -14,12 +19,15 @@ import { DeviceService } from 'src/device/services'; import { AddTapToRunSceneInterface, DeleteTapToRunSceneInterface, - GetTapToRunSceneByUnitInterface, SceneDetailsResult, } from '../interface/scene.interface'; import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter'; import { SpaceType } from '@app/common/constants/space-type.enum'; import { ActionExecutorEnum } from '@app/common/constants/automation.enum'; +import { + SceneIconRepository, + SceneRepository, +} from '@app/common/modules/scene/repositories'; @Injectable() export class SceneService { @@ -27,6 +35,8 @@ export class SceneService { constructor( private readonly configService: ConfigService, private readonly spaceRepository: SpaceRepository, + private readonly sceneIconRepository: SceneIconRepository, + private readonly sceneRepository: SceneRepository, private readonly deviceService: DeviceService, ) { const accessKey = this.configService.get('auth-config.ACCESS_KEY'); @@ -42,6 +52,7 @@ export class SceneService { async addTapToRunScene( addSceneTapToRunDto: AddSceneTapToRunDto, spaceTuyaId = null, + unitUuid?: string, ) { try { let unitSpaceTuyaId; @@ -89,6 +100,15 @@ export class SceneService { }); if (!response.success) { throw new HttpException(response.msg, HttpStatus.BAD_REQUEST); + } else { + await this.sceneRepository.save({ + sceneTuyaUuid: response.result.id, + sceneIcon: { + uuid: addSceneTapToRunDto.iconUuid, + }, + showInHomePage: addSceneTapToRunDto.showInHomePage, + unitUuid: unitUuid ? unitUuid : addSceneTapToRunDto.unitUuid, + }); } return { id: response.result.id, @@ -134,33 +154,32 @@ export class SceneService { } } } - async getTapToRunSceneByUnit(unitUuid: string) { + async getTapToRunSceneByUnit(unitUuid: string, inHomePage: GetSceneDto) { try { - const unit = await this.getUnitByUuid(unitUuid); - if (!unit.spaceTuyaUuid) { - throw new BadRequestException('Invalid unit UUID'); - } + const showInHomePage = inHomePage?.showInHomePage; - const path = `/v2.0/cloud/scene/rule?space_id=${unit.spaceTuyaUuid}&type=scene`; - const response: GetTapToRunSceneByUnitInterface = await this.tuya.request( - { - method: 'GET', - path, + const scenesData = await this.sceneRepository.find({ + where: { + unitUuid, + ...(showInHomePage ? { showInHomePage } : {}), }, + }); + + const scenes = await Promise.all( + scenesData.map(async (scene) => { + const sceneData = await this.getTapToRunSceneDetails( + scene.sceneTuyaUuid, + false, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { actions, ...rest } = sceneData; + return { + rest, + }; + }), ); - if (!response.success) { - throw new HttpException(response.msg, HttpStatus.BAD_REQUEST); - } - - return response.result.list.map((item) => { - return { - id: item.id, - name: item.name, - status: item.status, - type: 'tap_to_run', - }; - }); + return scenes; } catch (err) { if (err instanceof BadRequestException) { throw err; // Re-throw BadRequestException @@ -197,6 +216,8 @@ export class SceneService { if (!response.success) { throw new HttpException('Scene not found', HttpStatus.NOT_FOUND); + } else { + await this.sceneRepository.delete({ sceneTuyaUuid: sceneId }); } return response; @@ -273,11 +294,17 @@ export class SceneService { } } } - + const scene = await this.sceneRepository.findOne({ + where: { sceneTuyaUuid: sceneId }, + relations: ['sceneIcon'], + }); return { id: responseData.id, name: responseData.name, status: responseData.status, + icon: scene.sceneIcon?.icon, + iconUuid: scene.sceneIcon?.uuid, + showInHome: scene.showInHomePage, type: 'tap_to_run', actions: actions, ...(withSpaceId && { spaceId: responseData.spaceId }), @@ -334,13 +361,32 @@ export class SceneService { const addSceneTapToRunDto: AddSceneTapToRunDto = { ...updateSceneTapToRunDto, unitUuid: null, + iconUuid: updateSceneTapToRunDto.iconUuid, + showInHomePage: updateSceneTapToRunDto.showInHomePage, }; + const scene = await this.sceneRepository.findOne({ + where: { sceneTuyaUuid: sceneId }, + }); + const newTapToRunScene = await this.addTapToRunScene( addSceneTapToRunDto, spaceTuyaId.spaceId, + scene.unitUuid, ); if (newTapToRunScene.id) { await this.deleteTapToRunScene(null, sceneId, spaceTuyaId.spaceId); + + await this.sceneRepository.update( + { sceneTuyaUuid: sceneId }, + { + sceneTuyaUuid: newTapToRunScene.id, + showInHomePage: addSceneTapToRunDto.showInHomePage, + sceneIcon: { + uuid: addSceneTapToRunDto.iconUuid, + }, + unitUuid: scene.unitUuid, + }, + ); return newTapToRunScene; } } catch (err) { @@ -354,4 +400,38 @@ export class SceneService { } } } + async addSceneIcon(addSceneIconDto: AddSceneIconDto) { + try { + const icon = await this.sceneIconRepository.save({ + icon: addSceneIconDto.icon, + }); + return icon; + } catch (err) { + throw new HttpException( + { + status: HttpStatus.INTERNAL_SERVER_ERROR, + error: 'Failed to add scene icon', + message: err.message || 'Unexpected error occurred', + }, + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async getAllIcons() { + try { + const icons = await this.sceneIconRepository.find(); + return icons; + } catch (err) { + // Improved error handling + throw new HttpException( + { + statusCode: HttpStatus.INTERNAL_SERVER_ERROR, + message: 'Failed to fetch icons', + error: + err.message || 'An unexpected error occurred while fetching icons', + }, + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } } From cf846e2c3cdb40abe2092b58071f75da9e8ede09 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Tue, 22 Oct 2024 03:23:37 -0500 Subject: [PATCH 09/18] fix response --- src/device/services/device.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/device/services/device.service.ts b/src/device/services/device.service.ts index 96cba90..ebe73e2 100644 --- a/src/device/services/device.service.ts +++ b/src/device/services/device.service.ts @@ -986,11 +986,11 @@ export class DeviceService { (acc, currentStatus) => { const { code } = currentStatus; - if (code.includes('A')) { + if (code.endsWith('A')) { acc.phaseA.push(currentStatus); - } else if (code.includes('B')) { + } else if (code.endsWith('B')) { acc.phaseB.push(currentStatus); - } else if (code.includes('C')) { + } else if (code.endsWith('C')) { acc.phaseC.push(currentStatus); } else { acc.general.push(currentStatus); From ce9555a5f40e4495689edd327e2f1ebd91149a7a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Oct 2024 09:56:23 +0300 Subject: [PATCH 10/18] changed device log table --- libs/common/src/constants/source-type.enum.ts | 7 +++++ .../dtos/add.devices-status.dto.ts | 3 ++ .../services/devices-status.service.ts | 14 ++++++--- .../services/tuya.web.socket.service.ts | 3 +- .../entities/device-status-log.entity.ts | 31 ++++++++++++++----- 5 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 libs/common/src/constants/source-type.enum.ts diff --git a/libs/common/src/constants/source-type.enum.ts b/libs/common/src/constants/source-type.enum.ts new file mode 100644 index 0000000..781c6b7 --- /dev/null +++ b/libs/common/src/constants/source-type.enum.ts @@ -0,0 +1,7 @@ +export enum SourceType { + Device = 1, + Client = 2, + ThirdParty = 3, + Cloud = 4, + Unknown = -1, +} diff --git a/libs/common/src/firebase/devices-status/dtos/add.devices-status.dto.ts b/libs/common/src/firebase/devices-status/dtos/add.devices-status.dto.ts index 9ad7a11..ded0771 100644 --- a/libs/common/src/firebase/devices-status/dtos/add.devices-status.dto.ts +++ b/libs/common/src/firebase/devices-status/dtos/add.devices-status.dto.ts @@ -35,4 +35,7 @@ export class AddDeviceStatusDto { @ValidateNested({ each: true }) @Type(() => StatusDto) status: StatusDto[]; + + @IsOptional() + log?: any; } diff --git a/libs/common/src/firebase/devices-status/services/devices-status.service.ts b/libs/common/src/firebase/devices-status/services/devices-status.service.ts index 41a3b39..2e9bc8b 100644 --- a/libs/common/src/firebase/devices-status/services/devices-status.service.ts +++ b/libs/common/src/firebase/devices-status/services/devices-status.service.ts @@ -150,6 +150,7 @@ export class DeviceStatusFirebaseService { async createDeviceStatusFirebase( addDeviceStatusDto: AddDeviceStatusDto, ): Promise { + console.log(addDeviceStatusDto); const dataRef = ref( this.firebaseDb, `device-status/${addDeviceStatusDto.deviceUuid}`, @@ -188,11 +189,14 @@ export class DeviceStatusFirebaseService { value, })); const newLog = this.deviceStatusLogRepository.create({ - deviceUuid: addDeviceStatusDto.deviceUuid, - deviceTuyaUuid: addDeviceStatusDto.deviceTuyaUuid, - productUuid: addDeviceStatusDto.productUuid, - productType: addDeviceStatusDto.productType, - status: existingData.status, + deviceId: addDeviceStatusDto.deviceUuid, + deviceTuyaId: addDeviceStatusDto.deviceTuyaUuid, + productId: addDeviceStatusDto.productUuid, + log: addDeviceStatusDto.log, + code: existingData.status[0].code, + value: existingData.status[0].value, + eventId: addDeviceStatusDto.log.dataId, + eventTime: addDeviceStatusDto.log.properties[0].time, }); await this.deviceStatusLogRepository.save(newLog); diff --git a/libs/common/src/helper/services/tuya.web.socket.service.ts b/libs/common/src/helper/services/tuya.web.socket.service.ts index 5b8d89a..d117d62 100644 --- a/libs/common/src/helper/services/tuya.web.socket.service.ts +++ b/libs/common/src/helper/services/tuya.web.socket.service.ts @@ -16,7 +16,7 @@ export class TuyaWebSocketService { accessId: this.configService.get('tuya-config.TUYA_ACCESS_ID'), accessKey: this.configService.get('tuya-config.TUYA_ACCESS_KEY'), url: TuyaWebsocket.URL.EU, - env: TuyaWebsocket.env.TEST, + env: TuyaWebsocket.env.PROD, maxRetryTimes: 100, }); @@ -40,6 +40,7 @@ export class TuyaWebSocketService { await this.deviceStatusFirebaseService.addDeviceStatusToFirebase({ deviceTuyaUuid: message.payload.data.bizData.devId, status: message.payload.data.bizData.properties, + log: message.payload.data.bizData, }); this.client.ackMessage(message.messageId); diff --git a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts index d886ae3..5d99041 100644 --- a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts +++ b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts @@ -1,26 +1,43 @@ +import { SourceType } from '@app/common/constants/source-type.enum'; import { Entity, Column, PrimaryColumn, Index } from 'typeorm'; @Entity('device-status-log') -@Index('logTime_idx', ['logTime']) +@Index('logTime_idx', ['eventTime']) export class DeviceStatusLogEntity { @PrimaryColumn() id: number; + @Column({ type: 'text' }) + eventId: string; + @PrimaryColumn({ type: 'timestamptz' }) - logTime: Date; + eventTime: Date; + + @Column({ + type: 'enum', + enum: SourceType, + default: SourceType.Device, + }) + eventFrom: SourceType; @Column({ type: 'text' }) - deviceUuid: string; + deviceId: string; @Column({ type: 'text' }) - deviceTuyaUuid: string; + deviceTuyaId: string; @Column({ type: 'text' }) - productUuid: string; + productId: string; @Column({ type: 'text' }) - productType: string; + code: any; + + @Column({ type: 'text' }) + value: any; @Column({ type: 'jsonb' }) - status: any; // JSON array of status codes and values + log: any; + + @Column({ type: 'timestamptz', default: new Date() }) + ingestionTime: Date; } From 9160a982bac7b3a14aac5705e2c5b9bfd28759fa Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sun, 27 Oct 2024 02:23:28 -0500 Subject: [PATCH 11/18] fix issue in real time --- .../devices-status/services/devices-status.service.ts | 8 ++++---- .../entities/device-status-log.entity.ts | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libs/common/src/firebase/devices-status/services/devices-status.service.ts b/libs/common/src/firebase/devices-status/services/devices-status.service.ts index 2e9bc8b..b92947a 100644 --- a/libs/common/src/firebase/devices-status/services/devices-status.service.ts +++ b/libs/common/src/firebase/devices-status/services/devices-status.service.ts @@ -150,7 +150,6 @@ export class DeviceStatusFirebaseService { async createDeviceStatusFirebase( addDeviceStatusDto: AddDeviceStatusDto, ): Promise { - console.log(addDeviceStatusDto); const dataRef = ref( this.firebaseDb, `device-status/${addDeviceStatusDto.deviceUuid}`, @@ -191,14 +190,15 @@ export class DeviceStatusFirebaseService { const newLog = this.deviceStatusLogRepository.create({ deviceId: addDeviceStatusDto.deviceUuid, deviceTuyaId: addDeviceStatusDto.deviceTuyaUuid, - productId: addDeviceStatusDto.productUuid, + productId: addDeviceStatusDto.log.productId, log: addDeviceStatusDto.log, code: existingData.status[0].code, value: existingData.status[0].value, eventId: addDeviceStatusDto.log.dataId, - eventTime: addDeviceStatusDto.log.properties[0].time, + eventTime: new Date( + addDeviceStatusDto.log.properties[0].time, + ).toLocaleDateString(), }); - await this.deviceStatusLogRepository.save(newLog); // Save the updated data to Firebase await set(dataRef, existingData); diff --git a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts index 5d99041..82307e8 100644 --- a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts +++ b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts @@ -4,7 +4,11 @@ import { Entity, Column, PrimaryColumn, Index } from 'typeorm'; @Entity('device-status-log') @Index('logTime_idx', ['eventTime']) export class DeviceStatusLogEntity { - @PrimaryColumn() + @PrimaryColumn({ + type: 'int', + generated: true, + unsigned: true, + }) id: number; @Column({ type: 'text' }) From 057948344490bfbecd4d443222231a5cf7d12fec Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Oct 2024 11:19:42 +0300 Subject: [PATCH 12/18] changed date string to iso --- .../firebase/devices-status/services/devices-status.service.ts | 2 +- libs/common/src/helper/services/tuya.web.socket.service.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/common/src/firebase/devices-status/services/devices-status.service.ts b/libs/common/src/firebase/devices-status/services/devices-status.service.ts index b92947a..162313b 100644 --- a/libs/common/src/firebase/devices-status/services/devices-status.service.ts +++ b/libs/common/src/firebase/devices-status/services/devices-status.service.ts @@ -197,7 +197,7 @@ export class DeviceStatusFirebaseService { eventId: addDeviceStatusDto.log.dataId, eventTime: new Date( addDeviceStatusDto.log.properties[0].time, - ).toLocaleDateString(), + ).toISOString(), }); await this.deviceStatusLogRepository.save(newLog); // Save the updated data to Firebase diff --git a/libs/common/src/helper/services/tuya.web.socket.service.ts b/libs/common/src/helper/services/tuya.web.socket.service.ts index d117d62..edb6897 100644 --- a/libs/common/src/helper/services/tuya.web.socket.service.ts +++ b/libs/common/src/helper/services/tuya.web.socket.service.ts @@ -37,6 +37,8 @@ export class TuyaWebSocketService { this.client.message(async (ws: WebSocket, message: any) => { try { + console.log(message.payload.data.bizData); + await this.deviceStatusFirebaseService.addDeviceStatusToFirebase({ deviceTuyaUuid: message.payload.data.bizData.devId, status: message.payload.data.bizData.properties, From 060accceea555eef47a54e47f092bb0efd0a2aa3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Oct 2024 11:20:37 +0300 Subject: [PATCH 13/18] changed date string to iso --- libs/common/src/helper/services/tuya.web.socket.service.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/common/src/helper/services/tuya.web.socket.service.ts b/libs/common/src/helper/services/tuya.web.socket.service.ts index edb6897..d117d62 100644 --- a/libs/common/src/helper/services/tuya.web.socket.service.ts +++ b/libs/common/src/helper/services/tuya.web.socket.service.ts @@ -37,8 +37,6 @@ export class TuyaWebSocketService { this.client.message(async (ws: WebSocket, message: any) => { try { - console.log(message.payload.data.bizData); - await this.deviceStatusFirebaseService.addDeviceStatusToFirebase({ deviceTuyaUuid: message.payload.data.bizData.devId, status: message.payload.data.bizData.properties, From 008fe0a515ac44c751e45c9411c2e177b12e5877 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Oct 2024 11:37:25 +0300 Subject: [PATCH 14/18] changed date string to iso --- .../entities/device-status-log.entity.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts index 82307e8..4696baf 100644 --- a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts +++ b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts @@ -2,13 +2,9 @@ import { SourceType } from '@app/common/constants/source-type.enum'; import { Entity, Column, PrimaryColumn, Index } from 'typeorm'; @Entity('device-status-log') -@Index('logTime_idx', ['eventTime']) +@Index('event_time_idx', ['eventTime']) export class DeviceStatusLogEntity { - @PrimaryColumn({ - type: 'int', - generated: true, - unsigned: true, - }) + @Column({ type: 'int', generated: true, unsigned: true }) id: number; @Column({ type: 'text' }) From ccf3e34fbfab3cac2271ae2756a63b4b7199eddf Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Oct 2024 15:47:39 +0300 Subject: [PATCH 15/18] changed date string to iso --- .../device-status-log/entities/device-status-log.entity.ts | 4 ++-- src/auth/services/user-auth.service.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts index 4696baf..a7a998a 100644 --- a/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts +++ b/libs/common/src/modules/device-status-log/entities/device-status-log.entity.ts @@ -1,8 +1,8 @@ import { SourceType } from '@app/common/constants/source-type.enum'; -import { Entity, Column, PrimaryColumn, Index } from 'typeorm'; +import { Entity, Column, PrimaryColumn, Unique } from 'typeorm'; @Entity('device-status-log') -@Index('event_time_idx', ['eventTime']) +@Unique('event_time_idx', ['eventTime']) export class DeviceStatusLogEntity { @Column({ type: 'int', generated: true, unsigned: true }) id: number; diff --git a/src/auth/services/user-auth.service.ts b/src/auth/services/user-auth.service.ts index 9f9d82d..0c95297 100644 --- a/src/auth/services/user-auth.service.ts +++ b/src/auth/services/user-auth.service.ts @@ -256,11 +256,13 @@ export class UserAuthService { throw new BadRequestException('You entered wrong otp'); } - if (otp.expiryTime < new Date() || fromNewPassword) { + if (otp.expiryTime < new Date()) { await this.otpRepository.delete(otp.uuid); throw new BadRequestException('OTP expired'); } - + if (fromNewPassword) { + await this.otpRepository.delete(otp.uuid); + } if (data.type == OtpType.VERIFICATION) { await this.userRepository.update( { email: data.email }, From 1375b239b38c68bb1ce16c339aefab244539a79d Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Sun, 27 Oct 2024 23:39:38 -0500 Subject: [PATCH 16/18] resolve rest issue --- src/scene/services/scene.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scene/services/scene.service.ts b/src/scene/services/scene.service.ts index ba5436b..ea2237a 100644 --- a/src/scene/services/scene.service.ts +++ b/src/scene/services/scene.service.ts @@ -174,7 +174,7 @@ export class SceneService { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { actions, ...rest } = sceneData; return { - rest, + ...rest, }; }), ); From 86fb73ab8d28575d5c7868856e9f7557aaf9be67 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Mon, 28 Oct 2024 01:51:27 -0500 Subject: [PATCH 17/18] finished add default icon for scene --- .../src/constants/default.scene.icon.ts | 2 + .../src/constants/secne-icon-type.enum.ts | 4 ++ .../modules/scene/entities/scene.entity.ts | 8 ++++ libs/common/src/seed/seeder.module.ts | 4 ++ .../src/seed/services/scene.icon.seeder.ts | 38 +++++++++++++++++++ .../src/seed/services/seeder.service.ts | 3 ++ src/scene/dtos/scene.dto.ts | 4 +- src/scene/services/scene.service.ts | 11 +++++- 8 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 libs/common/src/constants/default.scene.icon.ts create mode 100644 libs/common/src/constants/secne-icon-type.enum.ts create mode 100644 libs/common/src/seed/services/scene.icon.seeder.ts diff --git a/libs/common/src/constants/default.scene.icon.ts b/libs/common/src/constants/default.scene.icon.ts new file mode 100644 index 0000000..637ca8c --- /dev/null +++ b/libs/common/src/constants/default.scene.icon.ts @@ -0,0 +1,2 @@ +export const defaultSceneIcon = + 'data:image/png;base64,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'; diff --git a/libs/common/src/constants/secne-icon-type.enum.ts b/libs/common/src/constants/secne-icon-type.enum.ts new file mode 100644 index 0000000..1cbb693 --- /dev/null +++ b/libs/common/src/constants/secne-icon-type.enum.ts @@ -0,0 +1,4 @@ +export enum SceneIconType { + Default = 'default', + Other = 'other', +} diff --git a/libs/common/src/modules/scene/entities/scene.entity.ts b/libs/common/src/modules/scene/entities/scene.entity.ts index d94d172..2ade9ad 100644 --- a/libs/common/src/modules/scene/entities/scene.entity.ts +++ b/libs/common/src/modules/scene/entities/scene.entity.ts @@ -1,6 +1,7 @@ import { Column, Entity, ManyToOne, OneToMany } from 'typeorm'; import { SceneDto, SceneIconDto } from '../dtos'; import { AbstractEntity } from '../../abstract/entities/abstract.entity'; +import { SceneIconType } from '@app/common/constants/secne-icon-type.enum'; // Define SceneIconEntity before SceneEntity @Entity({ name: 'scene-icon' }) @@ -11,6 +12,13 @@ export class SceneIconEntity extends AbstractEntity { }) public icon: string; + @Column({ + type: 'enum', + enum: SceneIconType, + default: SceneIconType.Other, + }) + iconType: SceneIconType; + @OneToMany( () => SceneEntity, (scenesIconEntity) => scenesIconEntity.sceneIcon, diff --git a/libs/common/src/seed/seeder.module.ts b/libs/common/src/seed/seeder.module.ts index f63c05d..0c89c5c 100644 --- a/libs/common/src/seed/seeder.module.ts +++ b/libs/common/src/seed/seeder.module.ts @@ -18,6 +18,8 @@ import { RegionSeeder } from './services/regions.seeder'; import { RegionRepository } from '../modules/region/repositories'; import { TimeZoneSeeder } from './services/timezone.seeder'; import { TimeZoneRepository } from '../modules/timezone/repositories'; +import { SceneIconSeeder } from './services/scene.icon.seeder'; +import { SceneIconRepository } from '../modules/scene/repositories'; @Global() @Module({ providers: [ @@ -35,6 +37,8 @@ import { TimeZoneRepository } from '../modules/timezone/repositories'; RegionRepository, TimeZoneSeeder, TimeZoneRepository, + SceneIconSeeder, + SceneIconRepository, ], exports: [SeederService], controllers: [], diff --git a/libs/common/src/seed/services/scene.icon.seeder.ts b/libs/common/src/seed/services/scene.icon.seeder.ts new file mode 100644 index 0000000..3f363ce --- /dev/null +++ b/libs/common/src/seed/services/scene.icon.seeder.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@nestjs/common'; +import { SceneIconRepository } from '@app/common/modules/scene/repositories'; +import { SceneIconType } from '@app/common/constants/secne-icon-type.enum'; +import { defaultSceneIcon } from '@app/common/constants/default.scene.icon'; + +@Injectable() +export class SceneIconSeeder { + constructor(private readonly sceneIconRepository: SceneIconRepository) {} + + async createSceneDefaultIconIfNotFound(): Promise { + try { + const defaultSceneIconData = await this.sceneIconRepository.find({ + where: { iconType: SceneIconType.Default }, + }); + + if (defaultSceneIconData.length <= 0) { + console.log('Creating default scene icon...'); + + await this.createDefaultSceneIcon(); + } + } catch (err) { + console.error('Error while checking default scene icon:', err); + throw err; + } + } + + private async createDefaultSceneIcon(): Promise { + try { + await this.sceneIconRepository.save({ + icon: defaultSceneIcon, + iconType: SceneIconType.Default, + }); + } catch (err) { + console.error('Error while creating default scene icon:', err); + throw err; + } + } +} diff --git a/libs/common/src/seed/services/seeder.service.ts b/libs/common/src/seed/services/seeder.service.ts index 47d899d..e627e44 100644 --- a/libs/common/src/seed/services/seeder.service.ts +++ b/libs/common/src/seed/services/seeder.service.ts @@ -5,6 +5,7 @@ import { SpaceTypeSeeder } from './space.type.seeder'; import { SuperAdminSeeder } from './supper.admin.seeder'; import { RegionSeeder } from './regions.seeder'; import { TimeZoneSeeder } from './timezone.seeder'; +import { SceneIconSeeder } from './scene.icon.seeder'; @Injectable() export class SeederService { constructor( @@ -14,6 +15,7 @@ export class SeederService { private readonly regionSeeder: RegionSeeder, private readonly timeZoneSeeder: TimeZoneSeeder, private readonly superAdminSeeder: SuperAdminSeeder, + private readonly sceneIconSeeder: SceneIconSeeder, ) {} async seed() { @@ -23,5 +25,6 @@ export class SeederService { await this.regionSeeder.addRegionDataIfNotFound(); await this.timeZoneSeeder.addTimeZoneDataIfNotFound(); await this.superAdminSeeder.createSuperAdminIfNotFound(); + await this.sceneIconSeeder.createSceneDefaultIconIfNotFound(); } } diff --git a/src/scene/dtos/scene.dto.ts b/src/scene/dtos/scene.dto.ts index 62690bd..24334e9 100644 --- a/src/scene/dtos/scene.dto.ts +++ b/src/scene/dtos/scene.dto.ts @@ -74,10 +74,10 @@ export class AddSceneTapToRunDto { public unitUuid: string; @ApiProperty({ description: 'Icon UUID', - required: true, + required: false, }) @IsString() - @IsNotEmpty() + @IsOptional() public iconUuid: string; @ApiProperty({ description: 'show in home page', diff --git a/src/scene/services/scene.service.ts b/src/scene/services/scene.service.ts index ba5436b..3278970 100644 --- a/src/scene/services/scene.service.ts +++ b/src/scene/services/scene.service.ts @@ -28,6 +28,7 @@ import { SceneIconRepository, SceneRepository, } from '@app/common/modules/scene/repositories'; +import { SceneIconType } from '@app/common/constants/secne-icon-type.enum'; @Injectable() export class SceneService { @@ -101,10 +102,16 @@ export class SceneService { if (!response.success) { throw new HttpException(response.msg, HttpStatus.BAD_REQUEST); } else { + const defaultSceneIcon = await this.sceneIconRepository.findOne({ + where: { iconType: SceneIconType.Default }, + }); + await this.sceneRepository.save({ sceneTuyaUuid: response.result.id, sceneIcon: { - uuid: addSceneTapToRunDto.iconUuid, + uuid: addSceneTapToRunDto.iconUuid + ? addSceneTapToRunDto.iconUuid + : defaultSceneIcon.uuid, }, showInHomePage: addSceneTapToRunDto.showInHomePage, unitUuid: unitUuid ? unitUuid : addSceneTapToRunDto.unitUuid, @@ -174,7 +181,7 @@ export class SceneService { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { actions, ...rest } = sceneData; return { - rest, + ...rest, }; }), ); From 1546aa1b5e1e7c566b5d992cac1e98ee4be62d97 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Mon, 28 Oct 2024 02:12:30 -0500 Subject: [PATCH 18/18] resolve icon issue --- libs/common/src/constants/default.scene.icon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/common/src/constants/default.scene.icon.ts b/libs/common/src/constants/default.scene.icon.ts index 637ca8c..c082768 100644 --- a/libs/common/src/constants/default.scene.icon.ts +++ b/libs/common/src/constants/default.scene.icon.ts @@ -1,2 +1,2 @@ export const defaultSceneIcon = - 'data:image/png;base64,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'; + 'iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAh9SURBVHgB3ZxfbFtXHce/59xrO7GTkLZUA6KpAa1aM62a80AZAymuxgs8sOZhvC7lCQkk2geg2UBJJMTgqZ2EBG/JkICtrdR24gGJSkklGgo8zBsP7WilOava/enauEsbx/a95+z3u+5N/D++9r3+k4+U2Nc+vvb9+vv7nd85514LtJH9f34QN2Q4rgXikHqfgIg7TwiMljTUSEml01qLtGGpd8wNpEKfWEv/fWUgiTYhECCj83q4fyA7pSFfoDeKa2AYTSKURngdaTOrlyKruQsK9tKV6V0pBEQgwhz4ayYB05ihuwkEgJHX6F+1IXP6vJGxX//Xy0Pn4TO+CnPgdG6KbmYqQiMgWKDImkLfqkpB23PL00ML8AlfhHEcYhjz7RKkHBYodseGmdG+CdSSMCTIKIXMPAIKGa9E79kUYopyNxaUzs21koOaFmbszMYxQM60klCDgJIzBj+yIPNIa9jHm3WPZ2EKPU2eBTmGLoVDa+g2iWPRhtCnLv9i4Dg84kkYDh1tGOcE1yFdTok4GkkbuUkvodWwME4+MYzFTiXYZigWhxyeorxzuFFxGhKmF0VxaVYcuV2DXhaFsUMCa18ynfvkglEpwovPvro6ut3rthWGc0qviuJiRQQe7ikcKotjIHwuMbtatzetK8zYmdzJXki0jbAxbCDf/yhz0DHl+0Mz9drXFIbL+27ukpvh4V4D2j1iLY598zcPah5f1eTLeUWYxtvdVrz5QV/aRuyuKmxo0FZuvFoyru4YKWf9FiVqoivgkFLuZxEYNkRovlq7Csc4I2SBefjE1/cK/OQpiUN7JTboi7p8V+MvN2ws39LoFOGHioYN9ua20OrwP6cHl4rbVPse6yYlLzz/FYHfP7f1Fn3kz+dJqKeHTby5R+H0dRt3M2g7uZgk19iFqphQQrIRvlrcpsQxfrvl4vdMjESr15Dsnps5OO75x4pqu0B9aUW5Zss1WttHiwec5TnGN7ccGBY1RXE+GL3z/j7gR08a+NU3TDw3EugsawXZIbnVQzHCKDn2zafGzmaP+FnIDYYaa/cYtZvYLXBi3MRvJ0w8ubs9ArEoG4NbynDh9+1X1xLu9uYzSmEKHcJ1z7Pksl+Se44eNLCnH4GTj5V+CVqITdc4wjh1ixAvoMOwe54mQSb3SfxuIoTvP7HtiKUl8v1l4QSRcIcKhYcNI4EuwXXPExHgxf2GE15B5p9cmWuy4dAU3zrCaOgj6DLYPfEocHBI4IcHC/kniPDK95W6Uko4kSMLG2ICXYhJX+bXIoXw4h6Ow8vv/LM5sHTRhdVRsf90Lm4IvA2f4Yr3TxP+jQMsKpQ/oLrnwzywTn8XV2y8dUPBD3a/n6eVzq1tbetxaQqVQA9Q7J5dYVBi9i//8HxNCVLFOS2Poof4glHIPV+mHPTF/kL++fF4a+GlKowt46YWeAY9huuePXRA1zeA8cek83f5lqLw8j7+snmHKB7UapoC7eE5l2L3MN8akfjZIe/hpcyy9kI+I7XWu9DDuO5hkRg3vL6zr/HiUBuVj0kIsQ87gMfDpducnBtFl2norCZghxArO5Iohdfjg833WDtGGNPnUcOOEea+Xbr9KfVMN9eanz6lOkavYAfAFXEx3G03Cy/ldsncffPwUIGnSO8+mr9dp9u3rvNke+PDBVkmKi0ypk3ab5LCsyd7Jg4fLvCyjyLmYko546d1y1sIybL2Wqn7JvXXqc4tZDSH65Lbj77p9+5pvHHNxs3PmjsSUWEukXQcgx6i2CWcYOf/ZznCtIKZq3h9klZXkGy8FOocxS7hPMJhw39ew6YaZrZsH4qEuf6DcHLsbC6tdfeOmYpdwgPFN6/6Iwhj0E5LQonWs5dfGUg6vRKJwuGUQJdR7BIOF+6CWw2bcsrdoqEuOY/zPwF1QUMm0EW4Lrm1XqhJvHS/XjA3yoUWzun3jjARM7KwYeVPogtwXXIj428eqUUoU7pvBWOJbx1hkpMifeBMjh9IoIO4LrnyscIbV3k9O9hCIpQhGYpE11pduDIdS/H9osrXnqNUlEAHcF2y+HEweaQW4bKxlJZ6wb1ferbD2dz7lH1G4QMjtJB18bvbjzjYJe8+AE7/36aZ/2DySC2GV6xNx1DflFo+Ed08FaT0kyvM+XUayK2H2kmcI9Hqz7su+ePV4PNINSKflYYRjQPmip+vPKPKR9ccorWl16usLbFL/nZb4w/v2oHnkVrUcwtTOR+j7aPwif/c0XjpkoVr6cIH4M/x9w8Lj/3631bHRNnOLUz1szbP5BYRQA8VpWm2dodMNUrdgoXlE7EKM1SfwTPtozwnAZ/pBlH67he5hY5RaTlXrV1VYa5N9qdUFXv1OjwhxefeuWilj1+Z7k9VbVtrJ++92HeKXPMadhB85e1mCGn92vL0wEKttnUnwyNGaFb02HxNLaIkSt+ae0a4SJIodS8HqCsMDxW0aU9SLKbQw5hZcsu9gijcNdsQk9u9ZtvlE843MOzDvSoO55WBjwoz5SyK0uJwrbxSTOOX/p3LjMI2Fv0q/toBi8JXt3Fe8SKK81o0iOucXsk5xaJwTvEiCtPUwiZNhZ6iWb+fokspcQr1PuFsbHZpVniqy5pe8eXrDoTEyW6bK+ZEyznFsHUatp67/PLAKTRBaz9hwHnHkrO0m5fQBXBVG/vUZpdcovp2ykvolOPPj17wVSsSM51KzE7Pc8eCmUFK0iC4/NqjZvD/Z1LaKBAve7BLqMxPCVvN1atkPe8bATB21jpC0xdT1EUGcn3CliDWJcols344pOI9ECBODsobCSH0EQgx0UqiZjHC6zodemC/E1pX5yOZ2ILXnsbT+6GNPHUuF9eWStBQf5R/swrOGaN6uOI8QK1XhO18uKS0dMq0dDJ6x04u/7x9P971OV/Bx65CjlpJAAAAAElFTkSuQmCC';