Skip to content

Commit

Permalink
Merge pull request #29 from mash/singleton-updater
Browse files Browse the repository at this point in the history
Use less move cron.CronJob from an instance variable to a package level singleton, to reduce the number of API calls
  • Loading branch information
kmaehashi authored May 1, 2023
2 parents 6c7b3c1 + 93503b9 commit 1907967
Showing 1 changed file with 60 additions and 46 deletions.
106 changes: 60 additions & 46 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const request = require('request');
const cron = require('cron');
const EventEmitter = require('events');

const DEFAULT_REQUEST_OPTIONS = {
baseUrl: 'https://api.nature.global/1/',
Expand All @@ -16,6 +17,13 @@ const RESPONSE_KEYS_BY_REQUEST_KEY = {

let hap;

// Singleton cron.CronJob that updates appliances and devices.
let updater = null;

// eventHandler emits events when updater has updated appliances and devices.
const eventHandler = {};
Object.assign(eventHandler, EventEmitter.prototype);

module.exports = homebridge => {
hap = homebridge.hap;
homebridge.registerAccessory('homebridge-nature-remo-cloud-aircon', 'NatureRemoAircon', NatureRemoAircon);
Expand Down Expand Up @@ -72,14 +80,55 @@ class NatureRemoAircon {
this.hasNotifiedConfiguration = false;

// Periodically refresh the target appliance information.
this.updater = new cron.CronJob({
cronTime: this.schedule,
onTick: () => {
this._refreshTargetAppliance();
},
runOnInit: true
if (! updater) {
updater = new cron.CronJob({
cronTime: this.schedule,
onTick: () => {
this._refreshTargetAppliance();
},
runOnInit: true
});
updater.start();
}

eventHandler.on('appliancesRefreshed', (json) => {
let appliance;
if (this.appliance_id) {
// Use the persisted appliance ID (i.e., ID discovered during the first
// refresh or ID specified in configuration by user).
appliance = json.find((app, i) => {
return app.id === this.appliance_id;
});
} else {
// ID not specified in configuration; automatically use the first
// aircon appliance.
// TODO: fix error if no aircon is registered.
appliance = json.filter(app => {
if (app.aircon !== null) {
this.log.debug(`Discovered aircon: ${app.id}: ${JSON.stringify(app)}`);
return true;
}
})[0];
}
if (appliance) {
this.log.debug(`Target aircon ID: ${appliance.id}`);
this.record = appliance;
this.appliance_id = appliance.id; // persist discovered ID
this._notifyConfigurationIfNeeded();
this._notifyLatestValues();
} else {
this.log('Target aircon could not be found. You can leave `appliance_id` blank to automatically use the first aircon.');
}
});

eventHandler.on('devicesRefreshed', (json) => {
const device = json.find(dev => {
return dev.id === this.record.device.id;
});
this.temperature = device.newest_events.te.val;
this.log.debug(`room temperature: ${this.temperature}`);
this._notifyLatestValues();
});
this.updater.start();
}

_updateTargetAppliance(params, callback) {
Expand Down Expand Up @@ -184,43 +233,13 @@ class NatureRemoAircon {
this.log(`failed to parse response: ${body}`);
return;
}
let appliance;
if (this.appliance_id) {
// Use the persisted appliance ID (i.e., ID discovered during the first
// refresh or ID specified in configuration by user).
appliance = json.find((app, i) => {
return app.id === this.appliance_id;
});
} else {
// ID not specified in configuration; automatically use the first
// aircon appliance.
// TODO: fix error if no aircon is registered.
appliance = json.filter(app => {
if (app.aircon !== null) {
this.log.debug(`Discovered aircon: ${app.id}: ${JSON.stringify(app)}`);
return true;
}
})[0];
}
if (appliance) {
this.log.debug(`Target aircon ID: ${appliance.id}`);
this.record = appliance;
this.appliance_id = appliance.id; // persist discovered ID
this._refreshTemperature();
this._notifyConfigurationIfNeeded();
this._notifyLatestValues();
} else {
this.log('Target aircon could not be found. You can leave `appliance_id` blank to automatically use the first aircon.');
}
eventHandler.emit('appliancesRefreshed', json);

this._refreshTemperature();
});
}

_refreshTemperature() {
if (this.record === null) {
this.log.debug('The aircon record is not available yet');
return;
}

this.log.debug('refreshing temperature record');
const options = Object.assign({}, DEFAULT_REQUEST_OPTIONS, {
uri: '/devices',
Expand All @@ -242,12 +261,7 @@ class NatureRemoAircon {
this.log(`failed to parse response of devices: ${body}`);
return;
}
const device = json.find(dev => {
return dev.id === this.record.device.id;
});
this.temperature = device.newest_events.te.val;
this.log.debug(`room temperature: ${this.temperature}`);
this._notifyLatestValues();
eventHandler.emit('devicesRefreshed', json);
});
}

Expand Down

0 comments on commit 1907967

Please sign in to comment.