mirror of
https://github.com/oznu/homebridge-unifi-occupancy-sensor.git
synced 2025-01-22 19:37:37 +00:00
commit
2da88b0026
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
node_modules
|
node_modules
|
||||||
yarn.lock
|
yarn.lock
|
||||||
package-lock.json.
|
package-lock.json.
|
||||||
|
/homebridge-unifi-occupancy-sensor.iml
|
||||||
|
/.idea/
|
||||||
|
@ -23,8 +23,12 @@ The plugin connects to the UniFi Controller event web socket to get instant noti
|
|||||||
"site": "default", // Optional. The UniFi site to connect to.
|
"site": "default", // Optional. The UniFi site to connect to.
|
||||||
"secure": false // Optional. Set true to validate the SSL certificate.
|
"secure": false // Optional. Set true to validate the SSL certificate.
|
||||||
},
|
},
|
||||||
"watch": ["44:00:10:f0:3e:66"] // Required. An array of device MAC addresses to watch for.
|
"watch": [
|
||||||
"watchGuests": true // Optional. Set false to not monitor guest networks.
|
"44:00:10:f0:3e:66",
|
||||||
|
{ "device": "44:00:10:f0:3e:67", "ap": "44:00:10:f0:3e:44" }
|
||||||
|
], // Required. An array of device MAC addresses to watch for or objects with device MAC / AP MAC
|
||||||
|
"watchGuests": true, // Optional. Set false to not monitor guest networks.
|
||||||
|
"interval": 1800, // Optional. Polling interval used to query Unifi in seconds
|
||||||
"mode": "any" // Optional. Set to "any", "all" or "none".
|
"mode": "any" // Optional. Set to "any", "all" or "none".
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -45,9 +45,20 @@
|
|||||||
"title": "Watched Devices",
|
"title": "Watched Devices",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"title": "MAC Address",
|
"title": "Device / AP",
|
||||||
"type": "string",
|
"type": "object",
|
||||||
"pattern": "^([a-f0-9]{2}:){5}[a-f0-9]{2}$"
|
"properties": {
|
||||||
|
"device": {
|
||||||
|
"title": "Device MAC Address",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^([a-f0-9]{2}:){5}[a-f0-9]{2}$"
|
||||||
|
},
|
||||||
|
"ap": {
|
||||||
|
"title": "AP MAC Address",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^([a-f0-9]{2}:){5}[a-f0-9]{2}$"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mode": {
|
"mode": {
|
||||||
@ -55,15 +66,36 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "any",
|
"default": "any",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{ "title": "Any - only trigger occupancy when at least one watched device is connected", "enum": ["any"] },
|
{
|
||||||
{ "title": "All - only trigger occupancy when all watched devices are connected", "enum": ["all"] },
|
"title": "Any - only trigger occupancy when at least one watched device is connected",
|
||||||
{ "title": "None - only trigger occupancy when none of the watched devices are connected", "enum": ["none"] }
|
"enum": [
|
||||||
|
"any"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "All - only trigger occupancy when all watched devices are connected",
|
||||||
|
"enum": [
|
||||||
|
"all"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "None - only trigger occupancy when none of the watched devices are connected",
|
||||||
|
"enum": [
|
||||||
|
"none"
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"watchGuests": {
|
"watchGuests": {
|
||||||
"title": "Watch Guest Networks?",
|
"title": "Watch Guest Networks?",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"interval": {
|
||||||
|
"title": "Interval in seconds to query Unifi Controller",
|
||||||
|
"type": "integer",
|
||||||
|
"required": false,
|
||||||
|
"default": 1800
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
192
index.js
192
index.js
@ -1,25 +1,37 @@
|
|||||||
'use strict'
|
'use strict';
|
||||||
|
|
||||||
const debug = require('debug')('unifi')
|
const debug = require('debug')('unifi');
|
||||||
const UnifiEvents = require('unifi-events')
|
const UnifiEvents = require('unifi-events');
|
||||||
const manifest = require('./package.json')
|
const manifest = require('./package.json');
|
||||||
|
|
||||||
var Service, Characteristic
|
var Service, Characteristic;
|
||||||
|
|
||||||
module.exports = function (homebridge) {
|
module.exports = function (homebridge) {
|
||||||
Service = homebridge.hap.Service
|
Service = homebridge.hap.Service;
|
||||||
Characteristic = homebridge.hap.Characteristic
|
Characteristic = homebridge.hap.Characteristic;
|
||||||
homebridge.registerAccessory('homebridge-unifi-occupancy-sensor', 'UniFi Occupancy Sensor', OccupancySensor)
|
homebridge.registerAccessory('homebridge-unifi-occupancy-sensor',
|
||||||
}
|
'UniFi Occupancy Sensor', OccupancySensor)
|
||||||
|
};
|
||||||
|
|
||||||
class OccupancySensor {
|
class OccupancySensor {
|
||||||
constructor (log, config) {
|
constructor(log, config) {
|
||||||
this.log = log
|
this.log = log;
|
||||||
this.name = config.name
|
this.name = config.name;
|
||||||
this.occupancyService = new Service.OccupancySensor(this.name)
|
this.occupancyService = new Service.OccupancySensor(this.name);
|
||||||
this.watch = config.watch || []
|
|
||||||
this.watchGuests = config.watchGuests
|
this._watch = config.watch || [];
|
||||||
this.mode = config.mode || 'any'
|
// This allows for backwards compatibility with simple strings
|
||||||
|
this.watch = this._watch.map(function (watched) {
|
||||||
|
if (typeof watched === 'string' || watched instanceof String) {
|
||||||
|
return {"device": watched, "ap": undefined};
|
||||||
|
} else {
|
||||||
|
return watched;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.watchGuests = config.watchGuests;
|
||||||
|
this.mode = config.mode || 'any';
|
||||||
|
this.interval = config.interval || 1800;
|
||||||
|
|
||||||
this.unifi = new UnifiEvents({
|
this.unifi = new UnifiEvents({
|
||||||
controller: config.unifi.controller,
|
controller: config.unifi.controller,
|
||||||
@ -28,109 +40,115 @@ class OccupancySensor {
|
|||||||
site: config.unifi.site || 'default',
|
site: config.unifi.site || 'default',
|
||||||
rejectUnauthorized: config.unifi.secure || false,
|
rejectUnauthorized: config.unifi.secure || false,
|
||||||
listen: true
|
listen: true
|
||||||
})
|
});
|
||||||
|
|
||||||
this.unifi.on('websocket-status', (socketLog) => {
|
this.unifi.on('websocket-status', (socketLog) => {
|
||||||
this.log(socketLog)
|
this.log(socketLog)
|
||||||
})
|
});
|
||||||
|
|
||||||
this.unifi.on('connected', (data) => {
|
this.unifi.on('connected', (data) => {
|
||||||
debug(`Device Connected Event Received from UniFi Controller: ${data.msg}`)
|
debug(`Device Connected Event Received from UniFi Controller: ${data.msg}`);
|
||||||
return this.checkOccupancy()
|
return this.checkOccupancy()
|
||||||
})
|
});
|
||||||
|
|
||||||
this.unifi.on('disconnected', (data) => {
|
this.unifi.on('disconnected', (data) => {
|
||||||
debug(`Device Disconnected Event Received from UniFi Controller: ${data.msg}`)
|
debug(`Device Disconnected Event Received from UniFi Controller: ${data.msg}`);
|
||||||
return this.checkOccupancy()
|
return this.checkOccupancy()
|
||||||
})
|
});
|
||||||
|
|
||||||
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED
|
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED;
|
||||||
this.checkOccupancy()
|
this.checkOccupancy();
|
||||||
setInterval(this.checkOccupancy.bind(this), 1800 * 1000)
|
setInterval(this.checkOccupancy.bind(this), this.interval * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkGuest (isGuest, mac) {
|
checkGuest(isGuest, mac) {
|
||||||
if (this.watchGuests && isGuest) {
|
if (this.watchGuests && isGuest) {
|
||||||
debug(`Device [${mac}] is connected to a guest network and guest network monitoring is enabled.`)
|
debug(`Device [${mac}] is connected to a guest network and guest network monitoring is enabled.`);
|
||||||
return true
|
return true
|
||||||
} else if (!this.watchGuests && isGuest) {
|
} else if (!this.watchGuests && isGuest) {
|
||||||
debug(`Device [${mac}] is connected to a guest network but guest network monitoring is NOT enabled.`)
|
debug(`Device [${mac}] is connected to a guest network but guest network monitoring is NOT enabled.`);
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
debug(`Device [${mac}] is NOT connected to a guest network.`)
|
debug(`Device [${mac}] is NOT connected to a guest network.`);
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkOccupancy () {
|
isInWatchlist(device) {
|
||||||
debug('Getting list of connected clients from UniFi Controller...')
|
return this.watch.some(watchedDevice => (
|
||||||
return this.unifi.getClients()
|
watchedDevice.device === device.mac && (watchedDevice.ap === undefined || watchedDevice.ap === device.ap_mac))
|
||||||
.then((res) => {
|
);
|
||||||
debug(`${res.data.length} devices are currently connected to the UniFi network, checking each one to see if any are on the watch list...`)
|
|
||||||
|
|
||||||
let activeDevices = res.data.filter((device) => {
|
|
||||||
debug(`Device [${device.mac}] HOSTNAME: "${device.hostname}" , GUEST: "${device.is_guest}", SSID: "${device.essid}"`)
|
|
||||||
if (this.watch.includes(device.mac) && this.checkGuest(device.is_guest, device.mac)) {
|
|
||||||
debug(`Device [${device.mac}] Device is on the watch list. Going to trigger occupancy.`)
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
debug(`Device [${device.mac}] Ignoring. Not on the watch list.`)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
debug(`Monitored devices found:`, activeDevices.map(x => x.mac))
|
|
||||||
|
|
||||||
if (this.mode === 'none') {
|
|
||||||
if (activeDevices.length > 0) {
|
|
||||||
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "none" so NOT triggering occupancy.`)
|
|
||||||
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED
|
|
||||||
} else {
|
|
||||||
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "none" so triggering occupancy.`)
|
|
||||||
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_DETECTED
|
|
||||||
}
|
|
||||||
} else if (this.mode === 'all') {
|
|
||||||
if (activeDevices.length === this.watch.length) {
|
|
||||||
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "all" and all watched devices are connected so triggering occupancy.`)
|
|
||||||
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_DETECTED
|
|
||||||
} else {
|
|
||||||
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "all" and not all watched devices are connected so NOT triggering occupancy.`)
|
|
||||||
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (activeDevices.length > 0) {
|
|
||||||
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "any" so triggering occupancy.`)
|
|
||||||
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_DETECTED
|
|
||||||
} else {
|
|
||||||
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "any" so NOT triggering occupancy.`)
|
|
||||||
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setOccupancyDetected(this.occupancyDetected)
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.log(`ERROR: Failed to check occupancy: ${err.message}`)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getOccupancyDetected (callback) {
|
checkOccupancy() {
|
||||||
|
debug('Getting list of connected clients from UniFi Controller...');
|
||||||
|
|
||||||
|
return this.unifi.getClients()
|
||||||
|
.then((res) => {
|
||||||
|
debug(`${res.data.length} devices are currently connected to the UniFi network, checking each one to see if any are on the watch list...`);
|
||||||
|
let activeDevices = res.data.filter((device) => {
|
||||||
|
debug(`Device [${device.mac}, ${device.ap_mac}] HOSTNAME: "${device.hostname}" , GUEST: "${device.is_guest}", SSID: "${device.essid}"`);
|
||||||
|
if (this.isInWatchlist(device) && this.checkGuest(device.is_guest, device.mac)) {
|
||||||
|
debug(`Device [${device.mac}, ${device.ap_mac}] Device is on the watch list. Going to trigger occupancy.`);
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
debug(`Device [${device.mac}] Ignoring. Not on the watch list.`);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
debug(`Monitored devices found:`, activeDevices.map(x => x.mac));
|
||||||
|
|
||||||
|
if (this.mode === 'none') {
|
||||||
|
if (activeDevices.length > 0) {
|
||||||
|
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "none" so NOT triggering occupancy.`);
|
||||||
|
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED
|
||||||
|
} else {
|
||||||
|
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "none" so triggering occupancy.`);
|
||||||
|
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_DETECTED
|
||||||
|
}
|
||||||
|
} else if (this.mode === 'all') {
|
||||||
|
if (activeDevices.length === this.watch.length) {
|
||||||
|
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "all" and all watched devices are connected so triggering occupancy.`);
|
||||||
|
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_DETECTED
|
||||||
|
} else {
|
||||||
|
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "all" and not all watched devices are connected so NOT triggering occupancy.`);
|
||||||
|
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (activeDevices.length > 0) {
|
||||||
|
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "any" so triggering occupancy.`);
|
||||||
|
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_DETECTED
|
||||||
|
} else {
|
||||||
|
this.log(`${activeDevices.length} monitored device(s) found. Accessory is in mode "any" so NOT triggering occupancy.`);
|
||||||
|
this.occupancyDetected = Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setOccupancyDetected(this.occupancyDetected)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.log(`ERROR: Failed to check occupancy: ${err.message}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getOccupancyDetected(callback) {
|
||||||
return callback(null, this.occupancyDetected)
|
return callback(null, this.occupancyDetected)
|
||||||
}
|
}
|
||||||
|
|
||||||
setOccupancyDetected (value) {
|
setOccupancyDetected(value) {
|
||||||
return this.occupancyService.setCharacteristic(Characteristic.OccupancyDetected, value)
|
return this.occupancyService.setCharacteristic(Characteristic.OccupancyDetected, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
getServices () {
|
getServices() {
|
||||||
var informationService = new Service.AccessoryInformation()
|
var informationService = new Service.AccessoryInformation()
|
||||||
.setCharacteristic(Characteristic.Manufacturer, 'oznu')
|
.setCharacteristic(Characteristic.Manufacturer, 'oznu')
|
||||||
.setCharacteristic(Characteristic.Model, 'unifi-occupancy')
|
.setCharacteristic(Characteristic.Model, 'unifi-occupancy')
|
||||||
.setCharacteristic(Characteristic.SerialNumber, manifest.version)
|
.setCharacteristic(Characteristic.SerialNumber, manifest.version);
|
||||||
|
|
||||||
this.occupancyService
|
this.occupancyService
|
||||||
.getCharacteristic(Characteristic.OccupancyDetected)
|
.getCharacteristic(Characteristic.OccupancyDetected)
|
||||||
.on('get', this.getOccupancyDetected.bind(this))
|
.on('get', this.getOccupancyDetected.bind(this));
|
||||||
|
|
||||||
return [informationService, this.occupancyService]
|
return [informationService, this.occupancyService]
|
||||||
}
|
}
|
||||||
|
102
package-lock.json
generated
102
package-lock.json
generated
@ -13,11 +13,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "6.8.1",
|
"version": "6.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
|
||||||
"integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==",
|
"integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^2.0.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
"json-schema-traverse": "^0.4.1",
|
"json-schema-traverse": "^0.4.1",
|
||||||
"uri-js": "^4.2.2"
|
"uri-js": "^4.2.2"
|
||||||
@ -37,9 +37,9 @@
|
|||||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||||
},
|
},
|
||||||
"async-limiter": {
|
"async-limiter": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||||
},
|
},
|
||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
@ -52,9 +52,9 @@
|
|||||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||||
},
|
},
|
||||||
"aws4": {
|
"aws4": {
|
||||||
"version": "1.8.0",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
|
||||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
|
||||||
},
|
},
|
||||||
"bcrypt-pbkdf": {
|
"bcrypt-pbkdf": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -65,9 +65,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bluebird": {
|
"bluebird": {
|
||||||
"version": "3.5.3",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||||
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
|
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
|
||||||
},
|
},
|
||||||
"caseless": {
|
"caseless": {
|
||||||
"version": "0.12.0",
|
"version": "0.12.0",
|
||||||
@ -75,9 +75,9 @@
|
|||||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||||
},
|
},
|
||||||
"combined-stream": {
|
"combined-stream": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
}
|
}
|
||||||
@ -128,14 +128,14 @@
|
|||||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||||
},
|
},
|
||||||
"fast-deep-equal": {
|
"fast-deep-equal": {
|
||||||
"version": "2.0.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
|
||||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
|
||||||
},
|
},
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.0.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||||
},
|
},
|
||||||
"forever-agent": {
|
"forever-agent": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
@ -226,21 +226,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.11",
|
"version": "4.17.15",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.37.0",
|
"version": "1.43.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||||
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
|
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.21",
|
"version": "2.1.26",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||||
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
|
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "~1.37.0"
|
"mime-db": "1.43.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
@ -259,9 +259,9 @@
|
|||||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||||
},
|
},
|
||||||
"psl": {
|
"psl": {
|
||||||
"version": "1.1.31",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
|
||||||
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
|
"integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ=="
|
||||||
},
|
},
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
@ -301,22 +301,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"request-promise": {
|
"request-promise": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.5.tgz",
|
||||||
"integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=",
|
"integrity": "sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bluebird": "^3.5.0",
|
"bluebird": "^3.5.0",
|
||||||
"request-promise-core": "1.1.1",
|
"request-promise-core": "1.1.3",
|
||||||
"stealthy-require": "^1.1.0",
|
"stealthy-require": "^1.1.1",
|
||||||
"tough-cookie": ">=2.3.3"
|
"tough-cookie": "^2.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"request-promise-core": {
|
"request-promise-core": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
|
||||||
"integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
|
"integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash": "^4.13.1"
|
"lodash": "^4.17.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
@ -380,9 +380,9 @@
|
|||||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||||
},
|
},
|
||||||
"unifi-events": {
|
"unifi-events": {
|
||||||
"version": "0.4.2",
|
"version": "0.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/unifi-events/-/unifi-events-0.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/unifi-events/-/unifi-events-0.4.3.tgz",
|
||||||
"integrity": "sha512-NKWbGGgvW/0yzbVv8zGBJArUixt4HOkWgRsrtV0IJQrDgLphUYHHdf+mKTbwvPSyXyugi/hRGlDc254kWTIQZQ==",
|
"integrity": "sha512-nXaP8p0hOZMD4mmMp5kuotQUvdITT4kDdmytYR7Xc+LJmC7HQZcAT+fVoMo1TluqH96vl8AuHI+xVdb2oOoSqA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@oznu/ws-connect": "^0.0.4",
|
"@oznu/ws-connect": "^0.0.4",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
@ -398,9 +398,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "3.3.2",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||||
},
|
},
|
||||||
"verror": {
|
"verror": {
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "homebridge-unifi-occupancy-sensor",
|
"name": "homebridge-unifi-occupancy-sensor",
|
||||||
"version": "0.1.2",
|
"version": "0.2.0",
|
||||||
"description": "An occupancy sensor for Homebridge and UniFi",
|
"description": "An occupancy sensor for Homebridge and UniFi",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^3.2.6",
|
"debug": "^3.2.6",
|
||||||
"unifi-events": "^0.4.2"
|
"unifi-events": "^0.4.3"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"homebridge-plugin"
|
"homebridge-plugin"
|
||||||
|
Loading…
Reference in New Issue
Block a user