forked from cyberjunky/node-apcupsd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
executable file
·172 lines (155 loc) · 4.88 KB
/
app.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
App to poll an APC UPS (via apcupsd) and publish interesting values to MQTT.
Published under MIT license by Ron Klinkien <ron@cyberjunky.nl>
Copyright (C) 2014 The Netherlands
https://github.com/cyberjunky/node-apcupsd
John D. Allen
March 2019
-- Added specific payloads depending on the key field.
*/
'use strict';
var topic = 'ups'; // topic basename
var devicename = process.env.UPSNAME;
var daemon = process.env.APCHOST;
var apccmd = "apcaccess -h " + daemon;
var pollint = 10000; // poll every 10 seconds, only changed values will be published
var alerttime = 0;
var exec = require('child_process').exec;
var mqtt = require('mqtt');
//var mclient = mqtt.createClient(mqttbroker.port, mqttbroker.address);
var copts = {
keepalive: 20000
};
var mclient = mqtt.connect("http://10.1.1.28", copts);
var curvalues = {}; // holds current values
var wanted = [ 'model', 'status', 'linev', 'linefreq', 'timeleft', 'loadpct', 'battv', 'bcharge'];
function executeCmd(cmd, callback) {
exec(cmd, function (err, stdout, stderror) {
// console.log('stdout: %s', output);
if (err) {
callback(err);
}
else if (stderror) {
callback(stderror);
}
else {
if (stdout) {
callback(null,stdout);
}
else {
callback(null, null);
}
}
});
}
function poll() {
executeCmd(apccmd, function(err, response) {
if (err) {
console.error(err);
}
else {
// console.log(response);
var lines = response.trim().split("\n");
//console.log(">" + lines.length);
// loop over every line
lines.forEach((line) => {
// assign values
var stats = line.split(' : ');
var label = stats[0].toLowerCase();
var value = stats[1];
// remove surrounding spaces
label = label.replace(/(^\s+|\s+$)/g, '');
// if found as wanted value, store it
if (wanted.indexOf(label) > -1) {
value = value.replace(/(^\s+|\s+$)/g, '');
// check if value is known, if not store and publish value
if (curvalues[label] != value) {
curvalues[label] = value;
// console.log(value+" changed!");
// publish value
//console.log('.');
setPayload(label, value).then((payload) => {
mclient.publish(topic+'/'+label+'/'+devicename, payload);
if (label == "status" && value !== "ONLINE" && value !== "ONLINE REPLACEBATT") {
if (alerttime + 300000 < Date.now()) { // only every five minutes
alerttime = Date.now();
mclient.publish("alert/" + devicename, "UPS is NOT Online: " + value);
}
}
});
if (err) throw err;
}
}
});
}
// console.log(curvalues);
setTimeout(poll, pollint);
});
}
// Create the Payload string
function setPayload(key, value) {
return new Promise((resolve, reject) => {
var vals = value.split(/ /);
switch (key) {
case 'linev':
resolve('{"volts": ' + vals[0] +'}');
break;
case 'loadpct':
resolve('{"percent": ' + vals[0] + '}');
break;
case 'timeleft':
resolve('{"minutes": ' + vals[0] + '}');
break;
case 'battv':
resolve('{"volts": ' + vals[0] + '}');
break;
case 'model':
resolve('{"model": "' + value + '"}');
break;
case 'status':
resolve('{"status": "' + value + '"}');
break;
case 'bcharge':
resolve('{"percent": ' + vals[0] + '}');
break;
default:
reject("Unknown Value!");
}
});
}
function setPayloadB(key, value) {
return new Promise((resolve, reject) => {
setPayload(key, value).then((payload) => {
resolve([key, payload]);
});
});
}
// periodic publishing of stored values
function statsOut() {
//console.log(">StatsOut: " + Object.keys(curvalues).length);
for (var k in curvalues) {
if (curvalues.hasOwnProperty(k)) {
//console.log('.');
setPayloadB(k, curvalues[k]).then((t) => {
//console.log(t[0] + ":" + t[1]);
mclient.publish(topic+'/'+t[0]+'/'+devicename, t[1]);
});
}
}
setTimeout(statsOut, 600000); // Every 10 minutes
}
// Check to see of the status says that we need to replace the Batteries!
function chkBattery() {
if (curvalues['status'] == "ONLINE REPLACEBATT") {
mclient.publish("alert/" + devicename, "UPS Battery needs to be replaced!");
}
setTimeout(chkBattery, 86400000); // 24 hours; recheck tomorrow
}
// start plugin
function main() {
console.log('Started APCUPSD monitor');
poll();
setTimeout(statsOut, 300000); // first go in 5 minues
setTimeout(chkBattery, 600000); // first check in 10 minutes
}
main();