”2016-09-23”

This commit is contained in:
Martin Donnelly 2016-09-23 16:45:05 +01:00
parent 7ae80679a8
commit 5c5f73fd6b
19 changed files with 296 additions and 181 deletions

View File

@ -1,3 +1,7 @@
node_modules node_modules
/sql/ /sql/
/dist/ /app/
/.vs/
/old_html/
/server/
/src/

View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.25420.1 VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "HIE(1)", "..\HIE", "{272EFB2D-871A-406F-8462-AF9CFE10C6A7}" Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "HIE(1)", ".", "{272EFB2D-871A-406F-8462-AF9CFE10C6A7}"
ProjectSection(WebsiteProperties) = preProject ProjectSection(WebsiteProperties) = preProject
TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0" TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
Debug.AspNetCompiler.VirtualPath = "/localhost_49439" Debug.AspNetCompiler.VirtualPath = "/localhost_49439"

View File

@ -5,11 +5,11 @@
var express = require('express'); var express = require('express');
var path = require('path'); var path = require('path');
var server = require('http').createServer(); var server = require('http').createServer();
var url = require('url');
var ejs = require('ejs'); var ejs = require('ejs');
var morgan = require('morgan'); var morgan = require('morgan');
var cookieparser = require('cookie-parser'); var cookieparser = require('cookie-parser');
var session = require('express-session'); var session = require('express-session');
var sessionLW = require('express-session-lw');
var methodoverride = require('method-override'); var methodoverride = require('method-override');
var bodyparser = require('body-parser'); var bodyparser = require('body-parser');
var errorhandler = require('errorhandler'); var errorhandler = require('errorhandler');
@ -23,31 +23,10 @@ var busEmitter = new Events.EventEmitter();
var WebSocketServer = require('ws').Server; var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server: server }); var wss = new WebSocketServer({ server: server });
//var SocketHandler = require('./lib/sockethandler');
var SocketHandler = require('./lib/wshandlerv2'); var SocketHandler = require('./lib/wshandlerv2');
console.log('Pre New SocketHandler');
var webSocket = new SocketHandler(busEmitter, wss); var webSocket = new SocketHandler(busEmitter, wss);
/*
wss.on('connection', function connection(ws) {
var location = url.parse(ws.upgradeReq.url, true);
// you might use location.query.access_token to authenticate or share sessions
// or ws.upgradeReq.headers.cookie (see http://stackoverflow.com/a/16395220/151312)
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
*/
console.log('Post New SocketHandler');
// Var apn = require('apn');
require('sugar-date'); require('sugar-date');
var isProduction = false; var isProduction = false;
@ -70,7 +49,7 @@ logger.warn('isProduction:', isProduction);
var heartBeat = function() { var heartBeat = function() {
this.pingTimer = 0; this.pingTimer = 0;
this.count = 0; this.count = 0;
this.rate = 20000; this.rate = 90000;
this.setupPing = function() { this.setupPing = function() {
logger.warn('Starting heartbeat...'); logger.warn('Starting heartbeat...');
@ -90,7 +69,7 @@ var heartBeat = function() {
_newDots[this.count - 1] = 'O'; _newDots[this.count - 1] = 'O';
logger.info(_newDots.join('')); logger.info(_newDots.join(''));
busEmitter.emit('sendSocket',{tick:new Date().getTime()}); busEmitter.emit('sendSocket',{tick: new Date().getTime()});
this.pingTimer = setTimeout(function() {this.ping();}.bind(this), mod); this.pingTimer = setTimeout(function() {this.ping();}.bind(this), mod);
}; };
@ -98,25 +77,17 @@ var heartBeat = function() {
this.setupPing(); this.setupPing();
}; };
var app = express(); var app = express();
/*App.use(authentication(({
hash: 'sha1', // type of hash
file: 'htpasswd', // path of file
suppress: true // suppress throwing Error if wrong user
})));*/
app.set('port', process.env.PORT || 4545); app.set('port', process.env.PORT || 4545);
app.set('views', __dirname + '/views'); app.set('views', __dirname + '/views');
app.set('view engine', 'ejs'); app.set('view engine', 'ejs');
app.use(morgan('combined')); app.use(morgan('combined'));
app.use(cookieparser('your secret here')); app.use(cookieparser('your secret here'));
app.use(session({ /*app.use(session({
secret: '1234567890QWERTY', resave: false, saveUninitialized: false secret: '1234567890QWERTY', resave: false, saveUninitialized: false
})); }));*/
/* 'default', 'short', 'tiny', 'dev' */ app.use(sessionLW());
app.use(methodoverride()); app.use(methodoverride());
app.use(bodyparser.urlencoded({extended: false})); app.use(bodyparser.urlencoded({extended: false}));
@ -130,7 +101,7 @@ app.use(function(req, res, next) {
next(); next();
}); });
// Run npm start --production to use dist // Run 'npm run production' to use dist
var staticDir = isProduction ? 'dist' : 'app'; var staticDir = isProduction ? 'dist' : 'app';
var graphFile = isProduction ? 'graph-release' : 'test2'; var graphFile = isProduction ? 'graph-release' : 'test2';
@ -145,26 +116,18 @@ function originIsAllowed(origin) {
return true; return true;
} }
app.get('/graph', authentication(({ app.get('/graph', authentication(({
hash: 'sha1', // Type of hash hash: 'sha1', // Type of hash
file: 'htpasswd', // Path of file file: 'htpasswd', // Path of file
suppress: true // Suppress throwing Error if wrong user suppress: true // Suppress throwing Error if wrong user
})), function(req, res) { })), function(req, res) {
res.render(graphFile,{delimiter: '^', port:(process.env.VCAP_APP_PORT || 3011)}); res.render(graphFile,{delimiter: '^', port: (process.env.VCAP_APP_PORT || 3011)});
}); });
app.get('/meeting', function(req, res) { app.get('/meeting', function(req, res) {
res.render('meeting',{delimiter: '^'}); res.render('meeting',{delimiter: '^'});
}); });
// ****
// Glue routes // Glue routes
mdotApi(app); mdotApi(app);
mdotApiV2(app); mdotApiV2(app);
@ -173,7 +136,9 @@ meetingApi(app);
messageApi(app, busEmitter); messageApi(app, busEmitter);
//heartBeat(); if (isProduction) {
heartBeat();
}
var port = (process.env.VCAP_APP_PORT || 3011); var port = (process.env.VCAP_APP_PORT || 3011);
var host = (process.env.VCAP_APP_HOST || 'localhost'); var host = (process.env.VCAP_APP_HOST || 'localhost');
@ -182,15 +147,8 @@ app.get('*', function(req, res) {
res.status(404).render('404',{delimiter: '^'}); res.status(404).render('404',{delimiter: '^'});
}); });
/*
var server = app.listen(port, function() {
logger.info('Express listening on ',host, port);
});
*/
server.on('request', app); server.on('request', app);
server.listen(port, function () { console.log('New server listening on ' + server.address().port) }); server.listen(port, function() { logger.info('New server listening on ' + server.address().port) });

