Files
iot/ac.js
d-popov 608344f876 working AC code generation for TLC_112;
fallback to HTTP if HTTPS certs not loaded.
2020-04-15 16:40:16 +03:00

283 lines
6.9 KiB
JavaScript

//#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;
const AcMode = Object.freeze({"Heat":1, "Dry":2, "Cool":3, "Fan":7, "Auto":8})
// var AcMode {
// Heat = 1,
// Dry = 2,
// Cool = 3,
// FanHi = 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 AcModeSize = 4; // Nr. of Bits
var AcFanSize = 3; // Nr. of Bits. Mask = 0b00000111
var AcFanAuto = 0b000;
var AcFanLow = 0b010;
var AcFanMed = 0b011;
var AcFanHigh = 0b101;
var AcHalfDegreeOffset = 5;
var AcTempMax = 31.0;
var AcTempMin = 16.0;
var AcPowerOffset = 2;
var AcBitEconoOffset = 7;
var AcBitLightOffset = 6;
var AcBitHealthOffset = 4;
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(24);
// console.log("" + state.toString('hex'));
setMode(AcMode.Heat);
// console.log("" + state.toString('hex'));
setPower(true);
// console.log("" + state.toString('hex'));
setFan(AcFanMed);check();
console.log("" + state.toString('hex'));
var rawTime = "38000,"+GenerateTimingString();
console.log(rawTime);
// const request = require('request');
// request.post(
// 'http://192.168.1.126/ir',
// { form: { code: rawTime, type: 30} },
// function (error, response, body) {
// if (!error && response.statusCode == 200) {
// console.log("GOT " + body);
// //var m = model;
// //res.render('accontrol', {model:{data:req.body, user:req.user, command:com[0], info:com[0].info}});
// }else{
// model.info = "Error executing command " + model.command.info + ". Server resturned:" + req.statusCode
// }
// }
// );
function GenerateTimingString()
{
var arr = [AcTimes.HdrMark, AcTimes.HdrSpace, AcTimes.BitMark];
for(i=0; i<state.length; i++)
{
for(j=0; j<8; j++)
{
if(bit_test(state[i],j)){//on
arr.push(AcTimes.OneSpace);arr.push(AcTimes.BitMark);
}else{//off
arr.push(AcTimes.ZeroSpace);arr.push(AcTimes.BitMark);
}
}
}
return arr.join(",");
}
function bit_test(num, bit){
return ((num>>bit) % 2 != 0);
}
function bit_set(num, bit){
return num | 1<<bit;
}
function bit_clear(num, bit){
return num & ~(1<<bit);
}
function check()
{
var length = state.length;
checksum(length);
}
function validChecksum(state, length) {
return (length > 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);
}
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, AcTempMax - nrHalfDegrees / 2);
}
function setFan( speed) {
switch (speed) {
case AcFanAuto:
case AcFanLow:
case AcFanMed:
case AcFanHigh:
state[8] = setBits(state[8], kLowNibble, AcFanSize, speed);
break;
default:
setFan(AcFanAuto);
}
}
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 "38000,"+GenerateTimingString();
},
};
module.exports.Tlc112 = AcControl;
module.exports.Mode = AcMode;