UNPKG

maxcube2

Version:

eq-3 Max! Cube interface for homebridge-platform-maxcube

164 lines (144 loc) 5.8 kB
var moment = require('moment'); function generateSetTemperatureCommand (rfAdress, room_id, mode, temperature, untilDate) { var date_until = '0000'; var time_until = '00'; // 00 = Auto weekprog (no temp is needed, just make the whole byte 00) // 01 = Permanent // 10 = Temporarily var modeBin; switch (mode) { case 'AUTO': { modeBin = '00'; break; } case 'MANUAL': { modeBin = '01'; break; } case 'VACATION': { modeBin = '10'; var momentDate = moment(untilDate); var year_until = padLeft((momentDate.get('year') - 2000).toString(2), 7); var month_until = padLeft((momentDate.get('month')+1).toString(2), 4); var day_until = padLeft(momentDate.get('date').toString(2), 5); date_until = padLeft(parseInt((month_until.substr(0,3) + day_until + month_until.substr(-1) + year_until), 2).toString(16), 4); time_until = padLeft(Math.round((momentDate.get('hour') + (momentDate.get('minute') / 60)) * 2).toString(16), 2); break; } case 'BOOST': { modeBin = '11'; break; } default: { console.error('Unknown mode: ' + mode); return false; } } // leading zero padding var reqTempBinary = modeBin + padLeft(((temperature || 0) * 2).toString(2), 6); // to hex string var reqTempHex = padLeft(parseInt(reqTempBinary, 2).toString(16), 2); // '00' sets all temperature for all devices var room_id_padded = padLeft(room_id, 2); var hexString = '000440000000' + rfAdress + room_id_padded + reqTempHex + date_until + time_until; var payload = Buffer.from(hexString, 'hex').toString('base64'); var data = 's:' + payload + '\r\n'; return data; } // Source: https://github.com/Bouni/max-cube-protocol/blob/master/S-Message.md // Description Length Example Value // ===================================================================== // Base String 6 000410000000 // RF Address 3 0FC380 // Room Nr 1 01 // Day of week 1 02 // Temp and Time 2 4049 // Temp and Time (2) 2 4c6e // Temp and Time (3) 2 40cb // Temp and Time (4) 2 4d20 // Temp and Time (5) 2 4d20 // Temp and Time (6) 2 4d20 // Temp and Time (7) 2 4d02 // Day of week // ===================================================================== // hex: | 02 | // dual: | 0000 0010 | // |||| // |+++-- day: 000: saturday // | 001: sunday // | 010: monday // | 011: tuesday // | 100: wednesday // | 101: thursday // | 110: friday // | // +----- telegram: 1: set // 0: not set // The meaning of telegram is unclear at the moment. // Temperature and Time // ===================================================================== // hex: | 40 | 49 | // dual: | 0100 0000 | 0100 1001 | // |||| |||| |||| |||| // |||| |||+---++++-++++-- Time: 0 0100 1001: 06:05 // |||| ||| // |||| |||+-------------- Temperature: 0100 000: 16 // This 16 bit word contains the temperature on the 7 MSB and Time until that temperature is set on the 9 LSB. Temperature value has to be divided by 2. // 20 (hex) = 32 (decimal) -> 32/2 = 16 // // Time is the value * 5 minutes since midnight. // 49 (hex) = 73 (decimal) -> 73*5 = 365 -> 6:05 // 4d02 (hex) = 21:00, 19 deg function generateSetDayProgramCommand (rfAdress, room_id, weekday, temperaturesArray, timesArray) { // weekday: 0=mo,1=tu,..,6=su // tempertures: [19.5,21,..] degrees Celsius (max 7) // times: ['HH:mm',..] 24h format (max 7, same amount as temperatures) var dayArr = ['010','011','100','101','110','000','001']; // mo - su var dayBin = dayArr[weekday]; var reqDayBin = padLeft(dayBin, 8); var reqDayHex = parseInt(reqDayBin, 2).toString(16); var hexTempTimeArr = []; for (var i = 0; i < temperaturesArray.length; i++) { if (i < 6 || i == temperaturesArray.length-1) // max: 7, take 6 first and last { var temp = temperaturesArray[i]; if (i < temperaturesArray.length-1 && temp == temperaturesArray[i+1]) { // temperature is the same as in the next time, so only set change @ the next time } else { var time = timesArray[i].split(':'); var mins = ( parseInt(time[0]) * 60 + parseInt(time[1]) ); var temB = padLeft(((temp || 0) * 2).toString(2), 7); var timB = padLeft(Math.round(mins / 5).toString(2), 9); var bin = temB + timB; var hex = parseInt(bin, 2).toString(16); hexTempTimeArr.push(hex); } } } // to hex string var reqTempTimeHex = hexTempTimeArr.join(''); var room_id_padded = padLeft(room_id.toString(16), 2); var req_day_padded = padLeft(reqDayHex, 2); var hexString = '000410000000' + rfAdress + room_id_padded + req_day_padded + reqTempTimeHex; var payload = Buffer.from(hexString, 'hex').toString('base64'); var data = 's:' + payload + '\r\n'; return data; } function generateResetCommand (rfAdress) { var hexString = rfAdress var payload = Buffer.from(hexString, 'hex').toString('base64'); var data = 'r:01,' + payload + '\r\n'; return data; } function padLeft(data, totalLength){ return Array(totalLength - String(data).length + 1).join('0') + data; } module.exports = { generateSetTemperatureCommand: generateSetTemperatureCommand, generateSetDayProgramCommand: generateSetDayProgramCommand, generateResetCommand:generateResetCommand };