UNPKG

timeline-state-resolver

Version:
166 lines • 6.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PanasonicPtzHttpInterface = exports.PanasonicFocusMode = exports.PanasonicPtzCamera = void 0; const _ = require("underscore"); const events_1 = require("events"); const got_1 = require("got"); const querystring = require("querystring"); const commands_1 = require("./commands"); const PROBE_INTERVAL = 10 * 1000; // Probe every 10s /** * Low level device class for Panasonic PTZ devices executing a * basic queue. */ class PanasonicPtzCamera extends events_1.EventEmitter { constructor(url, commandDelay = 130) { super(); this._commandQueue = []; this._executeQueueTimeout = []; this._commandDelay = commandDelay; this._url = url; } async sendCommand(command) { const p = new Promise((resolve, reject) => { this._commandQueue.push({ command: command, executing: false, resolve: resolve, reject: reject }); }); if (this._commandQueue.filter((i) => i.executing).length === 0) this._executeQueue(); return p; } dispose() { this._commandQueue = []; _.each(this._executeQueueTimeout, (item) => { clearTimeout(item); }); } _dropFromQueue(item) { const index = this._commandQueue.findIndex((i) => i === item); if (index >= 0) { this._commandQueue.splice(index, 1); } else { throw new Error(`Command ${item.command} should be dropped from the queue, but could not be found!`); } } _executeQueue() { const qItem = this._commandQueue.find((i) => !i.executing); if (!qItem) { return; } const queryUrl = this._url + '?' + querystring.stringify({ cmd: qItem.command, res: '1' }); this.emit('debug', 'Command sent', queryUrl); qItem.executing = true; got_1.default .get(queryUrl) .then((response) => { this._dropFromQueue(qItem); qItem.resolve(response.body); }) .catch((error) => { this.emit('error', error); this._dropFromQueue(qItem); qItem.reject(error); }); // find any commands that aren't executing yet and execute one after 130ms if (this._commandQueue.filter((i) => !i.executing).length > 0) { const timeout = setTimeout(() => { // remove from timeouts list const index = this._executeQueueTimeout.indexOf(timeout); if (index >= 0) { this._executeQueueTimeout.splice(index, 1); } this._executeQueue(); }, this._commandDelay); // add to timeouts list so that we can cancel them when disposing this._executeQueueTimeout.push(timeout); } } } exports.PanasonicPtzCamera = PanasonicPtzCamera; var PanasonicFocusMode; (function (PanasonicFocusMode) { PanasonicFocusMode[PanasonicFocusMode["MANUAL"] = 0] = "MANUAL"; PanasonicFocusMode[PanasonicFocusMode["AUTO"] = 1] = "AUTO"; })(PanasonicFocusMode = exports.PanasonicFocusMode || (exports.PanasonicFocusMode = {})); var PanasonicHttpResponse; (function (PanasonicHttpResponse) { PanasonicHttpResponse["POWER_MODE_ON"] = "p1"; PanasonicHttpResponse["POWER_MODE_STBY"] = "p0"; PanasonicHttpResponse["POWER_MODE_TURNING_ON"] = "p3"; PanasonicHttpResponse["ERROR_1"] = "E1"; PanasonicHttpResponse["ERROR_2"] = "E2"; PanasonicHttpResponse["ERROR_3"] = "E3"; })(PanasonicHttpResponse || (PanasonicHttpResponse = {})); /** * High level methods for interfacing with a panasonic PTZ camera. This class * depends on the PanasonicPtzCamera class. */ class PanasonicPtzHttpInterface extends events_1.EventEmitter { constructor(host, port, https) { super(); this._connected = false; this._device = new PanasonicPtzCamera((https ? 'https' : 'http') + '://' + host + (port ? ':' + port : '') + '/cgi-bin/aw_ptz'); this._device.on('error', (err) => { this.emit('error', err); }); this._device.on('debug', (...args) => { this.emit('debug', ...args); }); } init() { const check = () => { this.ping() .then((result) => { this._connected = result !== commands_1.PowerMode.POWER_MODE_STBY; }) .catch(() => { this._connected = false; }); }; this._pingInterval = setInterval(check, PROBE_INTERVAL); check(); // do a check right away } static _isError(response) { if (response === PanasonicHttpResponse.ERROR_1 || response === PanasonicHttpResponse.ERROR_2 || response === PanasonicHttpResponse.ERROR_3) { return true; } else { return false; } } dispose() { this._device.dispose(); if (this._pingInterval) clearInterval(this._pingInterval); this._connected = false; } get connected() { return this._connected; } /** * Ping a camera by checking its power status. Will return true if the camera is on, false if it's off but reachable and will fail otherwise * @returns {Promose<boolean | string>} A promise: true if the camera is ON, false if the camera is off, 'turningOn' if transitioning from STBY to ON * @memberof PanasonicPtzHttpInterface */ async ping() { return this.executeCommand(new commands_1.PowerModeQuery()); } async executeCommand(command) { let response; try { response = await this._device.sendCommand(command.serialize()); } catch (error) { this.emit('disconnected', error); throw error; } if (PanasonicPtzHttpInterface._isError(response)) { throw new Error(`Device returned an error: ${response}`); } return command.deserializeResponse(response); } } exports.PanasonicPtzHttpInterface = PanasonicPtzHttpInterface; //# sourceMappingURL=connection.js.map