From c335045aa3e751482592644144baaa87160deb38 Mon Sep 17 00:00:00 2001
From: foxthefox <16841643+foxthefox@users.noreply.github.com>
Date: Fri, 31 Mar 2023 08:18:23 +0200
Subject: [PATCH 1/2] 2.1.0
---
README.md | 49 +++-
lib/fritz_ahaapi.js | 141 ++++++++---
lib/fritz_mockserver.js | 340 ++++++++++++++++++---------
lib/mjs_version/start_mockserver.mjs | 16 ++
package.json | 2 +-
test/integration.js | 291 ++++++++++++++++++++---
6 files changed, 665 insertions(+), 174 deletions(-)
create mode 100644 lib/mjs_version/start_mockserver.mjs
diff --git a/README.md b/README.md
index f86b225..ae887b0 100644
--- a/README.md
+++ b/README.md
@@ -43,9 +43,56 @@ const logout = await fritz.logout_SID();
see the example.js.
## API Calls
-* todo for 1.0.3
+### reading FB
+
+|API-call|implements FB call|
+|:----|:---|
+|getDeviceListInfos()| getdevicelistinfos|
+|getTemplateListInfos()| gettemplatelistinfos|
+|getTriggerListInfos()| gettriggerlistinfos|
+|getColorDefaults()| getcolordefaults|
+|getDeviceInfos(ain)| getdeviceinfos|
+|getBasicDeviceStats(ain)| getbasicdevicestats|
+|getSwitchList()| getswitchlist|
+|getSwitchState(ain)| getswitchstate|
+|getSwitchPresent(ain)| getswitchpresent|
+|getSwitchPower(ain)| getswitchpower|
+|getSwitchEnergy(ain)| getswitchenergy|
+|getSwitchName(ain)| getswitchname|
+|getTemperature(ain)| gettemperature|
+|getHkrTsoll(ain)| gethkrtsoll|
+|getHkrKomfort(ain)| gethkrkomfort|
+|getHkrAbsenk(ain)| gethkrabsenk|
+|getUserPermissions()| not a FB call|
+
+### commands to FB
+
+|API-call|implements FB call|
+|:----|:---|
+|applyTemplate(ain)| applytemplate|
+|setSwitchOn(ain)| setswitchon|
+|setSwitchOff(ain)| setswitchoff|
+|setSwitchToggle(ain)| setswitchtoggle|
+|setSimpleOn(ain)| setsimpleonoff&onoff=1|
+|setSimpleOff(ain)| setsimpleonoff&onoff=0|
+|setSimpleToggle(ain)| setsimpletoggle|
+|setTempTarget(ain, temp)| sethkrtsoll|
+|setHkrBoost(ain, time)| sethkrboost|
+|setWindowOpen(ain, time)| sethkrwindowopen|
+|setBlind(ain, target)| setblind|
+|setLevel(ain, level)| setlevel|
+|setColorTemperature(ain, temp)| setcolortemperature|
+|setColor(ain, saturation, hue)| setcolor|
+|setUnmappedColor(ain, saturation, hue)| setunmappedcolor|
+|setTriggerActive(ain, active)| settriggeractive|
## Changelog
+### 2.1.0
+* (foxthefox) new functions setSimpleToggle, setLevelPercentage, setUnmappedColor, setTriggerActive
+* (foxthefox) remove spaces in ain if part of the function call
+* (foxthefox) extended testing
+* (foxthefox) debug-flag as new parameter during instantiation
+
### 2.0.1
* (foxthefox) forgotten "this." at apiresponse
diff --git a/lib/fritz_ahaapi.js b/lib/fritz_ahaapi.js
index ca6bee7..276d3ae 100644
--- a/lib/fritz_ahaapi.js
+++ b/lib/fritz_ahaapi.js
@@ -33,13 +33,13 @@ class Fritz {
* @param {string} uri
* @param {object} options
*/
- constructor(username, password, uri, options) {
+ constructor(username, password, uri, debug, options) {
this.sid = null;
this.username = username;
this.password = password;
this.url = { url: uri || 'http://fritz.box' };
this.options = options;
- this.debug = false;
+ this.debug = debug;
this.newVersion = null;
}
@@ -84,6 +84,7 @@ class Fritz {
*/
async getBasicDeviceStats(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('getbasicdevicestats', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -117,8 +118,10 @@ class Fritz {
*/
async setSwitchOn(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('setswitchon', ain, 1);
- return Promise.resolve(/^1/.test(body));
+ //return Promise.resolve(/^1/.test(body));
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
@@ -130,8 +133,10 @@ class Fritz {
*/
async setSwitchOff(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('setswitchoff', ain, 1);
- return Promise.resolve(/^1/.test(body));
+ //return Promise.resolve(/^1/.test(body));
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
@@ -139,8 +144,10 @@ class Fritz {
//set switchtoggle
async setSwitchToggle(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('setswitchtoggle', ain, 1);
- return Promise.resolve(/^1/.test(body));
+ //return Promise.resolve(/^1/.test(body));
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
@@ -152,8 +159,9 @@ class Fritz {
*/
async setSimpleOn(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('setsimpleonoff&onoff=1', ain, 1);
- return Promise.resolve('OK');
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
@@ -165,13 +173,27 @@ class Fritz {
*/
async setSimpleOff(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('setsimpleonoff&onoff=0', ain, 1);
- return Promise.resolve('OK');
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
}
+ // toggle an device. returns the state the outlet was set to
+ /**
+ * @param {string} ain
+ */
+ async setSimpleToggle(ain) {
+ try {
+ ain = ain.replace(/\s/g, '');
+ const body = await this.executeCommand2('setsimpleonoff&onoff=2', ain, 1);
+ return Promise.resolve(body);
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ }
// set target temperature (Solltemperatur)
/**
* @param {string} ain
@@ -179,8 +201,9 @@ class Fritz {
*/
async setTempTarget(ain, temp) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('sethkrtsoll¶m=' + Fritz.temp2api(temp), ain, 1);
- return Promise.resolve(temp);
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
@@ -193,6 +216,7 @@ class Fritz {
*/
async setHkrBoost(ain, time) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('sethkrboost&endtimestamp=' + time, ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -207,6 +231,7 @@ class Fritz {
*/
async setWindowOpen(ain, time) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('sethkrwindowopen&endtimestamp=' + time, ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -221,27 +246,43 @@ class Fritz {
*/
async setBlind(ain, target) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('setblind&target=' + target, ain, 1);
- return Promise.resolve(target);
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
}
- // set level (dimmer etc.)
+ // set level (dimmer etc.) 0...255
/**
* @param {string} ain
* @param {string | number | boolean} level
*/
async setLevel(ain, level) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('setlevel&level=' + level, ain, 1);
- return Promise.resolve(level);
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
}
+ // set level in percent (dimmer etc.) 0...199%
+ /**
+ * @param {string} ain
+ * @param {string | number | boolean} level
+ */
+ async setLevelPercentage(ain, level) {
+ try {
+ ain = ain.replace(/\s/g, '');
+ const body = await this.executeCommand2('setlevelpercentage&level=' + level, ain, 1);
+ return Promise.resolve(body);
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ }
// set color temperature
/**
* @param {string} ain
@@ -249,12 +290,13 @@ class Fritz {
*/
async setColorTemperature(ain, temp) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2(
'setcolortemperature&temperature=' + Fritz.colortemp2api(temp) + '&duration=0',
ain,
1
);
- return Promise.resolve(temp);
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
@@ -269,6 +311,7 @@ class Fritz {
*/
async setColor(ain, saturation, hue) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2(
'setcolor&saturation=' + saturation + '&hue=' + hue + '&duration=0',
ain,
@@ -289,6 +332,7 @@ class Fritz {
*/
async setUnmappedColor(ain, saturation, hue) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2(
'setunmappedcolor&saturation=' + saturation + '&hue=' + hue + '&duration=0',
ain,
@@ -307,9 +351,10 @@ class Fritz {
*/
async setTriggerActive(ain, active) {
try {
+ ain = ain.replace(/\s/g, '');
const val = active === 1 || active === '1' || active === true ? '1' : '0';
- const body = await this.executeCommand2('settriggeractive¶m=' + val, ain, 1);
- return Promise.resolve(active);
+ const body = await this.executeCommand2('settriggeractive&active=' + val, ain, 1);
+ return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
}
@@ -320,6 +365,7 @@ class Fritz {
*/
async applyTemplate(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = await this.executeCommand2('applytemplate', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -340,6 +386,7 @@ class Fritz {
// getswitchstate
async getSwitchState(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('getswitchstate', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -358,6 +405,7 @@ class Fritz {
// getswitchpower
async getSwitchPower(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('getswitchpower', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -367,6 +415,7 @@ class Fritz {
// getswitchenergy
async getSwitchEnergy(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('getswitchenergy', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -376,6 +425,7 @@ class Fritz {
// getswitchname
async getSwitchName(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('getswitchname', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -385,6 +435,7 @@ class Fritz {
// gettemperature
async getTemperature(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('gettemperature', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -394,6 +445,7 @@ class Fritz {
// gethkrtsoll
async getHkrTsoll(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('gethkrtsoll', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -403,6 +455,7 @@ class Fritz {
// gethkrkomfort
async getHkrKomfort(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('gethkrkomfort', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -412,6 +465,7 @@ class Fritz {
// gethkrabsenk
async getHkrAbsenk(ain) {
try {
+ ain = ain.replace(/\s/g, '');
const body = this.executeCommand2('gethkrabsenk', ain, 1);
return Promise.resolve(body);
} catch (error) {
@@ -421,7 +475,8 @@ class Fritz {
// getdeviceinfos
async getDeviceInfos(ain) {
try {
- const body = this.executeCommand2('getdevicelistinfos', ain, 1);
+ ain = ain.replace(/\s/g, '');
+ const body = this.executeCommand2('getdeviceinfos', ain, 1);
return Promise.resolve(body);
} catch (error) {
return Promise.reject(error);
@@ -446,7 +501,9 @@ class Fritz {
try {
const state = await this.get_login_state(box_url); //Aufrufe von statischen methoden aus anderen statischen methoden der gleichen Klasse mit this
let challenge_response = null;
- //console.log('state ', state);
+ if (this.debug) {
+ console.log('get_login_state ', state);
+ }
if (state.pbkf2 === true) {
if (this.debug) console.log('PBKDF2 supported');
this.newVersion = true;
@@ -477,11 +534,15 @@ class Fritz {
};
} else {
if (sidORrights === true) {
- //console.log('SID ', sid.sessionID);
+ if (this.debug) {
+ console.log('SID ', sid.sessionID);
+ }
this.sid = sid.sessionID;
return sid.sessionID;
} else {
- //console.log('rights ', sid.rights);
+ if (this.debug) {
+ console.log('rights ', sid.rights);
+ }
return sid.rights;
}
}
@@ -525,12 +586,12 @@ class Fritz {
if (protocol == 'http:') {
http = require('http');
defaultport = 80;
- if (this.debug) console.log('using http');
+ if (this.debug) console.log('get_login_state using http');
} else if (protocol == 'https:') {
http = require('https');
defaultport = 443;
//http.globalAgent.options.secureProtocol = 'SSLv3_method';
- if (this.debug) console.log('using https');
+ if (this.debug) console.log('get_login_state using https');
} else {
console.log('invalid protocol');
}
@@ -555,8 +616,8 @@ class Fritz {
reject({
msg: 'http.request error',
function: 'get_login_state',
- error: res.statusCode,
- response: res
+ error: res,
+ status: res.statusCode
});
}
// cumulate data
@@ -571,7 +632,16 @@ class Fritz {
const challenge = responseBody.match('(.*?)')[1];
const blocktime = Math.floor(responseBody.match('(.*?)')[1]);
const pbkf2 = challenge.startsWith('2$') ? true : false;
- //console.log('get login state result: ' + challenge + ' blocktime: ' + blocktime + ' pb: ' + pbkf2);
+ if (this.debug) {
+ console.log(
+ 'get login state result: ' +
+ challenge +
+ ' blocktime: ' +
+ blocktime +
+ ' pb: ' +
+ pbkf2
+ );
+ }
resolve({ challenge: challenge, blocktime: blocktime, pbkf2: pbkf2 });
} else {
reject({
@@ -661,12 +731,12 @@ class Fritz {
if (protocol == 'http:') {
http = require('http');
defaultport = 80;
- if (this.debug) console.log('using http');
+ if (this.debug) console.log('send_response using http');
} else if (protocol == 'https:') {
http = require('https');
defaultport = 443;
//http.globalAgent.options.secureProtocol = 'SSLv3_method';
- if (this.debug) console.log('using https');
+ if (this.debug) console.log('send_response using https');
} else {
console.log('invalid protocol');
}
@@ -696,7 +766,7 @@ class Fritz {
msg: 'http.request error',
function: 'send_response',
error: res.statusCode,
- response: res
+ status: res.statusCode
});
}
// cumulate data
@@ -795,8 +865,9 @@ class Fritz {
// das ist ein wenig tricky, der http.request wirft einen Fehler, also landet man hier
// damit ist der erste Aufruf beendet, aber in der catch routine wird ein 2ter Aufruf versucht
// dessen erfolgreicher Abschluß führt dann insgesamt zu einem Erfolg
- if (this.debug) console.log('ERROR ');
- if (count === loop) {
+ let statusCode = error.error;
+ if (this.debug) console.log('ERROR executeCommand2 ', error.error);
+ if (count === loop && error.error !== 400 && error.error !== 500) {
const login = await this.login_SID();
if (login === true) {
const secondresponse = await this.executeCommand2(command, ain, 2);
@@ -813,9 +884,10 @@ class Fritz {
}
// loop === 2
return Promise.reject({
- msg: 'relogin failed',
+ msg: 'relogin failed, or status400/500',
function: 'executeCommand2',
- error: error
+ error: error,
+ status: statusCode
});
}
}
@@ -837,12 +909,12 @@ class Fritz {
if (protocol == 'http:') {
http = require('http');
defaultport = 80;
- if (this.debug) console.log('using http');
+ if (this.debug) console.log('fritzAHA_Request using http');
} else if (protocol == 'https:') {
http = require('https');
defaultport = 443;
//http.globalAgent.options.secureProtocol = 'SSLv3_method';
- if (this.debug) console.log('using https');
+ if (this.debug) console.log('fritzAHA_Request using https');
} else {
console.log('invalid protocol');
}
@@ -861,6 +933,7 @@ class Fritz {
let p = new Promise((resolve, reject) => {
const req = http.request(options, (res) => {
res.setEncoding('utf8');
+ const statuscode = parseInt(res.statusCode);
if (res.statusCode !== 200) {
// throw Error(`HTTP request Failed. Status Code: ${res.statusCode}`);
console.log(`HTTP request Failed. Status Code: ${res.statusCode}`);
@@ -868,7 +941,7 @@ class Fritz {
msg: 'AHA request error',
function: 'fritzAHA_Request',
error: res.statusCode,
- response: res
+ status: statuscode
});
}
// cumulate data
@@ -880,7 +953,7 @@ class Fritz {
res.on('end', () => {
if (responseBody) {
//console.log('statusCode:', response.statusCode); // Print the response status code if a response was received
- //console.log('body:', responseBody); // Print the XML answer.
+ // console.log('body:', responseBody); // Print the XML answer.
resolve(responseBody.trim());
} else {
reject({
diff --git a/lib/fritz_mockserver.js b/lib/fritz_mockserver.js
index 0c168f9..db9b6d0 100644
--- a/lib/fritz_mockserver.js
+++ b/lib/fritz_mockserver.js
@@ -25,8 +25,8 @@ class FritzEmu {
xmlTemplates,
xmlTrigger,
xmlColors,
- xmlTempStat,
- xmlPowerStat,
+ xmlTempStats,
+ xmlPowerStats,
guestWlan,
hkr_batt
) {
@@ -36,8 +36,8 @@ class FritzEmu {
this.xmlTemplates = xmlTemplates;
this.xmlTrigger = xmlTrigger;
this.xmlColors = xmlColors;
- this.xmlTempStat = xmlTempStat;
- this.xmlPowerStat = xmlPowerStat;
+ this.xmlTempStats = xmlTempStats;
+ this.xmlPowerStats = xmlPowerStats;
this.guestWlan = guestWlan;
this.hkr_batt = hkr_batt;
this.apiresponse = {};
@@ -75,6 +75,8 @@ class FritzEmu {
temperature = null,
duration = null,
target = null,
+ level = null,
+ active = null,
username = null,
version = null,
logout = null,
@@ -97,16 +99,16 @@ class FritzEmu {
ain = commandsplit[1];
console.log('\x1b[36m', '-> ain : ', commandsplit[1]);
break;
- case 'ain':
+ case 'onoff':
onoff = commandsplit[1];
console.log('\x1b[36m', '-> onoff : ', commandsplit[1]);
break;
case 'param':
- onoff = commandsplit[1];
+ param = commandsplit[1];
console.log('\x1b[36m', '-> param : ', commandsplit[1]);
break;
case 'endtimestamp':
- onoff = commandsplit[1];
+ endtimestamp = commandsplit[1];
console.log('\x1b[36m', '-> endtimestamp : ', commandsplit[1]);
break;
case 'hue':
@@ -124,7 +126,7 @@ class FritzEmu {
console.log('\x1b[36m', '-> temperature : ', commandsplit[1]);
break;
case 'duration':
- temperature = commandsplit[1];
+ duration = commandsplit[1];
console.log('\x1b[36m', '-> duration : ', commandsplit[1]);
break;
case 'target':
@@ -143,6 +145,14 @@ class FritzEmu {
response = commandsplit[1];
console.log('\x1b[36m', '-> response : ', commandsplit[1]);
break;
+ case 'level':
+ level = commandsplit[1];
+ console.log('\x1b[36m', '-> level : ', commandsplit[1]);
+ break;
+ case 'active':
+ active = commandsplit[1];
+ console.log('\x1b[36m', '-> active : ', commandsplit[1]);
+ break;
case 'logout':
logout = commandsplit[1];
console.log('\x1b[36m', '-> logout : ', commandsplit[1]);
@@ -173,7 +183,9 @@ class FritzEmu {
saturation,
temperature,
duration,
- target
+ target,
+ level,
+ active
);
} else if (request.url == '/wlan/guest_access.lua?0=0&sid=' + mocksid) {
//check the URL of the current request
@@ -230,6 +242,7 @@ class FritzEmu {
} else {
console.log('\x1b[31m', '-> not supported call ' + request.method + ' ' + request.url);
response.statusCode = 403;
+ response.write(String(''));
response.end();
}
});
@@ -246,7 +259,56 @@ class FritzEmu {
callback();
});
}
-
+ JSONtoXML(obj) {
+ let xml = '';
+ for (let prop in obj) {
+ xml += obj[prop] instanceof Array ? '' : '<' + prop + '>';
+ if (obj[prop] instanceof Array) {
+ for (let array in obj[prop]) {
+ xml += '\n<' + prop + '>\n';
+ xml += JSONtoXML(new Object(obj[prop][array]));
+ xml += '' + prop + '>';
+ }
+ } else if (typeof obj[prop] == 'object') {
+ xml += JSONtoXML(new Object(obj[prop]));
+ } else {
+ xml += obj[prop];
+ }
+ xml += obj[prop] instanceof Array ? '' : '' + prop + '>\n';
+ }
+ xml = xml.replace(/<\/?[0-9]{1,}>/g, '');
+ return xml;
+ }
+ json2xml(o, tab) {
+ var toXml = function(v, name, ind) {
+ var xml = '';
+ if (v instanceof Array) {
+ for (var i = 0, n = v.length; i < n; i++) xml += ind + toXml(v[i], name, ind + '\t') + '\n';
+ } else if (typeof v == 'object') {
+ var hasChild = false;
+ xml += ind + '<' + name;
+ for (var m in v) {
+ if (m.charAt(0) == '@') xml += ' ' + m.substr(1) + '="' + v[m].toString() + '"';
+ else hasChild = true;
+ }
+ xml += hasChild ? '>' : '/>';
+ if (hasChild) {
+ for (var m in v) {
+ if (m == '#text') xml += v[m];
+ else if (m == '#cdata') xml += '';
+ else if (m.charAt(0) != '@') xml += toXml(v[m], m, ind + '\t');
+ }
+ xml += (xml.charAt(xml.length - 1) == '\n' ? ind : '') + '' + name + '>';
+ }
+ } else {
+ xml += ind + '<' + name + '>' + v.toString() + '' + name + '>';
+ }
+ return xml;
+ },
+ xml = '';
+ for (var m in o) xml += toXml(o[m], m, '');
+ return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, '');
+ }
// Functions for reply on the requests
loginoutAnswerV2(response, sid, method, username, userresponse, request) {
if (!sid && method == 'GET') {
@@ -361,6 +423,7 @@ class FritzEmu {
}
errorAnswer(response, code) {
response.statusCode = code;
+ //response.writeHead(code, { 'Content-Type': 'application/x-www-form-urlencoded' });
response.end();
return response;
}
@@ -376,7 +439,9 @@ class FritzEmu {
saturation,
temperature,
duration,
- target
+ target,
+ level,
+ active
) {
switch (switchcmd) {
case 'getdevicelistinfos':
@@ -390,16 +455,17 @@ class FritzEmu {
return response;
break;
case 'getdeviceinfos':
+ console.log('getdeviceinfos ' + ain);
const deviceinfos = this.apiresponse['devicelist']['device'].filter(
(device) => device.identifier === ain
);
if (deviceinfos) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(String(deviceinfos));
+ response.write(String(this.json2xml({ device: deviceinfos })));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -422,7 +488,7 @@ class FritzEmu {
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in templates ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -451,45 +517,47 @@ class FritzEmu {
const setgroupstate = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('switch') && group.identifier === ain)
.map((group) => group.switch.state);
- if (setswitchstate) {
+ if (setswitchstate.length == 1) {
const pos = this.findAin('device', ain);
- if ((switchcmd = 'setswitchon')) {
+ if (switchcmd == 'setswitchon') {
this.apiresponse.devicelist.device[pos].switch.state = 1;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ '1' ]));
+ response.write(String('1'));
response.end();
- } else if ((switchcmd = 'setswitchoff')) {
+ } else if (switchcmd == 'setswitchoff') {
this.apiresponse.devicelist.device[pos].switch.state = 0;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ '0' ]));
+ response.write(String('0'));
response.end();
- } else if ((switchcmd = 'setswitchtoggle')) {
- this.apiresponse.devicelist.device[pos].switch.state = !setswitchstate;
+ } else if (switchcmd == 'setswitchtoggle') {
+ let sstate = setswitchstate == '1' ? '0' : '1';
+ this.apiresponse.devicelist.device[pos].switch.state = sstate;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ "'" + !setswitchstate + "'" ]));
+ response.write(String(sstate));
response.end();
}
- } else if (setgroupstate) {
+ } else if (setgroupstate.length == 1) {
const pos = this.findAin('group', ain);
- if ((switchcmd = 'setswitchon')) {
- this.apiresponse.devicelist.group[pos].switch.state = 0;
+ if (switchcmd == 'setswitchon') {
+ this.apiresponse.devicelist.group[pos].switch.state = 1;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ '1' ]));
+ response.write(String('1'));
response.end();
- } else if ((switchcmd = 'setswitchoff')) {
- this.apiresponse.devicelist.group[pos].switch.state = 1;
+ } else if (switchcmd == 'setswitchoff') {
+ this.apiresponse.devicelist.group[pos].switch.state = 0;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ '0' ]));
+ response.write(String('0'));
response.end();
- } else if ((switchcmd = 'setswitchtoggle')) {
- this.apiresponse.devicelist.group[pos].switch.state = !setgroupstate;
+ } else if (switchcmd == 'setswitchtoggle') {
+ let gstate = setgroupstate == '1' ? '0' : '1';
+ this.apiresponse.devicelist.group[pos].switch.state = gstate;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ "'" + !setgroupstate + "'" ]));
+ response.write(String(gstate));
response.end();
}
} else {
console.log(' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -500,40 +568,42 @@ class FritzEmu {
const getgrouptemp = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('temperature') && device.identifier === ain)
.map((group) => group.temperature.celsius);
- if (gettemp) {
+ if (gettemp.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
response.write(String(gettemp));
response.end();
- } else if (getgrouptemp) {
+ } else if (getgrouptemp.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
response.write(String(getgrouptemp));
response.end();
} else {
console.log(' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
case 'getswitchname':
case 'getswitchpresent':
const item = switchcmd.replace('getswitch', '');
- const switchvalue = this.apiresponse['devicelist']['device']
- .filter((device) => device.hasOwnProperty('switch') && device.identifier === ain)
+ const devicevalue = this.apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty(item) && device.identifier === ain)
.map((device) => device[item]);
const groupvalue = this.apiresponse['devicelist']['group']
- .filter((group) => group.hasOwnProperty('switch') && group.identifier === ain)
+ .filter((group) => group.hasOwnProperty(item) && group.identifier === ain)
.map((group) => group[item]);
- if (switchvalue) {
+ if (devicevalue.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ "'" + switchvalue + "'" ]));
+ //response.write(JSON.stringify([ "'" + devicevalue + "'" ]));
+ response.write(String(devicevalue));
response.end();
- } else if (groupvalue) {
+ } else if (groupvalue.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ "'" + groupvalue + "'" ]));
+ //response.write(JSON.stringify([ "'" + groupvalue + "'" ]));
+ response.write(String(groupvalue));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -544,17 +614,19 @@ class FritzEmu {
const getgroupstate = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('switch') && group.identifier === ain)
.map((group) => group.switch.state);
- if (getswitchstate) {
+ if (getswitchstate.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ "'" + getswitchstate + "'" ]));
+ //response.write(JSON.stringify([ "'" + getswitchstate + "'" ]));
+ response.write(String(getswitchstate));
response.end();
- } else if (groupstate) {
+ } else if (getgroupstate.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(JSON.stringify([ "'" + getgroupstate + "'" ]));
+ //response.write(JSON.stringify([ "'" + getgroupstate + "'" ]));
+ response.write(String(getgroupstate));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -580,11 +652,11 @@ class FritzEmu {
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
//verursacht StatusCode400
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
- //alles KHR
+ //alles HKR
case 'gethkrtsoll':
case 'gethkrkomfort':
case 'gethkrabsenk':
@@ -595,17 +667,17 @@ class FritzEmu {
const getgrouphkrtemp = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('hkr') && group.identifier === ain)
.map((group) => group.hkr[item3]);
- if (gethkrtemp) {
+ if (gethkrtemp.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
response.write(String(gethkrtemp));
response.end();
- } else if (getgrouphkrtemp) {
+ } else if (getgrouphkrtemp.length > 0) {
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
response.write(String(getgrouphkrtemp));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.Answer(response, 400);
}
return response;
break;
@@ -617,19 +689,21 @@ class FritzEmu {
const setgrouphkrtemp = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('hkr') && group.identifier === ain)
.map((group) => group.hkr.tsoll);
- if (sethkrtemp) {
+ if (sethkrtemp.length > 0) {
const pos = this.findAin('device', ain);
this.apiresponse.devicelist.device[pos].hkr.tsoll = param;
response.statusCode = 200;
+ response.write(String(param));
response.end();
- } else if (setgrouphkrtemp) {
+ } else if (setgrouphkrtemp.length > 0) {
const pos = this.findAin('group', ain);
this.apiresponse.devicelist.group[pos].hkr.tsoll = param;
response.statusCode = 200;
+ response.write(String(param));
response.end();
} else {
console.log('\x1b[31m', '-> did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -638,29 +712,34 @@ class FritzEmu {
// todo prüfen ob gruppen statistik haben können
const thermostat = this.apiresponse['devicelist']['device']
.filter((device) => device.hasOwnProperty('hkr') && device.identifier === ain)
- .map((device) => device.hkr.tsoll);
+ .map((device) => device.temperature);
const groupthermo = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('hkr') && group.identifier === ain)
- .map((group) => group.hkr.tsoll);
+ .map((group) => group.temperature);
const switcher = this.apiresponse['devicelist']['device']
- .filter((device) => device.hasOwnProperty('hkr') && device.identifier === ain)
- .map((device) => device.hkr.tsoll);
+ .filter((device) => device.hasOwnProperty('switch') && device.identifier === ain)
+ .map((device) => device.switch);
const groupswitcher = this.apiresponse['devicelist']['group']
- .filter((group) => group.hasOwnProperty('hkr') && group.identifier === ain)
- .map((group) => group.hkr.tsoll);
- if (thermostat || groupthermo) {
+ .filter((group) => group.hasOwnProperty('switch') && group.identifier === ain)
+ .map((group) => group.switch);
+ if (thermostat.length > 0) {
//check the URL of the current request
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(String(this.xmlTempStat));
+ response.write(String(this.xmlTempStats));
response.end();
- } else if (switcher || groupswitcher) {
+ } else if (switcher.length > 0) {
//check the URL of the current request
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
response.write(String(this.xmlPowerStats));
response.end();
+ } else if (groupthermo.length > 0 || groupswitcher.length > 0) {
+ //check the URL of the current request
+ response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
+ response.write(String(''));
+ response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -674,9 +753,9 @@ class FritzEmu {
.map((group) => group.simpleonoff.state);
let newstate = null;
- if (simplevalue) {
+ if (simplevalue.length > 0) {
if (onoff == 2) {
- newstate = !simplevalue;
+ newstate = simplevalue == '1' ? '0' : '1';
} else {
//ohne prüfung ob auch 0 oder 1 geschickt wird
newstate = onoff;
@@ -684,10 +763,11 @@ class FritzEmu {
const pos = this.findAin('device', ain);
this.apiresponse.devicelist.device[pos].simpleonoff.state = newstate;
response.statusCode = 200;
+ response.write(String(newstate));
response.end();
- } else if (groupsimplevalue) {
+ } else if (groupsimplevalue.length > 0) {
if (onoff == 2) {
- newstate = !groupsimplevalue;
+ newstate = groupsimplevalue == '1' ? '0' : '1';
} else {
//ohne prüfung ob auch 0 oder 1 geschickt wird
newstate = onoff;
@@ -695,10 +775,11 @@ class FritzEmu {
const pos = this.findAin('group', ain);
this.apiresponse.devicelist.group[pos].simpleonoff.state = newstate;
response.statusCode = 200;
+ response.write(String(newstate));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response);
+ response = this.errorAnswer(response);
}
return response;
break;
@@ -710,25 +791,27 @@ class FritzEmu {
const grouplevel = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('levelcontrol') && group.identifier === ain)
.map((group) => group.levelcontrol.level);
- if (levelvalue) {
+ if (levelvalue.length > 0) {
const pos = this.findAin('device', ain);
this.apiresponse.devicelist.device[pos].levelcontrol.level = level;
this.apiresponse.devicelist.device[pos].levelcontrol.levelpercentage = Math.floor(
Number(level) / 255 * 100
);
+ response.write(String(level));
response.statusCode = 200;
response.end();
- } else if (grouplevel) {
+ } else if (grouplevel.length > 0) {
const pos = this.findAin('group', ain);
this.apiresponse.devicelist.group[pos].levelcontrol.level = level;
this.apiresponse.devicelist.device[pos].levelcontrol.levelpercentage = Math.floor(
Number(level) / 255 * 100
);
response.statusCode = 200;
+ response.write(String(level));
response.end();
} else {
console.log(' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response);
+ response = this.errorAnswer(response);
}
return response;
break;
@@ -740,21 +823,23 @@ class FritzEmu {
const grouplevelperc = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('levelcontrol') && group.identifier === ain)
.map((group) => group.levelcontrol.levelpercentage);
- if (levelvalueperc) {
+ if (levelvalueperc.length > 0) {
const pos = this.findAin('device', ain);
this.apiresponse.devicelist.device[pos].levelcontrol.level = Math.floor(Number(level) / 100 * 255);
this.apiresponse.devicelist.device[pos].levelcontrol.levelpercentage = level;
response.statusCode = 200;
+ response.write(String(level));
response.end();
- } else if (grouplevelperc) {
+ } else if (grouplevelperc.length > 0) {
const pos = this.findAin('group', ain);
this.apiresponse.devicelist.group[pos].levelcontrol.level = Math.floor(Number(level) / 100 * 255);
this.apiresponse.devicelist.device[pos].levelcontrol.levelpercentage = level;
response.statusCode = 200;
+ response.write(String(level));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -765,24 +850,28 @@ class FritzEmu {
console.log('additional cmd duration' + duration);
const colorvalue = this.apiresponse['devicelist']['device']
.filter((device) => device.hasOwnProperty('colorcontrol') && device.identifier === ain)
- .map((device) => device.colorontrol[cmd]);
+ .map((device) => device.colorcontrol[colorcmd]);
const groupcolor = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('colorcontrol') && group.identifier === ain)
- .map((group) => group.colorcontrol[cmd]);
+ .map((group) => group.colorcontrol[colorcmd]);
const newvalue = hue || saturation;
- if (colorvalue) {
+ if (colorvalue.length > 0) {
const pos = this.findAin('device', ain);
- this.apiresponse.devicelist.device[pos].colorcontrol[cmd] = newvalue;
+ this.apiresponse.devicelist.device[pos].colorcontrol[colorcmd] = newvalue;
response.statusCode = 200;
+ //todo was kommt wirklich zurück?
+ response.write(String(newvalue));
response.end();
- } else if (groupcolor) {
+ } else if (groupcolor.length > 0) {
const pos = this.findAin('group', ain);
- this.apiresponse.devicelist.group[pos].colorcontrol[cmd] = newvalue;
+ this.apiresponse.devicelist.group[pos].colorcontrol[colorcmd] = newvalue;
response.statusCode = 200;
+ //todo was kommt wirklich zurück?
+ response.write(String(newvalue));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -790,23 +879,27 @@ class FritzEmu {
console.log('temperature ' + temperature);
const settempvalue = this.apiresponse['devicelist']['device']
.filter((device) => device.hasOwnProperty('colorcontrol') && device.identifier === ain)
- .map((device) => device.colorontrol.temperature);
+ .map((device) => device.colorcontrol.temperature);
const setgrouptemp = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('colorcontrol') && group.identifier === ain)
.map((group) => group.colorcontrol.temperature);
- if (settempvalue) {
+ if (settempvalue.length > 0) {
const pos = this.findAin('device', ain);
this.apiresponse.devicelist.device[pos].colorcontrol.temperature = temperature;
response.statusCode = 200;
+ //todo was kommt wirklich zurück?
+ response.write(String(temperature));
response.end();
- } else if (setgrouptemp) {
+ } else if (setgrouptemp.length > 0) {
const pos = this.findAin('group', ain);
this.apiresponse.devicelist.group[pos].colorcontrol.temperature = temperature;
response.statusCode = 200;
+ //todo was kommt wirklich zurück?
+ response.write(String(temperature));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -825,16 +918,24 @@ class FritzEmu {
const groupboost = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('hkr') && group.identifier === ain)
.map((group) => group.hkr.boostactiveendtime);
- if (endttimestamp > now) {
- endtimepstamp = '';
+ const now = new Date();
+ /*
+ // auch in vergangenheit liegende Zeitstempel werden als gültig angesehen
+ if (parseInt(endtimestamp) < now.getTime()) {
+ endtimestamp = '';
}
- if (hkrboost) {
+ */
+
+ if (parseInt(endtimestamp) * 1000 > now.getTime() + 86400) {
+ console.log('\x1b[31m', ' endtime > now +24h ' + ain);
+ response = this.errorAnswer(response, 500);
+ } else if (hkrboost.length > 0) {
const pos = this.findAin('device', ain);
this.apiresponse.devicelist.device[pos].hkr.boostactiveendtime = endtimestamp;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
response.write(String(endtimestamp));
response.end();
- } else if (groupboost) {
+ } else if (groupboost.length > 0) {
const pos = this.findAin('group', ain);
this.apiresponse.devicelist.group[pos].hkr.boostactiveendtime = endtimestamp;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
@@ -842,7 +943,7 @@ class FritzEmu {
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -854,16 +955,23 @@ class FritzEmu {
const groupwindow = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('hkr') && group.identifier === ain)
.map((group) => group.hkr.windowopenactiveendtime);
- if (endttimestamp > now) {
- endtimepstamp = '';
+ const now2 = new Date();
+ /*
+ // auch in vergangenheit liegende Zeitstempel werden als gültig angesehen
+ if (parseInt(endtimestamp) < now2.getTime()) {
+ endtimestamp = '';
}
- if (hkrwindow) {
+ */
+ if (parseInt(endtimestamp) > now2.getTime() + 86400) {
+ console.log('\x1b[31m', ' endtime > now +24h ' + ain);
+ response = this.errorAnswer(response, 500);
+ } else if (hkrwindow.length > 0) {
const pos = this.findAin('device', ain);
- this.apiresponse.devicelist.device[pos].hkr.windowopenactiveendtime = endtimestamp;
+ //this.apiresponse.devicelist.device[pos].hkr.windowopenactiveendtime = endtimestamp;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
response.write(String(endtimestamp));
response.end();
- } else if (groupwindow) {
+ } else if (groupwindow.length > 0) {
const pos = this.findAin('group', ain);
this.apiresponse.devicelist.group[pos].hkr.windowopenactiveendtime = endtimestamp;
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
@@ -871,7 +979,7 @@ class FritzEmu {
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
@@ -883,33 +991,49 @@ class FritzEmu {
const groupblind = this.apiresponse['devicelist']['group']
.filter((group) => group.hasOwnProperty('blind') && group.identifier === ain)
.map((group) => group.blind.mode);
- if (blindvalue) {
+ if (blindvalue.length > 0) {
response.statusCode = 200;
+ response.write(String(target));
response.end();
- } else if (groupblind) {
+ } else if (groupblind.length > 0) {
response.statusCode = 200;
+ response.write(String(target));
response.end();
} else {
console.log('\x1b[31m', ' did not find the ain in devices/groups ' + ain);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
}
return response;
break;
case 'setname':
response.statusCode = 200;
+ response.write(String(name));
response.end();
return response;
break;
case 'setmetadata':
break;
- case 'gettriggerlistinfo':
+ case 'gettriggerlistinfos':
// todo empty templates
response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
- response.write(String(xmlTriggerlist));
+ response.write(String(this.xmlTrigger));
response.end();
return response;
break;
case 'settriggeractive':
+ console.log('active ' + active);
+ const trigger = this.apiresponse['triggerlist']['trigger'].filter(
+ (trigger) => trigger.hasOwnProperty('identifier') && trigger.identifier === ain
+ );
+ if (trigger.length > 0) {
+ response.writeHead(200, { 'xmlDevicesGroups-Type': 'application/json' });
+ response.write(String(active));
+ response.end();
+ } else {
+ console.log('\x1b[31m', ' did not find the ain in trigger ' + ain);
+ response = this.errorAnswer(response, 400);
+ }
+ return response;
break;
case 'setmappedcolor':
break;
@@ -923,7 +1047,7 @@ class FritzEmu {
break;
default:
console.log('\x1b[31m', 'switchcmd no case found ' + switchcmd);
- response = errorAnswer(response, 400);
+ response = this.errorAnswer(response, 400);
return response;
break;
}
@@ -939,8 +1063,8 @@ class FritzEmu {
}
}
} else if (type === 'group') {
- for (let i = 0; i < this.apiresponse['devicelist']['device'].length; i++) {
- if (this.apiresponse['devicelist']['device'][i].identifier === ain) {
+ for (let i = 0; i < this.apiresponse['devicelist']['group'].length; i++) {
+ if (this.apiresponse['devicelist']['group'][i].identifier === ain) {
position = i;
break;
}
diff --git a/lib/mjs_version/start_mockserver.mjs b/lib/mjs_version/start_mockserver.mjs
new file mode 100644
index 0000000..62e8a13
--- /dev/null
+++ b/lib/mjs_version/start_mockserver.mjs
@@ -0,0 +1,16 @@
+let FritzEmu;
+(async () => {
+ let fb = await import('fritzdect-aha-nodejs');
+ FritzEmu = fb.FritzEmu;
+})().catch((err) => console.error(err));
+
+console.log(FritzEmu);
+
+function fireUpEmu() {
+ let testfile = 'testFBall.xml';
+ let port = 3333;
+ const emulation = new FritzEmu(testfile, port, false);
+ emulation.setupHttpServer(function() {});
+}
+
+fireUpEmu();
diff --git a/package.json b/package.json
index 4df5bcd..f931997 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "fritzdect-aha-nodejs",
- "version": "2.0.1",
+ "version": "2.1.0",
"description": "NodeJS library using the AHA api of Fritzbox to control DECT smarthome devices.",
"main": "index.js",
"dependencies": {
diff --git a/test/integration.js b/test/integration.js
index a0650d9..9ca1127 100644
--- a/test/integration.js
+++ b/test/integration.js
@@ -13,18 +13,18 @@ const crypto = require('crypto');
const path = require('path');
console.log('PATH ist ' + path.join(__dirname, './data/'));
-const xmlDevicesGroups = fs.readFileSync(path.join(__dirname, './data/') + 'test_api_response.xml');
+const xmlDevicesGroups = String(fs.readFileSync(path.join(__dirname, './data/') + 'test_api_response.xml'));
//var xmlDevicesGroups = fs.readFileSync('./test.xml');
-const xmlTemplate = fs.readFileSync(path.join(__dirname, './data/') + 'template_answer.xml');
-const xmlTriggerlist = fs.readFileSync(path.join(__dirname, './data/') + 'getriggerlistinfos.xml');
-const xmlTempStat = fs.readFileSync(path.join(__dirname, './data/') + 'devicestat_temp_answer.xml');
-const xmlPowerStats = fs.readFileSync(path.join(__dirname, './data/') + 'devicestat_power_answer.xml');
-const xmlColorDefaults = fs.readFileSync(path.join(__dirname, './data/') + 'color_defaults.xml');
+const xmlTemplate = String(fs.readFileSync(path.join(__dirname, './data/') + 'template_answer.xml'));
+const xmlTriggerlist = String(fs.readFileSync(path.join(__dirname, './data/') + 'getriggerlistinfos.xml'));
+const xmlTempStats = String(fs.readFileSync(path.join(__dirname, './data/') + 'devicestat_temp_answer.xml'));
+const xmlPowerStats = String(fs.readFileSync(path.join(__dirname, './data/') + 'devicestat_power_answer.xml'));
+const xmlColorDefaults = String(fs.readFileSync(path.join(__dirname, './data/') + 'color_defaults.xml'));
const hkr_batt = fs.readFileSync(path.join(__dirname, './data/') + 'hkr_response.xml');
const guestWlan = fs.readFileSync(path.join(__dirname, './data/') + 'guest_wlan_form.xml');
-const devices2json = parser.xml2json(String(xmlDevicesGroups));
+const devices2json = parser.xml2json(xmlDevicesGroups);
let devices = [].concat((devices2json.devicelist || {}).device || []).map((device) => {
// remove spaces in AINs
device.identifier = device.identifier.replace(/\s/g, '');
@@ -35,10 +35,10 @@ let groups = [].concat((devices2json.devicelist || {}).group || []).map((group)
group.identifier = group.identifier.replace(/\s/g, '');
return group;
});
-const templates2json = parser.xml2json(String(xmlTemplate));
+const templates2json = parser.xml2json(xmlTemplate);
let templates = [].concat((templates2json.templatelist || {}).template || []).map(function(template) {
// remove spaces in AINs
- // template.identifier = group.identifier.replace(/\s/g, '');
+ template.identifier = template.identifier.replace(/\s/g, '');
return template;
});
@@ -58,7 +58,7 @@ describe('Test of Fritzdect-AHA-API', () => {
xmlTemplate,
xmlTriggerlist,
xmlColorDefaults,
- xmlTempStat,
+ xmlTempStats,
xmlPowerStats,
guestWlan,
hkr_batt
@@ -68,22 +68,157 @@ describe('Test of Fritzdect-AHA-API', () => {
var fritz;
// if promise is returned = success
it('should create a new fritzdect instance', function() {
- fritz = new Fritz('admin', 'password', 'http://localhost:3333', null);
+ fritz = new Fritz('admin', 'password', 'http://localhost:3333', false, null);
});
it('login success returns true', async () => {
const result = await fritz.login_SID();
//assert.equal(result, true);
expect(result).to.equal(true);
});
- /*
+ it('function getUserPermissions()', async () => {
+ const result = await fritz.getUserPermissions();
+ //console.log('getUserPermissions result', result);
+ const permissions =
+ 'Dial2App2HomeAuto2BoxAdmin2Phone2NAS2';
+ expect(result).to.eql(permissions);
+ console.log('----------------------');
+ });
it('function getdevicelistinfos', async () => {
const result = await fritz.getDeviceListInfos();
- //console.log('getdevicelistinfos result', JSON.parse(result));
+ const devicesgroups = parser.xml2json(result);
+ let devices = [].concat((devicesgroups.devicelist || {}).device || []).map((device) => {
+ // remove spaces in AINs
+ device.identifier = device.identifier.replace(/\s/g, '');
+ return device;
+ });
+ let groups = [].concat((devicesgroups.devicelist || {}).group || []).map((group) => {
+ // remove spaces in AINs
+ group.identifier = group.identifier.replace(/\s/g, '');
+ return group;
+ });
const devicelist = apiresponse['devicelist'];
- //console.log(switchlist);
- expect(parser.xml2json(result).devicelist).to.eql(devicelist);
+ expect({ version: '1', device: devices, group: groups }).to.eql(devicelist);
+ });
+ it('function gettemplatelistinfos', async () => {
+ const result = await fritz.getTemplateListInfos();
+ //console.log('gettemplatelistinfos result', result);
+ const templatelist = apiresponse['templatelist'];
+ expect(parser.xml2json(result).templatelist).to.eql(templatelist);
+ });
+ it('function gettriggerlistinfos', async () => {
+ const result = await fritz.getTriggerListInfos();
+ //console.log('gettriggerlistinfos result', result);
+ const triggerlist = apiresponse['triggerlist'];
+ expect(parser.xml2json(result).trigger).to.eql(triggerlist);
+ });
+ it('function getcolordefaults', async () => {
+ const result = await fritz.getColorDefaults();
+ //console.log('getcolordefaults result', result);
+ const colordefaults = parser.xml2json(xmlColorDefaults);
+ expect(parser.xml2json(result)).to.eql(colordefaults);
+ //expect(result).to.eql(xmlColorDefaults);
+ });
+ it('function getdeviceinfos', async () => {
+ let ain = '087610006161';
+ const result = await fritz.getDeviceInfos(ain);
+ const deviceinfo = apiresponse['devicelist']['device'].filter(
+ (device) => device.hasOwnProperty('switch') && device.identifier === ain
+ );
+ expect(parser.xml2json(result)).to.eql({ device: deviceinfo[0] });
+ });
+ it('function getbasicdevicestats Temp', async () => {
+ let ain = '119600642220';
+ const result = await fritz.getBasicDeviceStats(ain);
+ const basicdevicestats = parser.xml2json(xmlTempStats);
+ expect(parser.xml2json(result)).to.eql(basicdevicestats);
+ });
+ it('function getbasicdevicestats Power', async () => {
+ let ain = '087610006161';
+ const result = await fritz.getBasicDeviceStats(ain);
+ const basicdevicestats = parser.xml2json(xmlPowerStats);
+ expect(parser.xml2json(result)).to.eql(basicdevicestats);
+ });
+ it('function getswitchstate', async () => {
+ let ain = '087610006161';
+ const result = await fritz.getSwitchState(ain);
+ //console.log('getSwitchState result', result);
+ const switchstate = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('switch') && device.identifier === ain)
+ .map((device) => device.switch.state);
+ expect(result).to.equal(switchstate[0]);
+ });
+ it('function getswitchpresent', async () => {
+ let ain = '087610006161';
+ const result = await fritz.getSwitchPresent(ain);
+ //console.log('getswitchpresent result', result);
+ const switchpresent = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('present') && device.identifier === ain)
+ .map((device) => device.present);
+ expect(result).to.equal(switchpresent[0]);
+ });
+ it('function getswitchpower', async () => {
+ let ain = '087610006161';
+ const result = await fritz.getSwitchPower(ain);
+ //console.log('getswitchpower result', result);
+ const switchpower = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('powermeter') && device.identifier === ain)
+ .map((device) => device.powermeter.power);
+ expect(result).to.equal(switchpower[0]);
+ });
+ it('function getswitchenergy', async () => {
+ let ain = '087610006161';
+ const result = await fritz.getSwitchEnergy(ain);
+ //console.log('getswitchenergy result', result);
+ const switchenergy = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('powermeter') && device.identifier === ain)
+ .map((device) => device.powermeter.energy);
+ expect(result).to.equal(switchenergy[0]);
+ });
+ it('function getswitchname', async () => {
+ let ain = '087610006161';
+ const result = await fritz.getSwitchName(ain);
+ //console.log('getswitchname result', result);
+ const switchname = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('name') && device.identifier === ain)
+ .map((device) => device.name);
+ expect(result).to.equal(String(switchname[0]));
+ });
+ it('function gettemperature', async () => {
+ let ain = '119600642220';
+ const result = await fritz.getTemperature(ain);
+ //console.log('gettemperature result', result);
+ const temperature = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('temperature') && device.identifier === ain)
+ .map((device) => device.temperature.celsius);
+ expect(result).to.equal(temperature[0]);
+ });
+ it('function gethkrtsoll', async () => {
+ let ain = '119600642220';
+ const result = await fritz.getHkrTsoll(ain);
+ //console.log('gethkrtsoll result', result);
+ const tsoll = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('hkr') && device.identifier === ain)
+ .map((device) => device.hkr.tsoll);
+ expect(result).to.equal(tsoll[0]);
+ });
+ it('function gethkrkomfort', async () => {
+ let ain = '119600642220';
+ const result = await fritz.getHkrKomfort(ain);
+ //console.log('gethkrkomfort result', result);
+ const komfort = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('hkr') && device.identifier === ain)
+ .map((device) => device.hkr.komfort);
+ expect(result).to.equal(komfort[0]);
+ });
+ it('function gethkrabsenk', async () => {
+ let ain = '119600642220';
+ const result = await fritz.getHkrAbsenk(ain);
+ //console.log('gethkrabsenk result', result);
+ const absenk = apiresponse['devicelist']['device']
+ .filter((device) => device.hasOwnProperty('hkr') && device.identifier === ain)
+ .map((device) => device.hkr.absenk);
+ expect(result).to.equal(absenk[0]);
});
- */
it('function getswitchlist', async () => {
const result = await fritz.getSwitchList();
//console.log('getswitchlist result', result);
@@ -99,6 +234,116 @@ describe('Test of Fritzdect-AHA-API', () => {
//switchlist wäre ein array, über String() wird es vergleichbarer Text
expect(result).to.eql(String(switchlist));
});
+ it('applytemplate', async () => {
+ let ain = 'tmp6F0093-39091EED0';
+ const result = await fritz.applyTemplate(ain);
+ expect(result).to.equal('60010');
+ });
+ it('setswitchon', async () => {
+ let ain = '34:31:C1:AB:68:53';
+ const result = await fritz.setSwitchOn(ain);
+ expect(result).to.equal('1');
+ });
+ it('setswitchoff', async () => {
+ let ain = '34:31:C1:AB:68:53';
+ const result = await fritz.setSwitchOff(ain);
+ expect(result).to.equal('0');
+ });
+ it('setswitchtoggle', async () => {
+ let ain = 'EF:C4:CC-900';
+ const result = await fritz.setSwitchToggle(ain);
+ expect(result).to.equal('0');
+ });
+ it('setsimpleonoff&onoff=1', async () => {
+ let ain = '13077 0018976-1';
+ const result = await fritz.setSimpleOn(ain);
+ expect(result).to.equal('1');
+ });
+ it('setsimpleonoff&onoff=0', async () => {
+ let ain = '123456789012-1';
+ const result = await fritz.setSimpleOff(ain);
+ expect(result).to.equal('0');
+ });
+ it('setsimpleonoff&onoff=2', async () => {
+ let ain = 'grp9CEFB6-3BDCFFC80';
+ const result = await fritz.setSimpleToggle(ain);
+ expect(result).to.equal('0');
+ });
+ it('sethkrtsoll', async () => {
+ let ain = '11960 0642220';
+ let temp = 23;
+ const result = await fritz.setTempTarget(ain, temp);
+ expect(result).to.equal('46');
+ });
+ it('sethkrboost', async () => {
+ let ain = '11795 1033333';
+ const now = new Date();
+ let time = now.getTime() + 86410;
+ let result = null;
+ try {
+ result = await fritz.setHkrBoost(ain, time);
+ } catch (error) {
+ result = error;
+ }
+ expect(result.status).to.equal(500);
+ });
+ it('sethkrwindowopen', async () => {
+ let ain = '11795 1033333';
+ let time = 1677538435;
+ const result = await fritz.setWindowOpen(ain, time);
+ expect(result).to.equal('1677538435');
+ });
+ it('setblind', async () => {
+ let ain = '14276 0470139-1';
+ let target = 55;
+ const result = await fritz.setBlind(ain, target);
+ expect(result).to.equal('55');
+ });
+ it('setlevel', async () => {
+ let ain = '142760470139-1';
+ let level = 55;
+ const result = await fritz.setLevel(ain, level);
+ expect(result).to.equal('55');
+ });
+ it('setlevelpercentage', async () => {
+ let ain = '142760470139-1';
+ let level = 23;
+ const result = await fritz.setLevelPercentage(ain, level);
+ expect(result).to.equal('23');
+ });
+ it('setcolortemperature', async () => {
+ let ain = '13077 0018976-1';
+ let temp = 3600;
+ const result = await fritz.setColorTemperature(ain, temp);
+ expect(result).to.equal('3400');
+ });
+ it('setcolor', async () => {
+ let ain = '13077 0018976-1';
+ let saturation = 188;
+ let hue = 17;
+ const result = await fritz.setColor(ain, saturation, hue);
+ expect(result).to.equal('OK');
+ });
+ /*
+ it('setunmappedcolor', async () => {
+ let ain = '13077 0018976-1';
+ let saturation = 200;
+ let hue = 22;
+ const result = await fritz.setUnmappedColor(ain, saturation, hue);
+ expect(result).to.equal(false);
+ });
+ */
+ it('settriggeractive', async () => {
+ let ain = 'trg695F2D-3CBF1DC25';
+ let active = '1';
+ try {
+ const result = await fritz.setTriggerActive(ain, active);
+ } catch (error) {
+ console.log(error);
+ expect(result).to.equal(active);
+ }
+ });
+
it('logout success returns true', async () => {
const result = await fritz.logout_SID();
expect(result).to.equal(false);
@@ -106,17 +351,3 @@ describe('Test of Fritzdect-AHA-API', () => {
});
// alte Fb prüfen
-// alle exponierten CMDs prüfen
-// Inhalte prüfen
-
-/*
-var assert = require('assert');
-describe('login test', () => {
- const fritz = new Fritz('admin', 'password', 'http://localhost:3333', null);
- it('login success returns true', () => {
- return fritz.login_SID().then((result) => {
- assert.equal(result, true);
- });
- });
-});
-*/
From 0aacfec191caed2389cca79e69882055308b25d9 Mon Sep 17 00:00:00 2001
From: foxthefox <16841643+foxthefox@users.noreply.github.com>
Date: Wed, 5 Apr 2023 07:19:11 +0200
Subject: [PATCH 2/2] 2.1.0a
---
example.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/example.js b/example.js
index e9dc371..91e6d76 100644
--- a/example.js
+++ b/example.js
@@ -2,7 +2,7 @@
const Fritz = require('./index.js').Fritz;
-const fritz = new Fritz('admin', 'password', 'http://localhost:3333');
+const fritz = new Fritz('admin', 'password', 'http://localhost:3333', false);
async function test() {
const login = await fritz.login_SID().catch((e) => {