Skip to content

Commit

Permalink
Update code to reduce memory footprint over time
Browse files Browse the repository at this point in the history
  • Loading branch information
dwaan committed Jul 19, 2022
1 parent a84cfe0 commit fada477
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 130 deletions.
248 changes: 123 additions & 125 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ module.exports = function (homebridge) {
homebridge.registerPlatform("homebridge-broadlink-platform-outlet", "broadlinkPlatformOutlet", broadlinkPlatform);
}

function broadlinkPlatform(log, config, api) {
this.log = log;
this.config = config;
if (api) this.api = api;
}

broadlinkPlatform.prototype = {
accessories: function (callback) {
class broadlinkPlatform {
constructor(log, config, api) {
this.log = log;
this.config = config;
if (api)
this.api = api;
}
accessories(callback) {
//For each device in cfg, create an accessory!
var accessories = this.config.accessories;
var accessoriesList = [];
Expand All @@ -33,57 +33,58 @@ broadlinkPlatform.prototype = {
accessories[i].outletTimer = accessories[i].timer[outlet - 1];
accessories[i].interval = accessories[i].interval || 0;

accessoriesList.push(new BroadlinkAccessory(this.log, accessories[i]));
accessoriesList.push(new broadlinkAccessory(this.log, accessories[i]));
}
this.log(`${accessories[i].name} - Created`);
} else {
accessoriesList.push(new BroadlinkAccessory(this.log, accessories[i]));
accessoriesList.push(new broadlinkAccessory(this.log, accessories[i]));
this.log(`${accessories[i].name} - Created`);
}
}
callback(accessoriesList);
}
}

