This repository has been archived by the owner on Oct 1, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
136 lines (101 loc) · 3.47 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
var ping = require('ping');
var moment = require('moment');
var Service, Characteristic, HomebridgeAPI;
module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
HomebridgeAPI = homebridge;
homebridge.registerAccessory("homebridge-devices", "Devices", DeviceAccessory);
}
function DeviceAccessory(log, config) {
this.log = log;
this.name = config['name'];
this.devices = config['devices'];
this.threshold = config['threshold'];
this.services = [];
this.storage = require('node-persist');
this.stateCache = [];
//Init storage
this.storage.initSync({
dir: HomebridgeAPI.user.persistPath()
});
config['devices'].forEach(function(deviceConfig) {
var target = this.getTarget(deviceConfig);
var service = new Service.Switch(deviceConfig.name, deviceConfig.name);
service.target = target;
service
.getCharacteristic(Characteristic.On)
.on('get', this.getState.bind(this, target));
this.services.push(service);
}.bind(this));
this.populateStateCache();
//Start pinging the hosts
this.pingHosts();
}
DeviceAccessory.prototype.populateStateCache = function() {
this.devices.forEach(function(deviceConfig) {
var target = this.getTarget(deviceConfig);
var isActive = this.targetIsActive(target);
this.stateCache[target] = isActive;
}.bind(this));
}
DeviceAccessory.prototype.updateStateCache = function(target, state) {
this.stateCache[target] = state;
}
DeviceAccessory.prototype.getStateFromCache = function(target) {
return this.stateCache[target];
}
DeviceAccessory.prototype.getServices = function() {
return this.services;
}
DeviceAccessory.prototype.getServiceForTarget = function(target) {
var service = this.services.find(function(target, service) {
return (service.target == target);
}.bind(this, target));
return service;
}
DeviceAccessory.prototype.getState = function(target, callback) {
callback(null, this.getStateFromCache(target));
}
DeviceAccessory.prototype.pingHosts = function() {
this.devices.forEach(function(deviceConfig) {
var target = this.getTarget(deviceConfig);
ping.sys.probe(target, function(state){
//If target is alive update the last seen time
if (state) {
this.storage.setItem('device_' + target, Date.now());
}
var oldState = this.getStateFromCache(target);
var newState = this.targetIsActive(target);
if (oldState != newState) {
//Update our internal cache of states
this.updateStateCache(target, newState);
//Trigger an update to the Homekit service associated with the target
var service = this.getServiceForTarget(target);
service.getCharacteristic(Characteristic.On).setValue(newState);
}
}.bind(this));
}.bind(this));
setTimeout(DeviceAccessory.prototype.pingHosts.bind(this), 10000);
}
/**
* Handle old config entries that use a key of 'ip' instead of 'target'
*/
DeviceAccessory.prototype.getTarget = function(deviceConfig) {
if (deviceConfig.ip) {
return deviceConfig.ip;
}
return deviceConfig.target;
}
DeviceAccessory.prototype.targetIsActive = function(target) {
var lastSeenUnix = this.storage.getItem('device_' + target);
if (lastSeenUnix) {
var lastSeenMoment = moment(lastSeenUnix);
var activeThreshold = moment().subtract(this.threshold, 's');
var isActive = lastSeenMoment.isAfter(activeThreshold);
if (isActive) {
return true;
}
}
return false;
}