@felixgeelhaar/govee-api-client 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,425 @@
1
+ # Govee API Client - LLM Reference
2
+
3
+ ## Overview
4
+
5
+ The Govee API Client is an enterprise-grade TypeScript library for controlling Govee smart devices. It follows Domain-Driven Design (DDD) principles with comprehensive error handling, rate limiting, and retry capabilities.
6
+
7
+ **Package**: `@felixgeelhaar/govee-api-client`
8
+ **Version**: 2.0.0
9
+ **License**: MIT
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { GoveeClient, ColorRgb, Brightness } from '@felixgeelhaar/govee-api-client';
15
+
16
+ const client = new GoveeClient({ apiKey: 'your-api-key' });
17
+ const devices = await client.getDevices();
18
+ await client.setColor(deviceId, model, new ColorRgb(255, 0, 0));
19
+ ```
20
+
21
+ ## Core Classes
22
+
23
+ ### GoveeClient
24
+
25
+ Main entry point for the library.
26
+
27
+ ```typescript
28
+ class GoveeClient {
29
+ constructor(config: GoveeClientConfig);
30
+
31
+ // Device Management
32
+ getDevices(): Promise<GoveeDevice[]>;
33
+ getDeviceState(deviceId: string, model: string): Promise<DeviceState>;
34
+ getControllableDevices(): Promise<GoveeDevice[]>;
35
+ getRetrievableDevices(): Promise<GoveeDevice[]>;
36
+ findDeviceByName(deviceName: string): Promise<GoveeDevice | undefined>;
37
+ findDevicesByModel(model: string): Promise<GoveeDevice[]>;
38
+
39
+ // Device Control
40
+ sendCommand(deviceId: string, model: string, command: Command): Promise<void>;
41
+ turnOn(deviceId: string, model: string): Promise<void>;
42
+ turnOff(deviceId: string, model: string): Promise<void>;
43
+ setBrightness(deviceId: string, model: string, brightness: Brightness): Promise<void>;
44
+ setColor(deviceId: string, model: string, color: ColorRgb): Promise<void>;
45
+ setColorTemperature(
46
+ deviceId: string,
47
+ model: string,
48
+ colorTemperature: ColorTemperature
49
+ ): Promise<void>;
50
+
51
+ // Convenience Methods
52
+ turnOnWithBrightness(deviceId: string, model: string, brightness: Brightness): Promise<void>;
53
+ turnOnWithColor(
54
+ deviceId: string,
55
+ model: string,
56
+ color: ColorRgb,
57
+ brightness?: Brightness
58
+ ): Promise<void>;
59
+ turnOnWithColorTemperature(
60
+ deviceId: string,
61
+ model: string,
62
+ colorTemperature: ColorTemperature,
63
+ brightness?: Brightness
64
+ ): Promise<void>;
65
+
66
+ // Status Checks
67
+ isDeviceOnline(deviceId: string, model: string): Promise<boolean>;
68
+ isDevicePoweredOn(deviceId: string, model: string): Promise<boolean>;
69
+
70
+ // Monitoring
71
+ getRateLimiterStats(): RateLimiterStats;
72
+ getRetryMetrics(): RetryMetrics | undefined;
73
+ getServiceStats(): ServiceStats;
74
+ resetRetryMetrics(): void;
75
+ isRetryEnabled(): boolean;
76
+ }
77
+ ```
78
+
79
+ ### Configuration
80
+
81
+ ```typescript
82
+ interface GoveeClientConfig {
83
+ apiKey: string; // Required: Your Govee API key
84
+ timeout?: number; // Optional: Request timeout in ms (default: 30000)
85
+ rateLimit?: number; // Optional: Requests per minute (default: 95)
86
+ logger?: Logger; // Optional: Pino logger instance
87
+ enableRetries?: boolean; // Optional: Enable retry logic (default: false)
88
+ retryPolicy?: 'development' | 'testing' | 'production' | 'custom' | RetryPolicy;
89
+ }
90
+ ```
91
+
92
+ ## Domain Entities
93
+
94
+ ### GoveeDevice
95
+
96
+ Represents a Govee smart device.
97
+
98
+ ```typescript
99
+ class GoveeDevice {
100
+ readonly deviceId: string; // Unique device identifier
101
+ readonly model: string; // Device model/SKU
102
+ readonly sku: string; // Device SKU (same as model)
103
+ readonly deviceName: string; // Human-readable device name
104
+ readonly controllable: boolean; // Can the device be controlled
105
+ readonly retrievable: boolean; // Can device state be retrieved
106
+ readonly supportedCmds: readonly string[]; // Supported command types
107
+ readonly capabilities: readonly GoveeCapability[]; // Device capabilities
108
+
109
+ equals(other: GoveeDevice): boolean;
110
+ supportsCommand(command: string): boolean;
111
+ canControl(): boolean;
112
+ canRetrieve(): boolean;
113
+ toObject(): DeviceObject;
114
+ static fromObject(obj: DeviceObject): GoveeDevice;
115
+ }
116
+ ```
117
+
118
+ ### DeviceState
119
+
120
+ Represents the current state of a device.
121
+
122
+ ```typescript
123
+ class DeviceState {
124
+ readonly deviceId: string;
125
+ readonly model: string;
126
+ readonly properties: readonly StateProperty[];
127
+
128
+ getPowerState(): 'on' | 'off' | undefined;
129
+ getBrightness(): number | undefined; // 0-100
130
+ getColor(): { r: number; g: number; b: number } | undefined;
131
+ getColorTemperature(): number | undefined; // Kelvin
132
+ isOnline(): boolean;
133
+ hasProperty(type: string, instance: string): boolean;
134
+ getProperty(type: string, instance: string): StateProperty | undefined;
135
+ }
136
+ ```
137
+
138
+ ### Command
139
+
140
+ Base class for device commands.
141
+
142
+ ```typescript
143
+ abstract class Command {
144
+ abstract readonly name: string
145
+ abstract readonly value: unknown
146
+ abstract toApiFormat(): { name: string; value: unknown }
147
+ }
148
+
149
+ // Command types:
150
+ class PowerOnCommand extends Command
151
+ class PowerOffCommand extends Command
152
+ class BrightnessCommand extends Command
153
+ class ColorCommand extends Command
154
+ class ColorTemperatureCommand extends Command
155
+
156
+ // Command factory:
157
+ class CommandFactory {
158
+ static powerOn(): PowerOnCommand
159
+ static powerOff(): PowerOffCommand
160
+ static brightness(brightness: Brightness): BrightnessCommand
161
+ static color(color: ColorRgb): ColorCommand
162
+ static colorTemperature(temp: ColorTemperature): ColorTemperatureCommand
163
+ }
164
+ ```
165
+
166
+ ## Value Objects
167
+
168
+ ### ColorRgb
169
+
170
+ Represents RGB color values (0-255 for each component).
171
+
172
+ ```typescript
173
+ class ColorRgb {
174
+ constructor(r: number, g: number, b: number);
175
+
176
+ readonly r: number; // Red component (0-255)
177
+ readonly g: number; // Green component (0-255)
178
+ readonly b: number; // Blue component (0-255)
179
+
180
+ equals(other: ColorRgb): boolean;
181
+ toString(): string; // "rgb(r, g, b)"
182
+ toHex(): string; // "#rrggbb"
183
+ toObject(): { r: number; g: number; b: number };
184
+
185
+ static fromHex(hex: string): ColorRgb;
186
+ static fromObject(obj: { r: number; g: number; b: number }): ColorRgb;
187
+ }
188
+ ```
189
+
190
+ ### ColorTemperature
191
+
192
+ Represents color temperature in Kelvin (2000-9000K).
193
+
194
+ ```typescript
195
+ class ColorTemperature {
196
+ constructor(kelvin: number);
197
+
198
+ readonly kelvin: number; // Temperature in Kelvin (2000-9000)
199
+
200
+ equals(other: ColorTemperature): boolean;
201
+ toString(): string;
202
+ isWarm(): boolean; // < 4000K
203
+ isCool(): boolean; // > 5000K
204
+ toObject(): { kelvin: number };
205
+
206
+ static warmWhite(): ColorTemperature; // 2700K
207
+ static coolWhite(): ColorTemperature; // 6500K
208
+ static daylight(): ColorTemperature; // 5600K
209
+ static fromObject(obj: { kelvin: number }): ColorTemperature;
210
+ }
211
+ ```
212
+
213
+ ### Brightness
214
+
215
+ Represents brightness level (0-100).
216
+
217
+ ```typescript
218
+ class Brightness {
219
+ constructor(level: number);
220
+
221
+ readonly level: number; // Brightness level (0-100)
222
+
223
+ equals(other: Brightness): boolean;
224
+ toString(): string;
225
+ asPercent(): number; // 0.0-1.0
226
+ isDim(): boolean; // < 30
227
+ isBright(): boolean; // > 70
228
+ toObject(): { level: number };
229
+
230
+ static dim(): Brightness; // 25
231
+ static medium(): Brightness; // 50
232
+ static bright(): Brightness; // 75
233
+ static fromObject(obj: { level: number }): Brightness;
234
+ }
235
+ ```
236
+
237
+ ## Error Handling
238
+
239
+ ### Error Hierarchy
240
+
241
+ ```typescript
242
+ // Base error class
243
+ abstract class GoveeApiClientError extends Error {
244
+ abstract readonly errorType: string;
245
+ abstract isRetryable(): boolean;
246
+ }
247
+
248
+ // API-related errors
249
+ class GoveeApiError extends GoveeApiClientError {
250
+ constructor(message: string, statusCode?: number, response?: unknown);
251
+ readonly statusCode?: number;
252
+ readonly response?: unknown;
253
+ isDeviceOffline(): boolean;
254
+ getRecommendation(): string;
255
+ }
256
+
257
+ // Authentication errors
258
+ class InvalidApiKeyError extends GoveeApiClientError {
259
+ getRecommendation(): string;
260
+ }
261
+
262
+ // Rate limiting errors
263
+ class RateLimitError extends GoveeApiClientError {
264
+ constructor(message: string, retryAfterMs?: number);
265
+ readonly retryAfterMs?: number;
266
+ getRetryAfterMs(): number;
267
+ }
268
+
269
+ // Network errors
270
+ class NetworkError extends GoveeApiClientError {
271
+ constructor(message: string, cause?: Error);
272
+ readonly cause?: Error;
273
+ }
274
+
275
+ // Validation errors
276
+ class ValidationError extends GoveeApiClientError {
277
+ constructor(message: string, field?: string, value?: unknown);
278
+ readonly field?: string;
279
+ readonly value?: unknown;
280
+ }
281
+ ```
282
+
283
+ ## Rate Limiting & Retry
284
+
285
+ ### Rate Limiting
286
+
287
+ Built-in sliding window rate limiter (default: 95 requests/minute).
288
+
289
+ ```typescript
290
+ interface RateLimiterStats {
291
+ currentRequests: number;
292
+ maxRequests: number;
293
+ utilizationPercent: number;
294
+ queueSize: number;
295
+ canExecuteImmediately: boolean;
296
+ nextAvailableSlot: Date | null;
297
+ }
298
+ ```
299
+
300
+ ### Retry Logic
301
+
302
+ Configurable retry policies with exponential backoff, jitter, and circuit breaker.
303
+
304
+ ```typescript
305
+ class RetryPolicy {
306
+ constructor(config: RetryPolicyConfig);
307
+ }
308
+
309
+ interface RetryPolicyConfig {
310
+ backoff: BackoffStrategy;
311
+ jitter: JitterConfig;
312
+ condition: RetryCondition;
313
+ circuitBreaker: CircuitBreakerConfig;
314
+ enableMetrics: boolean;
315
+ }
316
+
317
+ // Presets: 'development', 'testing', 'production'
318
+ ```
319
+
320
+ ### Metrics
321
+
322
+ ```typescript
323
+ interface RetryMetrics {
324
+ totalAttempts: number;
325
+ successfulRetries: number;
326
+ failedRetries: number;
327
+ totalRetryTimeMs: number;
328
+ averageRetryDelayMs: number;
329
+ circuitBreakerState: 'closed' | 'open' | 'half-open';
330
+ lastError?: Error;
331
+ lastRetryTimestamp?: Date;
332
+ }
333
+
334
+ interface ServiceStats {
335
+ rateLimiter: RateLimiterStats;
336
+ retries?: RetryMetrics;
337
+ configuration: {
338
+ rateLimit: number;
339
+ timeout: number;
340
+ retriesEnabled: boolean;
341
+ retryPolicy?: string;
342
+ };
343
+ }
344
+ ```
345
+
346
+ ## Usage Patterns
347
+
348
+ ### Basic Usage
349
+
350
+ ```typescript
351
+ const client = new GoveeClient({ apiKey: 'your-key' });
352
+
353
+ // Get devices
354
+ const devices = await client.getDevices();
355
+ const controllableDevices = await client.getControllableDevices();
356
+
357
+ // Find specific device
358
+ const livingRoom = await client.findDeviceByName('Living Room');
359
+
360
+ // Control device
361
+ if (livingRoom) {
362
+ await client.turnOn(livingRoom.deviceId, livingRoom.model);
363
+ await client.setBrightness(livingRoom.deviceId, livingRoom.model, new Brightness(75));
364
+ await client.setColor(livingRoom.deviceId, livingRoom.model, new ColorRgb(255, 0, 0));
365
+ }
366
+ ```
367
+
368
+ ### Error Handling
369
+
370
+ ```typescript
371
+ try {
372
+ await client.turnOn(deviceId, model);
373
+ } catch (error) {
374
+ if (error instanceof InvalidApiKeyError) {
375
+ console.log('Invalid API key:', error.getRecommendation());
376
+ } else if (error instanceof RateLimitError) {
377
+ console.log(`Rate limited, retry after: ${error.getRetryAfterMs()}ms`);
378
+ } else if (error instanceof GoveeApiError) {
379
+ if (error.isDeviceOffline()) {
380
+ console.log('Device is offline');
381
+ }
382
+ }
383
+ }
384
+ ```
385
+
386
+ ### Advanced Configuration
387
+
388
+ ```typescript
389
+ import pino from 'pino';
390
+
391
+ const client = new GoveeClient({
392
+ apiKey: 'your-key',
393
+ timeout: 30000,
394
+ rateLimit: 90,
395
+ logger: pino({ level: 'info' }),
396
+ enableRetries: true,
397
+ retryPolicy: 'production',
398
+ });
399
+
400
+ // Monitor performance
401
+ const stats = client.getServiceStats();
402
+ console.log('Rate limiter utilization:', stats.rateLimiter.utilizationPercent);
403
+ ```
404
+
405
+ ## TypeScript Support
406
+
407
+ The library provides full TypeScript support with:
408
+
409
+ - Complete type definitions for all classes and interfaces
410
+ - Generic type parameters where appropriate
411
+ - Strict null checks compatibility
412
+ - Comprehensive JSDoc documentation
413
+ - Type-safe error handling
414
+
415
+ ## Dependencies
416
+
417
+ - **axios**: HTTP client
418
+ - **pino**: Logging (optional)
419
+ - **zod**: Runtime type validation
420
+
421
+ ## Node.js Compatibility
422
+
423
+ - **Minimum version**: Node.js 18.0.0
424
+ - **ESM/CommonJS**: Supports both module systems
425
+ - **TypeScript**: 5.8.3+ recommended