Skip to content

Commit 0489a3f

Browse files
authored
Merge pull request #1436 from rit-construct-makerspace/cowsed/hobbs_counting
Hobbs Time counting
2 parents d448993 + c914562 commit 0489a3f

14 files changed

Lines changed: 344 additions & 51 deletions

File tree

client/src/pages/makerspace_page/equipment_pages/EquipmentInstanceCard.tsx

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Autocomplete, Button, Card, Chip, IconButton, Link, MenuItem, Select, Stack, TextField, Typography } from "@mui/material";
2-
import { DELETE_EQUIPMENT_INSTANCE, EquipmentInstance, InstanceStatus, UPDATE_INSTANCE, UPDATE_INSTANCE_CONTROLLER_ASSIGNMENT } from "../../../queries/equipmentInstanceQueries";
2+
import { DELETE_EQUIPMENT_INSTANCE, EquipmentInstance, InstanceStatus, UPDATE_INSTANCE, UPDATE_INSTANCE_CONTROLLER_ASSIGNMENT, UPDATE_INSTANCE_HOBBS_TIME } from "../../../queries/equipmentInstanceQueries";
33
import ActionButton from "../../../common/ActionButton";
44
import DriveFileRenameOutlineIcon from '@mui/icons-material/DriveFileRenameOutline';
55
import { useMutation, useQuery } from "@apollo/client/react";
@@ -30,6 +30,11 @@ export default function EquipmentInstanceCard(props: EquipmentInstanceCardProps)
3030
awaitRefetchQueries: true
3131
});
3232

