// ./src/index.js const env = process.env.NODE_ENV || 'development'; console.log("ENV: %s", env); const config = require(__dirname + '/config/config.json')[env]; (function () { var exLog = console.log; console.log = function (msg) { exLog.apply(this, arguments); fs.appendFileSync(config.logFile, msg + "\r\n"); } })(); // importing the dependencies const util = require('util'); const express = require('express'); const bodyParser = require('body-parser'); const request = require('request'); const WebSocket = require('ws'); const cors = require('cors'); const helmet = require('helmet'); const morgan = require('morgan'); const cron = require('node-cron'); //!https endpoint var fs = require("fs"); var http = require('http'); var https = require('https'); try { var CERT_ROOT = "/etc/letsencrypt/live/iot.d-popov.com-0003"; var SECURE_KEY = CERT_ROOT + "/privkey.pem"; //__dirname + '/../../test/secure/tls-key.pem'; var SECURE_CERT = CERT_ROOT + "/cert.pem"; var _privateKey = fs.readFileSync(SECURE_KEY, 'utf8'); var _certificate = fs.readFileSync(SECURE_CERT, 'utf8'); var _ca = fs.readFileSync(CERT_ROOT + "/chain.pem", 'utf8'); var credentials = { key: _privateKey, cert: _certificate, ca: _ca }; } catch (ex) { console.log("can't load certificates."); } // defining the Express app const app = express(); app.use(helmet()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(express.static('public')); app.use(cors()); app.set('view engine', 'ejs'); app.use(require('express-ejs-layouts')); //https://www.npmjs.com/package/express-ejs-layouts // adding morgan to log HTTP requests app.use(morgan('combined')); //defining endpoints //!UI var auth = require('../src/auth.js'); var ac = require('./ac.js'); var db = require('../src/db'); var mqtt = require('../src/mqtt.js'); var ir = require('../src/devices/ir'); var u = require('../src/utils'); app.use(auth.init()); app.get('/', function (req, res) { res.redirect('/login'); }); app.get('/accontrol', auth.ensureLoggedIn_Orig, function (req, res) { res.render('accontrol', { model: { data: req.body, user: req.user, command: "", info: "" } }); }); app.post('/accontrol', //ensureLoggedIn, function (req, res) { console.log("POST accontrol"); var sess = req.session; var model = { model: { user: req.user, data: req.body } }; console.log("power:" + req.body.power); console.log("heat:" + req.body.heat); console.log("temp:" + req.body.temp); if (!req.body.temp) { req.body.temp = 23; } console.log("temp:" + req.body.temp); console.log("econo:" + req.body.econo); console.log("swing:" + req.body.swing); ac.Tlc112.Init(); ac.Tlc112.SetPower(req.body.power); ac.Tlc112.SetMode(req.body.heat ? ac.Mode.Heat : ac.Mode.Cool); ac.Tlc112.SetTemp(req.body.temp); ac.Tlc112.SetSwingVertical(req.body.swing); ac.Tlc112.SetFan(ac.FanSpeed.Med); var code = ac.Tlc112.GetCommand(); //!mqtt_client.publish('cmnd/', 'controller') //break it //code = code.substring(150); //console.log("RAW: " + code); if (ir.SendCmd("http://" + config.AcIP, code)) { console.log("OK. Temp: " + req.body.temp); BroadcastWS(ac.Tlc112.GetState()); } else { model.info = "Error executing command. Server resturned:" + req.statusCode; BroadcastWS("Error sending IR command"); } //console.log("req.user:" + util.inspect( req.user)); res.render('accontrol', model); // res.render('accontrol',{model: {data: req.body, user: req.user, command: "", info: model.info}}); }); app.get('/chart', auth.ensureLoggedIn_Orig, function (req, res) { res.render('chart', { user: req.user }); }); app.get('/garden/:days?', function (req, res) { res.render('chartGarden', { model: req.params }); }); //Authentication -- //! ESP HANDLERS const { parse } = require('querystring'); var moment = require('moment'); // var Sync = require('sync'); app.use('/dht', ir.html_handle_dht); app.use('/waterTest', function (req, res) { console.log("Watering TEST for: " + req.params); }); config.gardenIP = process.env.GARDEN_IP || config.gardenIP || ""; app.use('/water', function (req, res) { var time = req.query.t; console.log("Watering cmd for: " + time); if (config.gardenIP != "" && config.gardenIP != "0.0.0.0") { console.log("DHT> sending cmd over HTTP"); request('http://' + config.gardenIP + '/tools?cmd=event,manualwatering=' + time, { json: true }, (err, res, body) => { if (err) { return console.log("Problem watering: " + err); } console.log("Watering cmd successfully sent over HTTP!"); }); } mqtt.SendCmd("event,manualwatering=" + time); }); app.use('/waterStop', function (req, res) { if (config.gardenIP != "" && config.gardenIP != "0.0.0.0") { console.log("DHT> sending cmd over HTTP"); request('http://' + config.gardenIP + '/tools?cmd=event,stopwatering', { json: true }, (err, res, body) => { if (err) { return console.log("Problem watering: " + err); } console.log("STOP watering cmd sent!"); }); } mqtt.SendCmd("event,stopwatering"); }); function BroadcastWS(msg) { wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { client.send(moment().format() + " : " + msg); } }); } app.get("/device/:field_name/:days?", function (req, res) { db.devicemessages.findByName(req.params.field_name, req.params.days, function (err, data) { if (!err) { res.send(data); } else { console.log("error: ", err); } }); }); app.put('/device/:device_id/:field_name/:field_value', (req, res) => { db.devicemessages.insert(req.params.device_id, req.params.field_name, req.params.field_value, function (err, data) { if (!err) { res.send(data); } else { console.log("error: ", err); } }); }); //!Startup var wws; if (credentials) { var httpsServer = https.createServer(credentials, app); httpsServer.listen(2443, () => { console.log('\r\n\r\nHTTPS server listening on port 2443'); }); wss = new WebSocket.Server({ server: httpsServer }); } else { var httpServer = http.createServer(app); httpServer.listen(2080, () => { console.log('HTTP server listening on port 2080'); }); wss = new WebSocket.Server({ port: 2081 }); //not secure console.log('WebSocket server listening on port 2081'); } // // # ┌────────────── second (optional) // // # │ ┌──────────── minute // // # │ │ ┌────────── hour // // # │ │ │ ┌──────── day of month // // # │ │ │ │ ┌────── month // // # │ │ │ │ │ ┌──── day of week // // # │ │ │ │ │ │ // // # │ │ │ │ │ │ // // # * * * * * * // cron.schedule(' */30 * * * *', () => {//cron.schedule('*/5 * * * * *', () => { // console.log(new Date().toISOString() + ' running a task every 30 minutes'); // //StoreSensorReadings(); // db.devicemessages.getFromDht('http://192.168.1.126/json'); // }).start(); //db.devicemessages.getFromDht('http://192.168.1.126/json'); wss.on('connection', wss => { wss.on('message', message => { console.log('Received message => ${message}'); }); wss.send('ho!'); }); // const {keys} = Object; // const {Console} = console; // /** // * Redirect console to a file. Call without path or with false-y // * value to restore original behavior. // * @param {string} [path] // */ // function file(path) { // const con = path ? new Console(fs.createWriteStream(path)) : null; // keys(Console.prototype).forEach(key => { // if (path) { // this[key] = (...args) => con[key](...args); // } else { // delete this[key]; // } // }); // }; // // ///---patch global console object and export // module.exports = console.file = file; // console.file(__dirname + '/../log.txt');//__dirname + '/debug.log' log.txt // var log4js = require("log4js"); // log4js.configure({ // appenders: { // file: { // type: 'file', // filename: '/var/www/log4.txt', // maxLogSize: 10 * 1024 * 1024, // = 10Mb // backups: 5, // keep five backup files // compress: true, // compress the backups // encoding: 'utf-8', // mode: 0o0640, // flags: 'w+' // }, // console: { type: 'console' } // },categories: { // default: { appenders: ['console','file'], level: 'trace' } // } // }); // var logger = log4js.getLogger(); // logger.level = "debug"; // console.log("Some debug messages"); // //console.log = (msg) => console.log("C>" + msg); // console.log("Console MSG"); function formatDate(date) { var hour = date.getHours(); var minutes = date.getMinutes(); var seconds = date.getSeconds(); var milliseconds = date.getMilliseconds(); return '[' + ((hour < 10) ? '0' + hour : hour) + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds) + '.' + ('00' + milliseconds).slice(-3) + '] '; }