Skip to content

Commit 7fa943c

Browse files
committed
feat(ups): enhance UPS configuration with new enums and detailed input types; update resolver and service to utilize new structure
1 parent 4a0959b commit 7fa943c

File tree

5 files changed

+279
-50
lines changed

5 files changed

+279
-50
lines changed

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
"Bash(pnpm --filter @unraid/api test src/unraid-api/graph/resolvers/ups)",
3939
"Bash(pnpm --filter @unraid/api lint)",
4040
"Bash(pnpm --filter ./api test)",
41-
"Bash(pnpm --filter @unraid/api test)"
41+
"Bash(pnpm --filter @unraid/api test)",
42+
"Bash(pnpm --filter @unraid/api type-check)"
4243
]
4344
},
4445
"enableAllProjectMcpServers": false
Lines changed: 115 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,134 @@
1-
import { Field, InputType, Int } from '@nestjs/graphql';
1+
import { Field, InputType, Int, registerEnumType } from '@nestjs/graphql';
2+
3+
/**
4+
* Service state for UPS daemon
5+
*/
6+
export enum UPSServiceState {
7+
ENABLE = 'enable',
8+
DISABLE = 'disable',
9+
}
10+
11+
/**
12+
* UPS cable types
13+
*/
14+
export enum UPSCableType {
15+
USB = 'usb',
16+
SIMPLE = 'simple',
17+
SMART = 'smart',
18+
ETHER = 'ether',
19+
CUSTOM = 'custom',
20+
}
21+
22+
/**
23+
* UPS communication types
24+
*/
25+
export enum UPSType {
26+
USB = 'usb',
27+
APCSMART = 'apcsmart',
28+
NET = 'net',
29+
SNMP = 'snmp',
30+
DUMB = 'dumb',
31+
PCNET = 'pcnet',
32+
MODBUS = 'modbus',
33+
}
34+
35+
/**
36+
* Kill UPS power after shutdown option
37+
*/
38+
export enum UPSKillPower {
39+
YES = 'yes',
40+
NO = 'no',
41+
}
42+
43+
// Register enums with GraphQL
44+
registerEnumType(UPSServiceState, {
45+
name: 'UPSServiceState',
46+
description: 'Service state for UPS daemon',
47+
});
48+
49+
registerEnumType(UPSCableType, {
50+
name: 'UPSCableType',
51+
description: 'UPS cable connection types',
52+
});
53+
54+
registerEnumType(UPSType, {
55+
name: 'UPSType',
56+
description: 'UPS communication protocols',
57+
});
58+
59+
registerEnumType(UPSKillPower, {
60+
name: 'UPSKillPower',
61+
description: 'Kill UPS power after shutdown option',
62+
});
263

364
@InputType()
465
export class UPSConfigInput {
5-
@Field()
6-
SERVICE!: string;
66+
/**
67+
* Enable or disable the UPS monitoring service
68+
*/
69+
@Field(() => UPSServiceState)
70+
service!: UPSServiceState;
771

8-
@Field()
9-
UPSCABLE!: string;
72+
/**
73+
* Type of cable connecting the UPS to the server
74+
*/
75+
@Field(() => UPSCableType)
76+
upsCable!: UPSCableType;
1077

78+
/**
79+
* Custom cable configuration (only used when upsCable is CUSTOM)
80+
* Format depends on specific UPS model
81+
*/
1182
@Field({ nullable: true })
12-
CUSTOMUPSCABLE?: string;
83+
customUpsCable?: string;
1384

14-
@Field()
15-
UPSTYPE!: string;
85+
/**
86+
* UPS communication protocol
87+
*/
88+
@Field(() => UPSType)
89+
upsType!: UPSType;
1690

91+
/**
92+
* Device path or network address for UPS connection
93+
* Examples: '/dev/ttyUSB0' for USB, '192.168.1.100:3551' for network
94+
*/
1795
@Field({ nullable: true })
18-
DEVICE?: string;
96+
device?: string;
1997

98+
/**
99+
* Override UPS capacity for runtime calculations
100+
* Unit: watts (W)
101+
* Leave unset to use UPS-reported capacity
102+
*/
20103
@Field(() => Int, { nullable: true })
21-
OVERRIDE_UPS_CAPACITY?: number;
104+
overrideUpsCapacity?: number;
22105

106+
/**
107+
* Battery level percentage to initiate shutdown
108+
* Unit: percent (%) - Valid range: 0-100
109+
*/
23110
@Field(() => Int)
24-
BATTERYLEVEL!: number;
111+
batteryLevel!: number;
25112

113+
/**
114+
* Runtime left in minutes to initiate shutdown
115+
* Unit: minutes
116+
*/
26117
@Field(() => Int)
27-
MINUTES!: number;
118+
minutes!: number;
28119

120+
/**
121+
* Time on battery before shutdown
122+
* Unit: seconds
123+
* Set to 0 to disable timeout-based shutdown
124+
*/
29125
@Field(() => Int)
30-
TIMEOUT!: number;
126+
timeout!: number;
31127

32-
@Field()
33-
KILLUPS!: string;
128+
/**
129+
* Turn off UPS power after system shutdown
130+
* Useful for ensuring complete power cycle
131+
*/
132+
@Field(() => UPSKillPower)
133+
killUps!: UPSKillPower;
34134
}

