homebridge-samsung-airconditioner
Version:
node.js plugin for the Samsung smart samsung-airconditioners
402 lines (375 loc) • 21.1 kB
JavaScript
var Service, Characteristic;
var exec2 = require("child_process").exec;
var response;
module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
Accessory = homebridge.hap.Accessory;
homebridge.registerAccessory("homebridge-samsung-airconditioner", "SamsungAirconditioner", SamsungAirco);
};
function SamsungAirco(log, config) {
this.log=log;
this.name= config["name"];
this.ip=config["ip"];
this.token=config["token"];
this.patchCert=config["patchCert"];
this.accessoryName=config["name"];
}
SamsungAirco.prototype = {
execRequest: function(str, body, callback){
exec2(str, function(error, stdout, stderr){
callback(error, stdout, stderr)
})
},
identify: function(callback) {
this.log("Identify the clima!");
callback(); // success
},
getServices: function() {
this.aircoSamsung = new Service.HeaterCooler(this.name);
this.aircoSamsung.getCharacteristic(Characteristic.Active).on('get',this.getActive.bind(this)).on('set', this.setActive.bind(this)); //On or Off
this.aircoSamsung.getCharacteristic(Characteristic.CurrentTemperature)
.setProps({
minValue: 0,
maxValue: 100,
minStep: 0.01
})
.on('get', this.getCurrentTemperature.bind(this));
this.aircoSamsung.getCharacteristic(Characteristic.TargetHeaterCoolerState).on('get',this.getModalita.bind(this)).on('set', this.setModalita.bind(this));
this.aircoSamsung.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
.on('get', this.getCurrentHeaterCoolerState.bind(this));
this.aircoSamsung.getCharacteristic(Characteristic.HeatingThresholdTemperature)
.setProps({
minValue: 16,
maxValue: 30,
minStep: 1
})
.on('get', this.getHeatingUpOrDwTemperature.bind(this))
.on('set', this.setHeatingUpOrDwTemperature.bind(this));
//.RotationSpeed in my case Quite mode
this.aircoSamsung.getCharacteristic(Characteristic.SwingMode).on('get', this.getRotationSpeed.bind(this)).on('set', this.setRotationSpeed.bind(this));
var informationService = new Service.AccessoryInformation();
return [informationService, this.aircoSamsung];
},
//services
getRotationSpeed: function (callback) {
var body2;
str = 'curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure -X GET https://'+this.ip+':8888/devices|jq \'.Devices[0].Mode.options[0]\'';
this.log.debug(str);
this.execRequest(str, body2, function(error, stdout, stderr) {
if(error) {
//this.log('Power function failed', stderr);
callback(error);
} else {
this.response=stdout;
this.response= this.response.substr(1,this.response.length-3);
this.log.debug("Velocità Ventola ");
// body2=stdout;
this.log.debug(stdout);
if (this.response == "Comode_Quiet") {
body2=1;
this.log.debug('Quiet acceso');
// this.log.debug(this.response);
}
else if (this.response== "Comode_Off") {
body2=0;
this.log.debug('Quiet Spento');
// this.log.debug(this.response);
}
else {
body2=0;
this.log.debug('Unknow quit');
this.log(this.response);
}
this.log.debug(body2);
callback(null, body2);
}
}.bind(this))
},
setRotationSpeed: function (wind, callback) {
if(wind==0) {
var body;
str = 'curl -X PUT -d \'{"options": ["Comode_Off"]}\' -v -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure https://'+this.ip+':8888/devices/0/mode';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('Power function failed', stderr);
callback(error);
} else {
this.log('Setting AC to Normal . Off Quite');
this.log.debug(stdout);
body=0;
}
}.bind(this));
callback(null, body);
}
else if (wind==1){
var body;
str = 'curl -X PUT -d \'{"options": ["Comode_Quiet"]}\' -v -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure https://'+this.ip+':8888/devices/0/mode';
this.log(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('Power function failed', stderr);
callback(error);
} else {
this.log('Setting AC to Queit');
this.log.debug(stdout);
body=1;
}
}.bind(this));
callback(null, body);
}
else {
this.log('ERROR - Setting mode Unknow --> Setting to OFF QUITE');
callback(null, 0);
}
},
getHeatingUpOrDwTemperature: function(callback) {
var body;
str = 'curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure -X GET https://'+this.ip+':8888/devices|jq \'.Devices[0].Temperatures[0].desired\'';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log.debug('Power function failed', stderr);
callback(error);
} else {
this.log.debug('Power function OK');
//this.response=stdout;
this.log.debug("Check desidered temperature!");
body = stdout << 0;
if(body==0) {
this.log('------ ERROR ------- Reopen Home App -- Reboot Homebridge Chek IP Address of the clima! ----- The Clima is connected to wifi? ----- Is real 0 degrades?');
callback(null,16);
} else {
this.log.debug(stdout);
this.log.debug(body);
this.log.debug('QUIIIII');
callback(null, body);
//callback();
}
}
}.bind(this))
},
setHeatingUpOrDwTemperature: function(temp, callback) {
var body;
str = 'curl -X PUT -d \'{"desired": '+temp+'}\' -v -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure https://'+this.ip+':8888/devices/0/temperatures/0';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
//this.log('Power function failed', stderr);
callback(error);
} else {
//this.log('Power function OK');
this.log.debug('Set desidered temperature');
this.log.debug(stdout);
this.log.debug(temp);
callback(null, temp);
//callback();
}
}.bind(this))
},
getCurrentHeaterCoolerState: function (callback) {
var body;
str= 'curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure -X GET https://'+this.ip+':8888/devices|jq \'.Devices[0].Mode.modes[0]\'';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('getCurrentSTATE function failed', stderr);
callback(error);
} else {
this.log.debug('Get current HeaterCooler State function OK');
this.log.debug(stdout);
this.response=stdout;
this.response= this.response.substr(1,this.response.length-3);
this.log.debug(this.response);
if (this.response == "Cool") {
callback(null, Characteristic.CurrentHeaterCoolerState.COOLING);
} else if (this.response == "Heat") {
callback(null, Characteristic.CurrentHeaterCoolerState.HEATING);
} else if (this.response == "Fan") {
this.log('Clima state is FAN --> become AUTO');
callback(null, Characteristic.CurrentHeaterCoolerState.AUTO);
} else if (this.response == "Auto") {
callback(null, Characteristic.CurrentHeaterCoolerState.AUTO);
}else { //questa non c era
this.log(this.response);
this.log(' Undefined Current STATE of CLIMA, maybe DRY? set to AUTO');
callback(null,Characteristic.CurrentHeaterCoolerState.AUTO);
}
}
}.bind(this))
},
getCurrentTemperature: function(callback) {
var body;
str = 'curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure -X GET https://'+this.ip+':8888/devices|jq \'.Devices[0].Temperatures[0].current\'';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('getCurrentTemperature function failed', stderr);
callback(error);
} else {
this.log.debug('Get CurrentTemperature function OK');
this.log.debug(stdout);
body = stdout << 0; //Se stdout (cioè la temperatura corrente) è nulla, la trasforma in zero, perche non è possibile passare una variabile null. Se è nulla vuol dire che non riesce a ricevere il dato, quindi non è connesso all'indirizzo ip.
// body=parseInt(stdout) || 0; infatti con questa non si mette a zero
this.log.debug("Temperatura corrente: "+body);
this.aircoSamsung.getCharacteristic(Characteristic.CurrentTemperature).updateValue(body);
if(body==0) {
this.log('------ ERROR ------- Reopen Home App -- Reboot Homebridge Chek IP Address of the clima! ----- The Clima is connected to wifi? ----- Is real 0 degrades?');
callback(null,16);
}
else {
callback(null, body);
}
}
}.bind(this));
},
getActive: function(callback) {
var body;
var OFForON;
str = 'curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure -X GET https://'+this.ip+':8888/devices|jq \'.Devices[0].Operation.power\'';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('Power function failed', stderr);
callback(error);
} else {
this.log.debug('Power function OK');
this.log.debug(stdout);
this.response=stdout;
this.response= this.response.substr(1,this.response.length-3); //Elimina dalla stringa ricevuta il primo carattere e lunghezza-3
this.log.debug(this.response);
}
if (this.response == "Off") {
this.log.debug("Clima is OFF");
callback(null, Characteristic.Active.INACTIVE);
} else if (this.response == "On") {
this.log.debug("Clima is ON");
callback(null, Characteristic.Active.ACTIVE);
} else {
this.log(this.response+ "Error -- Unknow if Clima is ON or OFF, return OFF");
callback(null, Characteristic.Active.INACTIVE); //prima era ACTIVE
}
}.bind(this));
},
setActive: function(state, callback) {
var body;
var token, ip, patchCert;
token=this.token;
ip=this.ip;
patchCert=this.patchCert;
//this.log.debug(state); //lo stato del clima. 1 oppure 0 forse acceso o spento?
//this.log.debug(ip);
var activeFuncion = function(state) { //Crea un metodo activeFunction per accendere o spegnere il clima, passandogli le relative str, la variabile state gli viene passata direttamente da homekit?
if (state==Characteristic.Active.ACTIVE) {
str = 'curl -k -H "Content-Type: application/json" -H "Authorization: Bearer '+token+'" --cert '+patchCert+' --insecure -X PUT -d \'{"Operation" : {\"power"\ : \"On"\}}\' https://'+ip+':8888/devices/0';
console.log("The Clima is Activated");
} else {
console.log("The Clima is Inactive");
str = 'curl -k -H "Content-Type: application/json" -H "Authorization: Bearer '+token+'" --cert '+patchCert+' --insecure -X PUT -d \'{"Operation" : {\"power"\ : \"Off"\}}\' https://'+ip+':8888/devices/0';
}
}
activeFuncion(state); //Si richiama il metodo creato sopra activeFunction e gli passa
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('Active function failed', stderr);
callback(error);
} else {
this.log.debug('Active function');
callback();
this.log.debug(stdout);
}
}.bind(this));
},
getModalita: function(callback) {
var str;
var body;
this.log.debug("GetModalita ");
str= 'curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure -X GET https://'+this.ip+':8888/devices|jq \'.Devices[0].Mode.modes[0]\'';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('getModalita function failed', stderr);
callback(error);
} else {
this.log.debug('getModalita function OK ');
this.log.debug(stdout);
this.response=stdout;
this.response = this.response.substr(1,this.response.length-3);
this.log(this.response);
if (this.response == "Cool") {
this.log.debug("Cool ");
callback(null, Characteristic.TargetHeaterCoolerState.COOL);
} else if (this.response == "Heat") {
this.log.debug("Heat ");
callback(null, Characteristic.TargetHeaterCoolerState.HEAT);
} else if (this.response == "FAN") {
this.log.debug("Fan - return AUTO");
callback(null, Characteristic.TargetHeaterCoolerState.AUTO);
} else if (this.response == "Auto") {
this.log.debug("Auto ");
callback(null, Characteristic.TargetHeaterCoolerState.AUTO);
}else {
this.log(this.response+ "Unknow modalita, return AUTO - ERROR");
callback(null, Characteristic.TargetHeaterCoolerState.AUTO);
}
}
}.bind(this));
},
setModalita: function(state, callback) {
switch (state){
case Characteristic.TargetHeaterCoolerState.COOL:
var body;
this.log.debug("Setting AC to COOL...")
str = 'curl -X PUT -d \'{"modes": ["Cool"]}\' -v -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure https://'+this.ip+':8888/devices/0/mode';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('SetModalita COOL function failed', stderr);
callback(error);
} else {
this.log.debug('SetModalita Cool function OK');
callback();
this.log.debug(stdout);
}
}.bind(this));
break;
case Characteristic.TargetHeaterCoolerState.HEAT:
var body;
this.log.debug("Setting AC to HEAT...")
str = 'curl -X PUT -d \'{"modes": ["Heat"]}\' -v -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure https://'+this.ip+':8888/devices/0/mode';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('setModalita HEAT function failed', stderr);
callback(error);
} else {
this.log.debug('setModalita Heat function OK');
callback();
this.log.debug(stdout);
}
}.bind(this));
break;
case Characteristic.TargetHeaterCoolerState.AUTO:
var body;
// if (accessory.autoMode){
this.log("Setting AC to AUTO")
str = 'curl -X PUT -d \'{"modes": ["Auto"]}\' -v -k -H "Content-Type: application/json" -H "Authorization: Bearer '+this.token+'" --cert '+this.patchCert+' --insecure https://'+this.ip+':8888/devices/0/mode';
this.log.debug(str);
this.execRequest(str, body, function(error, stdout, stderr) {
if(error) {
this.log('setModalita AUTO function failed', stderr);
callback(error);
} else {
this.log('SetModalita Auto function OK');
callback();
this.log.debug(stdout);
}
}.bind(this));
//return accessory.lastMode.auto
//} //else return null
break;
}
}
};