View File

@ -1622,7 +1622,7 @@ th {
color: #F50057; } color: #F50057; }
.mui--text-accent-secondary { .mui--text-accent-secondary {
color: rgba(186, 214, 73, 0.54); } color: #32ffad; }
.mui--text-accent-hint { .mui--text-accent-hint {
color: rgba(186, 214, 73, 0.38); } color: rgba(186, 214, 73, 0.38); }

View File

@ -30,7 +30,7 @@ html, body { height: 100%; width: 100%; color: white; }
/*color: #FD5F00;*/ /*color: #FD5F00;*/
/*color: #ff0063;*/ /*color: #ff0063;*/
font-family: 'Ubuntu Condensed';; font-family: 'Ubuntu Condensed';
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 70px; font-size: 70px;
@ -38,6 +38,18 @@ html, body { height: 100%; width: 100%; color: white; }
text-align: center; text-align: center;
} }
.mui-select > select {
color:#32ffad;
border-bottom :none;
}
.mui-select__menu {
background-color:#212121
}
#example { #example {
position: relative; position: relative;
color: #ff0063; color: #ff0063;
@ -132,10 +144,13 @@ html, body { height: 100%; width: 100%; color: white; }
padding-left: 0px; padding-left: 0px;
margin-left:-20px; margin-left:-20px;
color:#00ffb6; color:#00ffb6;
margin-top:-10px;
} }
.widgetLogo { .widgetLogo {
font-family: 'Ubuntu Condensed', sans-serif; font-family: 'Ubuntu Condensed', sans-serif;
font-size: 16px;padding-left:20px; font-size: 16px;padding-left:20px;
padding-right:0px; padding-right:0px;
color:#00ffb6; color:#00ffb6;
font-size: 160% !important;
margin-top: -10px;
} }

