alexa-monit – Rev 1
?pathlinks?
#!/usr/bin/env nodejs
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2018 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
const request = require('request');
const mqtt = require('mqtt')
const YAML = require('yamljs');
const winston = require('winston');
const urljoin = require('url-join');
const fs = require('fs');
const jsonDiff = require('json-diff')
// Load configuration file.
const config = YAML.load('config.yml');
// Set up logger.
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({
filename: config.log
})
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}
// Create cookie jar.
const cookieJar = request.jar();
// Connect to MQTT
const mqttClient = mqtt.connect(config.mqtt.url);
function main() {
return new Promise((resolve, reject) => {
request({
method: 'GET',
url: urljoin(config.mmonit.url, '/index.csp'),
jar: cookieJar
},
(error, response, body) => {
if (error) {
reject(error);
return;
}
resolve(error);
});
});
}
function authenticate() {
return new Promise((resolve, reject) => {
request.post({
url: urljoin(config.mmonit.url, '/z_security_check'),
jar: cookieJar,
form: {
'z_username': config.mmonit.username,
'z_password': config.mmonit.password,
'z_csrf_protection': 'off'
}
},
(error, response, body) => {
if (error) {
reject(error);
return;
}
resolve(error);
});
});
}
function getHostStatusList() {
return new Promise((resolve, reject) => {
request({
method: 'GET',
url: urljoin(config.mmonit.url, '/status/hosts/list'),
jar: cookieJar
},
(error, response, body) => {
if (error) {
reject(error);
return;
}
resolve(body);
});
});
}
function writeState(state, file) {
// Store the state.
var data = JSON.stringify(state);
return new Promise(function (resolve, reject) {
fs.writeFile(file, data, function (error) {
if (error) {
reject(error);
return;
}
resolve();
});
});
}
function readState(file) {
// Store the state.
return new Promise(function (resolve, reject) {
fs.readFile(file, 'utf8', function (error, data) {
if (error) {
reject(error);
return;
}
resolve(JSON.parse(data));
})
});
}
function retrieveData() {
main().then((error) => {
if (error) {
logger.error('Could not reach main page.');
return;
}
logger.info('Got cookie.');
authenticate().then((error) => {
if (error) {
logger.error('Could not authenticate.');
return;
}
logger.info('Authentication successful.');
getHostStatusList().then((data) => {
if (error) {
logger.error('Could not get status list.');
return;
}
logger.info('Retrieved status list.');
var stateNew = JSON.parse(data);
fs.access(config.stateFile, fs.constants.F_OK, function (error) {
// State file does not exist, so write the data file and terminate.
if (error) {
logger.warn('State file not found, writing state.');
writeState(stateNew, config.stateFile).then(function () {
logger.info("Data stored.");
}, function (error) {
logger.error("Unable to store data: " + error);
});
return;
}
readState(config.stateFile).then(function (stateOld) {
logger.info("Comparing data.");
// stateOld, stateNew
stateOld.records.forEach(function (oldRecord) {
var hostname = oldRecord.hostname;
var id = oldRecord.id;
var newRecord = stateNew.records.find(function (record) {
return record.id === id;
});
var diff = jsonDiff.diff(oldRecord, newRecord);
if (typeof diff === undefined || diff == null) {
// No difference found so continue.
return;
}
// Filter out the "status" component.
if (typeof diff.status === undefined ||
diff.status == null) {
return;
}
// Build message out of hostname and new status change.
var message = hostname + " " + diff.status.__new;
logger.info(message);
mqttClient.publish(config.mqtt.topic, message, {}, function(error) {
if(error) {
logger.error("Unable to publish MQTT message: " + error);
return;
}
logger.info("Status change pushed to MQTT.");
});
});
// Save the retrieved data.
writeState(stateNew, config.stateFile).then(function () {
logger.info("Data stored.");
}, function (error) {
logger.error("Unable to store data: " + error);
});
}, function(error) {
logger.error("Unable to read state: " + error);
});
});
})
})
});
}
setInterval(retrieveData, config.interval);
Generated by GNU Enscript 1.6.5.90.