var express = require("express"); var hbs = require('express-hbs'); require('handlebars-form-helpers').register(hbs.handlebars); var nodemailer = require('nodemailer'); var courtsopenUtils = require('./courtsopenUtils.js'); var fs = require("fs"); var bodyParser = require("body-parser"); var app = express(); var logfile = fs.createWriteStream('./db/log.log', {flags: 'a'}); // Setup email var transporter = nodemailer.createTransport({ service: 'Gmail', auth: { user: 'alertmonitorfl@gmail.com', pass: '6g*hkvVc%91oo3#$' } }); var mailOptions = { from: 'Alert Monitor ', //to: 'jody@kaplon.us,don@gettner.com', to: 'jody@kaplon.us', subject: 'Device did not wish me a GoodMorning or GoodEvening', }; var file = "./db/courtsopen.db"; var exists = fs.existsSync(file); if(!exists) { console.log("Creating DB file."); fs.openSync(file, "w"); } var sqlite3 = require("sqlite3").verbose(); var db = new sqlite3.Database(file); db.serialize(function() { if(!exists) { // Can't create multiple tables w/one statement, semicolons not allowed. db.run( "CREATE TABLE Alerts (" + "origJSON TEXT," + "coreId TEXT," + "status TEXT," + "published_at TEXT)" ); db.run( "CREATE TABLE Cores (" + "coreId TEXT PRIMARY KEY," + "coreName TEXT," + "locationDesc TEXT)" ); } }); app.use(bodyParser.json()); // Needed for JSON POST requests from Particle Cores. app.use(bodyParser.urlencoded({ extended: false })); // Needed for web POST requests from edit form. // Use `.hbs` for extensions and find partials in `views/partials`. app.engine('hbs', hbs.express4({ partialsDir: __dirname + '/views/partials' })); app.set('view engine', 'hbs'); app.set('views', __dirname + '/views'); app.get('/', function(req, res){ var d = new Date(); console.log("GET /, " + JSON.stringify(d, 4)); var devIndexQry = "select status, published_at " + "from Alerts " + "where status in ('Open', 'Closed') " + "order by published_at desc " + "limit 2" db.all(devIndexQry, function(err, rows){ if(err !== null) { console.log(err); } else { //console.log(rows); // Loop over elements in rows array, convert ugly UTC times to pretty local times. rows.forEach(function(row){ row.pubDate = courtsopenUtils.getLocDateFromUTC(row.published_at); row.pubTime = courtsopenUtils.getLocTimeFromUTC(row.published_at); if(row.status.toLowerCase().indexOf('closed') > -1){ row.statusClass = 'closed'; } else { row.statusClass = 'open'; } }); res.render('index', {values: rows}, function(err, html) { if(err !== null) { console.log(err); } else { res.send(html); } }); } }); }); app.post('/', function(req, res){ var postEvent = req.body.postEvent; var source = req.body.source; console.log(req.body); // If it's stripped down JSON sent by cell modem, there won't be a req.body.data key w/full-nested JSON as value!!! // ???how to fix??? // If post body includes coreid and published_at, assume it's from a particle devcie and parse accordingly. if (req.body.coreid !== undefined && req.body.published_at !== undefined) { var innerDataJSON = JSON.parse(req.body.data); var status = JSON.stringify(innerDataJSON.status, null, 4).slice(1,-1); var coreid = JSON.stringify(req.body.coreid, null, 4).slice(1,-1); var pubAt = JSON.stringify(req.body.published_at, null, 4).slice(1,-1); var stmt = db.prepare("INSERT INTO Alerts (OrigJSON, coreid, published_at, status) VALUES (?, ?, ?, ?)"); stmt.run( JSON.stringify(req.body, null, 4), coreid, pubAt, status ); stmt.finalize(); } else { // parse for minimal data from cell modem. var deviceid = JSON.stringify(req.body.data, null, 4).slice(1,4); var statusCode = JSON.stringify(req.body.data, null, 4).slice(5,7); var statusFromCode; switch (statusCode) { case "01": statusFromCode = "Open"; break; case "02": statusFromCode = "Closed"; break; case "03": statusFromCode = "GoodMorning"; break; case "04": statusFromCode = "GoodEvening"; default: statusFromCode = "UnknownStatus" }; var received_at = new Date(Date.now()); received_at = received_at.toISOString(); console.log(statusFromCode + ' ' + received_at); var stmtCell = db.prepare("INSERT INTO Alerts (OrigJSON, coreid, published_at, status) VALUES (?, ?, ?, ?)"); stmtCell.run( JSON.stringify(req.body, null, 4), deviceid, received_at, statusFromCode ); stmtCell.finalize(); } }); setInterval(function() { // Check every hour to see if GoodMorning or GoodEvening has gone missing. var deadManQry = "select published_at from Alerts where datetime(published_at) > datetime('now', '-14.5 hours') order by datetime(published_at) limit 1"; db.get(deadManQry, function(err, row){ if (err !== null) { console.log(err); } //else if (typeof row == undefined) { else { // TEST, send the email as long as there's no error. mailOptions.text = "TEST TEST TEST...It's been too long since the last data transmission from device. \n\n"; // Don't include any other details for now, will need to change DB query to get details on last message received. //mailOptions.text = mailOptions.text + 'Status message, ' + status + '\n'; //mailOptions.text = mailOptions.text + 'Published at, ' + courtsopenUtils.getLocDateFromUTC(pubAt) + ' ' + courtsopenUtils.getLocTimeFromUTC(pubAt) + '\n'; //transporter.sendMail(mailOptions, function(error, info){ //if(error){ //console.log(error); //}else{ //console.log('Message sent: ' + info.response); //} //}); } }); }, 60000); app.listen(3000, function() { console.log("Started on PORT 3000"); })