iobroker.lgtv
Version:
ioBroker LG WebOS SmartTV Adapter
836 lines (782 loc) • 38.3 kB
JavaScript
;
const utils = require('@iobroker/adapter-core');
let adapter;
const LGTV = require('lgtv2');
const wol = require('wol');
const fs = require('fs');
const path = require('path');
let hostUrl;
let isConnect = false;
let lgtvobj, clientKey, volume, oldvolume;
let keyfile = 'lgtvkeyfile';
let renewTimeout = null;
let healthInterval = null;
let curApp = '';
function startAdapter(options) {
options = options || {};
Object.assign(options, {
systemConfig: true,
name: 'lgtv',
stateChange: (id, state) => {
if (id && state && !state.ack) {
id = id.substring(adapter.namespace.length + 1);
let vals, dx, dy;
if (~state.val.toString().indexOf(',')) {
vals = state.val.toString().split(',');
dx = parseInt(vals[0]);
dy = parseInt(vals[1]);
}
adapter.log.debug(`State change "${id}" - VALUE: ${state.val}`);
switch (id) {
case 'states.popup':
adapter.log.debug(`Sending popup message "${state.val}" to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://system.notifications/createToast', { message: state.val }, (err, _val) => {
if (!err) {
adapter.setState('states.popup', state.val, true);
}
});
break;
case 'states.turnOff':
adapter.log.debug(`Sending turn OFF command to WebOS TV: ${adapter.config.ip}`);
if (adapter.config.power) {
sendCommand('button', { name: 'power' }, (err, _val) => {
if (!err) {
adapter.setState('states.turnOff', state.val, true);
}
});
} else {
adapter.getState(`${adapter.namespace}.states.on`, (err, tv_on) => {
if (err) {
adapter.log.debug(`Error getting "on" state ${err}`);
return;
}
if (!tv_on.val) {
adapter.log.debug('TV is already off');
adapter.setState('states.turnOff', state.val, true);
return;
}
sendCommand('ssap://system/turnOff', (err, val) => {
if (!err && val.returnValue === true) {
adapter.setState('states.turnOff', state.val, true);
adapter.setState('states.on', false, true);
}
});
});
}
break;
case 'states.power':
if (!state.val) {
adapter.log.debug(`Sending turn OFF command to WebOS TV: ${adapter.config.ip}`);
if (adapter.config.power) {
sendCommand('button', { name: 'power' }, (err, _val) => {
if (!err) {
adapter.setState('states.power', state.val, true);
}
});
} else {
adapter.getState(`${adapter.namespace}.states.on`, (err, tv_on) => {
if (err) {
adapter.log.debug(`Error getting "on" state ${err}`);
return;
}
if (!tv_on.val) {
adapter.log.debug('TV is already off');
adapter.setState('states.power', state.val, true);
return;
}
sendCommand('ssap://system/turnOff', (err, val) => {
if (!err && val.returnValue === true) {
adapter.setState('states.power', state.val, true);
adapter.setState('states.on', false, true);
}
});
});
}
} else {
adapter.getState(`${adapter.namespace}.states.mac`, (err, macState) => {
adapter.log.debug(`GetState mac: ${JSON.stringify(macState)}`);
if (macState) {
if (adapter.config.wolwithip) {
adapter.log.debug(`Should include mac address with WOL packet.`);
wol.wake(macState.val, { address: adapter.config.ip }, (err, _res) => {
if (!err) {
adapter.log.debug(
`Send WOL to MAC: {${macState.val}} & IP: {${adapter.config.ip}} OK`,
);
}
});
} else {
wol.wake(macState.val, (err, _res) => {
if (!err) {
adapter.log.debug(`Send WOL to MAC: {${macState.val}} OK`);
}
});
}
} else {
adapter.log.error(
'Error get MAC address TV. Please turn on the TV manually first!',
);
}
});
}
break;
case 'states.mute':
adapter.log.debug(`Sending mute ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://audio/setMute', { mute: state.val }, (err, _val) => {
if (!err) {
adapter.setState('states.mute', state.val, true);
}
});
break;
case 'states.volume':
adapter.log.debug(
`Sending volume change ${state.val} command to WebOS TV: ${adapter.config.ip}`,
);
oldvolume = volume;
SetVolume(state.val);
break;
case 'states.volumeUp':
adapter.log.debug(`Sending volumeUp ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://audio/volumeUp', null, (err, _val) => {
if (!err) {
adapter.setState('states.volumeUp', !!state.val, true);
}
});
break;
case 'states.volumeDown':
adapter.log.debug(`Sending volumeDown ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://audio/volumeDown', null, (err, _val) => {
if (!err) {
adapter.setState('states.volumeDown', !!state.val, true);
}
});
break;
case 'states.channel':
adapter.log.debug(
`Sending switch to channel ${state.val} command to WebOS TV: ${adapter.config.ip}`,
);
sendCommand('ssap://tv/openChannel', { channelNumber: state.val.toString() }, (err, _val) => {
if (!err) {
adapter.setState('states.channel', state.val, true);
} else {
adapter.log.debug(`Error in switching to channel: ${err}`);
}
});
break;
case 'states.channelUp':
adapter.log.debug(`Sending channelUp ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://tv/channelUp', null, (err, _val) => {
if (!err) {
adapter.setState('states.channelUp', !!state.val, true);
}
});
break;
case 'states.channelDown':
adapter.log.debug(`Sending channelDown ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://tv/channelDown', null, (err, _val) => {
if (!err) {
adapter.setState('states.channelDown', !!state.val, true);
}
});
break;
case 'states.mediaPlay':
adapter.log.debug(`Sending mediaPlay ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://media.controls/play', null, (err, _) => {
if (!err) {
adapter.setState('states.mediaPlay', !!state.val, true);
}
});
break;
case 'states.mediaPause':
adapter.log.debug(`Sending mediaPause ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://media.controls/pause', null, (err, _val) => {
if (!err) {
adapter.setState('states.mediaPause', !!state.val, true);
}
});
break;
case 'states.openURL':
if (!state.val) {
return adapter.setState('states.openURL', '', true);
}
adapter.log.debug(`Sending open ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://system.launcher/open', { target: state.val }, (err, _val) => {
if (!err) {
adapter.setState('states.openURL', state.val, true);
}
});
break;
case 'states.mediaStop':
adapter.log.debug(`Sending mediaStop ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://media.controls/stop', null, (err, _val) => {
if (!err) {
adapter.setState('states.mediaStop', !!state.val, true);
}
});
break;
case 'states.mediaFastForward':
adapter.log.debug(
`Sending mediaFastForward ${state.val} command to WebOS TV: ${adapter.config.ip}`,
);
sendCommand('ssap://media.controls/fastForward', null, (err, _val) => {
if (!err) {
adapter.setState('states.mediaFastForward', !!state.val, true);
}
});
break;
case 'states.mediaRewind':
adapter.log.debug(`Sending mediaRewind ${state.val} command to WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://media.controls/rewind', null, (err, _val) => {
if (!err) {
adapter.setState('states.mediaRewind', !!state.val, true);
}
});
break;
case 'states.3Dmode':
adapter.log.debug(`Sending 3Dmode ${state.val} command to WebOS TV: ${adapter.config.ip}`);
switch (state.val) {
case true:
sendCommand('ssap://com.webos.service.tv.display/set3DOn', null, (err, _val) => {
if (!err) {
adapter.setState('states.3Dmode', !!state.val, true);
}
});
break;
case false:
sendCommand('ssap://com.webos.service.tv.display/set3DOff', null, (err, _val) => {
if (!err) {
adapter.setState('states.3Dmode', !!state.val, true);
}
});
break;
}
break;
case 'states.launch':
adapter.log.debug(`Sending launch command ${state.val} to WebOS TV: ${adapter.config.ip}`);
switch (state.val) {
case 'livetv':
adapter.log.debug(`Switching to LiveTV on WebOS TV: ${adapter.config.ip}`);
sendCommand(
'ssap://system.launcher/launch',
{ id: 'com.webos.app.livetv' },
(err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
}
},
);
break;
case 'smartshare':
adapter.log.debug(`Switching to SmartShare App on WebOS TV: ${adapter.config.ip}`);
sendCommand(
'ssap://system.launcher/launch',
{ id: 'com.webos.app.smartshare' },
(err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
}
},
);
break;
case 'tvuserguide':
adapter.log.debug(`Switching to TV Userguide App on WebOS TV: ${adapter.config.ip}`);
sendCommand(
'ssap://system.launcher/launch',
{ id: 'com.webos.app.tvuserguide' },
(err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
}
},
);
break;
case 'netflix':
adapter.log.debug(`Switching to Netflix App on WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://system.launcher/launch', { id: 'netflix' }, (err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
}
});
break;
case 'youtube':
adapter.log.debug(`Switching to Youtube App on WebOS TV: ${adapter.config.ip}`);
sendCommand(
'ssap://system.launcher/launch',
{ id: 'youtube.leanback.v4' },
(err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
}
},
);
break;
case 'prime':
adapter.log.debug(`Switching to Amazon Prime App on WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://system.launcher/launch', { id: 'lovefilm.de' }, (err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
}
});
break;
case 'amazon':
adapter.log.debug(`Switching to Amazon Prime App on WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://system.launcher/launch', { id: 'amazon' }, (err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
}
});
break;
default:
//state.val = '"' + state.val + '"';
adapter.log.debug(`Opening app ${state.val} on WebOS TV: ${adapter.config.ip}`);
sendCommand('ssap://system.launcher/launch', { id: state.val }, (err, _val) => {
if (!err) {
adapter.setState('states.launch', state.val, true);
} else {
adapter.log.debug(
`Error opening app ${state.val} on WebOS TV: ${adapter.config.ip}`,
);
}
});
break;
}
break;
case 'states.input':
adapter.log.debug(
`Sending switch to input "${state.val}" command to WebOS TV: ${adapter.config.ip}`,
);
sendCommand('ssap://tv/switchInput', { inputId: state.val }, (err, val) => {
if (!err && val.returnValue) {
adapter.setState('states.input', state.val, true);
}
});
break;
case 'states.raw':
adapter.log.debug(`Sending RAW command api "${state.val}" to WebOS TV: ${adapter.config.ip}`);
try {
const obj = JSON.parse(state.val);
sendCommand(obj.url, obj.cmd, (err, val) => {
if (!err) {
adapter.log.debug(`Response RAW command api ${JSON.stringify(val)}`);
adapter.setState('states.raw', JSON.stringify(val), true);
}
});
} catch (e) {
adapter.log.error(`Parse error RAW command api - ${e}`);
}
break;
case 'states.youtube': {
let uri = state.val;
if (!uri) {
return adapter.setState('states.youtube', '', true);
}
if (!~uri.indexOf('http')) {
uri = `https://www.youtube.com/watch?v=${uri}`;
}
sendCommand(
'ssap://system.launcher/launch',
{ id: 'youtube.leanback.v4', contentId: uri },
(err, _val) => {
if (!err) {
adapter.setState('states.youtube', state.val, true);
}
},
);
break;
}
case 'states.drag':
// The event type is 'move' for both moves and drags.
if (dx && dy) {
sendCommand('move', { dx: dx, dy: dy, drag: vals[2] === 'drag' ? 1 : 0 }, (err, _val) => {
if (!err) {
adapter.setState(id, state.val, true);
}
});
}
break;
case 'states.scroll':
if (dx && dy) {
sendCommand('scroll', { dx: dx, dy: dy }, (err, _val) => {
if (!err) {
adapter.setState(id, state.val, true);
}
});
}
break;
case 'states.click':
sendCommand('click', {}, (err, _val) => {
if (!err) {
adapter.setState(id, state.val, true);
}
});
break;
case 'states.soundOutput':
sendCommand(
'ssap://com.webos.service.apiadapter/audio/changeSoundOutput',
{ output: state.val },
(err, _val) => {
if (!err) {
adapter.setState(id, state.val, true);
}
},
);
break;
default:
if (~id.indexOf('remote')) {
adapter.log.debug(`State change "${id}" - VALUE: ${JSON.stringify(state)}`);
const ids = id.split('.');
const key = ids[ids.length - 1].toString().toUpperCase();
sendCommand('button', { name: key }, (err, _val) => {
if (!err) {
adapter.setState(id, state.val, true);
} // ?
});
}
break;
}
}
},
unload: callback => {
renewTimeout && clearTimeout(renewTimeout);
lgtvobj && lgtvobj.disconnect();
isConnect = false;
checkConnection(true);
callback();
},
ready: () => {
main();
},
});
adapter = new utils.Adapter(options);
return adapter;
}
function connect(cb) {
hostUrl = `wss://${adapter.config.ip}:3001`;
let reconnect = adapter.config.reconnect;
if (!reconnect || isNaN(reconnect) || reconnect < 5000) {
reconnect = 5000;
}
lgtvobj = new LGTV({
url: hostUrl,
timeout: adapter.config.timeout,
reconnect: reconnect,
clientKey: clientKey,
saveKey: (key, cb) => {
fs.writeFile(keyfile, key, cb);
},
wsconfig: {
keepalive: true,
keepaliveInterval: 10000,
dropConnectionOnKeepaliveTimeout: false,
keepaliveGracePeriod: 5000,
tlsOptions: {
rejectUnauthorized: false,
},
},
});
lgtvobj.on('connecting', host => {
adapter.log.debug(`Connecting to WebOS TV: ${host}`);
checkConnection();
});
lgtvobj.on('close', e => {
adapter.log.debug(`Connection closed: ${e}`);
checkConnection();
});
lgtvobj.on('prompt', () => {
adapter.log.debug(`Waiting for pairing confirmation on WebOS TV ${adapter.config.ip}`);
});
lgtvobj.on('error', error => {
adapter.log.debug(`Error on connecting or sending command to WebOS TV: ${error}`);
});
lgtvobj.on('connect', (_error, _response) => {
adapter.log.debug('WebOS TV Connected');
isConnect = true;
adapter.setStateChanged('info.connection', true, true);
lgtvobj.subscribe('ssap://audio/getVolume', (err, res) => {
adapter.log.debug(`audio/getVolume: ${JSON.stringify(res)}`);
/*
{"changed":["volume"],"returnValue":true,"cause":"volumeUp","volumeMax":100,"scenario":"mastervolume_tv_speaker","muted":false,"volume":14,"action":"changed","supportvolume"...
{"changed":["muted"],"returnValue":true,"volumeMax":100,"scenario":"mastervolume_tv_speaker","muted":true,"volume":15,"caller":"com.webos.surfacemanager.audio","action":"change..
changed in WebOS 5?
{"volumeStatus":{"cause":"volumeDown","mode":"normal","adjustVolume":true,"activeStatus":true,"muteStatus":false,"volume":7,"soundOutput":"tv_speaker","maxVolume":100}
{"volumeStatus":{"activeStatus":true,"adjustVolume":true,"maxVolume":100,"muteStatus":true,"volume":10,"mode":"normal","soundOutput":"tv_speaker"}
*/
if (res) {
if (res.changed) {
if (~res.changed.indexOf('volume')) {
volume = parseInt(res.volume);
adapter.setState('states.volume', volume, true);
}
if (~res.changed.indexOf('muted')) {
adapter.setState('states.mute', res.muted, true);
}
} else if (res.volumeStatus) {
volume = parseInt(res.volumeStatus.volume);
adapter.setState('states.volume', volume, true);
adapter.setState('states.mute', res.volumeStatus.muteStatus, true);
}
}
});
lgtvobj.request('ssap://tv/getExternalInputList', (err, res) => {
if (!err && res.devices) {
adapter.extendObject('states.input', { common: { states: null } }, () => {
adapter.extendObject('states.input', { common: { states: inputList(res.devices) } });
});
}
});
lgtvobj.request('ssap://com.webos.applicationManager/listLaunchPoints', (err, res) => {
if (!err && res.launchPoints) {
adapter.extendObject('states.launch', { common: { states: null } }, () => {
adapter.extendObject('states.launch', { common: { states: launchList(res.launchPoints) } });
});
}
});
lgtvobj.subscribe('ssap://tv/getCurrentChannel', (err, res) => {
if (!err && res) {
adapter.log.debug(`tv/getCurrentChannel: ${JSON.stringify(res)}`);
adapter.setState('states.channel', res.channelNumber || '', true);
adapter.setState('states.channelId', res.channelId || '', true);
} else {
adapter.log.debug(`ERROR on getCurrentChannel: ${err}`);
}
});
lgtvobj.subscribe('ssap://com.webos.applicationManager/getForegroundAppInfo', (err, res) => {
if (!err && res) {
adapter.log.debug(`DEBUGGING getForegroundAppInfo: ${JSON.stringify(res)}`);
curApp = res.appId || '';
if (!curApp) {
// some TV send empty app first, if they switched on
setTimeout(function () {
if (!curApp) {
// curApp is not set in meantime
if (healthInterval && !adapter.config.healthInterval) {
clearInterval(healthInterval);
healthInterval = false; // TV works fine, healthInterval is not longer nessessary
adapter.log.info(
'detect poweroff event, polling not longer nessesary. if you have problems, check settings',
);
}
checkCurApp(); // so TV is off
}
}, 1500);
} else {
checkCurApp();
}
} else {
adapter.log.debug(`ERROR on get input and app: ${err}`);
}
});
lgtvobj.subscribe('ssap://com.webos.service.apiadapter/audio/getSoundOutput', (err, res) => {
if (!err && res) {
adapter.log.debug(`audio/getSoundOutput: ${JSON.stringify(res)}`);
adapter.setState('states.soundOutput', res.soundOutput || '', true);
} else {
adapter.log.debug(`ERROR on getSoundOutput: ${err}`);
}
});
sendCommand('ssap://api/getServiceList', null, (err, val) => {
if (!err) {
adapter.log.debug(`Service list: ${JSON.stringify(val)}`);
}
});
sendCommand('ssap://com.webos.service.update/getCurrentSWInformation', null, (err, val) => {
if (!err) {
adapter.log.debug(`getCurrentSWInformation: ${JSON.stringify(val)}`);
adapter.setState('states.mac', adapter.config.mac ? adapter.config.mac : val.device_id, true);
}
});
sendCommand('ssap://system/getSystemInfo', null, (err, val) => {
if (!err) {
adapter.log.debug(`getSystemInfo: ${JSON.stringify(val)}`);
adapter.setState('states.model', val.modelName, true);
}
});
cb && cb();
});
}
const launchList = arr => {
const obj = { livetv: 'Live TV' };
arr.forEach(function (o, _i) {
obj[o.id] = o.title;
});
return obj;
};
const inputList = arr => {
const obj = {};
arr.forEach(function (o, _i) {
obj[o.id] = `${o.label} (${o.id})`;
});
return obj;
};
function checkConnection(secondCheck) {
if (secondCheck) {
if (!isConnect) {
adapter.setStateChanged('info.connection', false, true);
healthInterval && clearInterval(healthInterval);
checkCurApp(true);
}
} else {
isConnect = false;
setTimeout(checkConnection, 10000, true); //check, if isConnect is changed in 10 sec
}
}
function checkCurApp(powerOff) {
if (powerOff) {
curApp = '';
}
const isTVon = !!curApp;
adapter.log.debug(curApp ? `cur app is ${curApp}` : 'TV is off');
if (curApp == 'com.webos.app.livetv') {
setTimeout(() => {
lgtvobj.subscribe('ssap://tv/getCurrentChannel', (err, res) => {
if (!err && res) {
adapter.log.debug(`tv/getCurrentChannel: ${JSON.stringify(res)}`);
adapter.setState('states.channel', res.channelNumber || '', true);
adapter.setState('states.channelId', res.channelId || '', true);
} else {
adapter.log.debug(`ERROR on getCurrentChannel: ${err}`);
}
});
}, 3000);
}
adapter.setStateChanged('states.currentApp', curApp, true);
const inp = curApp.split('.').pop();
if (inp && inp.indexOf('hdmi') == 0) {
adapter.setStateChanged('states.input', `HDMI_${inp[4]}`, true);
adapter.setStateChanged('states.launch', '', true);
} else {
adapter.setStateChanged('states.input', '', true);
adapter.setStateChanged('states.launch', inp, true);
}
adapter.setStateChanged('states.power', isTVon, true);
adapter.setStateChanged('states.on', isTVon, true, function (err, stateID, notChanged) {
if (!notChanged) {
// state was changed
renewTimeout && clearTimeout(renewTimeout); // avoid toggeling
if (isTVon) {
// if tv is now switched on ...
adapter.log.debug('renew connection in one minute for stable subscriptions...');
renewTimeout = setTimeout(() => {
lgtvobj.disconnect();
setTimeout(lgtvobj.connect, 500, hostUrl);
if (healthInterval !== false) {
healthInterval = setInterval(
sendCommand,
adapter.config.healthInterval || 60000,
'ssap://com.webos.service.tv.time/getCurrentTime',
null,
(err, _val) => {
adapter.log.debug(`check TV connection: ${err || 'ok'}`);
if (err) {
checkCurApp(true);
}
},
);
}
}, 60000);
}
}
});
}
function sendCommand(cmd, options, cb) {
if (isConnect) {
sendPacket(cmd, options, (_error, response) => {
cb && cb(_error, response);
});
}
}
function sendPacket(cmd, options, cb) {
if (~cmd.indexOf('ssap:') || ~cmd.indexOf('com.')) {
lgtvobj.request(cmd, options, (_error, response) => {
if (_error) {
adapter.log.debug(`ERROR! Response from TV: ${response ? JSON.stringify(response) : _error}`);
}
cb && cb(_error, response);
});
} else {
bypassCertificateValidation();
lgtvobj.getSocket('ssap://com.webos.service.networkinput/getPointerInputSocket', (err, sock) => {
if (!err) {
sock.send(cmd, options);
}
});
}
}
function bypassCertificateValidation() {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
const tls = require('tls');
tls.checkServerIdentity = (_servername, _cert) => {
// Skip certificate verification
return undefined;
};
}
function SetVolume(val) {
if (val >= volume + 5) {
let vol = oldvolume;
const interval = setInterval(() => {
vol = vol + 2;
if (vol >= val) {
vol = val;
clearInterval(interval);
}
sendCommand('ssap://audio/setVolume', { volume: vol }, (err, _resp) => {
if (!err) {
//
}
});
}, 500);
} else {
sendCommand('ssap://audio/setVolume', { volume: val }, (err, _resp) => {
if (!err) {
//
}
});
}
}
function main() {
if (adapter.config.ip) {
adapter.log.info(`Ready. Configured WebOS TV IP: ${adapter.config.ip}`);
adapter.subscribeStates('*');
const dir = path.join(utils.getAbsoluteDefaultDataDir(), adapter.namespace.replace('.', '_'));
keyfile = path.join(dir, keyfile);
adapter.log.debug(`adapter.config = ${JSON.stringify(adapter.config)}`);
if (adapter.config.healthInterval < 1) {
healthInterval = false;
} else if (adapter.config.healthInterval < 5000) {
adapter.log.info(`Health-Interval must not be less than 5s; setting adjusted.`);
adapter.config.healthInterval = 5000;
}
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
fs.readFile(keyfile, (err, data) => {
if (!err) {
try {
clientKey = data.toString();
} catch {
fs.writeFile(keyfile, '', err => {
if (err) {
adapter.log.error(`writeFile ERROR = ${JSON.stringify(err)}`);
}
});
}
} else {
fs.writeFile(keyfile, '', err => {
if (err) {
adapter.log.error(`writeFile ERROR = ${JSON.stringify(err)}`);
}
});
}
connect();
});
} else {
adapter.log.error('No configure IP address');
}
}
// If started as allInOne/compact mode => return function to create instance
if (module && module.parent) {
module.exports = startAdapter;
} else {
// or start the instance directly
startAdapter();
}