[PLUGIN DEVELOPMENT] Centralising HTTP plugins
See original GitHub issueHi there,
As the title suggests, I am currently in the process of working on some ‘HTTP type’ plugins for homebridge. More specifically, I’ve recently done a fair bit of work on the homebridge-thermostat plugin attempting to streamline it. However, I’ve run into an issue which stretches a bit further than my JavaScipt knowledge, despite all my attempts!
Here is a snippet of example code taken from the original index.js
:
_httpRequest: function (url, body, method, callback) {
request({
url: url,
body: body,
method: this.http_method,
timeout: this.timeout,
rejectUnauthorized: false,
auth: this.auth
},
function (error, response, body) {
callback(error, response, body);
});
},
getTargetTemperature: function(callback) {
this.log("[+] getTargetTemperature from:", this.apiroute+"/status");
var url = this.apiroute+"/status";
this._httpRequest(url, '', 'GET', function (error, response, responseBody) {
if (error) {
this.log("[!] Error getting targetTemperature: %s", error.message);
callback(error);
} else {
var json = JSON.parse(responseBody);
this.targetTemperature = parseFloat(json.targetTemperature);
this.log("[*] targetTemperature: %s", this.targetTemperature);
callback(null, this.targetTemperature);
}
}.bind(this));
},
setTargetTemperature: function(value, callback) {
this.log("[+] setTargetTemperature from %s to %s", this.targetTemperature, value);
var url = this.apiroute+"/targetTemperature/"+value;
this._httpRequest(url, '', 'GET', function (error, response, responseBody) {
if (error) {
this.log("[!] Error setting targetTemperature", error.message);
callback(error);
} else {
this.log("[*] Sucessfully set targetTemperature to %s", value);
callback();
}
}.bind(this));
},
As you can see, for the sake of simplicity, I have removed numerous get
and set
functions but have kept two (getTargetTemperature
and setTargetTemperature
) for the sake of illustrating my point.
To summarise the what happens with the Thermostat: When the state is refreshed (by opening the Home app), numerous (4-6) get
functions are called, all of which contact the HTTP device simultaneously and attempt to retrieve the same JSON (containing data like the target temperature, current state etc.), they then proceed to extract just 1 field each; meaning that whilst the JSON only needs to be retrieved once, it is retrieved multiple times, which is extremely wasteful and can cause Homebridge to hang while this takes place. It is also worth noting that the set
functions are not an issue because they are only called individually once you update a field like the target temperature.
I have tried seeking a solution to the issue. My first thought was creating a centralised function called something like _getStatuses
which would be called by each of the get
functions. If it was being called for the first time in a while, it would request the JSON once, parse each of the fields and store them ready for the other incoming requests, reducing the number of requests greatly.
However, the problem is that I have tried multiple approaches to this problem and none of them have worked to a satisfactory level for a variety of reasons, including the fact that JavaScript is asynchronous and makes it hard to work step-by-step. Thus, I am hoping that someone may have an idea or solution which will solve the problem. I would be really grateful if someone could provide an idea, some sample code or a pre-existing plugin which relates to the issue.
Thank you in advance for your help,
Kind regards, Tom
Issue Analytics
- State:
- Created 5 years ago
- Comments:23 (11 by maintainers)
Top GitHub Comments
My rant against .on(‘get’
Using .on(‘get’ causes the home app to behave slow on loading, as homebridge needs to get current status from the device, rather than using the cached value.
Using automations with .on(‘get’ will not work as the status is not updated in real time, and only update when looking at the page in the home app
Device status does not change in real time when viewing in the home app, a change in room is required to update the status
@ebaauw Tks for your input on this and if you want to take a look at the final result take a look at this
https://github.com/Tommrodrigues/homebridge-web-thermostat
In the final design, we went with a 1 minute polling loop, removed all .on(‘get’ and used updateValue for everything