View File

@ -99,7 +99,8 @@ var Clock = Backbone.View.extend({
if (this.prevDate !== curDate) { if (this.prevDate !== curDate) {
this.$date.html(now.format( this.$date.html(now.format(
//'<span class="wd-{do}">{Weekday}</span><br><span class="mo mo-{M}">{Month} {dd}</span><br>{yyyy}')); //'<span class="wd-{do}">{Weekday}</span><br><span class="mo mo-{M}">{Month} {dd}</span><br>{yyyy}'));
'<span class="wd-{do}">{Weekday}</span><br><span class="mo mo-{M}">{Month} {dd}</span>')); //'<span class="wd-{do}">{Weekday}</span><br><span class="mo mo-{M}">{Month} {dd}</span>'));
'<span class="wd-{do}">{Weekday}</span> <span class="mo mo-{M}">{Month} {dd}</span>'));
this.prevDate = curDate; this.prevDate = curDate;
} }
} }

View File

@ -79,7 +79,8 @@ gulp.task('styles', function() {
'app/css/custom.css', 'app/css/custom.css',
'app/css/test.css', 'app/css/test.css',
'app/css/style.css', 'app/css/style.css',
'app/css/weather-icons.css']) 'app/css/weather-icons.css',
'app/css/material-icons.css'])
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4')) .pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
.pipe(cssnano()) .pipe(cssnano())
.pipe(concat('app.css')) .pipe(concat('app.css'))

View File

