//#region Constants var kDefaultMessageGap = 100000; var kNibbleSize = 4; var kLowNibble = 0; var kHighNibble = 4; var kModeBitsSize = 3; var INT8_MIN = -128; var INT8_MAX = 127; var UINT8_MAX = 255; var UINT8_MAX2 = 0xFF; var AcModeSize = 4; // Nr. of Bits const AcMode = Object.freeze({"Heat":1, "Dry":2, "Cool":3, "Fan":7, "Auto":8}) // Constants var AcTimes = { HdrMark:3000, HdrSpace:1650, BitMark:500, OneSpace: 1050, ZeroSpace: 325, Gap :kDefaultMessageGap // Total tolerance percentage to use for matching the header mark. // var AcHdrMarkTolerance = 6; // var AcTolerance = 5; // Extra Percentage for the rest. }; var AcFanSize = 3; // Nr. of Bits. Mask = 0b00000111 var AcFan = Object.freeze({ "Auto":0b000, "Low":0b010, "Med":0b011, "High":0b101}); //5 var AcHalfDegreeOffset = 5; var AcTempMax = 31.0; var AcTempMin = 16.0; var AcPowerOffset = 2; var AcBitEconoOffset = 7; var AcBitLightOffset = 6; var AcBitHealthOffset = 4; //3 var AcBitSwingHOffset = 3; var AcSwingVOffset = 3; // Mask 0b00111000 var AcSwingVSize = 3; // Nr. of bits. var AcSwingVOn = 0b111; var AcSwingVOff = 0b000; var AcBitTurboOffset = 6; //#endregion Constants var buf = require('buffer'); var initialState =new Int16Array([0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, 0x07, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03]); var state; state = Buffer.from(initialState.slice()); //remote_state = initialState.slice(); var b = setBits(state[0],0,5,0x0); // b = setBits(remote_state[0],0,6,0x0); // b = setBits(remote_state[0],0,6,0x0); // b = setBits(remote_state[0],0,7,0x0); // b = setBits(remote_state[0],0,8,0x0); // state[0] = setBits(state[0],0,8,0x0); // state[0] = setBit(state[0],0,true); // state[0] = setBit(state[0],1,true); // state[0] = setBit(state[0],2,true); // state[0] = setBit(state[0],1,0); // state[0] = setBits(state[0],0,8,0xFF); // console.log("" + state.toString('hex')); setTemp(23); setMode(AcMode.Heat); setPower(true); setFan(AcFan.Med);check(); console.log("" + state.toString('hex')); var rawTime = "38000,"+GenerateTimingString(); // console.log(rawTime); function GetState() { return state.toString('hex').toUpperCase(); } function GenerateTimingString() { var arr = [AcTimes.HdrMark, AcTimes.HdrSpace, AcTimes.BitMark]; for(i=0; i>bit) % 2 != 0); } function bit_set(num, bit){ return num | 1< 1 && state[length - 1] == sumBytes(state, length)); } // Calculate & set the checksum for the current internal state of the remote. function checksum(length) { if (length > 1) state[length - 1] = sumBytes(state, length-1); } function sumBytes(state, length, start=0) { var checksum = 0; for (i = 0; i - start < length; i++) {checksum += state[i + start];} return checksum; } function setBit(data, position, on) { if (position >= 8) return data; // Outside of range. mask = 1 << position; if (on){ data = data | mask; } else { data = data & ~mask; } return data; } function setBits(data, offset, nbits, val) { if (offset >= 8 || !nbits) return data; // Short circuit as it won't change. // Calculate the mask for the supplied value. mask = UINT8_MAX >> (8 - ((nbits > 8) ? 8 : nbits)); // Calculate the mask & clear the space for the data. // Clear the destination bits. data &= ~(mask << offset); // Merge in the data. data |= ((val & mask) << offset); return data; } function setPower(on) { state[5] = setBit(state[5], AcPowerOffset, on); state[12] = setBit(state[12], 7, !on); } function setMode(mode) { // If we get an unexpected mode, default to AUTO. switch (mode) { case AcMode.Fan: setFan(AcFanHigh);break; case AcMode.Auto: case AcMode.Cool: case AcMode.Heat: case AcMode.Dry: state[6] = setBits(state[6], kLowNibble, AcModeSize, mode); break; default: setMode(AcMode.Auto); } } function setTemp(celsius) { // Make sure we have desired temp in the correct range. var tsafe = Math.max(celsius, AcTempMin); tsafe = Math.min(tsafe, AcTempMax); // Convert to integer nr. of half degrees. var nrHalfDegrees = tsafe * 2; // Do we have a half degree celsius? state[12] = setBit(state[12], AcHalfDegreeOffset, nrHalfDegrees & 1); state[7] = setBits(state[7], kLowNibble, kNibbleSize, (nrHalfDegrees % 2) + (AcTempMax - nrHalfDegrees / 2)); } function setFan(speed) { switch (speed) { case AcFan.Auto: case AcFan.Low: case AcFan.Med: case AcFan.High: state[8] = setBits(state[8], kLowNibble, AcFanSize, speed); break; default: setFan(AcFan.Auto); } } function setEcono(on) { console.log("[5]"); state[5] = setBit(state[5], AcBitEconoOffset, on); } function setHealth(on) { console.log("[6]"); state[6] = setBit(state[6], AcBitHealthOffset, on); } function setLight(on) { console.log("[5]"); state[5] = setBit(state[5], AcBitLightOffset, !on); // Cleared when on. } function setSwingHorizontal(on) { console.log("[12]"); state[12] = setBit(state[12], AcBitSwingHOffset, on); } function setSwingVertical(on) { console.log("[8]"); state[8] = setBits(state[8], AcSwingVOffset, AcSwingVSize, on ? AcSwingVOn : AcSwingVOff); } function setTurbo(on) { console.log("[6]"); state[6] = setBit(state[6], AcBitTurboOffset, on); if (on) { setFan(AcFanHigh); setSwingVertical(true); } } var AcControl = { Init:function() { state = Buffer.from(initialState.slice()); }, SetPower: setPower, SetMode : setMode, SetTemp : setTemp, SetFan : setFan, SetEcono : setEcono, SetHealth: setHealth, SetLight: setLight, SetSwingHorizontal: setSwingHorizontal, SetSwingVertical: setSwingVertical, SetTurbo: setTurbo, GetCommand: function(){ check(); console.log("GetCommand:" + state.toString('hex')); return GenerateTimingString(); }, GetState:GetState(), }; module.exports.Tlc112 = AcControl; module.exports.Mode = AcMode; module.exports.FanSpeed = AcFan;