iobroker.fhem
Version:
199 lines (173 loc) • 6.51 kB
JavaScript
'use strict';
const events = require('events');
const net = require('net');
const util = require('util');
// define a constructor (object) and inherit EventEmitter functions
function Telnet(options) {
if (!(this instanceof Telnet)) return new Telnet();
const that = this;
this.params = {
port: options.port || 7072,
host: options.host || '127.0.0.1',
password: options.password || '',
_reconnect: options.reconnectTimeout || 10000,
_readOnly: options.readOnly || false,
prompt: options.prompt || 'fhem'
};
this.connectTimeout = null;
this.requestCB = null;
this.result = '';
this.ready = false;
this.shutdown = false;
this.connect = function () {
let buffer = '';
that.ready = false;
if (this.connectTimeout) {
clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
this.telnetSocket = net.createConnection(this.params, () => {
// write password
if (that.params.password) {
that.telnetSocket.write(that.params.password + '\n');
that.telnetSocket.write('\n\n');
} else {
that.telnetSocket.write('\n\n\n');
}
});
this.telnetSocket.on('error', error => {
buffer = null;
if (that.telnetSocket) {
that.emit('error', error);
that.telnetSocket.destroy();
that.telnetSocket = null;
}
if (!that.shutdown && !that.connectTimeout) that.connectTimeout = setTimeout(that.connect.bind(that), that.params._reconnect);
});
this.telnetSocket.on('end', () => {
buffer = null;
if (that.telnetSocket) {
that.telnetSocket.destroy();
that.telnetSocket = null;
that.emit('end');
}
if (!that.shutdown && !that.connectTimeout) that.connectTimeout = setTimeout(that.connect.bind(that), that.params._reconnect);
});
this.telnetSocket.on('close', () => {
buffer = null;
if (that.telnetSocket) {
that.telnetSocket.destroy();
that.telnetSocket = null;
that.emit('close');
}
if (!that.shutdown && !that.connectTimeout) that.connectTimeout = setTimeout(that.connect.bind(that), that.params._reconnect);
});
this.telnetSocket.on('data', data => {
if (that.shutdown) {
return;
}
buffer += data.toString();
const lines = buffer.split('\n');
buffer = lines[lines.length - 1];
lines.pop();
for (let line = 0; line < lines.length; line++) {
if (that.ready && lines[line] === that.params.prompt + ' ') {
continue;
}
// if event connection
if (that.params._readOnly) {
// if no prompt yet received
if (!that.ready) {
// wait for prompt
if (lines[line] === that.params.prompt + ' ') {
that.ready = true;
// send "inform" command
setTimeout(() => that.telnetSocket.write('inform on\n'), 100);
}
} else {
// emit command
that.emit('data', lines[line]);
}
} else {
// if command connection
// if no prompt yet received
if (!that.ready) {
// wait for prompt
if (lines[line] === that.params.prompt + ' ') {
that.ready = true;
that.emit('ready');
}
} else
// command finished
if (lines[line] === that.params.prompt + ' ') {
if (that.requestCB) {
that.requestCB(null, that.result);
that.result = '';
that.requestCB = null;
}
} else if (that.requestCB && lines[line].trim()) {
that.result += lines[line] + '\n';
} // else ignore
}
}
// if prompt
if (buffer === that.params.prompt + ' ') {
buffer = '';
if (that.params._readOnly) {
if (!that.ready) {
that.ready = true;
that.telnetSocket && setTimeout(() =>
that.telnetSocket && that.telnetSocket.write('inform on\n'), 100);
}
} else {
if (!that.ready) {
that.ready = true;
that.emit('ready');
} else if (that.requestCB) {
// command finished
that.requestCB(null, that.result);
that.result = '';
that.requestCB = null;
}
}
}
});
};
this.send = function (cmd, cb) {
if (!cmd) return;
if (cmd[cmd.length - 1] !== '\n') {
cmd += '\n';
}
if (that.telnetSocket) {
that.telnetSocket.write(cmd);
} else {
that.emit('error', 'Socket not exists');
}
if (cb) {
this.result = null;
this.result = '';
this.requestCB = cb;
}
};
this.destroy = function () {
this.shutdown = true;
if (this.connectTimeout) {
clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
if (this.telnetSocket) {
this.telnetSocket.destroy();
this.telnetSocket = null;
}
};
this.isReady = function () {
return this.ready;
};
this.isCommandRunning = function () {
return !!this.requestCB;
};
this.connect();
return this;
}
util.inherits(Telnet, events.EventEmitter);
module.exports = Telnet;