var request = require('request'); const MCrypt = require('mcrypt').MCrypt; const crypto = require('crypto'); // ------------------------------------------------------------------------------------------------------------------------------------------------------------------- var server = "http://192.168.178.31:80"; // Achtung: Gerätepasswort in ASCII! var gatewaypassword = "xxxx-xxxx-xxxx-xxxx"; // Achtung: Eigenes Passwort in ASCII! var privatepassword = "abc"; // ------------------------------------------------------------------------------------------------------------------------------------------------------------------- var key = getAccesskey(gatewaypassword,privatepassword); var adapter = "javascript.0."; var root = "km200.recordings."; var hh = "actualPower._Hours"; var hhdhw= "actualDHWPower._Hours"; var dd = "actualPower._Days"; var dddhw= "actualDHWPower._Days"; var mm = "actualPower._Months"; var mmdhw= "actualDHWPower._Months"; //Nach erfolgreichem anlegen bitte auskommentieren create_states(); enable_states(); // die abzufragenden Felder im Buderus-Gateway für Gesamtenergie und Warmwasser var felddhw = "/recordings/heatSources/actualDHWPower?interval="; var feld = "/recordings/heatSources/actualPower?interval="; // Einmal Ausführen hours(); days(); months(); // Schedules schedule('*/15 * * * *', hours); schedule('* */4 * * *',days); schedule('* * * * *',months); //************************************************************************************************************************************************** */ async function hours() { // id's der datenpunkte lesen var idhh = await getdp(hh); var idhhdhw = await getdp(hhdhw); console.log(idhh + " " + idhhdhw); var datum= new Date(); var datums = datum.toLocaleDateString(); var url1 = server + feld + datums; var url11 = server + felddhw + datums; try { var body = await get(url1); var data=decrypt(body); } catch(error) {console.error(body);data = " "; } if (data != " ") writehh (data,idhh); try { var body = await get(url11); var data=decrypt(body); } catch(error) {console.error(body);data = " "; } if (data != " ") writehh (data,idhhdhw); datum.setDate(datum.getDate() - 1); datums = datum.toLocaleDateString(); var url2 = server + feld + datums; var url21 = server + felddhw + datums; try { var body = await get(url2); data=decrypt(body); } catch(error) {console.error(body);data = " "; } if (data != " ") writehh (data,idhh); try { var body = await get(url21); var data=decrypt(body); } catch(error) {console.error(body);data = " "; } if (data != " ") writehh (data,idhhdhw); datum.setDate(datum.getDate() - 1); datums = datum.toLocaleDateString(); var url3 = server + feld + datums; var url31 = server + felddhw + datums; try { var body = await get(url3); data=decrypt(body); } catch(error) {console.error(body);data = " "; } if (data != " ") writehh (data,idhh); try { var body = await get(url31); var data=decrypt(body); } catch(error) {console.error(body);data = " "; } if (data != " ") writehh (data,idhhdhw); } //************************************************************************************************************************************************** */ async function days() { // id's der datenpunkte lesen var iddd = await getdp(dd); var iddddhw = await getdp(dddhw); // aktueller Monat var datum= new Date(); var jetzt = datum.getFullYear()+"-"; if (datum.getMonth()<9) jetzt = jetzt+"0"; var datums = jetzt+parseInt(datum.getMonth()+1); var url1 = server + feld + datums; var url11 = server + felddhw + datums; try { var body = await get(url1); var data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writedd (data,iddd); try { var body = await get(url11); var data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writedd (data,iddddhw); // Vormonat var jetzt = datum.getFullYear()+"-"; if (datum.getMonth()<9) jetzt = jetzt+"0"; var datums = jetzt+parseInt(datum.getMonth()); var url1 = server + feld + datums; var url11 = server + felddhw + datums; try { var body = await get(url1); data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writedd (data,iddd); try { var body = await get(url11); var data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writedd (data,iddddhw); } //************************************************************************************************************************************************** */ async function months() { // id's der datenpunkte lesen var idmm = await getdp(mm); var idmmdhw = await getdp(mmdhw); // aktuelles Jahr var datum= new Date(); var datums = datum.getFullYear(); var url1 = server + feld + datums; var url11 = server + felddhw + datums; try { var body = await get(url1); var data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writemm (data,idmm); try { var body = await get(url11); var data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writemm (data,idmmdhw); // Vorjahr var datums = datum.getFullYear()-1; var url1 = server + feld + datums; var url11 = server + felddhw + datums; try { var body = await get(url1); data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writemm (data,idmm); try { var body = await get(url11); var data=decrypt(body); } catch(error) {data = " "; } if (data != " ") writemm (data,idmmdhw); } //************************************************************************************************************************************************** */ function get(url) { return new Promise(function(resolve,reject) { var options = {url: url, method: 'GET', timeout: 4000, headers: {'Accept': "application/json", 'agent': 'TeleHeater/2.2.3', 'User-Agent': "TeleHeater/2.2.3"} }; request(options, function(error,response,body) {if (error) return reject(error); resolve(body);}); }); } function decrypt(body) { var b = new Buffer(body, 'base64'); var aeskey = new Buffer(key, 'hex'); var Ecb = new MCrypt('rijndael-128', 'ecb'); Ecb.open(aeskey); var s = Ecb.decrypt(new Buffer(b, 'hex')).toString('utf8'); while (s.charCodeAt(s.length - 1) === 0) s = s.slice(0, s.length - 1); var info = JSON.parse(s); return info; } function create_states() { createState(root+hh, 0, {type: 'number'}); createState(root+hhdhw, 0, {type: 'number'}); createState(root+dd, 0, {type: 'number'}); createState(root+dddhw, 0, {type: 'number'}); createState(root+mm, 0, {type: 'number'}); createState(root+mmdhw, 0, {type: 'number'}); } function enable_states() { enable_state(root+hh); enable_state(root+hhdhw); enable_state(root+dd); enable_state(root+dddhw); enable_state(root+mm); enable_state(root+mmdhw); } function enable_state(stateid) { var id = adapter + stateid; sendTo('sql.0', 'enableHistory', { id: id, options: { changesOnly: false, debounce: 0, retention: 31536000, maxLength: 3, changesMinDelta: 0, aliasId: "" } } , function (result) { if (result.error) {console.log(result.error); } if (result.success) { } }); setState(id,0); } function getdp(datapoint) { return new Promise(function(resolve,reject){ var query = "SELECT id FROM iobroker.datapoints where name = '" + adapter + root + datapoint + "';"; sendTo('sql.0', 'query', query, function (result) { var id = result.result[0].id; resolve(id); }); }); } function writehh (data,id){ var counter = 0; var interval = data.interval; var ut1 = new Date(interval).getTime(); var ut2 = ut1 + 3600000 * 24; var liste = data.recording; var query = "DELETE FROM iobroker.ts_number WHERE ID = " + id + " and TS >= " + ut1 + " AND TS < " + ut2 +";"; sendTo('sql.0', 'query', query, function (result) {} ); var command = "INSERT INTO iobroker.ts_number (id, val, ts, ack, _from, q) VALUES "; for (i = 0; i < liste.length; i++){ if (liste[i] !== null) { var val = parseInt(liste[i].y / 6) / 10; data = " ("; data += id +","; data += val + ","; var ts = parseInt (ut1 + (i * 3600000 ) ); data += ts + ","; data += "1,"; data += "14,"; data += "0);"; query = command + data; sendTo('sql.0', 'query', query, function (result) {} ); //console.log(query); counter ++; } } } function writedd (data,id){ var counter = 0; var interval = data.interval; var ut1 = new Date(interval).getTime(); var year = interval.substr(0,4); var month = interval.substr(5,7); var liste = data.recording; var query = "DELETE FROM iobroker.ts_number WHERE ID = " + id + " and YEAR(FROM_UNIXTIME((ts/ 1000))) = " + year + " and MONTH(FROM_UNIXTIME((ts/1000))) = " + month + " ;"; sendTo('sql.0', 'query', query, function (result) {} ); var command = "INSERT INTO iobroker.ts_number (id, val, ts, ack, _from, q) VALUES "; for (i = 0; i < liste.length; i++){ if (liste[i] !== null) { var val = parseInt(liste[i].y / 6) / 10; data = " ("; data += id +","; data += val + ","; var ts = parseInt (ut1 + (i * 3600000 * 24) ); data += ts + ","; data += "1,"; data += "14,"; data += "0);"; query = command + data; if (liste[i].c > 1 ) sendTo('sql.0', 'query', query, function (result) {} ); counter ++; } } } function writemm (data,id){ var interval = data.interval + "-01-01"; var ut1 = new Date(interval).getTime(); var year = interval.substr(0,4); var liste = data.recording; var query = "DELETE FROM iobroker.ts_number WHERE ID = " + id + " and YEAR(FROM_UNIXTIME((ts/ 1000))) = " + year + " ;"; sendTo('sql.0', 'query', query, function (result) {} ); console.log(JSON.stringify(liste)); var command = "INSERT INTO iobroker.ts_number (id, val, ts, ack, _from, q) VALUES "; var ts = ut1; var days = 0; for (i = 0; i < liste.length; i++) { if (liste[i] != null) { days = daysofmonth(year,i); console.log(year+ " " +(i+1) + " " + days ); val = liste[i].y / liste[i].c; val = parseInt(val * days * 24 * 10) / 10; var m = i+1; var t = year+ "-" + m.toString() +"-02" ; ts = new Date(t).getTime(); data = " ("; data += id +","; data += val + ","; data += ts + ","; data += "1,"; data += "14,"; data += "0);"; query = command + data; sendTo('sql.0', 'query', query, function (result) {} ); } } } function daysofmonth(year,i) { var month = i+1; var y = new Date().getFullYear(); var m = new Date().getMonth(); if ((year == y) && (i == m)) { var days = new Date().getDate(); return days; } if(month != 2) { if(month == 9 || month == 4 || month == 6 || month == 11) { return 30; } else { return 31; } } else { return (year % 4) == "" && (year % 100) !="" ? 29 : 28; } } function getAccesskey(gatewaypassword, privatepassword) { const km200_crypt_md5_salt = new Uint8Array([ 0x86, 0x78, 0x45, 0xe9, 0x7c, 0x4e, 0x29, 0xdc, 0xe5, 0x22, 0xb9, 0xa7, 0xd3, 0xa3, 0xe0, 0x7b, 0x15, 0x2b, 0xff, 0xad, 0xdd, 0xbe, 0xd7, 0xf5, 0xff, 0xd8, 0x42, 0xe9, 0x89, 0x5a, 0xd1, 0xe4 ]); function md5(text) { return crypto.createHash('md5').update(text).digest("hex"); } function str2ab(str) { let buf = new ArrayBuffer(str.length * 1); // 2 bytes for each char let bufView = new Uint8Array(buf); for (let i = 0, strLen = str.length; i < strLen; i++) { bufView[i] = str.charCodeAt(i); } return bufView; } function concatUint8Array(array1, array2) { const array3 = new Uint8Array(array1.length + array2.length); for (let i = 0; i < array1.length; i++) { array3[i] = array1[i]; } for (let i = 0; i < array2.length; i++) { array3[array1.length + i] = array2[i]; } return array3; } gatewaypassword = gatewaypassword.replace(/-/g, ''); let km200_gateway_password = str2ab(gatewaypassword); let km200_private_password = str2ab(privatepassword); // Erste Hälfte des Schlüssels: MD5 von ( Gerätepasswort . Salt ) let key_1 = md5(concatUint8Array(km200_gateway_password, km200_crypt_md5_salt)); // Zweite Hälfte des Schlüssels - privat: MD5 von ( Salt . privates Passwort ) let key_2_private = md5(concatUint8Array(km200_crypt_md5_salt, km200_private_password)); let km200_crypt_key_private = key_1 + key_2_private; return km200_crypt_key_private.trim().toLowerCase(); }