api/src/unraid-api/graph/resolvers/ups/ups.model.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,90 +2,219 @@ import { Field, Float, ID, Int, ObjectType } from '@nestjs/graphql';
22

33
@ObjectType()
44
export class UPSBattery {
5+
/**
6+
* Battery charge level as a percentage (0-100)
7+
* Unit: percent (%)
8+
* Example: 100 means battery is fully charged
9+
*/
510
@Field(() => Int)
611
chargeLevel!: number;
712

13+
/**
14+
* Estimated runtime remaining on battery power
15+
* Unit: seconds
16+
* Example: 3600 means 1 hour of runtime remaining
17+
*/
818
@Field(() => Int)
919
estimatedRuntime!: number;
1020

21+
/**
22+
* Battery health status
23+
* Possible values: 'Good', 'Replace', 'Unknown'
24+
* Indicates if the battery needs replacement
25+
*/
1126
@Field()
1227
health!: string;
1328
}
1429

1530
@ObjectType()
1631
export class UPSPower {
32+
/**
33+
* Input voltage from the wall outlet/mains power
34+
* Unit: volts (V)
35+
* Example: 120.5 for typical US household voltage
36+
*/
1737
@Field(() => Float)
1838
inputVoltage!: number;
1939

40+
/**
41+
* Output voltage being delivered to connected devices
42+
* Unit: volts (V)
43+
* Example: 120.5 - should match input voltage when on mains power
44+
*/
2045
@Field(() => Float)
2146
outputVoltage!: number;
2247

48+
/**
49+
* Current load on the UPS as a percentage of its capacity
50+
* Unit: percent (%)
51+
* Example: 25 means UPS is loaded at 25% of its maximum capacity
52+
*/
2353
@Field(() => Int)
2454
loadPercentage!: number;
2555
}
2656

2757
@ObjectType()
2858
export class UPSDevice {
59+
/**
60+
* Unique identifier for the UPS device
61+
* Usually based on the model name or a generated ID
62+
*/
2963
@Field(() => ID)
3064
id!: string;
3165

66+
/**
67+
* Display name for the UPS device
68+
* Can be customized by the user
69+
*/
3270
@Field()
3371
name!: string;
3472

73+
/**
74+
* UPS model name/number
75+
* Example: 'APC Back-UPS Pro 1500'
76+
*/
3577
@Field()
3678
model!: string;
3779

80+
/**
81+
* Current operational status of the UPS
82+
* Common values: 'Online', 'On Battery', 'Low Battery', 'Replace Battery', 'Overload', 'Offline'
83+
* 'Online' means running on mains power
84+
* 'On Battery' means running on battery backup
85+
*/
3886
@Field()
3987
status!: string;
4088

89+
/**
90+
* Battery-related information
91+
*/
4192
@Field(() => UPSBattery)
4293
battery!: UPSBattery;
4394

95+
/**
96+
* Power-related information
97+
*/
4498
@Field(() => UPSPower)
4599
power!: UPSPower;
46100
}
47101