@ -83,11 +83,6 @@ module.exports = function(events, server) {
}; };
events.on('sendSocket', sendSocketHandler); events.on('sendSocket', sendSocketHandler);
/*
Events.on('sendSocket', function(o){
logger.debug('sendSocket!!', o);
});
*/
connection.on('message', function(message) { connection.on('message', function(message) {
if (message.type === 'utf8') { if (message.type === 'utf8') {

View File

@ -13,8 +13,6 @@ var logger = require('log4js').getLogger();
module.exports = function(events, wsServer) { module.exports = function(events, wsServer) {
'use strict'; 'use strict';
logger.debug(wsServer);
wsServer.on('connection', function connection(ws) { wsServer.on('connection', function connection(ws) {
var location = url.parse(ws.upgradeReq.url, true); var location = url.parse(ws.upgradeReq.url, true);
@ -35,9 +33,11 @@ module.exports = function(events, wsServer) {
events.on('sendSocket', sendSocketHandler); events.on('sendSocket', sendSocketHandler);
/*
ws.on('message', function(message) { ws.on('message', function(message) {
console.log('received:', message); console.log('received:', message);
}); });
*/
ws.on('close', function(reasonCode, description) { ws.on('close', function(reasonCode, description) {
logger.info((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.'); logger.info((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');

View File

@ -19,6 +19,7 @@
"events": "^1.1.1", "events": "^1.1.1",
"express": "^4.13.4", "express": "^4.13.4",
"express-session": "*", "express-session": "*",
"express-session-lw": "^1.0.9",
"gulp-babel": "^6.1.2", "gulp-babel": "^6.1.2",
"gulp-banner": "^0.1.3", "gulp-banner": "^0.1.3",
"htmlparser": "^1.7.7", "htmlparser": "^1.7.7",
@ -82,7 +83,10 @@
}, },
"scripts": { "scripts": {
"test": "mocha --recursive --reporter spec --bail --check-leaks --timeout 3000", "test": "mocha --recursive --reporter spec --bail --check-leaks --timeout 3000",
"start": "node app.js" "start": "node app.js",
"build": "gulp default",
"production": "NODE_ENV=production node app.js",
"release": "cf push 'mdotserver'"
}, },
"author": "Martin Donnelly", "author": "Martin Donnelly",
"license": "ISC", "license": "ISC",

View File

@ -45,32 +45,38 @@
<div class='mui-row'> <div class='mui-row'>
<div class="mui-col-md-3"> <div class="mui-col-md-3">
<div class="mui-row"> <div class="mui-row">
<div class="mui-col-md-12"> <div class="mui-col-md-12 ">
<div class=" mui--bg-primary-dark " style="height:15%;"> <div class=" mui--bg-primary-dark" style="padding-top: 15px;padding-bottom: 7px;display: flex;">
<img src="gfx/SB_logo.png" <div class="mui-col-md-3 ">
style="height:70%; width:100%;margin-top:10%"/> <i class="material-icons" style="font-size: 66px;color:#00ffb6;">&#xE7F1;</i>
</div>
<div class="mui-col-md-9 mui--align-middle " style="text-align: center;font-family: 'Ubuntu Condensed', sans-serif;font-size: 30px;line-height: 100%;color:#00ffb6;">
SMART<br>Building
</div>
</div> </div>
</div>
</div>
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark " style="height:15%;"> <div class=" mui--bg-primary-dark " style="height:15%;">
<div class='' id="main"></div> <div class='' id="main" style="margin-left:10%; margin-right:10%"></div>
<!--<div id="output"></div>--> <!--<div id="output"></div>-->
</div> </div>
</div> </div>
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark " style="height:15%;"> <div class=" mui--bg-primary-dark " style="height:15%;">
<div class="mui-col-xs-6 mui--bg-primary-dark"> <div class="mui-col-xs-12 mui--bg-primary-dark">
<div id="time" <div id="time"
class="mui--text-center time mui--text-accent"></div> class="mui--text-center time mui--text-accent-secondary"></div>
</div> </div>
<div class="mui-col-xs-6 mui--bg-primary-dark"> <div class="mui-col-xs-12 mui--bg-primary-dark">
<div id="date" <div id="date"
class="mui--text-center date mui--text-accent"></div> class="mui--text-center date mui--text-accent"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark weather mui--text-accent" style="font-size: 150%;"> <div class=" mui--bg-primary-dark weather mui--text-accent-secondary" style="font-size: 300%;">
Glasgow Glasgow
</div> </div>
<div <div
@ -79,23 +85,23 @@
<div id="weatherIcon" <div id="weatherIcon"
class="mui-col-xs-6 mui--bg-primary-dark"></div> class="mui-col-xs-6 mui--bg-primary-dark"></div>
<div id="weatherText" <div id="weatherText"
class="mui-col-xs-6 mui--bg-primary-dark"></div> class="mui-col-xs-6 mui--bg-primary-dark" ></div>
</div> </div>
<div class=" mui--bg-primary-dark weather mui--text-accent" style="font-size: 150%;" id="weatherSummary"> <div class=" mui--bg-primary-dark weather mui--text-accent" style="font-size: 150%;" id="weatherSummary">
</div> </div>
</div> </div>
<div class="mui-col-md-12 spacer"> <!--<div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark mui--text-accent" style="font-size: 100%;" id="example"> <div class=" mui--bg-primary-dark mui--text-accent" style="font-size: 100%;" id="example">
</div> </div>
</div> </div>-->
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div <div
class=" mui--bg-primary-dark mui--text-center weather mui--text-accent" class=" mui--bg-primary-dark mui--text-center weather mui--text-accent"
style="height:15%;"> style="height:15%;">
<div id="censisLogo" class="mui-col-xs-12 "> <div id="censisLogo" class="mui-col-xs-12 ">
<img src="gfx/censis_logo_white.png" <img src="gfx/censis_logo_white.png"
style="height:70%; width:80%;margin-top:5%;margin-left:10%"/> style="height:70%; width:80%;margin-top:0%;margin-left:0%"/>
</div> </div>
</div> </div>
</div> </div>
@ -113,69 +119,59 @@
<div class='mui-row'> <div class='mui-row'>
<div class="mui-col-md-3"> <div class="mui-col-md-3">
<div class="mui--bg-primary-dark widget"> <div class="mui--bg-primary-dark widget">
<!--<div class="mui-col-md-12"> <div class="mui-col-md-12 mui--align-middle" style="height:40%;padding-top: 30px;">
<div class="mui-col-md-3 mui&#45;&#45;align-middle"> <div class="mui-col-md-3 mui--align-middle">
<i class="wi wi-smog widgeticon mui&#45;&#45;text-left mui&#45;&#45;align-middle"></i> <i class="wi wi-smog widgeticon mui--text-left mui--align-middle"></i>
</div> </div>
<div class="mui-col-md-9 widgetLogo mui&#45;&#45;align-middle"> <div class="mui-col-md-9 widgetLogo mui--align-middle">
Carbon Dioxide Carbon Dioxide
</div> </div>
</div>-->
<div style="height:40%">
<img src="gfx/CarbonDioxide.png" class="logo"/>
</div> </div>
<div class="mui-row" style="height:50%;" id="widget-co2"></div> <div class="mui-row" style="height:50%;" id="widget-co2"></div>
</div> </div>
</div> </div>
<div class="mui-col-md-3"> <div class="mui-col-md-3">
<div class=" mui--bg-primary-dark widget"> <div class=" mui--bg-primary-dark widget">
<!-- <div class="mui-col-md-12"> <div class="mui-col-md-12 mui--align-middle" style="height:40%;padding-top: 30px;">
<div class="mui-col-md-3 mui&#45;&#45;align-middle"> <div class="mui-col-md-3 mui--align-middle">
<i class="wi wi-thermometer widgeticon mui&#45;&#45;text-left mui&#45;&#45;align-middle"></i> <i class="wi wi-thermometer widgeticon mui--text-left mui--align-middle"></i>
</div> </div>
<div class="mui-col-md-9 widgetLogo mui&#45;&#45;align-middle"> <div class="mui-col-md-9 widgetLogo mui--align-middle">
Temperature Temperature
</div> </div>
</div>--> </div>
<div style="height:40%">
<img src="gfx/Temperature.png" class="logo"/>
</div>
<div class="mui-row" style="height:50%" id="widget-temp"></div> <div class="mui-row" style="height:50%" id="widget-temp"></div>
</div> </div>
</div> </div>
<div class="mui-col-md-3"> <div class="mui-col-md-3">
<div class=" mui--bg-primary-dark widget"> <div class=" mui--bg-primary-dark widget">
<!-- <div class="mui-col-md-12"> <div class="mui-col-md-12 mui--align-middle" style="height:40%;padding-top: 30px;">
<div class="mui-col-md-3 mui&#45;&#45;align-middle"> <div class="mui-col-md-3 mui--align-middle">
<i class="wi wi-humidity widgeticon mui&#45;&#45;text-left mui&#45;&#45;align-middle"></i> <i class="wi wi-humidity widgeticon mui--text-left mui--align-middle"></i>
</div> </div>
<div class="mui-col-md-9 widgetLogo mui&#45;&#45;align-middle"> <div class="mui-col-md-9 widgetLogo mui--align-middle">
Humidity Humidity
</div> </div>
</div>
</div>-->
<div style="height:40%">
<img src="gfx/Humidity.png" class="logo"/>
</div>
<div class="mui-row" style="height:50%;" id="widget-humidity"></div> <div class="mui-row" style="height:50%;" id="widget-humidity"></div>
</div> </div>
</div> </div>
<div class="mui-col-md-3"> <div class="mui-col-md-3">
<div class=" mui--bg-primary-dark widget"> <div class=" mui--bg-primary-dark widget">
<!-- <div class="mui-col-md-12"> <div class="mui-col-md-12 mui--align-middle" style="height:40%;padding-top: 30px;">
<div class="mui-col-md-3 mui&#45;&#45;align-middle"> <div class="mui-col-md-3 mui--align-middle">
<i class="wi wi-horizon-alt widgeticon mui&#45;&#45;text-left mui&#45;&#45;align-middle"></i> <i class="wi wi-horizon-alt widgeticon mui--text-left mui--align-middle"></i>
</div> </div>
<div class="mui-col-md-9 widgetLogo mui&#45;&#45;align-middle"> <div class="mui-col-md-9 widgetLogo mui--align-middle">
Light Light Level
</div> </div>
</div>
</div>-->
<div style="height:40%">
<img src="gfx/Lux.png" class="logo"/>
</div>
<div class="mui-row" style="height:100%;" id="widget-lux"></div> <div class="mui-row" style="height:100%;" id="widget-lux"></div>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
@ -43,6 +43,7 @@
<link href="css/test.css" rel="stylesheet" type="text/css"/> <link href="css/test.css" rel="stylesheet" type="text/css"/>
<link href="css/style.css" rel="stylesheet" type="text/css"/> <link href="css/style.css" rel="stylesheet" type="text/css"/>
<link href="css/weather-icons.css" rel="stylesheet" type="text/css"/> <link href="css/weather-icons.css" rel="stylesheet" type="text/css"/>
<link href="css/material-icons.css" rel="stylesheet" type="text/css"/>
<!-- endbuild --> <!-- endbuild -->
<style> <style>
html, body { height: 100%; width: 100%; color: white; } html, body { height: 100%; width: 100%; color: white; }
@ -51,7 +52,7 @@
/*color: #FD5F00;*/ /*color: #FD5F00;*/
/*color: #ff0063;*/ /*color: #ff0063;*/
font-family: 'Ubuntu Condensed';; font-family: 'Ubuntu Condensed';
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 70px; font-size: 70px;
@ -59,6 +60,18 @@
text-align: center; text-align: center;
} }
.mui-select > select {
color:#32ffad;
border-bottom :none;
}
.mui-select__menu {
background-color:#212121
}
#example { #example {
position: relative; position: relative;
color: #ff0063; color: #ff0063;
@ -170,32 +183,38 @@
<div class='mui-row'> <div class='mui-row'>
<div class="mui-col-md-3"> <div class="mui-col-md-3">
<div class="mui-row"> <div class="mui-row">
<div class="mui-col-md-12"> <div class="mui-col-md-12 ">
<div class=" mui--bg-primary-dark " style="height:15%;"> <div class=" mui--bg-primary-dark" style="padding-top: 15px;padding-bottom: 7px;display: flex;">
<img src="gfx/SB_logo.png" <div class="mui-col-md-3 ">
style="height:70%; width:100%;margin-top:10%"/> <i class="material-icons" style="font-size: 66px;color:#00ffb6;">&#xE7F1;</i>
</div>
<div class="mui-col-md-9 mui--align-middle " style="text-align: center;font-family: 'Ubuntu Condensed', sans-serif;font-size: 30px;line-height: 100%;color:#00ffb6;">
SMART<br>Building
</div>
</div> </div>
</div>
</div>
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark " style="height:15%;"> <div class=" mui--bg-primary-dark " style="height:15%;">
<div class='' id="main"></div> <div class='' id="main" style="margin-left:10%; margin-right:10%"></div>
<!--<div id="output"></div>--> <!--<div id="output"></div>-->
</div> </div>
</div> </div>
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark " style="height:15%;"> <div class=" mui--bg-primary-dark " style="height:15%;">
<div class="mui-col-xs-6 mui--bg-primary-dark"> <div class="mui-col-xs-12 mui--bg-primary-dark">
<div id="time" <div id="time"
class="mui--text-center time mui--text-accent"></div> class="mui--text-center time mui--text-accent-secondary"></div>
</div> </div>
<div class="mui-col-xs-6 mui--bg-primary-dark"> <div class="mui-col-xs-12 mui--bg-primary-dark">
<div id="date" <div id="date"
class="mui--text-center date mui--text-accent"></div> class="mui--text-center date mui--text-accent"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark weather mui--text-accent" style="font-size: 150%;"> <div class=" mui--bg-primary-dark weather mui--text-accent-secondary" style="font-size: 300%;">
Glasgow Glasgow
</div> </div>
<div <div
@ -204,23 +223,23 @@
<div id="weatherIcon" <div id="weatherIcon"
class="mui-col-xs-6 mui--bg-primary-dark"></div> class="mui-col-xs-6 mui--bg-primary-dark"></div>
<div id="weatherText" <div id="weatherText"
class="mui-col-xs-6 mui--bg-primary-dark"></div> class="mui-col-xs-6 mui--bg-primary-dark" ></div>
</div> </div>
<div class=" mui--bg-primary-dark weather mui--text-accent" style="font-size: 150%;" id="weatherSummary"> <div class=" mui--bg-primary-dark weather mui--text-accent" style="font-size: 150%;" id="weatherSummary">
</div> </div>
</div> </div>
<div class="mui-col-md-12 spacer"> <!--<div class="mui-col-md-12 spacer">
<div class=" mui--bg-primary-dark mui--text-accent" style="font-size: 100%;" id="example"> <div class=" mui--bg-primary-dark mui--text-accent" style="font-size: 100%;" id="example">
</div> </div>
</div> </div>-->
<div class="mui-col-md-12 spacer"> <div class="mui-col-md-12 spacer">
<div <div
class=" mui--bg-primary-dark mui--text-center weather mui--text-accent" class=" mui--bg-primary-dark mui--text-center weather mui--text-accent"
style="height:15%;"> style="height:15%;">
<div id="censisLogo" class="mui-col-xs-12 "> <div id="censisLogo" class="mui-col-xs-12 ">
<img src="gfx/censis_logo_white.png" <img src="gfx/censis_logo_white.png"
style="height:70%; width:80%;margin-top:5%;margin-left:10%"/> style="height:70%; width:80%;margin-top:0%;margin-left:0%"/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,2 +1,4 @@
node_modules node_modules
/sql/ /sql/
/src/
/tools/

View File

@ -1,4 +1,131 @@
# MQTT Archiver # MQTT Archiver
This app listens to all the available subscriptions for a given MQTT server then archives the raw data in a PGSQL database. This app listens to all the available subscriptions for a given MQTT server then archives the raw data in a PGSQL database.
### Index
[Configuration](#configuration)
[Historian Service](#historian-service)
### Configuration
There is a file in the root directory called *config.js*, it is configured as:
```
mqttAccount : {
orgId: 'yourOrgID',
userName: 'yourOrgID-username',
address: '.messaging.internetofthings.ibmcloud.com',
appKey: 'IBM SECRET KEY',
subscribeTopic: 'iot-2/type/+/id/+/evt/+/fmt/json'
},
pgConnection:{
host: 'localhost',
port: 5432,
database: 'mqttstore',
user: 'postgres',
password: ''
},
keypair: {
accessKey: 'ACCESSKEY',
secret: 'SECRET'
}
```
#### mqttAccount
The **orgID**, **userName** and **appKey** are the ones supplied via IBM or other vendor for MQTT.
The **address** shouldn't be changed unless it has to talk to another vendor's MQTT server.
The **subscribeTopic** is set here to listen to every type of device, every ID and every type of event. This should capture everything transmitted.
#### pgConnection
The settings for **pgConnection** are used to connect the application to the Postgres database being used.
#### keypair
The **keypair** is used to authenticate users to approve access to the Historian service. It is advisable to create a strong pair here to ensure tight security.
### Historian Service
There are two ways of accessing the data from the Historian service. The first method is just to do a simple request for data.
```
http://servername.mybluemix.net/apiv2/historian/types/DEVICETYPE/devices/DEVICEID
```
Replacing the **DEVICETYPE** and **DEVICEID** portions of the url with the relevant device type and device id as set up on Bluemix. Such as:
```
http://myserver.mybluemix.net/apiv2/historian/types/myDevice/devices/Sensor1
```
Just like the original IBM Historian service, ranged data can be requested based on timestamps, such as:
```
http://myserver.mybluemix.net/apiv2/historian/types/myDevice/devices/Sensor1?start=1473850059000&end=1473936459000
```
Data is returned in a similar format to the IBM service. However it does differ from the IBM Service in that it returns more than 100 records at a time.
There is now no longer a requirement to perform multiple requests for each block of 100 records, everything is returned at once.
```
{
"events": [
{
"id": "164427",
"timestamp": "2016-07-08T09:37:14.000Z",
"type": "myDevice",
"device": "Sensor1",
"event": "update",
"data": "Reading1"
}
},
{
"id": "164426",
"timestamp": "2016-07-08T09:53:39.000Z",
"type": "myDevice",
"device": "Sensor1",
"event": "update",
"data": "Reading2"
}
},
{
"id": "164425",
"timestamp": "2016-07-08T10:10:31.000Z",
"type": "myDevice",
"device": "Sensor1",
"event": "update",
"data": "Reading3"
}
},
{
"id": "164424",
"timestamp": "2016-07-08T10:35:01.000Z",
"type": "myDevice",
"device": "Sensor1",
"event": "update",
"data": "Reading4"
}
}
]
```
## Running on IBM Bluemix
Before running the application on IBM Bluemix you must create a new Node based Cloud Foundry instance.
You can find documentation required for that here:
- [Creating Cloud Foundry apps](https://console.ng.bluemix.net/docs/cfapps/index.html)
- [Hosting apps in Bluemix](https://console.ng.bluemix.net/docs/cfapps/hostingapps.html)
- [Deploying your app with the command line interface](https://console.ng.bluemix.net/docs/starters/install_cli.html)
Once you have done that, download the zip file created by IBM and copy the *manifest.yml* file from that into the folder.

View File

@ -1,15 +1,24 @@
/* /*
This file details IBM MQTT settings This file details IBM MQTT settings
*/ */
module.exports = { module.exports = {
mqttAccount : { mqttAccount: {
orgId: 'qz0da4', orgId: 'qz0da4',
userName: 'a-qz0da4-dfwwdkmkzr', userName: 'a-qz0da4-dfwwdkmkzr',
address: '.messaging.internetofthings.ibmcloud.com', address: '.messaging.internetofthings.ibmcloud.com',
appKey: '9txJEf3Cjy7hkSOvkv', appKey: '9txJEf3Cjy7hkSOvkv',
subscribeTopic: 'iot-2/type/+/id/+/evt/+/fmt/json' subscribeTopic: 'iot-2/type/+/id/+/evt/+/fmt/json'
}, pgConnection: {
host: 'localhost',
port: 5432,
database: 'mqttstore',
user: 'postgres',
password: ''
}, keypair: {
accessKey: '59079A75F7FBA5B8DD19076D18CE87A7',
secret: '7C7320FEE40BE5CC5E1955354045B6C7A701FF1F64568AE6B3BA3E6D7DB42D6F'
} }
}; };

View File

@ -14,12 +14,7 @@ var logger = require('log4js').getLogger();
var db = require('../server/db-connector').dbConnection; var db = require('../server/db-connector').dbConnection;
var dbHistorian = require('../server/db-historian.js')(db); var dbHistorian = require('../server/db-historian.js')(db);
var config = require('../../config');
var keypair = {
accessKey : '59079A75F7FBA5B8DD19076D18CE87A7',
secret : '7C7320FEE40BE5CC5E1955354045B6C7A701FF1F64568AE6B3BA3E6D7DB42D6F'
};
module.exports = function(app) { module.exports = function(app) {
var express = require('express'); var express = require('express');
@ -29,48 +24,45 @@ module.exports = function(app) {
var credentials = auth(req); var credentials = auth(req);
if (!credentials || credentials.name !== keypair.accessKey || credentials.pass !== keypair.secret) if (!credentials || credentials.name !== config.keypair.accessKey || credentials.pass !== config.keypair.secret) {
{
console.error('Invalid credentials'); console.error('Invalid credentials');
res.status(401).send({ res.status(401).send({
status: 'error', status: 'error', error: 'Access denied'
error: 'Access denied' });
}); return;
return;
} }
var data = {}; var data = {};
if (!req.params.type && !req.params.deviceid) { if (!req.params.type && !req.params.deviceid) {
{ {
logger.error('Historian','Missing required parameter'); logger.error('Historian', 'Missing required parameter');
res.status(400).send({ res.status(400).send({
status: 'error', status: 'error', error: 'missing required parameter'
error: 'missing required parameter' });
}); return;
return; }
}
} }
if (req.query.hasOwnProperty('start') && req.query.hasOwnProperty('end')) { if (req.query.hasOwnProperty('start') && req.query.hasOwnProperty('end')) {
data.start = req.query.start; data.start = req.query.start;
data.end = req.query.end; data.end = req.query.end;
} }
data.type = req.params.type; data.type = req.params.type;
data.device = req.params.deviceid; data.device = req.params.deviceid;
if (data.hasOwnProperty('type') && data.hasOwnProperty('device')) { if (data.hasOwnProperty('type') && data.hasOwnProperty('device')) {
dbHistorian.doGet(data) dbHistorian.doGet(data)
.then((d) => { .then((d) => {
res.json({events:d}); res.json({events: d});
}) })
.catch((e) => { .catch((e) => {
logger.error(e); logger.error(e);
res.status(500).json({}); res.status(500).json({});
}); });
} }
}); });

View File

@ -7,15 +7,9 @@
* *
*/ */
var config = require('../../config');
var pgp = require('pg-promise')(); var pgp = require('pg-promise')();
var cn = { exports.dbConnection = pgp(config.pgConnection);
host: 'localhost',
port: 5432,
database: 'mqttstore',
user: 'postgres',
password: ''
};
exports.dbConnection = pgp(cn);

View File

@ -3,8 +3,6 @@ var logger = require('log4js').getLogger();
var Sugar = require('sugar/date'); var Sugar = require('sugar/date');
module.exports = function(db) { module.exports = function(db) {
var module = {}; var module = {};