@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.
- package/dist/errors/GoveeApiError.d.ts +1 -1
- package/dist/errors/GoveeApiError.d.ts.map +1 -1
- package/dist/errors/GoveeApiError.js +9 -2
- package/dist/errors/GoveeApiError.js.map +1 -1
- package/dist/infrastructure/GoveeDeviceRepository.d.ts.map +1 -1
- package/dist/infrastructure/GoveeDeviceRepository.js +25 -2
- package/dist/infrastructure/GoveeDeviceRepository.js.map +1 -1
- package/docs/EXAMPLES.md +799 -0
- package/docs/LLM_API_REFERENCE.md +425 -0
- package/docs/TYPE_DEFINITIONS.md +803 -0
- package/package.json +10 -4
|
@@ -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
|