48102
@ObjectType()
49103
export class UPSConfiguration {
104+
/**
105+
* UPS service state
106+
* Values: 'enable' or 'disable'
107+
* Controls whether the UPS monitoring service is running
108+
*/
50109
@Field({ nullable: true })
51110
service?: string;
52111

112+
/**
113+
* Type of cable connecting the UPS to the server
114+
* Common values: 'usb', 'smart', 'ether', 'custom'
115+
* Determines communication protocol
116+
*/
53117
@Field({ nullable: true })
54118
upsCable?: string;
55119

120+
/**
121+
* Custom cable configuration string
122+
* Only used when upsCable is set to 'custom'
123+
* Format depends on specific UPS model
124+
*/
56125
@Field({ nullable: true })
57126
customUpsCable?: string;
58127

128+
/**
129+
* UPS communication type
130+
* Common values: 'usb', 'net', 'snmp', 'dumb', 'pcnet', 'modbus'
131+
* Defines how the server communicates with the UPS
132+
*/
59133
@Field({ nullable: true })
60134
upsType?: string;
61135

136+
/**
137+
* Device path or network address for UPS connection
138+
* Examples: '/dev/ttyUSB0' for USB, '192.168.1.100:3551' for network
139+
* Depends on upsType setting
140+
*/
62141
@Field({ nullable: true })
63142
device?: string;
64143

144+
/**
145+
* Override UPS capacity for runtime calculations
146+
* Unit: volt-amperes (VA)
147+
* Example: 1500 for a 1500VA UPS
148+
* Leave unset to use UPS-reported capacity
149+
*/
65150
@Field(() => Int, { nullable: true })
66151
overrideUpsCapacity?: number;
67152

153+
/**
154+
* Battery level threshold for shutdown
155+
* Unit: percent (%)
156+
* Example: 10 means shutdown when battery reaches 10%
157+
* System will shutdown when battery drops to this level
158+
*/
68159
@Field(() => Int, { nullable: true })
69160
batteryLevel?: number;
70161

162+
/**
163+
* Runtime threshold for shutdown
164+
* Unit: minutes
165+
* Example: 5 means shutdown when 5 minutes runtime remaining
166+
* System will shutdown when estimated runtime drops below this
167+
*/
71168
@Field(() => Int, { nullable: true })
72169
minutes?: number;
73170

171+
/**
172+
* Timeout for UPS communications
173+
* Unit: seconds
174+
* Example: 0 means no timeout
175+
* Time to wait for UPS response before considering it offline
176+
*/
74177
@Field(() => Int, { nullable: true })
75178
timeout?: number;
76179

180+
/**
181+
* Kill UPS power after shutdown
182+
* Values: 'yes' or 'no'
183+
* If 'yes', tells UPS to cut power after system shutdown
184+
* Useful for ensuring complete power cycle
185+
*/
77186
@Field({ nullable: true })
78187
killUps?: string;
79188

189+
/**
190+
* Network Information Server (NIS) IP address
191+
* Default: '0.0.0.0' (listen on all interfaces)
192+
* IP address for apcupsd network information server
193+
*/
80194
@Field({ nullable: true })
81195
nisIp?: string;
82196

197+
/**
198+
* Network server mode
199+
* Values: 'on' or 'off'
200+
* Enable to allow network clients to monitor this UPS
201+
*/
83202
@Field({ nullable: true })
84203
netServer?: string;
85204

205+
/**
206+
* UPS name for network monitoring
207+
* Used to identify this UPS on the network
208+
* Example: 'SERVER_UPS'
209+
*/
86210
@Field({ nullable: true })
87211
upsName?: string;
88212

213+
/**
214+
* Override UPS model name
215+
* Used for display purposes
216+
* Leave unset to use UPS-reported model
217+
*/
89218
@Field({ nullable: true })
90219
modelName?: string;
91220
}

0 commit comments

Comments
 (0)