Skip to content

Commit daff8ff

Browse files
committed
features/command
1 parent c9a55e5 commit daff8ff

File tree

6 files changed

+220
-16
lines changed

6 files changed

+220
-16
lines changed
Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
1-
import { UseGuards } from '@nestjs/common';
1+
import { UseGuards } from "@nestjs/common";
22
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
3-
import { CommandResponse } from './dto/command.dto';
4-
import { JwtAuthGuard } from '../../guards/auth/auth.guard';
5-
import { CommandService } from './command.service';
3+
import { CommandResponse, CommandResponseList } from "./entities/command.entity";
4+
import { JwtAuthGuard } from "../../guards/auth/auth.guard";
5+
import { CommandService } from "./command.service";
6+
import { CreateCommandInput } from "./dto/command.input";
7+
import { CommandAnalyzeOutput } from "./dto/commandAnalyze.output";
68

79
@Resolver()
810
export class CommandResolver {
911
constructor(private readonly commandService: CommandService) {}
1012

11-
@Query(() => CommandResponse)
13+
@Query(() => CommandResponseList)
1214
@UseGuards(JwtAuthGuard)
13-
async command(@Args("userID") userID: number) {
14-
return this.commandService.command(userID);
15+
async commands_by_user(@Args("userID") userID: number) {
16+
return this.commandService.commandsByUser(userID);
1517
}
1618

19+
@Query(() => CommandResponseList)
20+
@UseGuards(JwtAuthGuard)
21+
async commands_by_device(@Args("deviceID") deviceID: number) {
22+
return this.commandService.commandsByDevice(deviceID);
23+
}
24+
25+
@Query(() => CommandAnalyzeOutput)
26+
async analyze_commands_by_device(@Args("deviceID") deviceID: number) {
27+
return this.commandService.analyzeCommandsByDevice(deviceID);
28+
}
29+
30+
@Mutation(() => CommandResponse)
31+
@UseGuards(JwtAuthGuard)
32+
async create_command(@Args("input") input: CreateCommandInput) {
33+
return this.commandService.createCommand(input);
34+
}
1735
}
Lines changed: 126 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,133 @@
1-
import { Injectable } from '@nestjs/common';
2-
import { PrismaService } from '../prisma/prisma.service';
1+
import { Injectable } from "@nestjs/common";
2+
import { PrismaService } from "../prisma/prisma.service";
3+
import { CreateCommandInput } from "./dto/command.input";
4+
import { CommandResponse } from "./entities/command.entity";
5+
import { Time } from "./dto/commandAnalyze.output";
36

47
@Injectable()
58
export class CommandService {
69
constructor(private readonly prisma: PrismaService) {}
710

8-
async command(userID: number) {
9-
return this.prisma.command.findFirst({
10-
where: { userID: userID },
11-
orderBy: { created_at: "desc" }
12-
});
11+
async commandsByUser(userID: number) {
12+
try {
13+
const list_commands = await this.prisma.command.findMany({
14+
where: { userID: userID },
15+
orderBy: { created_at: "desc" },
16+
});
17+
if (list_commands.length === 0) {
18+
return { commands: [] };
19+
}
20+
return { commands: list_commands };
21+
} catch (error) {
22+
throw error;
23+
}
24+
}
25+
26+
async commandsByDevice(deviceID: number) {
27+
try {
28+
const list_commands = await this.prisma.command.findMany({
29+
where: {
30+
deviceID: deviceID,
31+
},
32+
orderBy: { created_at: "desc" },
33+
});
34+
if (list_commands.length === 0) {
35+
return { commands: [] };
36+
}
37+
return { commands: list_commands };
38+
} catch (error) {
39+
throw error;
40+
}
41+
}
42+
43+
calculateActiveHours(commands: CommandResponse[], days: string[]) {
44+
var activeHours: Time[] = [{ hours: 0, minutes: 0, seconds: 0 }];
45+
for (var i = 0; i < commands.length - 1; i++) {
46+
const dateOne = commands[i].created_at.toISOString().split("T")[0];
47+
const dateTwo = commands[i + 1].created_at.toISOString().split("T")[0];
48+
if (commands[i].command === "ON" && commands[i + 1].command === "OFF" && dateOne === dateTwo) {
49+
var diff = Math.abs(Number(commands[i].created_at) - Number(commands[i + 1].created_at));
50+
console.log("Diff:", diff);
51+
const hour = Math.floor(diff / (1000 * 60 * 60));
52+
diff = diff % (1000 * 60 * 60);
53+
const minute = Math.floor(diff / (1000 * 60));
54+
diff = diff % (1000 * 60);
55+
const second = Math.floor(diff / 1000);
56+
days.forEach((day, index) => {
57+
if (day === dateOne) {
58+
activeHours[index].hours += hour;
59+
activeHours[index].minutes += minute;
60+
activeHours[index].seconds += second;
61+
}
62+
});
63+
}
64+
}
65+
console.log("Active hours:", activeHours);
66+
if (commands[commands.length - 1].command === "ON" && days[days.length - 1] === commands[commands.length - 1].created_at.toISOString().split("T")[0]) {
67+
const date = new Date(commands[commands.length - 1].created_at);
68+
const currentDate = new Date();
69+
const diff = Math.abs(currentDate.getTime() - date.getTime());
70+
const hours = Math.floor(diff / (1000 * 60 * 60));
71+
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
72+
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
73+
activeHours[days.length - 1].hours += hours;
74+
activeHours[days.length - 1].minutes += minutes;
75+
activeHours[days.length - 1].seconds += seconds;
76+
}
77+
console.log("Active hours:", activeHours);
78+
return activeHours;
79+
}
80+
81+
async analyzeCommandsByDevice(deviceID: number) {
82+
try {
83+
const list_commands = await this.prisma.command.findMany({
84+
where: {
85+
deviceID: deviceID,
86+
},
87+
orderBy: { created_at: "asc" },
88+
});
89+
if (list_commands.length === 0) {
90+
return { commands: [] };
91+
}
92+
const days: string[] = [];
93+
list_commands.forEach((command, index) => {
94+
const date = new Date(command.created_at);
95+
const month = date.getMonth() + 1;
96+
const dayx = date.getDate();
97+
const hours = date.getHours();
98+
const minutes = date.getMinutes();
99+
console.log(`${index} - Date: ${month}/${dayx} Time: ${hours}:${minutes} - ${command.command}`);
100+
const day = command.created_at.toISOString().split("T")[0];
101+
if (!days.includes(day)) {
102+
days.push(day);
103+
}
104+
});
105+
const activeHours = this.calculateActiveHours(list_commands, days);
106+
console.log(days);
107+
return { days: days, hoursPerDay: activeHours };
108+
} catch (error) {
109+
throw error;
110+
}
111+
}
112+
113+
async createCommand(input: CreateCommandInput) {
114+
try {
115+
const data = await this.prisma.command.create({
116+
data: {
117+
deviceID: input.deviceID,
118+
command: input.command,
119+
sender: input.sender,
120+
receiver: input.receiver,
121+
userID: input.userID,
122+
created_at: input.created_at,
123+
},
124+
});
125+
if (data) {
126+
return data;
127+
}
128+
throw new Error("Failed to create command");
129+
} catch (error) {
130+
throw error;
131+
}
13132
}
14133
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Field, InputType } from "@nestjs/graphql";
2+
import { IsDate, IsNumber, IsString } from "class-validator";
3+
4+
@InputType()
5+
export class CreateCommandInput {
6+
@Field(() => Number, { nullable: false })
7+
@IsNumber()
8+
deviceID: number;
9+
10+
@Field(() => String, { nullable: false })
11+
@IsString()
12+
command: string;
13+
14+
@Field(() => String, { nullable: true })
15+
@IsString()
16+
sender: string;
17+
18+
@Field(() => String, { nullable: true })
19+
@IsString()
20+
receiver: string;
21+
22+
@Field(() => Number, { nullable: false })
23+
@IsNumber()
24+
userID: number;
25+
26+
@Field(() => Date, { nullable: false })
27+
@IsDate()
28+
created_at: Date;
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Field, ObjectType } from "@nestjs/graphql";
2+
3+
@ObjectType()
4+
export class Time {
5+
@Field()
6+
hours: number;
7+
8+
@Field()
9+
minutes: number;
10+
11+
@Field()
12+
seconds: number;
13+
}
14+
@ObjectType()
15+
export class CommandAnalyzeOutput {
16+
@Field(() => [String], { nullable: false })
17+
days: String[];
18+
19+
@Field(() => [Time], { nullable: false })
20+
hoursPerDay: Time[];
21+
}

src/modules/command/dto/command.dto.ts renamed to src/modules/command/entities/command.entity.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,11 @@ export class CommandResponse {
3030
@Field(() => Date, { nullable: false })
3131
@IsDate()
3232
created_at: Date;
33+
}
34+
35+
@ObjectType()
36+
export class CommandResponseList {
37+
@Field(() => [CommandResponse], { nullable: false })
38+
@IsNumber()
39+
commands: CommandResponse[];
3340
}

src/modules/device/device.service.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,23 @@ export class DeviceService {
9696

9797
async update(input: UpdateItemInput) {
9898
try {
99-
const data = await this.prisma.device.update({
99+
console.log('update device', input);
100+
const updated_device = await this.prisma.device.update({
100101
where: { id: input.id },
101102
data: {
102103
current_state: input.current_state,
103104
},
104105
});
105-
return data;
106+
await this.prisma.command.create({
107+
data: {
108+
deviceID: input.id,
109+
command: input.current_state == 0 ? "OFF" : "ON",
110+
sender: "device",
111+
receiver: "server",
112+
userID: updated_device.userID,
113+
},
114+
});
115+
return updated_device;
106116
} catch (err) {
107117
throw new GraphQLError(err);
108118
}

0 commit comments

Comments
 (0)