33+
const [updateInstanceHobbsTime] = useMutation(UPDATE_INSTANCE_HOBBS_TIME, {
34+
refetchQueries: ["EquipmentInstances", "GetUnpairedAccessControllers"],
35+
awaitRefetchQueries: true
36+
});
37+
3338
const [updatePairing] = useMutation(UPDATE_INSTANCE_CONTROLLER_ASSIGNMENT, {
3439
refetchQueries: ["EquipmentInstances", "GetUnpairedAccessControllers"],
3540
awaitRefetchQueries: true
@@ -48,9 +53,11 @@ export default function EquipmentInstanceCard(props: EquipmentInstanceCardProps)
4853
const [sendCommandedState] = useMutation(COMMAND_CONTROLLER_STATE);
4954
const [commandedState, setCommandedState] = useState<string>("IDLE");
5055

56+
const [hobbsTime, setHobbsTime] = useState(props.instance.hobbsTime);
5157

5258
async function handleSave() {
5359
setAllowEdit(false);
60+
await updateInstanceHobbsTime({ variables: { id: props.instance.id, hobbsTime: hobbsTime } })
5461
await updateInstance({ variables: { id: props.instance.id, name: name, status: status } })
5562
await updatePairing({ variables: { id: Number(props.instance.id), accessControllerID: pairedController?.id } })
5663
}
@@ -93,6 +100,20 @@ export default function EquipmentInstanceCard(props: EquipmentInstanceCardProps)
93100
/>;
94101
}
95102

103+
function formatSeconds(allSeconds: number){
104+
const hours = Math.floor(allSeconds / 3600);
105+
if (hours > 0){
106+
return (allSeconds / 3600).toFixed(2) + " hrs"
107+
}
108+
const minutes = Math.floor((allSeconds % 3600) / 60);
109+
const seconds = allSeconds % 60;
110+
if (minutes > 0){
111+
return (minutes + seconds / 50).toFixed(2) + " min"
112+
} else {
113+
return Math.floor(allSeconds) + "sec"
114+
}
115+
}
116+
96117
function activeUserDisplay() {
97118
if (!currentAccessController) {
98119
return <Typography>No User</Typography>;
@@ -109,6 +130,15 @@ export default function EquipmentInstanceCard(props: EquipmentInstanceCardProps)
109130
<AuditLogEntity entityCode={`user:${currentAccessController.core?.activeUser.id}:${currentAccessController.core?.activeUser?.firstName} ${currentAccessController.core?.activeUser?.lastName}`} />
110131
</Stack>
111132
}
133+
function hobbsTimeSetField(){
134+
return <TextField label="Hobbs (s)"
135+
required
136+
fullWidth
137+
value={hobbsTime}
138+
onChange={(e) => setHobbsTime(Math.abs(Number(e.target.value)))}
139+
>
140+
</TextField>
141+
}
112142

113143
return (
114144
<Card sx={{ padding: "15px" }} >
@@ -131,6 +161,16 @@ export default function EquipmentInstanceCard(props: EquipmentInstanceCardProps)
131161
</>
132162
}
133163
</Stack>
164+
165+
<Stack alignItems={"center"} justifyContent={"space-between"}>
166+
{
167+
!allowEdit
168+
? formatSeconds(props.instance.hobbsTime)
169+
: hobbsTimeSetField()
170+
}
171+
</Stack>
172+
173+
134174
<Stack alignItems={"center"} spacing={1}>
135175
{
136176
!allowEdit

client/src/pages/makerspace_page/equipment_pages/EquipmentInstanceRow.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Autocomplete, Button, Card, Chip, IconButton, Link, MenuItem, Select, Stack, TextField, Typography } from "@mui/material";
2-
import { DELETE_EQUIPMENT_INSTANCE, EquipmentInstance, InstanceStatus, UPDATE_INSTANCE, UPDATE_INSTANCE_CONTROLLER_ASSIGNMENT } from "../../../queries/equipmentInstanceQueries";
2+
import { DELETE_EQUIPMENT_INSTANCE, EquipmentInstance, InstanceStatus, UPDATE_INSTANCE, UPDATE_INSTANCE_CONTROLLER_ASSIGNMENT, UPDATE_INSTANCE_HOBBS_TIME } from "../../../queries/equipmentInstanceQueries";
33
import DriveFileRenameOutlineIcon from '@mui/icons-material/DriveFileRenameOutline';
44
import { useMutation, useQuery } from "@apollo/client/react";
55
import { useState } from "react";
@@ -29,6 +29,11 @@ export default function EquipmentInstanceRow(props: EquipmentInstanceRowProps) {
2929
awaitRefetchQueries: true
3030
});
3131

32+
const [updateInstanceHobbsTime] = useMutation(UPDATE_INSTANCE_HOBBS_TIME, {
33+
refetchQueries: ["EquipmentInstances", "GetUnpairedAccessControllers"],
34+
awaitRefetchQueries: true
35+
});
36+
3237
const [updatePairing] = useMutation(UPDATE_INSTANCE_CONTROLLER_ASSIGNMENT, {
3338
refetchQueries: ["EquipmentInstances", "GetUnpairedAccessControllers"],
3439
awaitRefetchQueries: true
@@ -47,9 +52,12 @@ export default function EquipmentInstanceRow(props: EquipmentInstanceRowProps) {
4752
const [sendCommandedState] = useMutation(COMMAND_CONTROLLER_STATE);
4853
const [commandedState, setCommandedState] = useState<string>("IDLE");
4954

55+
const [hobbsTime, setHobbsTime] = useState(props.instance.hobbsTime);
56+
5057

5158
async function handleSave() {
5259
setAllowEdit(false);
60+
await updateInstanceHobbsTime({ variables: { id: props.instance.id, hobbsTime: hobbsTime } })
5361
await updateInstance({ variables: { id: props.instance.id, name: name, status: status } })
5462
await updatePairing({ variables: { id: Number(props.instance.id), accessControllerID: pairedController?.id } })
5563
}
@@ -91,6 +99,20 @@ export default function EquipmentInstanceRow(props: EquipmentInstanceRowProps) {
9199
/>;
92100
}
93101

102+
function formatSeconds(allSeconds: number){
103+
const hours = Math.floor(allSeconds / 3600);
104+
if (hours > 0){
105+
return (allSeconds / 3600).toFixed(2) + " hrs"
106+
}
107+
const minutes = Math.floor((allSeconds % 3600) / 60);
108+
const seconds = allSeconds % 60;
109+
if (minutes > 0){
110+
return (minutes + seconds / 50).toFixed(2) + " min"
111+
} else {
112+
return Math.floor(allSeconds) + "sec"
113+
}
114+
}
115+
94116
function activeUserDisplay() {
95117
if (!currentAccessController) {
96118
return <Typography>No User</Typography>;
@@ -108,6 +130,15 @@ export default function EquipmentInstanceRow(props: EquipmentInstanceRowProps) {
108130
</Stack>
109131
}
110132

133+
function hobbsTimeSetField(){
134+
return <TextField label="Hobbs (s)"
135+
required
136+
value={hobbsTime}
137+
onChange={(e) => setHobbsTime(Math.abs(Number(e.target.value)))}
138+
>
139+
</TextField>
140+
}
141+
111142
return (
112143
<Card sx={{ padding: "15px" }} >
113144
<Stack spacing={1} direction={"row"} width={"100%"} height={"60px"} alignItems={"center"}>
@@ -127,6 +158,16 @@ export default function EquipmentInstanceRow(props: EquipmentInstanceRowProps) {
127158
: controllerPairingField()
128159
}
129160
</Stack>
161+
162+
<Stack alignItems={"center"} direction={"row"} width={"200px"}>
163+
{
164+
!allowEdit
165+
? formatSeconds(props.instance.hobbsTime)
166+
: hobbsTimeSetField()
167+
}
168+
</Stack>
169+
170+
130171
<Stack direction={"row"} alignItems={"center"} width={"300px"}>
131172
{activeUserDisplay()}
132173
</Stack>

client/src/queries/equipmentInstanceQueries.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export interface EquipmentInstance {
2020
name: string;
2121
status: InstanceStatus;
2222
accessController: AccessController | undefined;
23+
hobbsTime: number
2324
}
2425

2526
export const GET_EQUIPMENT_INSTANCES = gql`
@@ -32,6 +33,7 @@ export const GET_EQUIPMENT_INSTANCES = gql`
3233
}
3334
name
3435
status
36+
hobbsTime
3537
accessController {
3638
id
3739
channelID
@@ -63,6 +65,7 @@ export const GET_EQUIPMENT_INSTANCE_BY_ID = gql`
6365
}
6466
name
6567
status
68+
hobbsTime
6669
reader {
6770
id
6871
name
@@ -106,6 +109,22 @@ export const UPDATE_INSTANCE = gql`
106109
}
107110
name
108111
status
112+
hobbsTime
113+
}
114+
}
115+
`;
116+
117+
export const UPDATE_INSTANCE_HOBBS_TIME = gql`
118+
mutation UpdateInstanceHobbsTime($id: ID!, $hobbsTime: Int!) {
119+
updateInstanceHobbsTime(id: $id, hobbsTime: $hobbsTime) {
120+
id
121+
equipment {
122+
id
123+
name
124+
}
125+
name
126+
status
127+
hobbsTime
109128
}
110129
}
111130
`;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { Knex } from "knex";
2+
3+
4+
export async function up(knex: Knex): Promise<void> {
5+
knex.schema.hasTable("EquipmentInstances").then(function (exists) {
6+
if (!exists) return;
7+
8+
return knex.schema.alterTable("EquipmentInstances", function (t) {
9+
t.integer("hobbsTime").defaultTo(0);
10+
});
11+
});
12+
13+
}
14+
15+
16+
export async function down(knex: Knex): Promise<void> {
17+
knex.schema.hasTable("EquipmentInstances").then(function (exists) {
18+
if (!exists) return;
19+
20+
return knex.schema.alterTable("EquipmentInstances", function (t) {
21+
t.dropColumn("hobbsTime");
22+
});
23+
});
24+
25+
}
26+

server/src/database/knex/tables.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ export interface EquipmentInstancesRow {
8181
/** The state of the equipment, ACTIVE,RETIRED,NEEDS_REPAIRED, etc. */
8282
status: string;
8383
/** Optional FK of the card reader associated with this instance */
84-
accessControllerID: number | null
84+
accessControllerID: number | null;
85+
/** Required number of seconds that this equipment has been run for */
86+
hobbsTime: number;
8587
}
8688

8789
export interface HoldRow {
@@ -700,6 +702,7 @@ export interface CoreRow {
700702
flags: CoreFlags;
701703
sealedDeployment: ACSDeployment | undefined;
702704
reportedDeployment: ACSDeployment | undefined;
705+
hobbsTime: number
703706
}
704707

705708
export enum AccessControllerState {

server/src/database/models/api/ACSFormats.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { ACSDeployment } from "../ACS/deployment.js";
44
export interface CoreStatusReport {
55
channels: {
66
channelID: number,
7-
state: AccessControllerState
7+
state: AccessControllerState,
8+
hobbsTime: number,
89
}[];
910
currentCardTag: string;
1011
}
@@ -66,7 +67,8 @@ export enum CoreInfoOptions {
6667
TIME = "TIME",
6768
STATE = "STATE",
6869
HMI = "HMI",
69-
FLAGS = "FLAGS"
70+
FLAGS = "FLAGS",
71+
HOBBS_TIME = "HOBBS_TIME"
7072
}
7173

7274
export interface CoreInfoRequest {
@@ -125,6 +127,7 @@ export interface ServerCommand {
125127
action?: CoreActions;
126128
identifyChannel?: number;
127129
flags?: CoreFlags;
130+
hobbsTime?: {channelID: number, hobbsTime: number}[]
128131
}
129132

130133
export enum CoreRole {
@@ -144,13 +147,18 @@ export interface ServerInfoResponse {
144147
}[];
145148
hmi?: {
146149
role: CoreRole;
150+
deviceName: string,
147151
makerspace: string;
148152
channels: {
149153
channelID: number;
150154
pairedEntity: string;
151155
}[];
152156
};
153-
flags?: CoreFlags
157+
flags?: CoreFlags;
158+
hobbsTime?: {
159+
channelID: number;
160+
hobbsTime: number;
161+
}[]
154162
}
155163

156164
export interface WelcomeRequest {

0 commit comments

Comments
 (0)