UNPKG

homebridge-pioneer-avr-2025

Version:

A Pioneer AVR plugin for homebridge. This plugin is designed for Pioneer models that use Telnet Commands (e.g., VSX-922). It may not be compatible with newer models (e.g., VSX-LX304).

157 lines 6.77 kB
"use strict"; // src/telnet-avr/messageQueue.ts var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageQueue = void 0; class MessageQueue { constructor(connection) { this.connection = connection; this.queue = []; // Array storing message and its callback character string this.queueCallbackChars = {}; // Maps callback character strings to an array of associated callbacks this.callbackLocks = {}; // Locks specific to callback characters // Start periodic queue checking this.startQueueCheck(); this.conn = connection; this.log = connection.log; } /** * Starts periodic checking and processing of the queue. * Releases locks and processes messages as needed. */ startQueueCheck() { setInterval(() => { var _a; // Process the next item in the queue if it is not locked if (this.queue.length > 0 && ((_a = this.conn) === null || _a === void 0 ? void 0 : _a.socket) && this.conn.socket.readyState === 'open') { // Unlock callbackLocks if they are active for more than 5 seconds for (const key of Object.keys(this.callbackLocks)) { const lock = this.callbackLocks[key]; if (lock.message && key !== '!none' && lock.queueLock && lock.queueLockDate && Date.now() - lock.queueLockDate > 13000) { this.connection.directSend(lock.message); lock.message = undefined; } else if (lock.queueLock && lock.queueLockDate && Date.now() - lock.queueLockDate > 25000) { delete this.callbackLocks[key]; } } this.processQueue(); } }, 7); // Check every 7ms } /** * Processes the first item in the queue, sending the message if not locked. */ processQueue() { return __awaiter(this, void 0, void 0, function* () { var _a; if (this.queue.length === 0) { return; } const [message, callbackKey] = this.queue[0]; // Skip processing if the lock for the callback key is active const lock = this.callbackLocks[callbackKey]; // this.log.debug('in processQueue', message, lock?.queueLock); if (lock === null || lock === void 0 ? void 0 : lock.queueLock) { return; } // Lock the callback key before sending the message if (!this.callbackLocks[callbackKey]) { this.callbackLocks[callbackKey] = { queueLock: true, queueLockDate: Date.now(), message: message, }; } else { this.callbackLocks[callbackKey].queueLock = true; this.callbackLocks[callbackKey].queueLockDate = Date.now(); } // Enforce a delay between messages if necessary if (Date.now() - ((_a = this.connection.lastWrite) !== null && _a !== void 0 ? _a : 0) < 17) { yield new Promise((resolve) => setTimeout(resolve, 7)); } // Send the message via the connection this.connection.directSend(message); }); } /** * Adds a message to the queue with optional callback characters and a callback function. * @param message - The message to send * @param callbackChars - The callback character string to track * @param callback - The function to execute when the response is received */ enqueue(message, callbackChars, callback) { if (!callbackChars) { callbackChars = '!none'; } // Add the message to the queue if not already present if (message === '?P') { this.queue.unshift([message, callbackChars]); } else { this.queue.push([message, callbackChars]); } if (callback) { // Add the callback to the list of callbacks for the callback character string if (!this.queueCallbackChars[callbackChars]) { this.queueCallbackChars[callbackChars] = []; } this.queueCallbackChars[callbackChars].push(callback); } } /** * Clears the entire queue and resets all locks and callbacks. */ clearQueue() { // this.log.debug('clearQueue called', this.queue, this.queueCallbackChars, this.callbackLocks); this.queue = []; this.queueCallbackChars = {}; this.callbackLocks = {}; } /** * Removes all callbacks associated with a specific callback character key. * @param callbackKey - The callback key to clear * @param callback - The specific callback to remove */ removeCallbackForKey(callbackKey) { if (this.queueCallbackChars[callbackKey]) { // If no more callbacks exist for the key, delete the key delete this.queueCallbackChars[callbackKey]; } if (this.callbackLocks[callbackKey]) { this.callbackLocks[callbackKey].queueLock = false; this.callbackLocks[callbackKey].queueLockDate = null; } } /** * Retrieves all callback keys currently in the queueCallbackChars map. * @returns {string[]} - An array of callback keys */ getCallbackKeys() { return Object.keys(this.queueCallbackChars); } /** * Retrieves all callbacks associated with a specific callback key. * @param callbackKey - The key to retrieve callbacks for * @returns {Function[]} - An array of callbacks */ getCallbacksForKey(callbackKey) { return this.queueCallbackChars[callbackKey] || []; } } exports.MessageQueue = MessageQueue; //# sourceMappingURL=messageQueue.js.map