function BroadlinkAccessory(log, config) {
this.log = log;
this.config = config;
this.type = config.type || MP; // Expected value MP or SP (default)
this.outletName = config.outletName || "";
this.name = (config.name || this.type) + (this.type == MP ? ": " : "") + this.outletName;
this.index = config.index || 0;
this.mac = config.mac;
this.timer = config.outletTimer;
this.interval = config.interval < 1000 ? 1000 : config.interval;

// Other value
this.powered = false;
this.firstTime = true;
this.onGetState = false;
this.onSetState = false;

if (!this.mac) throw new Error("You must provide a config value for 'mac' address.");

// MAC string to MAC buffer
this.mac_buff = function (mac) {
var mb = new Buffer.alloc(6, 0);
if (mac) {
var values = mac.split(':');
if (!values || values.length != 6) {
throw new Error('Invalid MAC [' + mac + ']; should follow pattern ##:##:##:##:##:##');
}
for (var i = 0; i < values.length; ++i) {
var tmpByte = parseInt(values[i], 16);
mb.writeUInt8(tmpByte, i);
class broadlinkAccessory {
constructor(log, config) {
this.log = log;
this.config = config;
this.type = config.type || MP; // Expected value MP or SP (default)
this.outletName = config.outletName || "";
this.name = (config.name || this.type) + (this.type == MP ? ": " : "") + this.outletName;
this.index = config.index || 0;
this.mac = config.mac;
this.timer = config.outletTimer;
this.interval = config.interval < 1000 ? 1000 : config.interval;

// Other value
this.powered = false;
this.firstTime = true;
this.onGetState = false;
this.onSetState = false;
this.device = null;

if (!this.mac) throw new Error("You must provide a config value for 'mac' address.");

// MAC string to MAC buffer
this.mac_buff = function (mac) {
var mb = new Buffer.alloc(6, 0);
if (mac) {
var values = mac.split(':');
if (!values || values.length != 6) {
throw new Error('Invalid MAC [' + mac + ']; should follow pattern ##:##:##:##:##:##');
}
for (var i = 0; i < values.length; ++i) {
var tmpByte = parseInt(values[i], 16);
mb.writeUInt8(tmpByte, i);
}
}
}

return mb;
return mb;
};
}
}

BroadlinkAccessory.prototype = {
getServices: function () {
getServices() {
var type = this.config.type;
var services = [];

Expand All @@ -107,118 +108,115 @@ BroadlinkAccessory.prototype = {
this.updateState();

return services;
},
}

discover: function (broadlink) {
discover(broadlink) {
try {
broadlink.discover();
} catch (error) {
this.onGetState = false;
this.onSetState = false;
}
},

// Get MP/SP outlets status
getState: function (callback) {
if (this.onGetState || this.onSetState) {
if (callback) callback(null, this.powered);
return;
}
}

var device = new broadlink();

this.onGetState = true;
this.discover(device);
device.on("deviceReady", (dev) => {
if (this.mac_buff(this.mac).equals(dev.mac) && !this.onSetState) {
dev.check_power();
dev.on(this.type == MP ? "mp_power" : "power", (statuses) => {
var status = (this.type == MP ? statuses[this.index - 1] : statuses) ? true : false;

dev.exit();
this.onGetState = false;

if (this.firstTime || this.powered != status) {
this.powered = status ? true : false;
this.firstTime = false;
this.switchService.updateCharacteristic(Characteristic.On, this.powered);
this.logState();
}
});
} else {
device = null;
this.onGetState = false;
}
// Get device
async _getDevice() {
return new Promise(async (resolve) => {
var device = new broadlink();
var checkAgain;

device = null;
// Find device
this.discover(device);
checkAgain = setInterval(() => {
this.discover(device);
}, 1000);

// Device is ready
device.on("deviceReady", (dev) => {
if (this.mac_buff(this.mac).equals(dev.mac)) {
clearInterval(checkAgain);
device = null;

// return the device
resolve(dev);
}
});
});
}

if (callback) callback(null, this.powered);
},
// Initiialized device
async _initDevice() {
this.device = await this._getDevice();

// Set MP/SP outlets status
setState: function (state, callback) {
var device = new broadlink();
var checkAgain;
// When recived power
this.device.on(this.type == MP ? "mp_power" : "power", (statuses) => {
var status = (this.type == MP ? statuses[this.index - 1] : statuses) ? true : false;

this.onSetState = true;
state = state ? true : false;
if (this.firstTime || this.powered != status) {
if (this.firstTime) this.firstTime = false;

this.log(`[${this.name}] 👈`);
this.powered = status ? true : false;
this.switchService.updateCharacteristic(Characteristic.On, this.powered);

this.discover(device);
checkAgain = setInterval(() => {
this.discover(device);
}, 1000);

device.on("deviceReady", (dev) => {
if (this.mac_buff(this.mac).equals(dev.mac)) {
// Set the power
this.powered = state;
if (this.type == MP) dev.set_power(this.index, this.powered);
else dev.set_power(this.powered);
this.logState();
}

// Check status while making sure state changed
dev.check_power();
dev.on(this.type == MP ? "mp_power" : "power", (statuses) => {
if (this.mac_buff(this.mac).equals(dev.mac)) {
var status = (this.type == MP ? statuses[this.index - 1] : statuses) ? true : false;
this.onGetState = false;
});
}

if (status != state) this.switchService.setCharacteristic(Characteristic.On, this.powered);
// Get MP/SP outlets status
async getState(callback) {
callback(null, this.powered);
}

// Stop the set loop
this.onSetState = false;
}
});
// Set MP/SP outlets status
async setState(state, callback) {
// Initialized device if it get disconnected
if (!this.device) await this._initDevice();

// Stop the loop
clearInterval(checkAgain);
dev.exit();
callback(null);
}
// Log state
this.log(`[${this.name}] 👈`);

device = null;
});
},
// Set the power
this.powered = state ? true : false;
if (this.type == MP) this.device.set_power(this.index, this.powered);
else this.device.set_power(this.powered);
this.switchService.updateCharacteristic(Characteristic.On, this.powered);

// Log state
this.logState();

// Send check power command
this.device.check_power();

// Callback;
callback(null);
}

// Update outlets status based on the last status
updateState: function () {
async updateState() {
// Send check power command and loop it
if (this.mainInterval) clearInterval(this.mainInterval);
this.mainInterval = setInterval(async () => {
this.onGetState = true;

// Initialized device if it get disconnected
if (!this.device) await this._initDevice();

this.mainInterval = setInterval(() => {
this.getState();
// Send check power command
this.device.check_power();
}, this.interval);
},
}

logState: function (extra, tail) {
logState(extra, tail) {
var message = `${extra ? extra + ": " : ""}${this.bulb(this.powered)} [${this.name}] ${tail ? "-> " + tail : ""}`;

if (message != this._message) this.log(message);
this._message = message;
},
}

bulb: function (state) {
bulb(state) {
return state ? "🟡" : "⚪️";
}
}
31 changes: 29 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "homebridge-broadlink-platform-outlet",
"version": "1.0.5",
"version": "1.1.0",
"description": "Homebridge plugin for Broadlink MP1 and SP2/3",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -31,6 +31,6 @@
},
"homepage": "https://github.com/dwaan/homebridge-broadlink-platform#readme",
"dependencies": {
"broadlinkjs-dw": "^0.1.11"
"broadlinkjs-dw": "^0.1.12"
}
}
}

0 comments on commit fada477

Please sign in to comment.