Skip to content

Commit ef15389

Browse files
committed
testing fixes
1 parent 74ed970 commit ef15389

5 files changed

Lines changed: 17 additions & 154 deletions

File tree

src/AccessoryManager.js

Lines changed: 7 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,7 @@ export class AccessoryManager {
5050
this.config = platform.config;
5151
this.api = platform.api;
5252

53-
// Command management
54-
this._commandTimers = new Map();
55-
this._lastCommandTimes = new Map();
56-
57-
// Default command debounce configuration
58-
this.defaultCmdDebounceConfig = {
59-
setLevel: { delay: 600, trailing: true },
60-
setVolume: { delay: 600, trailing: true },
61-
setSpeed: { delay: 600, trailing: true },
62-
setSaturation: { delay: 600, trailing: true },
63-
setHue: { delay: 600, trailing: true },
64-
setColorTemperature: { delay: 600, trailing: true },
65-
setHeatingSetpoint: { delay: 600, trailing: true },
66-
setCoolingSetpoint: { delay: 600, trailing: true },
67-
setThermostatSetpoint: { delay: 600, trailing: true },
68-
setThermostatMode: { delay: 600, trailing: true },
69-
};
53+
// Command management handled by HubitatClient
7054

7155
// Initialize device handlers and tests
7256
this.deviceHandlers = {
@@ -415,57 +399,14 @@ export class AccessoryManager {
415399
return characteristic;
416400
};
417401

418-
// Command handling with debouncing
402+
// Command handling - delegate to HubitatClient batching
419403
accessory.sendCommand = async (command, params = []) => {
420404
try {
421-
// Get the command debounce config
422-
const cmdConfig = this.defaultCmdDebounceConfig[command];
423-
const delay = cmdConfig?.delay || 300;
424-
const trailing = cmdConfig?.trailing || false;
425-
426-
// Get the time since the last command
427-
const now = Date.now();
428-
const lastTime = this._lastCommandTimes.get(command) || 0;
429-
const timeSinceLastCommand = now - lastTime;
430-
431-
// Clear any existing timer for this command
432-
const existingTimer = this._commandTimers.get(command);
433-
if (existingTimer) {
434-
clearTimeout(existingTimer);
435-
this._commandTimers.delete(command);
436-
}
437-
438405
// Ensure params is an array and filter out null/undefined
439406
const validParams = Array.isArray(params) ? params.filter((p) => p !== null) : [params].filter((p) => p !== null);
440407

441-
// Execute the command (check for trailing debounce)
442-
const executeCommand = async () => {
443-
this._lastCommandTimes.set(command, Date.now());
444-
return await this.platform.client.sendHubitatCommand(accessory.context.deviceData, command, validParams);
445-
};
446-
447-
// If trailing or time since last command is less than delay, set a timer
448-
if (trailing || timeSinceLastCommand < delay) {
449-
return new Promise((resolve, reject) => {
450-
const timer = setTimeout(
451-
async () => {
452-
try {
453-
const result = await executeCommand();
454-
resolve(result);
455-
} catch (error) {
456-
reject(error);
457-
} finally {
458-
this._commandTimers.delete(command);
459-
}
460-
},
461-
trailing ? delay : Math.max(0, delay - timeSinceLastCommand),
462-
);
463-
this._commandTimers.set(command, timer);
464-
});
465-
}
466-
467-
// Otherwise, execute the command immediately
468-
return await executeCommand();
408+
// Send command through HubitatClient's batching system
409+
return await this.platform.client.sendHubitatCommand(accessory.context.deviceData, command, validParams);
469410
} catch (error) {
470411
this.logManager.logError(`Error executing command ${command} for device ${accessory.context.deviceData.name}:`, error);
471412
throw error;
@@ -691,14 +632,11 @@ export class AccessoryManager {
691632

692633
/**
693634
* Clean up all timers and clear maps
635+
* Command timers are now handled by HubitatClient
694636
*/
695637
cleanupTimers() {
696-
// Clear all pending command timers
697-
for (const timer of this._commandTimers.values()) {
698-
clearTimeout(timer);
699-
}
700-
this._commandTimers.clear();
701-
this._lastCommandTimes.clear();
638+
// No command timers to clean up in AccessoryManager
639+
// HubitatClient handles its own timer cleanup
702640
}
703641

704642
/**

src/HubitatClient.js

Lines changed: 8 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ export default class HubitatClient {
3737
batchSize: 10,
3838
batchDelay: 25,
3939
maxBatchDelay: 100,
40-
isProcessing: false,
41-
totalQueued: 0,
42-
totalProcessed: 0,
43-
totalBatches: 0,
4440
};
4541

4642
// Retry configuration
@@ -155,32 +151,14 @@ export default class HubitatClient {
155151
}
156152

157153
async processBatch() {
158-
// Prevent concurrent batch processing
159-
if (this.commandState.isProcessing) {
160-
this.logManager.logDebug("Batch processing already in progress, skipping");
161-
return;
162-
}
163-
164-
if (!this.commandState.queue.length) {
165-
this.commandState.batchTimer = null;
166-
return;
167-
}
168-
169-
// Set processing flag and clear timer
170-
this.commandState.isProcessing = true;
171-
this.commandState.batchTimer = null;
154+
if (!this.commandState.queue.length) return;
172155

173156
const commands = this.commandState.queue.splice(0, this.commandState.batchSize);
157+
this.commandState.batchTimer = null;
174158
const startTime = Date.now();
175159
let success = false;
176160
let error = null;
177161

178-
// Update statistics
179-
this.commandState.totalBatches++;
180-
this.commandState.totalProcessed += commands.length;
181-
182-
this.logManager.logDebug(`Processing batch of ${commands.length} commands (${this.commandState.queue.length} remaining in queue) | Total batches: ${this.commandState.totalBatches}, Total processed: ${this.commandState.totalProcessed}`);
183-
184162
try {
185163
const formattedCommands = commands.map((cmd) => ({
186164
deviceId: cmd.devData.deviceid,
@@ -199,24 +177,15 @@ export default class HubitatClient {
199177
timeout: 5000,
200178
});
201179
success = true;
202-
this.logManager.logDebug(`Successfully processed batch of ${commands.length} commands`);
203180
} catch (err) {
204181
success = false;
205182
error = err.message;
206183
this.handleError("processBatch", err);
207-
this.logManager.logWarn(`Batch processing failed, falling back to individual commands for ${commands.length} commands`);
208-
209184
// Fall back to individual commands - metrics will be recorded in sendSingleCommand
210185
for (const cmd of commands) {
211-
try {
212-
await this.sendSingleCommand(cmd.devData, cmd.command, cmd.params);
213-
} catch (singleErr) {
214-
this.logManager.logError(`Failed to send individual command ${cmd.command} to device ${cmd.devData.name}:`, singleErr);
215-
}
186+
await this.sendSingleCommand(cmd.devData, cmd.command, cmd.params);
216187
}
217-
} finally {
218-
// Always clear processing flag
219-
this.commandState.isProcessing = false;
188+
return; // Skip metrics recording as individual commands will handle it
220189
}
221190

222191
// Record batch command metrics only if successful
@@ -239,7 +208,7 @@ export default class HubitatClient {
239208
}
240209

241210
// Process remaining queue if any
242-
if (this.commandState.queue.length > 0) {
211+
if (this.commandState.queue.length) {
243212
this.scheduleBatchProcessing();
244213
}
245214
}
@@ -297,19 +266,12 @@ export default class HubitatClient {
297266
// Add command to batch queue
298267
this.commandState.queue.push({ devData, command: cmd, params });
299268
this.commandState.lastExecutions.set(cmd, Date.now());
300-
this.commandState.totalQueued++;
301-
302-
this.logManager.logDebug(`Command queued. Queue size: ${this.commandState.queue.length}, Processing: ${this.commandState.isProcessing}, Total queued: ${this.commandState.totalQueued}`);
303269

304270
// If queue reaches batch size, process immediately
305271
if (this.commandState.queue.length >= this.commandState.batchSize) {
306-
this.logManager.logDebug(`Queue reached batch size (${this.commandState.batchSize}), processing immediately`);
307272
await this.processBatch();
308273
} else {
309-
// Only schedule if not already processing
310-
if (!this.commandState.isProcessing) {
311-
this.scheduleBatchProcessing();
312-
}
274+
this.scheduleBatchProcessing();
313275
}
314276

315277
return true;
@@ -320,23 +282,9 @@ export default class HubitatClient {
320282
}
321283

322284
scheduleBatchProcessing() {
323-
// Don't schedule if already processing or timer exists
324-
if (this.commandState.isProcessing || this.commandState.batchTimer) {
325-
return;
326-
}
327-
328-
// Don't schedule if queue is empty
329-
if (this.commandState.queue.length === 0) {
330-
return;
331-
}
285+
if (this.commandState.batchTimer) return;
332286

333-
this.commandState.batchTimer = setTimeout(
334-
() => {
335-
this.commandState.batchTimer = null;
336-
this.processBatch();
337-
},
338-
Math.min(this.commandState.batchDelay, this.commandState.maxBatchDelay),
339-
);
287+
this.commandState.batchTimer = setTimeout(() => this.processBatch(), Math.min(this.commandState.batchDelay, this.commandState.maxBatchDelay));
340288
}
341289

342290
handleError(source, error) {
@@ -437,19 +385,6 @@ export default class HubitatClient {
437385
};
438386
}
439387

440-
getCommandQueueStats() {
441-
return {
442-
queueSize: this.commandState.queue.length,
443-
isProcessing: this.commandState.isProcessing,
444-
batchSize: this.commandState.batchSize,
445-
batchDelay: this.commandState.batchDelay,
446-
totalQueued: this.commandState.totalQueued,
447-
totalProcessed: this.commandState.totalProcessed,
448-
totalBatches: this.commandState.totalBatches,
449-
hasTimer: !!this.commandState.batchTimer,
450-
};
451-
}
452-
453388
/**
454389
* Clean up idle connections
455390
*/
@@ -648,7 +583,6 @@ export default class HubitatClient {
648583
// Clear command batching timers
649584
if (this.commandState.batchTimer) {
650585
clearTimeout(this.commandState.batchTimer);
651-
this.commandState.batchTimer = null;
652586
}
653587
if (this.attributeBatchTimer) {
654588
clearTimeout(this.attributeBatchTimer);
@@ -666,7 +600,6 @@ export default class HubitatClient {
666600
this.commandState.queue = [];
667601
this.commandState.timers.clear();
668602
this.commandState.lastExecutions.clear();
669-
this.commandState.isProcessing = false;
670603
this.attributeUpdateQueue.clear();
671604
this.appEvts.removeAllListeners();
672605

src/HubitatPlatform.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,15 +344,9 @@ export default class HubitatPlatform {
344344
* Configure an accessory during platform initialization
345345
* @param {PlatformAccessory} accessory - The accessory to configure
346346
*/
347-
async configureAccessory(accessory) {
347+
configureAccessory(accessory) {
348348
const deviceId = accessory.context.deviceData?.deviceid;
349349
if (deviceId) {
350-
// Reconfigure the accessory to restore controllers like adaptive lighting
351-
try {
352-
await this.accessoryManager.configureAccessory(accessory);
353-
} catch (error) {
354-
this.logManager.logError(`Error reconfiguring restored accessory ${accessory.displayName}:`, error);
355-
}
356350
this.addAccessoryToCache(accessory);
357351
} else {
358352
this.logManager.logWarn(`Accessory ${accessory.displayName} is missing deviceData.deviceid`);

src/WebServer.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,11 +511,9 @@ export class WebServer {
511511
// Get queue statistics
512512
webApp.get("/monitoring/queues", (req, res) => {
513513
const queueStats = this.getQueueStats();
514-
const commandQueueStats = this.platform.client.getCommandQueueStats();
515514
res.send({
516515
status: "OK",
517516
queues: queueStats,
518-
commandQueue: commandQueueStats,
519517
timestamp: new Date().toISOString(),
520518
});
521519
});

src/devices/Light.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export class Light {
105105
// This ensures proper restoration of adaptive lighting state after reboots
106106
if (accessory.adaptiveLightingController) {
107107
const controllerId = accessory.adaptiveLightingController.controllerId();
108-
if (!accessory.controllers[controllerId]) {
108+
if (!accessory.controllers || !accessory.controllers[controllerId]) {
109109
accessory.configureController(accessory.adaptiveLightingController);
110110
}
111111
}

0 commit comments

Comments
 (0)