-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
124 lines (103 loc) · 3.11 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
const defaultHosts = "google.com,heroku.com";
const deviceNames = splitAndTrim(process.env.WEMODEVICES || "");
const hosts = splitAndTrim(process.env.WEMOHOSTS || defaultHosts);
const Wemo = require("wemo-client");
const wemo = new Wemo();
const Rx = require("rxjs/Rx");
const ManageDevice = require("./manage-device");
const isConnected = require("./is-connected");
const { logInfo, logError } = require("./logs");
const manageDevice = new ManageDevice();
const deviceStream = new Rx.ReplaySubject(10);
const pingDelay = 60 * 1000; // 1 minute
const resetDelay = 5 * 60 * 1000; // 5 minutes;
let lastReset;
let isNotifiedDisconnection = false;
let isNotifiedConnection = false;
logInfo("*** Wemo Switch Timer ***");
logInfo("+ Devices to monitor:", deviceNames.join(", "));
logInfo("+ Hosts:", hosts.join(", "));
if (deviceNames.length) {
Rx.Observable.interval(pingDelay)
.startWith(0)
.flatMap(async i => {
return await isConnected(hosts);
})
.subscribe(resetDevices, logError);
} else {
logInfo("NO DEVICE TO MONITOR!!")
}
deviceStream.subscribe(addDevice, logError);
wemo.discover(function(err, deviceInfo) {
if (err) {
deviceStream.error(err);
} else {
logInfo(
"Discovered a device:",
deviceInfo.friendlyName,
`(${deviceInfo.macAddress})`
);
deviceStream.next(deviceInfo);
}
});
function addDevice(deviceInfo) {
if (deviceNames.indexOf(deviceInfo.friendlyName) > -1) {
const client = wemo.client(deviceInfo);
client.on("error", function(err) {
logInfo("* Unable to connect to", deviceInfo.friendlyName, err.message);
});
client.on("binaryState", function(value) {
logInfo(
deviceInfo.friendlyName,
"(binary) status changed to",
parseInt(value, 10) ? "On" : "Off"
);
});
manageDevice.add(deviceInfo);
}
}
function resetDevices(status) {
if (status === false) {
notifyDisconnection();
if (isOkToReset(lastReset)) {
lastReset = new Date().getTime();
manageDevice.resetAll(20); // turn on device after 20 seconds
}
} else {
notifyConnection();
}
}
function isOkToReset(lastReset) {
const now = new Date().getTime();
return !lastReset || now - lastReset > resetDelay;
}
function timeToReset(lastReset, timeToReset) {
const totalSeconds = (new Date().getTime() - lastReset - resetDelay) / 1000;
const minutes = parseInt(totalSeconds / 60, 10);
const seconds = parseInt(totalSeconds - minutes * 60, 10);
return `${minutes} minutes ${seconds} seconds to reset`;
}
function notifyConnection() {
if (!isNotifiedConnection) {
logInfo("* CONNECTED");
isNotifiedConnection = true;
isNotifiedDisconnection = false;
}
}
function notifyDisconnection() {
if (!isNotifiedDisconnection) {
logInfo("* DISCONNECTED");
isNotifiedConnection = false;
isNotifiedDisconnection = true;
// only display time to reset if the last reset within TimeToReset
if (lastReset && !isOkToReset(lastReset)) {
logInfo(timeToReset(lastReset, timeToReset));
}
}
}
function splitAndTrim(str) {
return str
.split(",")
.map(s => s.trim())
.filter(s => s.length);
}