mos-connection
Advanced tools
Comparing version 0.3.12 to 0.3.14
@@ -5,2 +5,17 @@ # Change Log | ||
<a name="0.3.14"></a> | ||
## [0.3.14](https://github.com/nrkno/tv-automation-mos-connection/compare/0.3.13...0.3.14) (2018-06-11) | ||
<a name="0.3.13"></a> | ||
## [0.3.13](https://github.com/nrkno/tv-automation-mos-connection/compare/0.3.12...0.3.13) (2018-06-11) | ||
### Bug Fixes | ||
* **mosDuration:** fixes bug with mosDurations displaying wrong values once consumed ([c558777](https://github.com/nrkno/tv-automation-mos-connection/commit/c558777)) | ||
<a name="0.3.12"></a> | ||
@@ -7,0 +22,0 @@ ## [0.3.12](https://github.com/nrkno/tv-automation-mos-connection/compare/0.3.11...0.3.12) (2018-06-05) |
@@ -9,3 +9,3 @@ import { IProfiles } from './config/connectionConfig'; | ||
export interface IMosConnection { | ||
readonly isListening: Promise<boolean[]>; | ||
readonly isListening: boolean; | ||
readonly acceptsConnections: boolean; | ||
@@ -12,0 +12,0 @@ readonly profiles: IProfiles; |
@@ -23,8 +23,8 @@ /// <reference types="node" /> | ||
private _queueMessages; | ||
private _ready; | ||
private processQueueInterval; | ||
private _sentMessage; | ||
private processQueueTimeout; | ||
private _startingUp; | ||
private dataChunks; | ||
/** */ | ||
constructor(host: string, port: number, description: string, debug?: boolean); | ||
constructor(host: string, port: number, description: string, timeout?: number, debug?: boolean); | ||
/** */ | ||
@@ -55,2 +55,3 @@ autoReconnect: boolean; | ||
private connected; | ||
private _sendReply(messageId, err, res); | ||
/** */ | ||
@@ -63,3 +64,2 @@ private executeCommand(message); | ||
/** */ | ||
private _onCommandTimeout(); | ||
/** */ | ||
@@ -73,2 +73,3 @@ private _onConnected(); | ||
private _onClose(hadError); | ||
private _triggerQueueCleanup(); | ||
} |
@@ -15,3 +15,3 @@ "use strict"; | ||
/** */ | ||
constructor(host, port, description, debug) { | ||
constructor(host, port, description, timeout, debug) { | ||
super(); | ||
@@ -23,7 +23,7 @@ this._autoReconnect = true; | ||
this._shouldBeConnected = false; | ||
this._connected = false; | ||
this._reconnectAttempt = 0; | ||
this._commandTimeout = 10000; | ||
this._queueCallback = {}; | ||
this._queueMessages = []; | ||
this._ready = false; | ||
this._sentMessage = null; | ||
this._startingUp = true; | ||
@@ -34,2 +34,3 @@ this.dataChunks = ''; | ||
this._description = description; | ||
this._commandTimeout = timeout || 5000; | ||
if (debug) | ||
@@ -55,3 +56,3 @@ this._debug = debug; | ||
// throttling attempts | ||
if (!this._lastConnectionAttempt || (Date.now() - this._lastConnectionAttempt) >= this._reconnectDelay) { | ||
if (!this._lastConnectionAttempt || (Date.now() - this._lastConnectionAttempt) >= this._reconnectDelay) { // !_lastReconnectionAttempt (means first attempt) OR time > _reconnectionDelay since last attempt | ||
// recreate client if new attempt: | ||
@@ -82,5 +83,8 @@ if (this._client && this._client.connecting) { | ||
if (!this._connectionAttemptTimer) { | ||
this._connectionAttemptTimer = global.setInterval(this._autoReconnectionAttempt, this._reconnectDelay); | ||
this._connectionAttemptTimer = global.setInterval(() => { | ||
this._autoReconnectionAttempt(); | ||
}, this._reconnectDelay); | ||
} | ||
this._ready = true; | ||
// this._readyToSendMessage = true | ||
// this._sentMessage = null | ||
} | ||
@@ -95,19 +99,24 @@ } | ||
// console.log('queueing', message.messageID, message.constructor.name ) | ||
this._queueCallback[message.messageID] = cb; | ||
this._queueMessages.push(message); | ||
this._queueCallback[message.messageID + ''] = cb; | ||
this._queueMessages.push({ time: Date.now(), msg: message }); | ||
this.processQueue(); | ||
} | ||
processQueue() { | ||
if (this._ready) { | ||
if (this.processQueueInterval) | ||
clearInterval(this.processQueueInterval); | ||
if (this._queueMessages.length) { | ||
this._ready = false; | ||
let message = this._queueMessages[0]; | ||
// console.log('this.connected', this.connected) | ||
if (!this._sentMessage && this.connected) { | ||
if (this.processQueueTimeout) | ||
clearTimeout(this.processQueueTimeout); | ||
let message = this._queueMessages.shift(); | ||
if (message) { | ||
// Send the message: | ||
this.executeCommand(message); | ||
} | ||
else { | ||
// The queue is empty, do nothing | ||
} | ||
} | ||
else { | ||
clearInterval(this.processQueueInterval); | ||
this.processQueueInterval = setInterval(() => { | ||
// Try again later: | ||
clearTimeout(this.processQueueTimeout); | ||
this.processQueueTimeout = setTimeout(() => { | ||
this.processQueue(); | ||
@@ -133,3 +142,4 @@ }, 200); | ||
dispose() { | ||
this._ready = false; | ||
// this._readyToSendMessage = false | ||
this.connected = false; | ||
this._shouldBeConnected = false; | ||
@@ -160,13 +170,39 @@ this._clearConnectionAttemptTimer(); | ||
} | ||
_sendReply(messageId, err, res) { | ||
let cb = this._queueCallback[messageId + '']; | ||
if (cb) { | ||
cb(err, res); | ||
} | ||
else { | ||
// this._onUnhandledCommandTimeout() | ||
} | ||
this._sentMessage = null; | ||
delete this._queueCallback[messageId + '']; | ||
} | ||
/** */ | ||
executeCommand(message) { | ||
if (this._sentMessage) | ||
throw Error('executeCommand: there already is a sent Command!'); | ||
this._sentMessage = message; | ||
let sentMessageId = message.msg.messageID; | ||
// console.log('executeCommand', message) | ||
// message.prepare() // @todo, is prepared? is sent already? logic needed | ||
let str = message.toString(); | ||
let buf = iconv.encode(str, 'utf16-be'); | ||
// console.log('sending',this._client.name, str) | ||
global.clearTimeout(this._commandTimeoutTimer); | ||
this._commandTimeoutTimer = global.setTimeout(() => this._onCommandTimeout(), this._commandTimeout); | ||
let messageString = message.msg.toString(); | ||
if (this._debug) | ||
console.log('messageString', messageString); | ||
let buf = iconv.encode(messageString, 'utf16-be'); | ||
// if (this._debug) console.log('sending',this._client.name, str) | ||
// Command timeout: | ||
global.setTimeout(() => { | ||
if (this._sentMessage && this._sentMessage.msg.messageID === sentMessageId) { | ||
if (this._debug) | ||
console.log('timeout ' + sentMessageId); | ||
this._sendReply(sentMessageId, Error('Command timed out'), null); | ||
this.processQueue(); | ||
} | ||
}, this._commandTimeout); | ||
this._client.write(buf, 'ucs2'); | ||
if (this._debug) | ||
console.log(`MOS command sent from ${this._description} : ${str}\r\nbytes sent: ${this._client.bytesWritten}`); | ||
console.log(`MOS command sent from ${this._description} : ${messageString}\r\nbytes sent: ${this._client.bytesWritten}`); | ||
this.emit('rawMessage', 'sent', messageString); | ||
} | ||
@@ -176,4 +212,4 @@ /** */ | ||
if (this._autoReconnect) { | ||
if (this._reconnectAttempts > 0) { | ||
if ((this._reconnectAttempt >= this._reconnectAttempts)) { | ||
if (this._reconnectAttempts > 0) { // no reconnection if no valid reconnectionAttemps is set | ||
if ((this._reconnectAttempt >= this._reconnectAttempts)) { // if current attempt is not less than max attempts | ||
// reset reconnection behaviour | ||
@@ -200,6 +236,6 @@ this._clearConnectionAttemptTimer(); | ||
/** */ | ||
_onCommandTimeout() { | ||
global.clearTimeout(this._commandTimeoutTimer); | ||
this.emit(socketConnection_1.SocketConnectionEvent.TIMEOUT); | ||
} | ||
// private _onUnhandledCommandTimeout () { | ||
// global.clearTimeout(this._commandTimeoutTimer) | ||
// this.emit(SocketConnectionEvent.TIMEOUT) | ||
// } | ||
/** */ | ||
@@ -217,2 +253,3 @@ _onConnected() { | ||
let messageString = iconv.decode(data, 'utf16-be').trim(); | ||
this.emit('rawMessage', 'recieved', messageString); | ||
if (this._debug) | ||
@@ -249,19 +286,28 @@ console.log(`${this._description} Received: ${messageString}`); | ||
if (messageId) { | ||
let cb = this._queueCallback[messageId]; | ||
let msg = this._queueMessages[0]; | ||
if (msg) { | ||
if (msg.messageID.toString() !== (messageId + '')) { | ||
console.log('Mos reply id diff: ' + messageId + ', ' + msg.messageID); | ||
console.log(parsedData); | ||
if (this._sentMessage) { | ||
if (this._sentMessage.msg.messageID.toString() === (messageId + '')) { | ||
this._sendReply(this._sentMessage.msg.messageID, null, parsedData); | ||
} | ||
if (cb) { | ||
cb(null, parsedData); | ||
this._queueMessages.shift(); // remove the first message | ||
delete this._queueCallback[messageId]; | ||
else { | ||
if (this._debug) | ||
console.log('Mos reply id diff: ' + messageId + ', ' + this._sentMessage.msg.messageID); | ||
if (this._debug) | ||
console.log(parsedData); | ||
this.emit('warning', 'Mos reply id diff: ' + messageId + ', ' + this._sentMessage.msg.messageID); | ||
this._triggerQueueCleanup(); | ||
} | ||
// let cb: CallBackFunction | undefined = this._queueCallback[messageId] | ||
// if (cb) { | ||
// cb(null, parsedData) | ||
// } | ||
// delete this._queueCallback[messageId] | ||
// this._sentMessage = null | ||
} | ||
else { | ||
// huh, we've got a reply to something we've not sent. | ||
console.log('Got reply to something we\'ve not asked for', messageString); | ||
if (this._debug) | ||
console.log('Got a reply (' + messageId + '), but we haven\'t sent any message', messageString); | ||
this.emit('warning', 'Got a reply (' + messageId + '), but we haven\'t sent any message ' + messageString); | ||
} | ||
clearTimeout(this._commandTimeoutTimer); | ||
} | ||
@@ -271,3 +317,4 @@ else { | ||
if (parsedData.mos.mosAck && parsedData.mos.mosAck.status === 'NACK') { | ||
console.log('Mos Error message:' + parsedData.mos.mosAck.statusDescription); | ||
if (this._debug) | ||
console.log('Mos Error message:' + parsedData.mos.mosAck.statusDescription); | ||
this.emit('error', 'Error message: ' + parsedData.mos.mosAck.statusDescription); | ||
@@ -289,3 +336,3 @@ } | ||
catch (e) { | ||
console.log('messageString', messageString); | ||
// console.log('messageString', messageString) | ||
if (this._startingUp) { | ||
@@ -301,3 +348,3 @@ // when starting up, we might get half a message, let's ignore this error then | ||
} | ||
this._ready = true; | ||
// this._readyToSendMessage = true | ||
this.processQueue(); | ||
@@ -314,3 +361,3 @@ } | ||
this.connected = false; | ||
this._ready = false; | ||
// this._readyToSendMessage = false | ||
if (hadError) { | ||
@@ -331,4 +378,17 @@ if (this._debug) | ||
} | ||
_triggerQueueCleanup() { | ||
// in case we're in unsync with messages, prevent deadlock: | ||
setTimeout(() => { | ||
console.log('QueueCleanup'); | ||
for (let i = this._queueMessages.length - 1; i >= 0; i--) { | ||
let message = this._queueMessages[i]; | ||
if (Date.now() - message.time > this._commandTimeout) { | ||
this._sendReply(message.msg.messageID, Error('Command Timeout'), null); | ||
this._queueMessages.splice(i, 1); | ||
} | ||
} | ||
}, this._commandTimeout); | ||
} | ||
} | ||
exports.MosSocketClient = MosSocketClient; | ||
//# sourceMappingURL=mosSocketClient.js.map |
@@ -10,2 +10,3 @@ /// <reference types="node" /> | ||
private _debug; | ||
private _connectedSockets; | ||
/** */ | ||
@@ -15,3 +16,3 @@ constructor(port: number, description: IncomingConnectionType, debug?: boolean); | ||
/** */ | ||
listen(): Promise<boolean>; | ||
listen(): Promise<void>; | ||
/** */ | ||
@@ -18,0 +19,0 @@ private _onClientConnection(socket); |
@@ -11,2 +11,3 @@ "use strict"; | ||
this._debug = false; | ||
this._connectedSockets = []; | ||
this._port = port; | ||
@@ -33,5 +34,11 @@ this._portDescription = description; | ||
closePromises.push(new Promise((resolve) => { | ||
this._socketServer.on('close', resolve); | ||
this._socketServer.close(); | ||
// this._socketServer.on('close', resolve) | ||
this._socketServer.close(() => { | ||
resolve(); | ||
}); | ||
})); | ||
// close any server connections: | ||
this._connectedSockets.forEach((socket) => { | ||
socket.destroy(); | ||
}); | ||
return Promise.all(closePromises); | ||
@@ -44,38 +51,43 @@ } | ||
return new Promise((resolve, reject) => { | ||
if (this._debug) | ||
console.log('inside promise', this._portDescription, this._port); | ||
// already listening | ||
if (this._socketServer.listening) { | ||
try { | ||
if (this._debug) | ||
console.log('already listening', this._portDescription, this._port); | ||
resolve(true); | ||
return; | ||
} | ||
// handles listening-listeners and cleans up | ||
let handleListeningStatus = (e) => { | ||
if (this._debug) | ||
console.log('handleListeningStatus'); | ||
this._socketServer.removeListener('listening', handleListeningStatus); | ||
this._socketServer.removeListener('close', handleListeningStatus); | ||
this._socketServer.removeListener('error', handleListeningStatus); | ||
console.log('inside promise', this._portDescription, this._port); | ||
// already listening | ||
if (this._socketServer.listening) { | ||
if (this._debug) | ||
console.log('listening', this._portDescription, this._port); | ||
resolve(true); | ||
console.log('already listening', this._portDescription, this._port); | ||
resolve(); | ||
return; | ||
} | ||
else { | ||
// handles listening-listeners and cleans up | ||
let handleListeningStatus = (e) => { | ||
if (this._debug) | ||
console.log('not listening', this._portDescription, this._port); | ||
reject(e || false); | ||
} | ||
}; | ||
// listens and handles error and events | ||
this._socketServer.on('listening', () => { | ||
if (this._debug) | ||
console.log('listening!!'); | ||
}); | ||
this._socketServer.once('listening', handleListeningStatus); | ||
this._socketServer.once('close', handleListeningStatus); | ||
this._socketServer.once('error', handleListeningStatus); | ||
this._socketServer.listen(this._port); | ||
console.log('handleListeningStatus'); | ||
this._socketServer.removeListener('listening', handleListeningStatus); | ||
this._socketServer.removeListener('close', handleListeningStatus); | ||
this._socketServer.removeListener('error', handleListeningStatus); | ||
if (this._socketServer.listening) { | ||
if (this._debug) | ||
console.log('listening', this._portDescription, this._port); | ||
resolve(); | ||
} | ||
else { | ||
if (this._debug) | ||
console.log('not listening', this._portDescription, this._port); | ||
reject(e || false); | ||
} | ||
}; | ||
// listens and handles error and events | ||
this._socketServer.on('listening', () => { | ||
if (this._debug) | ||
console.log('listening!!'); | ||
}); | ||
this._socketServer.once('listening', handleListeningStatus); | ||
this._socketServer.once('close', handleListeningStatus); | ||
this._socketServer.once('error', handleListeningStatus); | ||
this._socketServer.listen(this._port); | ||
} | ||
catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
@@ -85,2 +97,9 @@ } | ||
_onClientConnection(socket) { | ||
this._connectedSockets.push(socket); | ||
socket.on('close', () => { | ||
let i = this._connectedSockets.indexOf(socket); | ||
if (i !== -1) { | ||
this._connectedSockets.splice(i, 1); | ||
} | ||
}); | ||
this.emit(socketConnection_1.SocketServerEvent.CLIENT_CONNECTED, { | ||
@@ -87,0 +106,0 @@ socket: socket, |
@@ -0,5 +1,8 @@ | ||
/// <reference types="node" /> | ||
import { ConnectionType } from './socketConnection'; | ||
import { MosSocketClient } from '../connection/mosSocketClient'; | ||
import { MosMessage } from '../mosModel/MosMessage'; | ||
import { EventEmitter } from 'events'; | ||
export interface ClientDescription { | ||
heartbeatConnected: boolean; | ||
client: MosSocketClient; | ||
@@ -9,3 +12,3 @@ clientDescription: string; | ||
/** */ | ||
export declare class NCSServerConnection { | ||
export declare class NCSServerConnection extends EventEmitter { | ||
private _connected; | ||
@@ -17,2 +20,3 @@ private _id; | ||
private _debug; | ||
private _disposed; | ||
private _clients; | ||
@@ -23,4 +27,2 @@ private _callbackOnConnectionChange; | ||
constructor(id: string, host: string, mosID: string, timeout?: number, debug?: boolean); | ||
/** */ | ||
registerOutgoingConnection(clientID: string, client: MosSocketClient, clientDescription: ConnectionType): void; | ||
createClient(clientID: string, port: number, clientDescription: ConnectionType): void; | ||
@@ -39,4 +41,6 @@ /** */ | ||
readonly queryPortClients: MosSocketClient[]; | ||
readonly host: string; | ||
readonly id: string; | ||
dispose(): Promise<void>; | ||
private _sendHeartBeats(); | ||
} |
@@ -5,8 +5,11 @@ "use strict"; | ||
const _0_heartBeat_1 = require("../mosModel/0_heartBeat"); | ||
const events_1 = require("events"); | ||
// Namnförslag: NCSServer | ||
// Vi ansluter från oss till NCS | ||
/** */ | ||
class NCSServerConnection { | ||
class NCSServerConnection extends events_1.EventEmitter { | ||
constructor(id, host, mosID, timeout, debug) { | ||
super(); | ||
this._debug = false; | ||
this._disposed = false; | ||
this._clients = {}; | ||
@@ -22,14 +25,15 @@ this._id = id; | ||
} | ||
/** */ | ||
registerOutgoingConnection(clientID, client, clientDescription) { | ||
createClient(clientID, port, clientDescription) { | ||
let client = new mosSocketClient_1.MosSocketClient(this._host, port, clientDescription, this._timeout, this._debug); | ||
if (this._debug) | ||
console.log('registerOutgoingConnection', clientID); | ||
this._clients[clientID] = { | ||
heartbeatConnected: false, | ||
client: client, | ||
clientDescription: clientDescription | ||
}; | ||
client.on('rawMessage', (type, message) => { | ||
this.emit('rawMessage', type, message); | ||
}); | ||
} | ||
createClient(clientID, port, clientDescription) { | ||
this.registerOutgoingConnection(clientID, new mosSocketClient_1.MosSocketClient(this._host, port, clientDescription, this._debug), clientDescription); | ||
} | ||
/** */ | ||
@@ -49,6 +53,5 @@ removeClient(clientID) { | ||
// Send heartbeat and check connection | ||
this._heartBeatsTimer = global.setInterval(() => this._sendHeartBeats(), this._heartBeatsDelay); | ||
this._sendHeartBeats(); | ||
// Emit to _callbackOnConnectionChange | ||
if (this._callbackOnConnectionChange) | ||
this._callbackOnConnectionChange(); | ||
// if (this._callbackOnConnectionChange) this._callbackOnConnectionChange() | ||
} | ||
@@ -94,3 +97,12 @@ executeCommand(message) { | ||
get connected() { | ||
return this._connected; | ||
if (!this._connected) | ||
return false; | ||
let connected = true; | ||
Object.keys(this._clients).forEach(key => { | ||
let client = this._clients[key]; | ||
if (!client.heartbeatConnected) { | ||
connected = false; | ||
} | ||
}); | ||
return connected; | ||
} | ||
@@ -127,3 +139,10 @@ /** */ | ||
} | ||
get host() { | ||
return this._host; | ||
} | ||
get id() { | ||
return this._id; | ||
} | ||
dispose() { | ||
this._disposed = true; | ||
return new Promise((resolveDispose) => { | ||
@@ -133,3 +152,3 @@ for (let key in this._clients) { | ||
} | ||
global.clearInterval(this._heartBeatsTimer); | ||
global.clearTimeout(this._heartBeatsTimer); | ||
this._connected = false; | ||
@@ -142,11 +161,46 @@ if (this._callbackOnConnectionChange) | ||
_sendHeartBeats() { | ||
return Promise.all(Object.keys(this._clients).map((key) => { | ||
if (this._heartBeatsTimer) | ||
clearTimeout(this._heartBeatsTimer); | ||
if (this._disposed) | ||
return; | ||
let triggerNextHeartBeat = () => { | ||
this._heartBeatsTimer = global.setTimeout(() => { | ||
if (!this._disposed) { | ||
this._sendHeartBeats(); | ||
} | ||
}, this._heartBeatsDelay); | ||
}; | ||
let connected = this.connected; | ||
Promise.all(Object.keys(this._clients).map((key) => { | ||
let client = this._clients[key]; | ||
let heartbeat = new _0_heartBeat_1.HeartBeat(); | ||
heartbeat.port = this._clients[key].clientDescription; | ||
return this.executeCommand(heartbeat) | ||
.then((data) => { | ||
.then(() => { | ||
client.heartbeatConnected = true; | ||
if (this._debug) | ||
console.log(`Heartbeat on ${this._clients[key].clientDescription} received.`, data); | ||
console.log(`Heartbeat on ${this._clients[key].clientDescription} received.`); | ||
}) | ||
.catch((e) => { | ||
// probably a timeout | ||
client.heartbeatConnected = false; | ||
if (this._debug) | ||
console.log(`Heartbeat on ${this._clients[key].clientDescription}: ${e.toString()}`); | ||
}); | ||
})); | ||
})) | ||
.then(() => { | ||
if (connected !== this.connected) { | ||
if (this._callbackOnConnectionChange) | ||
this._callbackOnConnectionChange(); | ||
} | ||
triggerNextHeartBeat(); | ||
}) | ||
.catch((e) => { | ||
if (connected !== this.connected) { | ||
if (this._callbackOnConnectionChange) | ||
this._callbackOnConnectionChange(); | ||
} | ||
triggerNextHeartBeat(); | ||
this.emit('error', e); | ||
}); | ||
} | ||
@@ -153,0 +207,0 @@ } |
@@ -23,3 +23,2 @@ "use strict"; | ||
s -= mm * 60; | ||
console.log(hh); | ||
let ss = Math.floor(s); | ||
@@ -26,0 +25,0 @@ return hh + ':' + mm + ':' + ss; |
@@ -5,3 +5,2 @@ /// <reference types="node" /> | ||
import { MosDevice } from './MosDevice'; | ||
import { NCSServerConnection } from './connection/NCSServerConnection'; | ||
import { EventEmitter } from 'events'; | ||
@@ -21,2 +20,3 @@ export declare class MosConnection extends EventEmitter implements IMosConnection { | ||
private _mosDevices; | ||
private _initialized; | ||
private _isListening; | ||
@@ -26,8 +26,8 @@ private _onconnection; | ||
constructor(configOptions: IConnectionConfig); | ||
init(): Promise<boolean>; | ||
/** */ | ||
connect(connectionOptions: IMOSDeviceConnectionOptions): Promise<MosDevice>; | ||
onConnection(cb: (mosDevice: MosDevice) => void): void; | ||
registerMosDevice(myMosID: string, theirMosId0: string, theirMosId1: string | null, primary: NCSServerConnection | null, secondary: NCSServerConnection | null): MosDevice; | ||
/** */ | ||
readonly isListening: Promise<boolean[]>; | ||
readonly isListening: boolean; | ||
/** */ | ||
@@ -41,4 +41,9 @@ readonly isCompliant: boolean; | ||
dispose(): Promise<void>; | ||
getDevice(id: string): MosDevice; | ||
getDevices(): Array<MosDevice>; | ||
disposeMosDevice(mosDevice: MosDevice): Promise<void>; | ||
disposeMosDevice(myMosID: string, theirMosId0: string, theirMosId1: string | null): Promise<void>; | ||
/** */ | ||
readonly complianceText: string; | ||
private _registerMosDevice(myMosID, theirMosId0, theirMosId1, primary, secondary); | ||
/** */ | ||
@@ -45,0 +50,0 @@ private _initiateIncomingConnections(); |
@@ -23,6 +23,5 @@ "use strict"; | ||
this._mosDevices = {}; | ||
this._initialized = false; | ||
this._isListening = false; | ||
this._conf = new connectionConfig_1.ConnectionConfig(configOptions); | ||
if (this._conf.acceptsConnections) { | ||
this._isListening = this._initiateIncomingConnections(); | ||
} | ||
if (this._conf.debug) { | ||
@@ -32,5 +31,23 @@ this._debug = this._conf.debug; | ||
} | ||
init() { | ||
this._initialized = true; | ||
if (this._conf.acceptsConnections) { | ||
return new Promise((resolve, reject) => { | ||
this._initiateIncomingConnections() | ||
.then(() => { | ||
this._isListening = true; | ||
resolve(true); | ||
}) | ||
.catch((err) => { | ||
// this.emit('error', err) | ||
reject(err); | ||
}); | ||
}); | ||
} | ||
return Promise.resolve(false); | ||
} | ||
/** */ | ||
connect(connectionOptions) { | ||
// @todo: implement this | ||
if (!this._initialized) | ||
throw Error('Not initialized, run .init() first!'); | ||
return new Promise((resolve) => { | ||
@@ -43,2 +60,5 @@ // connect to mos device | ||
this._ncsConnections[connectionOptions.primary.host] = primary; | ||
primary.on('rawMessage', (type, message) => { | ||
this.emit('rawMessage', 'primary', type, message); | ||
}); | ||
primary.createClient(MosConnection.nextSocketID, MosConnection.CONNECTION_PORT_LOWER, 'lower'); | ||
@@ -49,2 +69,5 @@ primary.createClient(MosConnection.nextSocketID, MosConnection.CONNECTION_PORT_UPPER, 'upper'); | ||
this._ncsConnections[connectionOptions.secondary.host] = secondary; | ||
secondary.on('rawMessage', (type, message) => { | ||
this.emit('rawMessage', 'secondary', type, message); | ||
}); | ||
secondary.createClient(MosConnection.nextSocketID, MosConnection.CONNECTION_PORT_LOWER, 'lower'); | ||
@@ -54,3 +77,3 @@ secondary.createClient(MosConnection.nextSocketID, MosConnection.CONNECTION_PORT_UPPER, 'upper'); | ||
// initialize mosDevice: | ||
let mosDevice = this.registerMosDevice(this._conf.mosID, connectionOptions.primary.id, (connectionOptions.secondary ? connectionOptions.secondary.id : null), primary, secondary); | ||
let mosDevice = this._registerMosDevice(this._conf.mosID, connectionOptions.primary.id, (connectionOptions.secondary ? connectionOptions.secondary.id : null), primary, secondary); | ||
resolve(mosDevice); | ||
@@ -62,18 +85,5 @@ }); | ||
} | ||
registerMosDevice(myMosID, theirMosId0, theirMosId1, primary, secondary) { | ||
let id0 = myMosID + '_' + theirMosId0; | ||
let id1 = (theirMosId1 ? myMosID + '_' + theirMosId1 : null); | ||
let mosDevice = new MosDevice_1.MosDevice(id0, id1, this._conf, primary, secondary); | ||
this._mosDevices[id0] = mosDevice; | ||
if (id1) | ||
this._mosDevices[id1] = mosDevice; | ||
mosDevice.connect(); | ||
// emit to .onConnection | ||
if (this._onconnection) | ||
this._onconnection(mosDevice); | ||
return mosDevice; | ||
} | ||
/** */ | ||
get isListening() { | ||
return this._isListening || Promise.reject(`Mos connection is not listening for connections. "Config.acceptsConnections" is "${this._conf.acceptsConnections}"`); | ||
return this._isListening; | ||
} | ||
@@ -101,3 +111,3 @@ /** */ | ||
} | ||
let disposePromises = sockets.map((socket) => { | ||
let disposePromises0 = sockets.map((socket) => { | ||
return new Promise((resolve) => { | ||
@@ -109,10 +119,61 @@ socket.on('close', resolve); | ||
}); | ||
disposePromises.push(this._lowerSocketServer.dispose([])); | ||
disposePromises.push(this._upperSocketServer.dispose([])); | ||
disposePromises.push(this._querySocketServer.dispose([])); | ||
return Promise.all(disposePromises) | ||
let disposePromises1 = [ | ||
this._lowerSocketServer.dispose([]), | ||
this._upperSocketServer.dispose([]), | ||
this._querySocketServer.dispose([]) | ||
]; | ||
let disposePromises2 = []; | ||
Object.keys(this._mosDevices).map(deviceId => { | ||
let device = this._mosDevices[deviceId]; | ||
disposePromises2.push(this.disposeMosDevice(device)); | ||
}); | ||
return Promise.all(disposePromises0) | ||
.then(() => { | ||
return Promise.all(disposePromises1); | ||
}) | ||
.then(() => { | ||
return Promise.all(disposePromises2); | ||
}) | ||
.then(() => { | ||
return; | ||
}); | ||
} | ||
getDevice(id) { | ||
return this._mosDevices[id]; | ||
} | ||
getDevices() { | ||
return Object.keys(this._mosDevices).map((id) => { | ||
return this._mosDevices[id]; | ||
}); | ||
} | ||
disposeMosDevice(myMosIDOrMosDevice, theirMosId0, theirMosId1) { | ||
let id0; | ||
let id1; | ||
if (myMosIDOrMosDevice && myMosIDOrMosDevice instanceof MosDevice_1.MosDevice) { | ||
// myMosID = myMosIDOrMosDevice | ||
let mosDevice = myMosIDOrMosDevice; | ||
id0 = mosDevice.idPrimary; | ||
id1 = mosDevice.idSecondary; | ||
} | ||
else { | ||
let myMosID = myMosIDOrMosDevice; | ||
id0 = myMosID + '_' + theirMosId0; | ||
id1 = (theirMosId1 ? myMosID + '_' + theirMosId1 : null); | ||
} | ||
if (this._mosDevices[id0]) { | ||
return this._mosDevices[id0].dispose() | ||
.then(() => { | ||
delete this._mosDevices[id0]; | ||
}); | ||
} | ||
else if (id1 && this._mosDevices[id1]) { | ||
return this._mosDevices[id1].dispose() | ||
.then(() => { | ||
delete this._mosDevices[id1 || '']; | ||
}); | ||
} | ||
else { | ||
return Promise.reject('Device not found'); | ||
} | ||
} | ||
/** */ | ||
@@ -132,2 +193,15 @@ get complianceText() { | ||
} | ||
_registerMosDevice(myMosID, theirMosId0, theirMosId1, primary, secondary) { | ||
let id0 = myMosID + '_' + theirMosId0; | ||
let id1 = (theirMosId1 ? myMosID + '_' + theirMosId1 : null); | ||
let mosDevice = new MosDevice_1.MosDevice(id0, id1, this._conf, primary, secondary); | ||
this._mosDevices[id0] = mosDevice; | ||
if (id1) | ||
this._mosDevices[id1] = mosDevice; | ||
mosDevice.connect(); | ||
// emit to .onConnection | ||
if (this._onconnection) | ||
this._onconnection(mosDevice); | ||
return mosDevice; | ||
} | ||
/** */ | ||
@@ -138,4 +212,4 @@ _initiateIncomingConnections() { | ||
if (!this._conf.acceptsConnections) { | ||
return Promise.reject('Not configured for accepting connections'); | ||
// console.log('reject') | ||
return Promise.reject(false); | ||
} | ||
@@ -154,3 +228,6 @@ // setup two socket servers, then resolve with their listening statuses | ||
this._querySocketServer.listen() | ||
]); | ||
]).then(() => { | ||
// All sockets are open and listening at this point | ||
return; | ||
}); | ||
} | ||
@@ -160,6 +237,8 @@ /** */ | ||
let socketID = MosConnection.nextSocketID; | ||
this.emit('rawMessage', 'incoming_' + socketID, 'newConnection', 'From ' + client.socket.remoteAddress + ':' + client.socket.remotePort); | ||
// console.log('_registerIncomingClient', socketID, e.socket.remoteAddress) | ||
// handles socket listeners | ||
client.socket.on('close', () => { | ||
client.socket.on('close', ( /*hadError: boolean*/) => { | ||
this._disposeIncomingSocket(socketID); | ||
this.emit('rawMessage', 'incoming_' + socketID, 'closedConnection', ''); | ||
}); // => this._disposeIncomingSocket(e.socket, socketID)) | ||
@@ -176,2 +255,3 @@ client.socket.on('end', () => { | ||
let messageString = iconv.decode(data, 'utf16-be').trim(); | ||
this.emit('rawMessage', 'incoming', 'recieved', messageString); | ||
if (this._debug) | ||
@@ -221,5 +301,6 @@ console.log(`Socket got data (${socketID}, ${client.socket.remoteAddress}, ${client.portDescription}): ${data}`); | ||
message.prepare(mosMessageId); | ||
let msgStr = message.toString(); | ||
let buf = iconv.encode(msgStr, 'utf16-be'); | ||
let messageString = message.toString(); | ||
let buf = iconv.encode(messageString, 'utf16-be'); | ||
client.socket.write(buf, 'usc2'); | ||
this.emit('rawMessage', 'incoming_' + socketID, 'sent', messageString); | ||
}; | ||
@@ -230,6 +311,6 @@ if (!mosDevice && this._conf.openRelay) { | ||
if (parsed.mos.ncsID === this._conf.mosID) { | ||
mosDevice = this.registerMosDevice(this._conf.mosID, parsed.mos.mosID, null, null, null); | ||
mosDevice = this._registerMosDevice(this._conf.mosID, parsed.mos.mosID, null, null, null); | ||
} | ||
else if (parsed.mos.mosID === this._conf.mosID) { | ||
mosDevice = this.registerMosDevice(this._conf.mosID, parsed.mos.ncsID, null, null, null); | ||
mosDevice = this._registerMosDevice(this._conf.mosID, parsed.mos.ncsID, null, null, null); | ||
} | ||
@@ -277,2 +358,3 @@ } | ||
console.log('messageString---------\n', messageString); | ||
console.log('error', e); | ||
this.emit('error', e); | ||
@@ -279,0 +361,0 @@ } |
@@ -59,4 +59,9 @@ /// <reference types="node" /> | ||
readonly idSecondary: string | null; | ||
readonly primaryHost: string | null; | ||
readonly primaryId: string | null; | ||
readonly secondaryHost: string | null; | ||
readonly secondaryId: string | null; | ||
emitConnectionChange(): void; | ||
connect(): void; | ||
dispose(): Promise<void>; | ||
routeData(data: any): Promise<any>; | ||
@@ -63,0 +68,0 @@ getMachineInfo(): Promise<IMOSListMachInfo>; |
@@ -94,2 +94,14 @@ "use strict"; | ||
} | ||
get primaryHost() { | ||
return (this._primaryConnection ? this._primaryConnection.host : null); | ||
} | ||
get primaryId() { | ||
return (this._primaryConnection ? this._primaryConnection.id : null); | ||
} | ||
get secondaryHost() { | ||
return (this._secondaryConnection ? this._secondaryConnection.host : null); | ||
} | ||
get secondaryId() { | ||
return (this._secondaryConnection ? this._secondaryConnection.id : null); | ||
} | ||
emitConnectionChange() { | ||
@@ -105,2 +117,13 @@ if (this._callbackOnConnectionChange) | ||
} | ||
dispose() { | ||
let ps = []; | ||
if (this._primaryConnection) | ||
ps.push(this._primaryConnection.dispose()); | ||
if (this._secondaryConnection) | ||
ps.push(this._secondaryConnection.dispose()); | ||
return Promise.all(ps) | ||
.then(() => { | ||
return; | ||
}); | ||
} | ||
routeData(data) { | ||
@@ -110,7 +133,7 @@ if (data && data.hasOwnProperty('mos')) | ||
return new Promise((resolve, reject) => { | ||
if (this._debug) { | ||
if (this._debug) | ||
console.log('parsedData', data); | ||
// console.log('parsedTest', keys) | ||
// if (this._debug) console.log('parsedTest', keys) | ||
if (this._debug) | ||
console.log('keys', Object.keys(data)); | ||
} | ||
// Route and format data: | ||
@@ -470,3 +493,4 @@ // Profile 0: | ||
else { | ||
console.log(data); | ||
if (this._debug) | ||
console.log(data); | ||
let msg = new mosAck_1.MOSAck(); | ||
@@ -540,3 +564,3 @@ msg.ID = new mosString128_1.MosString128(0); // Depends on type of message, needs logic | ||
if (data.mos.roAck) { | ||
reject(data.mos.roAck); | ||
reject(Parser_1.Parser.xml2ROAck(data.mos.roAck)); | ||
} | ||
@@ -563,3 +587,3 @@ else if (data.mos.mosObj) { | ||
if (data.mos.roAck) { | ||
reject(data.mos.roAck); | ||
reject(Parser_1.Parser.xml2ROAck(data.mos.roAck)); | ||
} | ||
@@ -600,3 +624,3 @@ else if (data.mos.mosListAll) { | ||
if (data.mos.roAck) { | ||
reject(data.mos.roAck); | ||
reject(Parser_1.Parser.xml2ROAck(data.mos.roAck)); | ||
} | ||
@@ -728,4 +752,4 @@ else if (data.mos.roList) { | ||
this._currentConnection.executeCommand(message).then((data) => { | ||
if ((data.mos.roListAll || {}).ro) { | ||
let xmlRos = data.mos.roListAll.ro; | ||
if (data.mos.hasOwnProperty('roListAll')) { | ||
let xmlRos = (data.mos.roListAll || {}).ro; | ||
if (!Array.isArray(xmlRos)) | ||
@@ -735,3 +759,5 @@ xmlRos = [xmlRos]; | ||
xmlRos.forEach((xmlRo) => { | ||
ros.push(Parser_1.Parser.xml2ROBase(xmlRo)); | ||
if (xmlRo) { | ||
ros.push(Parser_1.Parser.xml2ROBase(xmlRo)); | ||
} | ||
}); | ||
@@ -742,3 +768,3 @@ resolve(ros); | ||
console.log(data.mos); | ||
reject('Unknown reply '); | ||
reject('Unknown reply'); | ||
} | ||
@@ -745,0 +771,0 @@ }).catch(reject); |
{ | ||
"name": "mos-connection", | ||
"version": "0.3.12", | ||
"version": "0.3.14", | ||
"description": "MOS compliant TCP/IP Socket connection.", | ||
@@ -99,7 +99,7 @@ "main": "dist/index.js", | ||
"trash-cli": "^1.4.0", | ||
"ts-jest": "^22.0.4", | ||
"tslint": "^5.4.3", | ||
"tslint-config-standard": "^6.0.1", | ||
"typedoc": "^0.8.0", | ||
"typescript": "^2.4.1" | ||
"ts-jest": "^22.4.4", | ||
"tslint": "^5.10.0", | ||
"tslint-config-standard": "^7.0.0", | ||
"typedoc": "^0.11.1", | ||
"typescript": "^2.8.3" | ||
}, | ||
@@ -106,0 +106,0 @@ "keywords": [ |
@@ -8,2 +8,4 @@ # MOS-Connection | ||
Docs: https://nrkno.github.io/tv-automation-mos-connection/ | ||
*Note: This library is currently under heavy develpoment, expect breaking changes.* | ||
@@ -10,0 +12,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
287373
4016
63