Socket
Socket
Sign inDemoInstall

homebridge-multiswitcheroo

Package Overview
Dependencies
15
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0 to 3.0.0

26

CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file.
# ❗**WARNING**❗
# *If using `Switcheroo` type accessories, please see [README](https://github.com/iSteve-O/homebridge-multiswitcheroo/blob/NewVersion/README.md) note before updating to v2.0!!
# *Version 2.0 contains breaking changes for `Switcheroo` type accessories.
## [2.0] - 2023-08-19
</br>
</br>
## *Version 3.0 is a total re-write for optimization*
</br>
# Changelog
## [3.0.0] - 2023-08-21
### Added
- ability to set `firmwareVersion` in the config.
- Proper error, warning & debug logging (almost).
### Changed
- removed unnecessary & outdated `require` dependancy. Should clear some install warnings.
- changed from using deprecated `request` to `axios` for http requests.
- fixed status polling so each accessory's `statusUrl` is called only once to update all switch statuses, instead of calling once for each switch at the `pollingInterval`.
- v3.0 uses about 75% less CPU & 15% less memory, on average, than even v2.0 (based on `top`)!
## [2.0.0] - 2023-08-19
### Changed
- Optimized code to remove unnecessary `Switcheroo` accessory
(Install homebridge-http-switch to replace functionality as stated in README).
(Install [`homebridge-http-switch`](https://github.com/Supereg/homebridge-http-switch/tree/master) to replace functionality as stated in [README](https://github.com/iSteve-O/homebridge-multiswitcheroo/blob/NewVersion/README.md)).
- Added ability to create `MultiSwitcheroo` accessories in the ConfigUI.

@@ -12,0 +34,0 @@

@@ -40,2 +40,9 @@ {

},
"firmwareRevision": {
"type": "string",
"title": "Firmware Revision",
"required": false,
"description": "Firmware version displayed in HomeKit. HomeKit expects Semantic Versioning, ie. `1.0.0` or `23.24.16-beta`, & does not display the pre-release or build metadata, ie. will show 23.24.16",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"
},
"statusUrl": {

@@ -42,0 +49,0 @@ "type": "string",

139

index.js

@@ -1,3 +0,4 @@

const request = require('request');
const axios = require('axios');
const pollingtoevent = require('polling-to-event');
const pkgVersion = require('./package.json').version;

@@ -21,11 +22,49 @@ let Service, Characteristic;

this.pollingInterval = config.pollingInterval || 3000;
this.statusPattern = config.statusPattern || "/1/";
this.statusPattern = config.statusPattern || '/1/';
this.manufacturer = config.manufacturer || 'iSteve-O';
this.model = config.model || 'MultiSwitcheroo';
this.serialNumber = config.serialNumber || this.name;
this.firmwareRevision = config.firmwareRevision || pkgVersion;
this.switches = [];
const statusemitter = pollingtoevent((done) => {
if (this.config.statusUrl) {
//this.log.debug(`Emitter calling URL`);
axios.get(this.config.statusUrl, { rejectUnauthorized: false })
.then((response) => done(null, response.data))
.catch((error) => {
this.log.error(`Error fetching status data: ${error.message}`);
done(error, null);
});
} else {
this.log.warn(`Error: No statusURL defined in config.json`);
done(null, null); // No status URL defined
}
}, { longpolling: true, interval: this.config.pollingInterval });
statusemitter.on('longpoll', (data) => {
//this.log.debug(`Parsing URL data`);
//this.log.debug(`Received status data:`, data);
const statusData = JSON.stringify(data);
for (const switchService of this.switches) {
const switchConfig = switchService.switchConfig;
if (switchConfig.statusPattern) {
const isOn = !!statusData.match(switchConfig.statusPattern);
switchService.getCharacteristic(Characteristic.On).updateValue(isOn);
//if (!isOn && switchService.getCharacteristic(Characteristic.On).value) {
//this.log.warn(`$(switchConfig.name) is off in the Home app, but should be on bsed on server respone.`);
//switchService.getCharacteristic(Characteristic.On).setValue(true);
//}
}
}
});
statusemitter.on('error', (error) => {
this.log.error(`Polling error: ${error}`);
});
for (const switchConfig of config.switches) {
const switchName = switchConfig.name;
const switchService = new Service.Switch(switchName, switchName);
switchService.switchConfig = switchConfig; // Attach switchConfig to the service
switchService

@@ -36,24 +75,4 @@ .getCharacteristic(Characteristic.On)

if (this.config.statusUrl && switchConfig.statusPattern) { // Use this.config.statusUrl
const statusemitter = pollingtoevent((done) => {
request.get({
url: this.config.statusUrl, // Use this.config.statusUrl
rejectUnauthorized: false
}, (err, response, body) => {
if (err) return done(err, null);
done(null, body);
});
}, { longpolling: true, interval: this.config.pollingInterval });
statusemitter.on('longpoll', (data) => {
const isOn = !!data.match(switchConfig.statusPattern);
switchService.getCharacteristic(Characteristic.On).updateValue(isOn);
});
statusemitter.on('error', (error) => {
this.log(`Polling error: ${error}`);
});
}
this.switches.push(switchService);
this.log.info(`Switch created: ${switchConfig.name}`);
}

@@ -65,31 +84,59 @@

.setCharacteristic(Characteristic.Model, this.model)
.setCharacteristic(Characteristic.SerialNumber, this.serialNumber);
.setCharacteristic(Characteristic.SerialNumber, this.serialNumber)
.setCharacteristic(Characteristic.FirmwareRevision, this.firmwareRevision);
this.log.info(`${this.name} initialized...\n\t|Model: ${this.model}\n\t|Manufacturer: ${this.manufacturer}\n\t|Serial Number: ${this.serialNumber}\n\t|Firmware Version: ${this.firmwareRevision}`);
}
setOn(on, callback, switchConfig) {
request.get({
url: on ? switchConfig.onUrl : switchConfig.offUrl,
rejectUnauthorized: false
}, (err, response, body) => {
if (!err && response.statusCode === 200) {
callback(null);
} else {
callback(err || new Error(`Invalid response: ${response.statusCode}`));
}
});
//this.log.debug(`setOn calling URL`);
axios.get(on ? switchConfig.onUrl : switchConfig.offUrl, { rejectUnauthorized: false })
.then((response) => {
if (response.status === 200) {
//this.log.debug(`${switchConfig.name} toggled successfully ${response.status}`);
callback(null);
} else {
this.log.warn(`ERROR SETTING ${switchConfig.name}, CODE: ${response.status}`);
callback(new Error(`setOn Invalid response: ${response.status}`));
}
})
.catch((error) => {
this.log.error(`setOn ERROR SETTING ${switchConfig.name}: ${error}`);
callback(error);
});
}
getOn(callback, switchConfig) {
if (!this.config.statusUrl || !switchConfig.statusPattern) return callback(null, false);
request.get({
url: this.config.statusUrl, // Use this.config.statusUrl
rejectUnauthorized: false
}, (err, response, body) => {
if (!err && response.statusCode === 200) {
const isOn = !!body.match(switchConfig.statusPattern);
callback(null, isOn);
} else {
callback(err || new Error(`Invalid response: ${response.statusCode}`));
}
});
//this.log.debug(`getOn URL Rec'd: ${this.config.statusUrl}`);
//this.log.debug(`getOn Pattern Rec'd: ${switchConfig.statusPattern}`);
if (!this.config.statusUrl || !switchConfig.statusPattern) {
return callback(null, false);
this.log.warn(`Make sure statusUrl & statusPattern are defined properly in your config`);
}
//this.log.debug(`getOn statusPattern: ${switchConfig.statusPattern}`);
//this.log.debug(`getOn calling URL`);
axios.get(this.config.statusUrl, { rejectUnauthorized: false })
.then((response) => {
if (response.status === 200) {
//this.log.debug(`getOn Response Data:`, response.data);
const statusData = JSON.stringify(response.data); // Parse the response data
const isOn = !!statusData.match(switchConfig.statusPattern);
//this.log.debug(`getOn Status URL: ${this.config.statusUrl}`);
//this.log.debug(`getOn switchConfig Pattern: ${switchConfig.statusPattern}`);
callback(null, isOn);
} else {
this.log.warn(`getOn REQUEST ERROR: ${this.config.statusUrl}, CODE: ${response.status}`);
callback(new Error(`getOn Invalid response: ${response.status}`));
}
})
.catch((error) => {
this.log.error(`getOn REQUEST ERROR: ${this.config.statusUrl}, CODE: ${error}`);
callback(error);
});
}

@@ -96,0 +143,0 @@

{
"name": "homebridge-multiswitcheroo",
"displayName": "MultiSwitcheroo",
"version": "2.0.0",
"version": "3.0.0",
"author": "iSteve-O",
"description": "User defined switches for http GET requests. Simple on/off or multiswitch on/off. Useful for lights, A/V systems, home automation, and includes live status polling!",
"license": "MIT",
"homepage": "https://github.com/iSteve-O/homebridge-multiswitcheroo/blob/NewVersion/README.md",
"homepage": "https://github.com/iSteve-O/homebridge-multiswitcheroo/blob/TestSingle/README.md",
"repository": {
"type": "git",
"url": "git+https://github.com/iSteve-O/homebridge-multiswitcheroo/tree/NewVersion"
"url": "git+https://github.com/iSteve-O/homebridge-multiswitcheroo/tree/TestSingle"
},

@@ -33,5 +33,4 @@ "keywords": [

"dependencies": {
"polling-to-event": "^2.1.0",
"request": "^2.65.0",
"require": "^2.4.20"
"axios": "^1.4.0",
"polling-to-event": "^2.1.0"
},

@@ -38,0 +37,0 @@ "bugs": {

@@ -5,3 +5,4 @@ <p align="left">

[![NPM version](https://badge.fury.io/js/homebridge-multiswitcheroo.svg)](https://npmjs.org/package/homebridge-multiswitcheroo)
[![npm version](https://badgen.net/npm/v/homebridge-multiswitcheroo)](https://www.npmjs.com/package/homebridge-multiswitcheroo)
[![npm downloads](https://badgen.net/npm/dt/homebridge-multiswitcheroo)](https://www.npmjs.com/package/homebridge-multiswitcheroo)

@@ -30,2 +31,3 @@ # **MultiSwitcheroo**

</br>
Define your `MultiSwitcheroo` with whatever `name` you want to appear as the main switch title in the home app. This is what is visible if left displayed as a single tile (default). The `name` for each switch is what the individual switches should show. Sometimes these transfer to the home app, and sometimes not, so you may have to rename them all once in the home app, but only once.

@@ -35,7 +37,7 @@

The `statusPattern` is a regular expression string (regexp) sought in the response from the server to get an accurate status for each switch (see the `Mute` switch in the `MultiSwitcheroo` config example below for a really good example of a complex pattern where an unknown number is present in the string).
The `statusPattern` is a regular expression string (regex) sought in the response from the server to get an accurate status for each switch (see the `Mute` switch in the `MultiSwitcheroo` config example below for a really good example of a complex pattern where an unknown number is present in the string).
Set the `onUrl` & `offUrl` as appropriate. Must be the full URL, including `http://` & port.
Set the `onUrl` & `offUrl` as appropriate for each switch. Must be the full URL, including `http://` & port.
The `manufacturer`, `model`, and `serialNumber` are all optional, but it is best to set them. Controller for HomeKit will throw errors about duplicate serial numbers if you have multiple devices using `DEFAULT-SERIAL`. Plus, it's fun to set these with your name!
The `manufacturer`, `model`, `serialNumber`, & `firmwareRevision` are all optional, but it is best to set them. If you do not set them, they will all default to things that will not error in Controller for HomeKit because of duplicate serial numbers if you have multiple devices using the same one. Plus, it's fun to set these with your own stuff anyway, plus I made it super easy for you in the ConfigUI!

@@ -106,2 +108,3 @@ Currently only built to support the `GET` http method.

| `serialNumber` | will show in Home app description of this Homekit accessory, ex. 'SERIALNUMBER1' | |
| `firmwareRevision` | will show in Home app description of this Homekit accessory, ex. '1.0.0' | |

@@ -126,2 +129,3 @@

### This plugin was generated with a lot of help from ChatGPT.
### This plugin was originally generated with a lot of help from ChatGPT, but i have since re-written it.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc