init
This commit is contained in:
commit
14b32f2819
32
.editorconfig
Normal file
32
.editorconfig
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
; http://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.txt]
|
||||||
|
insert_final_newline = false
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.m]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
|
|
||||||
|
[*.{js,json}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
180
.gitignore
vendored
Normal file
180
.gitignore
vendored
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Archives template
|
||||||
|
# It's better to unpack these files and commit the raw source because
|
||||||
|
# git has its own built in compression methods.
|
||||||
|
*.7z
|
||||||
|
*.jar
|
||||||
|
*.rar
|
||||||
|
*.zip
|
||||||
|
*.gz
|
||||||
|
*.bzip
|
||||||
|
*.bz2
|
||||||
|
*.xz
|
||||||
|
*.lzma
|
||||||
|
*.cab
|
||||||
|
|
||||||
|
#packing-only formats
|
||||||
|
*.iso
|
||||||
|
*.tar
|
||||||
|
|
||||||
|
#package management formats
|
||||||
|
*.dmg
|
||||||
|
*.xpi
|
||||||
|
*.gem
|
||||||
|
*.egg
|
||||||
|
*.deb
|
||||||
|
*.rpm
|
||||||
|
*.msi
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
### Windows template
|
||||||
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
### OSX template
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
## Directory-based project format:
|
||||||
|
.idea/
|
||||||
|
# if you remove the above rule, at least ignore the following:
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
# .idea/workspace.xml
|
||||||
|
# .idea/tasks.xml
|
||||||
|
# .idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
# .idea/dataSources.ids
|
||||||
|
# .idea/dataSources.xml
|
||||||
|
# .idea/sqlDataSources.xml
|
||||||
|
# .idea/dynamic.xml
|
||||||
|
# .idea/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
# .idea/gradle.xml
|
||||||
|
# .idea/libraries
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
# .idea/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
### Node template
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directory
|
||||||
|
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
|
||||||
|
node_modules
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
### VisualStudioCode template
|
||||||
|
.settings
|
||||||
|
|
||||||
|
### Xcode template
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.xccheckout
|
||||||
|
*.moved-aside
|
||||||
|
*.xcuserstate
|
||||||
|
|
||||||
|
dist
|
46
.jscsrc
Normal file
46
.jscsrc
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"disallowKeywords": ["with"],
|
||||||
|
"disallowKeywordsOnNewLine": ["else"],
|
||||||
|
"disallowMixedSpacesAndTabs": true,
|
||||||
|
"disallowMultipleVarDecl": "exceptUndefined",
|
||||||
|
"disallowNewlineBeforeBlockStatements": true,
|
||||||
|
"disallowQuotedKeysInObjects": true,
|
||||||
|
"disallowSpaceAfterObjectKeys": true,
|
||||||
|
"disallowSpaceAfterPrefixUnaryOperators": true,
|
||||||
|
"disallowSpacesInFunction": {
|
||||||
|
"beforeOpeningRoundBrace": true
|
||||||
|
},
|
||||||
|
"disallowSpacesInsideParentheses": true,
|
||||||
|
"disallowTrailingWhitespace": true,
|
||||||
|
"maximumLineLength": 160,
|
||||||
|
"requireCamelCaseOrUpperCaseIdentifiers": false,
|
||||||
|
"requireCapitalizedComments": true,
|
||||||
|
"requireCapitalizedConstructors": true,
|
||||||
|
"requireCurlyBraces": true,
|
||||||
|
"requireSpaceAfterKeywords": [
|
||||||
|
"if",
|
||||||
|
"else",
|
||||||
|
"for",
|
||||||
|
"while",
|
||||||
|
"do",
|
||||||
|
"switch",
|
||||||
|
"case",
|
||||||
|
"return",
|
||||||
|
"try",
|
||||||
|
"catch",
|
||||||
|
"typeof"
|
||||||
|
],
|
||||||
|
"requireSpaceAfterLineComment": true,
|
||||||
|
"requireSpaceAfterBinaryOperators": true,
|
||||||
|
"requireSpaceBeforeBinaryOperators": true,
|
||||||
|
"requireSpaceBeforeBlockStatements": true,
|
||||||
|
"requireSpaceBeforeObjectValues": true,
|
||||||
|
"requireSpacesInFunction": {
|
||||||
|
"beforeOpeningCurlyBrace": true
|
||||||
|
},
|
||||||
|
"requireTrailingComma": false,
|
||||||
|
"requireEarlyReturn": false,
|
||||||
|
"validateIndentation": 2,
|
||||||
|
"validateLineBreaks": "LF",
|
||||||
|
"validateQuoteMarks": "'"
|
||||||
|
}
|
37
.jshintrc
Normal file
37
.jshintrc
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"predef": [
|
||||||
|
"Promise",
|
||||||
|
"$"
|
||||||
|
],
|
||||||
|
"globals": {
|
||||||
|
"$": false,
|
||||||
|
"MicroEvent": false
|
||||||
|
},
|
||||||
|
"node":true,
|
||||||
|
"browser": true,
|
||||||
|
"boss": true,
|
||||||
|
"curly": true,
|
||||||
|
"debug": false,
|
||||||
|
"devel": true,
|
||||||
|
"eqeqeq": true,
|
||||||
|
"evil": true,
|
||||||
|
"forin": false,
|
||||||
|
"immed": false,
|
||||||
|
"laxbreak": false,
|
||||||
|
"newcap": true,
|
||||||
|
"noarg": true,
|
||||||
|
"noempty": false,
|
||||||
|
"nonew": false,
|
||||||
|
"nomen": false,
|
||||||
|
"onevar": false,
|
||||||
|
"plusplus": false,
|
||||||
|
"regexp": false,
|
||||||
|
"undef": true,
|
||||||
|
"sub": true,
|
||||||
|
"strict": false,
|
||||||
|
"white": false,
|
||||||
|
"eqnull": true,
|
||||||
|
"esnext": true,
|
||||||
|
"unused": true,
|
||||||
|
"supernew":true
|
||||||
|
}
|
262
app.js
Normal file
262
app.js
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
/**
|
||||||
|
* Created by Martin on 08/02/2016.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
var express = require('express');
|
||||||
|
var path = require('path');
|
||||||
|
var http = require('http');
|
||||||
|
var ejs = require('ejs');
|
||||||
|
var morgan = require('morgan');
|
||||||
|
var cookieparser = require('cookie-parser');
|
||||||
|
var session = require('express-session');
|
||||||
|
var methodoverride = require('method-override');
|
||||||
|
var bodyparser = require('body-parser');
|
||||||
|
var errorhandler = require('errorhandler');
|
||||||
|
var mqttConnect = require('./lib/mqtt/mqttConnect');
|
||||||
|
var log4js = require('log4js');
|
||||||
|
var logger = log4js.getLogger();
|
||||||
|
|
||||||
|
|
||||||
|
var WebSocketServer = require('websocket').server;
|
||||||
|
|
||||||
|
var EventEmitter = require('events');
|
||||||
|
var busEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
var apn = require('apn');
|
||||||
|
|
||||||
|
require('sugar-date');
|
||||||
|
|
||||||
|
var calendar = require('./lib/office/officeController.js');
|
||||||
|
var cal = new calendar.officeController(busEmitter);
|
||||||
|
|
||||||
|
var lighting_v1 = require('./routes/lighting_v1');
|
||||||
|
var heating_v1 = require('./routes/heating_v1');
|
||||||
|
var projector_v1 = require('./routes/projector_v1');
|
||||||
|
var isProduction = false;
|
||||||
|
|
||||||
|
|
||||||
|
function restartTimer() {
|
||||||
|
// Ibm / mqtt things go a bit weird if left on for too long so restart the server
|
||||||
|
// at 7:30 ever morning before anyone is using it.
|
||||||
|
var tom = Date.create('tomorrow at 7:30am');
|
||||||
|
|
||||||
|
var ms = tom.getTime() - Date.create('now').getTime();
|
||||||
|
|
||||||
|
|
||||||
|
console.log('Restarting in: ', ms);
|
||||||
|
setTimeout(function() {process.exit(1);}, ms);
|
||||||
|
|
||||||
|
}
|
||||||
|
mqttConnect.setEmitter(busEmitter);
|
||||||
|
mqttConnect.doConnection();
|
||||||
|
|
||||||
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
isProduction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug('isProduction:', isProduction);
|
||||||
|
|
||||||
|
var app = express();
|
||||||
|
|
||||||
|
app.set('port', process.env.PORT || 4545);
|
||||||
|
app.set('views', __dirname + '/views');
|
||||||
|
app.set('view engine', 'ejs');
|
||||||
|
app.use(morgan('combined'));
|
||||||
|
app.use(cookieparser('your secret here'));
|
||||||
|
app.use(session({
|
||||||
|
secret: '1234567890QWERTY', resave: false, saveUninitialized: false
|
||||||
|
}));
|
||||||
|
/* 'default', 'short', 'tiny', 'dev' */
|
||||||
|
app.use(methodoverride());
|
||||||
|
|
||||||
|
app.use(bodyparser.urlencoded({extended: false}));
|
||||||
|
|
||||||
|
// Parse application/json
|
||||||
|
app.use(bodyparser.json());
|
||||||
|
|
||||||
|
app.use(function(req, res, next) {
|
||||||
|
res.header('Access-Control-Allow-Origin', '*');
|
||||||
|
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run npm start --production to use dist
|
||||||
|
var staticDir = isProduction ? 'dist' : 'app';
|
||||||
|
|
||||||
|
app.use(express.static(path.join(__dirname, staticDir)));
|
||||||
|
app.use(errorhandler({dumpExceptions: true, showStack: true}));
|
||||||
|
|
||||||
|
lighting_v1.use(mqttConnect);
|
||||||
|
heating_v1.use(mqttConnect);
|
||||||
|
projector_v1.use(mqttConnect);
|
||||||
|
|
||||||
|
// Calendar handler
|
||||||
|
|
||||||
|
busEmitter.on('lightingOn', lighting_v1.doLightsOn);
|
||||||
|
busEmitter.on('lightingOff', lighting_v1.doLightsOff);
|
||||||
|
|
||||||
|
busEmitter.on('heatingOn', mqttConnect.heatingOn);
|
||||||
|
busEmitter.on('heatingOff', mqttConnect.heatingOff);
|
||||||
|
busEmitter.on('projectorOn', projector_v1.doProjectorOn);
|
||||||
|
busEmitter.on('projectorOff', projector_v1.doProjectorOff);
|
||||||
|
|
||||||
|
|
||||||
|
busEmitter.on('connectWS', mqttConnect.connectWS);
|
||||||
|
busEmitter.on('restartMQTTSocket', mqttConnect.restartMQTTSocket);
|
||||||
|
|
||||||
|
mqttConnect.setupPing();
|
||||||
|
cal.startController(busEmitter);
|
||||||
|
|
||||||
|
app.get('/stop', function(request, response) {
|
||||||
|
cal.stopController();
|
||||||
|
response.sendStatus(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/start', function(request, response) {
|
||||||
|
|
||||||
|
cal.startController();
|
||||||
|
response.sendStatus(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/api/calendar', function(req, res) {
|
||||||
|
var calJson = cal.returnCalendar();
|
||||||
|
logger.info(calJson);
|
||||||
|
res.json(calJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/calendar/extend', function(req, res) {
|
||||||
|
res.json({});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Events and sockets
|
||||||
|
|
||||||
|
busEmitter.on('clientConnected', (socketSet) => {
|
||||||
|
logger.info('-=-=-=-=-');
|
||||||
|
logger.info(socketSet.getClientStatus());
|
||||||
|
heating_v1.setsocket(socketSet).subscribe();
|
||||||
|
lighting_v1.setsocket(socketSet).subscribe();
|
||||||
|
projector_v1.setsocket(socketSet).subscribe();
|
||||||
|
});
|
||||||
|
|
||||||
|
busEmitter.on('clientStatusUpdated', (v) => {
|
||||||
|
logger.info(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
logger.info('Configuring WebSocket Listener...');
|
||||||
|
var server = http.createServer(function(request, response) {
|
||||||
|
logger.info((new Date()) + ' Received request for ' + request.url);
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(3001, function() {
|
||||||
|
logger.info((new Date()) + ' Server is listening on port 3001');
|
||||||
|
});
|
||||||
|
var wsServer = new WebSocketServer({
|
||||||
|
httpServer: server, // You should not use autoAcceptConnections for production
|
||||||
|
// applications, as it defeats all standard cross-origin protection
|
||||||
|
// facilities built into the protocol and the browser. You should
|
||||||
|
// *always* verify the connection's origin and decide whether or not
|
||||||
|
// to accept it.
|
||||||
|
autoAcceptConnections: false
|
||||||
|
});
|
||||||
|
|
||||||
|
function originIsAllowed(origin) {
|
||||||
|
// Put logic here to detect whether the specified origin is allowed.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsServer.on('request', function(request) {
|
||||||
|
|
||||||
|
if (!originIsAllowed(request.origin)) {
|
||||||
|
// Make sure we only accept requests from an allowed origin
|
||||||
|
request.reject();
|
||||||
|
logger.info((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var connection = request.accept('stream', request.origin);
|
||||||
|
logger.info((new Date()) + ' Connection accepted.');
|
||||||
|
|
||||||
|
var sendSocketHandler = (obj) => {
|
||||||
|
try {
|
||||||
|
connection.sendUTF(JSON.stringify(obj));
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
logger.error(err);
|
||||||
|
logger.warn('Offending object: ', obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
busEmitter.on('sendSocket', sendSocketHandler);
|
||||||
|
|
||||||
|
connection.on('message', function(message) {
|
||||||
|
if (message.type === 'utf8') {
|
||||||
|
logger.info('Received Message: ' + message.utf8Data);
|
||||||
|
connection.sendUTF(message.utf8Data);
|
||||||
|
} else if (message.type === 'binary') {
|
||||||
|
logger.info('Received Binary Message of ' + message.binaryData.length + ' bytes');
|
||||||
|
connection.sendBytes(message.binaryData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('close', function(reasonCode, description) {
|
||||||
|
logger.info((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
|
||||||
|
busEmitter.removeListener('sendSocket', sendSocketHandler);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
mqttConnect.connectWS(function() {
|
||||||
|
logger.info('Ready to plug in sockets...');
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/v1/lighting/off', lighting_v1.turnoff);
|
||||||
|
app.post('/api/v1/lighting/on', lighting_v1.turnon);
|
||||||
|
app.post('/api/v1/lighting/cmd', lighting_v1.command);
|
||||||
|
|
||||||
|
app.post('/api/v1/heating/off', heating_v1.turnoff);
|
||||||
|
app.post('/api/v1/heating/on', heating_v1.turnon);
|
||||||
|
|
||||||
|
app.post('/api/v1/projector/off', projector_v1.turnoff);
|
||||||
|
app.post('/api/v1/projector/on', projector_v1.turnon);
|
||||||
|
app.post('/api/v1/projector/cmd', projector_v1.command);
|
||||||
|
|
||||||
|
app.post('/api/v1/register/ios', function(req, res) {
|
||||||
|
|
||||||
|
var body = req.body, registrationId;
|
||||||
|
|
||||||
|
logger.debug(body);
|
||||||
|
|
||||||
|
if (body.hasOwnProperty('registrationId')) {
|
||||||
|
registrationId = body['registrationId'];
|
||||||
|
logger.debug(registrationId);
|
||||||
|
|
||||||
|
cal.registeriOSToken(registrationId);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/v1/extend', function(req, res) {
|
||||||
|
|
||||||
|
var body = req.body, data;
|
||||||
|
|
||||||
|
if (body.hasOwnProperty('extendBy') && body.hasOwnProperty('uid')) {
|
||||||
|
data = req.body;
|
||||||
|
|
||||||
|
cal.extendMeeting(data);
|
||||||
|
res.sendStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(3000, function() {
|
||||||
|
logger.info('Express listening on 3000');
|
||||||
|
restartTimer();
|
||||||
|
});
|
24
bower.json
Normal file
24
bower.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "sodashserver",
|
||||||
|
"description": "Smart Office Dashboard Server",
|
||||||
|
"main": "index.js",
|
||||||
|
"authors": [
|
||||||
|
"Martin Donnelly"
|
||||||
|
],
|
||||||
|
"license": "ISC",
|
||||||
|
"homepage": "",
|
||||||
|
"private": true,
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"chroma-js": "^1.1.1",
|
||||||
|
"jquery": "^2.2.3",
|
||||||
|
"mui": "^0.5.3",
|
||||||
|
"sugarjs-date": "^1.5.1"
|
||||||
|
}
|
||||||
|
}
|
117
gulpfile.js
Normal file
117
gulpfile.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
'use strict';
|
||||||
|
var gulp = require('gulp');
|
||||||
|
var autoprefixer = require('gulp-autoprefixer');
|
||||||
|
var cssnano = require('gulp-cssnano');
|
||||||
|
var jshint = require('gulp-jshint');
|
||||||
|
var uglify = require('gulp-uglify');
|
||||||
|
var jsmin = require('gulp-jsmin');
|
||||||
|
var rename = require('gulp-rename');
|
||||||
|
var concat = require('gulp-concat');
|
||||||
|
var notify = require('gulp-notify');
|
||||||
|
var cache = require('gulp-cache');
|
||||||
|
var livereload = require('gulp-livereload');
|
||||||
|
var htmlmin = require('gulp-htmlmin');
|
||||||
|
var inject = require('gulp-inject');
|
||||||
|
var del = require('del');
|
||||||
|
var htmlreplace = require('gulp-html-replace');
|
||||||
|
var googleWebFonts = require('gulp-google-webfonts');
|
||||||
|
|
||||||
|
var stripDebug = require('gulp-strip-debug');
|
||||||
|
var size = require('gulp-size');
|
||||||
|
|
||||||
|
var debug = require('gulp-debug');
|
||||||
|
|
||||||
|
var filePath = {
|
||||||
|
build_dir: './dist'
|
||||||
|
};
|
||||||
|
|
||||||
|
gulp.task('scripts', function() {
|
||||||
|
return gulp.src(['app/js/sowebsocket.js','app/js/colours.js','app/js/appv2.js'])
|
||||||
|
.pipe(jshint('.jshintrc'))
|
||||||
|
.pipe(jshint.reporter('default'))
|
||||||
|
.pipe(concat('app.js'))
|
||||||
|
// .pipe(stripDebug())
|
||||||
|
.pipe(jsmin())
|
||||||
|
.pipe(size({title: 'Scripts'}))
|
||||||
|
.pipe(gulp.dest('dist/js'));
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('vendor', function() {
|
||||||
|
return gulp.src(['bower_components/jquery/dist/jquery.min.js',
|
||||||
|
'bower_components/mui/packages/cdn/js/mui.min.js',
|
||||||
|
'bower_components/chroma-js/chroma.min.js',
|
||||||
|
'bower_components/sugar/release/sugar-full.min.js',
|
||||||
|
'app/lib/skycons.js',
|
||||||
|
'app/lib/microevent.js'])
|
||||||
|
.pipe(concat('vendor.js'))
|
||||||
|
.pipe(uglify({mangle: false}))
|
||||||
|
.pipe(size({title: 'Vendor'}))
|
||||||
|
.pipe(gulp.dest('dist/js'));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gulp.task('styles', function() {
|
||||||
|
return gulp.src(['app/css/mui.custom.css','app/css/material-icons.css','app/css/app.css'])
|
||||||
|
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
|
||||||
|
.pipe(cssnano())
|
||||||
|
.pipe(concat('app.css'))
|
||||||
|
.pipe(size({title: 'Styles'}))
|
||||||
|
.pipe(gulp.dest('dist/css'));
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('partials', function() {
|
||||||
|
|
||||||
|
// Gulp.src(['app/partials/**/*']).pipe(gulp.dest('dist/partials'));
|
||||||
|
// gulp.src(['app/libs/ejs_production.js']).pipe(gulp.dest('dist/libs'));
|
||||||
|
// gulp.src(['app/libs/microevent.js']).pipe(gulp.dest('dist/libs'));
|
||||||
|
gulp.src(['app/fav/**/*']).pipe(size({title: 'Partials'})).pipe(gulp.dest('dist/fav'));
|
||||||
|
gulp.src(['app/gfx/censis_logo_white.png']).pipe(gulp.dest('dist/gfx'));
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('migrate', function() {
|
||||||
|
return gulp.src(['dist/**/*'])
|
||||||
|
.pipe(debug({title: 'migrate:'}))
|
||||||
|
.pipe(size({title: 'Migrate'}))
|
||||||
|
.pipe(gulp.dest('/Users/martin/newdev/SODashApp/www'));
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('index', function() {
|
||||||
|
var sources = gulp.src(['js/apps.js', 'css/app.css'], {read: false});
|
||||||
|
|
||||||
|
return gulp.src(['app/index.html'])
|
||||||
|
.pipe(htmlreplace({
|
||||||
|
css: 'css/app.css',
|
||||||
|
js: 'js/app.js',
|
||||||
|
vendor: 'js/vendor.js',
|
||||||
|
fonts: 'fonts/fonts.css'
|
||||||
|
}))
|
||||||
|
.pipe(htmlmin({removeComments: true, collapseWhitespace: true, keepClosingSlash: true}))
|
||||||
|
.pipe(size({title: 'Index'}))
|
||||||
|
.pipe(gulp.dest('dist/'));
|
||||||
|
});
|
||||||
|
|
||||||
|
var options = { };
|
||||||
|
|
||||||
|
gulp.task('fonts', function() {
|
||||||
|
return gulp.src('./fonts.list')
|
||||||
|
.pipe(googleWebFonts(options))
|
||||||
|
.pipe(size({title: 'Fonts'}))
|
||||||
|
.pipe(gulp.dest('dist/fonts'))
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
gulp.task('clean', function() {
|
||||||
|
return del(['dist']);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
gulp.task('default', ['clean'], function() {
|
||||||
|
gulp.start('styles', 'scripts', 'vendor', 'fonts', 'partials', 'index');
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('Cordova', ['clean'], function() {
|
||||||
|
gulp.start('styles', 'scripts', 'vendor', 'fonts', 'index');
|
||||||
|
});
|
30
index.js
Normal file
30
index.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
var log4js = require('log4js');
|
||||||
|
var logger = log4js.getLogger();
|
||||||
|
|
||||||
|
|
||||||
|
var WebSocketServer = require('websocket').server;
|
||||||
|
|
||||||
|
var EventEmitter = require('events');
|
||||||
|
var busEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var mqttClient = require('./lib/mqtt/mqttClient');
|
||||||
|
var mqttConnect = require('./lib/mqtt/mqttConnect');
|
||||||
|
|
||||||
|
var mqtt = new mqttClient.mqttClient();
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
mqttConnect.setEmitter(busEmitter);
|
||||||
|
mqttConnect.doConnection();
|
||||||
|
|
||||||
|
|
||||||
|
mqttConnect.connectWS();
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
'use strict';
|
||||||
|
mqtt.lightsIn();
|
||||||
|
},15000);
|
130
lib/mqtt/IoTFconnector.js
Normal file
130
lib/mqtt/IoTFconnector.js
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var IoTFconnector = function (orgId, api_key, auth_token, $rootScope) {
|
||||||
|
|
||||||
|
|
||||||
|
//this.connected = '';
|
||||||
|
this.clientId = "a:" + orgId + ":" + Date.now();
|
||||||
|
|
||||||
|
console.log("clientId: " + this.clientId);
|
||||||
|
this.hostname = orgId + ".messaging.internetofthings.ibmcloud.com";
|
||||||
|
this.client = '';
|
||||||
|
|
||||||
|
this.initialize = function () {
|
||||||
|
|
||||||
|
client = new Messaging.Client(this.hostname, 8883, this.clientId);
|
||||||
|
|
||||||
|
|
||||||
|
client.onMessageArrived = function (msg) {
|
||||||
|
console.log("Message from :" + msg.destinationName);
|
||||||
|
};
|
||||||
|
|
||||||
|
var connectOptions = new Object();
|
||||||
|
connectOptions.keepAliveInterval = 3600;
|
||||||
|
connectOptions.useSSL = true;
|
||||||
|
connectOptions.userName = api_key;
|
||||||
|
connectOptions.password = auth_token;
|
||||||
|
|
||||||
|
connectOptions.onSuccess = function () {
|
||||||
|
IoTFconnector.prototype.clientStatus.connected = true;
|
||||||
|
// $rootScope.$broadcast("clientStatusUpdated", clientStatus);
|
||||||
|
console.log("MQTT connected to host: " + client.host + " port : " + client.port + " at " + Date.now());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
connectOptions.onFailure = function (e) {
|
||||||
|
console.log("MQTT connection failed at " + Date.now() + "\nerror: " + e.errorCode + " : " + e.errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("about to connect to " + client.host);
|
||||||
|
client.connect(connectOptions);
|
||||||
|
|
||||||
|
//client = new Messaging.Client(this.hostname, 8883, this.clientId);
|
||||||
|
|
||||||
|
//// Initialize the Realtime Graph
|
||||||
|
////var rtGraph = new RealtimeGraph();
|
||||||
|
//client.onMessageArrived = function(msg) {
|
||||||
|
// //var topic = msg.destinationName;
|
||||||
|
|
||||||
|
// //var payload = JSON.parse(msg.payloadString);
|
||||||
|
// ////First message, instantiate the graph
|
||||||
|
// //if (firstMessage) {
|
||||||
|
// // $('#chart').empty();
|
||||||
|
// // firstMessage = false;
|
||||||
|
// // rtGraph.displayChart(null, payload);
|
||||||
|
// //} else {
|
||||||
|
// // rtGraph.graphData(payload);
|
||||||
|
// //}
|
||||||
|
// console.log("Message from :" + msg.destinationName);
|
||||||
|
//};
|
||||||
|
|
||||||
|
//client.onConnectionLost = function(e) {
|
||||||
|
// console.log("Connection Lost at " + Date.now() + " : " + e.errorCode + " : " + e.errorMessage);
|
||||||
|
// this.connect(connectOptions);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//var connectOptions = new Object();
|
||||||
|
//connectOptions.keepAliveInterval = 3600;
|
||||||
|
//connectOptions.useSSL = true;
|
||||||
|
//connectOptions.userName = api_key;
|
||||||
|
//connectOptions.password = auth_token;
|
||||||
|
|
||||||
|
//connectOptions.onSuccess = function() {
|
||||||
|
// IoTFconnector.prototype.connected = true;
|
||||||
|
// console.log("MQTT connected to host: " + client.host + " port : " + client.port + " at " + Date.now());
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
//connectOptions.onFailure = function(e) {
|
||||||
|
// console.log("MQTT connection failed at " + Date.now() + "\nerror: " + e.errorCode + " : " + e.errorMessage);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//console.log("about to connect to " + client.host);
|
||||||
|
//client.connect(connectOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.initialize();
|
||||||
|
|
||||||
|
//var imageHTML = '<div class="iotdashboardtext">The selected device is not currently sending events to the Internet of Things Foundation</div><br><div class="iotdashboardtext">Select to view historical data or select a different device.</div> <img class="iotimagesMiddle" align="middle" alt="Chart" src="../../images/IOT_Icons_Thing02.svg">';
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IoTFconnector.prototype.clientStatus = { connected: false, subscribeTopic: '' };;
|
||||||
|
|
||||||
|
IoTFconnector.prototype.disconnect = function disconnect() {
|
||||||
|
client.disconnect();
|
||||||
|
console.log("Connection closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
IoTFconnector.prototype.connect = function connect() {
|
||||||
|
// this.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IoTFconnector.prototype.subscribe = function subscribe(deviceId) {
|
||||||
|
var subscribeOptions = {
|
||||||
|
qos: 0,
|
||||||
|
onSuccess: function () {
|
||||||
|
console.log("subscribed to " + IoTFconnector.prototype.clientStatus.subscribeTopic);
|
||||||
|
},
|
||||||
|
onFailure: function () {
|
||||||
|
console.log("Failed to subscribe to " + IoTFconnector.prototype.clientStatus.subscribeTopic);
|
||||||
|
console.log("As messages are not available, visualization is not possible");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (IoTFconnector.prototype.clientStatus.subscribeTopic != "") {
|
||||||
|
console.log("Unsubscribing to " + IoTFconnector.prototype.clientStatus.subscribeTopic);
|
||||||
|
client.unsubscribe(IoTFconnector.prototype.clientStatus.subscribeTopic);
|
||||||
|
};
|
||||||
|
|
||||||
|
IoTFconnector.prototype.clientStatus.subscribeTopic = "iot-2/type/iotsample-ti-cc3200/id/" + deviceId + "/evt/+/fmt/json";
|
||||||
|
|
||||||
|
client.subscribe(IoTFconnector.prototype.clientStatus.subscribeTopic, subscribeOptions);
|
||||||
|
}
|
68
lib/mqtt/mqttClient.js
Normal file
68
lib/mqtt/mqttClient.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
var mqtt = require('mqtt');
|
||||||
|
|
||||||
|
var mqttClient = function() {
|
||||||
|
|
||||||
|
var orgId = '';
|
||||||
|
var userName = '';
|
||||||
|
var appKey = 'bob';
|
||||||
|
|
||||||
|
|
||||||
|
this.lighting = 'lights';
|
||||||
|
|
||||||
|
this.connected = false;
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
keepalive: 3600,
|
||||||
|
clientId: 'a:' + orgId + ':' + Date.now(),
|
||||||
|
username: userName,
|
||||||
|
password: new Buffer(appKey)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.client = mqtt.connect('mqtt://' + orgId + 'silvrtree.co.uk', options);
|
||||||
|
|
||||||
|
this.client.on('connect', function() {
|
||||||
|
connected = true;
|
||||||
|
console.log('Connected to SIlvr Broker');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client.subscribe('lightsOut');
|
||||||
|
this.client.on('message', function(topic, message) {
|
||||||
|
console.log(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.isConnected = function() {
|
||||||
|
return this.connected;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Client = mqtt.connect();
|
||||||
|
|
||||||
|
client.subscribe('presence');
|
||||||
|
client.on('message', function(topic, message) {
|
||||||
|
console.log(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mqttClient.prototype.lightsIn = function() {
|
||||||
|
|
||||||
|
var destinationName = 'lightsIn';
|
||||||
|
this.client.publish(destinationName, '0');
|
||||||
|
var destinationName = 'lightsIn';
|
||||||
|
this.client.publish(destinationName, '1');
|
||||||
|
};
|
||||||
|
|
||||||
|
mqttClient.prototype.lightsOut = function() {
|
||||||
|
|
||||||
|
var destinationName = 'lightsOut';
|
||||||
|
this.client.publish(destinationName, 'f');
|
||||||
|
destinationName = 'lightsOut';
|
||||||
|
this.client.publish(destinationName, 'g');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.mqttClient = mqttClient;
|
353
lib/mqtt/mqttConnect.js
Normal file
353
lib/mqtt/mqttConnect.js
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/**
|
||||||
|
* Created by Martin on 08/02/2016.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
var mqtt = require('mqtt');
|
||||||
|
|
||||||
|
var Messaging = require('mqtt_over_websockets');
|
||||||
|
var log4js = require('log4js');
|
||||||
|
var logger = log4js.getLogger();
|
||||||
|
|
||||||
|
var mqttConfig = {
|
||||||
|
orgId: 'qz0da4',
|
||||||
|
userName: 'martind2000',
|
||||||
|
appKey: 'MPReoa43',
|
||||||
|
prefix: 'iot-2/type/Ti-CC3200/id/'
|
||||||
|
};
|
||||||
|
|
||||||
|
function randomString(length) {
|
||||||
|
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Projector: 'ProjectorISP15',
|
||||||
|
lighting: 'LightingISP15',
|
||||||
|
heating: 'HeatingISP15',
|
||||||
|
|
||||||
|
*/
|
||||||
|
var live = true;
|
||||||
|
|
||||||
|
logger.warn('!!! Live? ', live);
|
||||||
|
module.exports = {
|
||||||
|
restartTimer : 0,
|
||||||
|
pingTimer: 0,
|
||||||
|
statuses: {},
|
||||||
|
sockets: null,
|
||||||
|
wsClient: null,
|
||||||
|
watches: {},
|
||||||
|
client: null,
|
||||||
|
projector: live ? 'Projector' : 'ProjectorISP15',
|
||||||
|
lighting: live ? 'Lighting' : 'LightingISP15',
|
||||||
|
heating: live ? 'Heating' : 'HeatingISP15',
|
||||||
|
myID: 0,
|
||||||
|
connected: false,
|
||||||
|
options: {
|
||||||
|
// Keepalive: 3600,
|
||||||
|
keepalive: 60,
|
||||||
|
clientId: 'a:' + mqttConfig.orgId + ':' + Date.now(),
|
||||||
|
username: mqttConfig.userName,
|
||||||
|
password: new Buffer(mqttConfig.appKey)
|
||||||
|
|
||||||
|
},
|
||||||
|
lightList: {o: 'frontLight', f: 'frontLight',n: 'backLight', g: 'backLight'},
|
||||||
|
updateStatus: function(id, packet) {
|
||||||
|
this.statuses[id] = packet;
|
||||||
|
logger.info('Statuses:', this.statuses);
|
||||||
|
},
|
||||||
|
|
||||||
|
setEmitter: function(newEmitter) {
|
||||||
|
this.emitter = newEmitter;
|
||||||
|
},
|
||||||
|
doConnection: function(cb) {
|
||||||
|
console.log('Do connection');
|
||||||
|
var self = this;
|
||||||
|
if (this.client === null) {
|
||||||
|
this.client = mqtt.connect('mqtt://' + 'silvrtree.co.uk', this.options);
|
||||||
|
|
||||||
|
this.client.on('connect', function() {
|
||||||
|
logger.info('Connected to SilvrBroker');
|
||||||
|
self.connected = this.connected;
|
||||||
|
});
|
||||||
|
this.client.on('connected', function() {
|
||||||
|
logger.debug('mqttConnect - doConnection - Connected');
|
||||||
|
|
||||||
|
});
|
||||||
|
this.client.on('disconnect', function(e) {
|
||||||
|
logger.error('mqttConnect - doConnection - disconnect');
|
||||||
|
logger.error(e);
|
||||||
|
});
|
||||||
|
this.client.on('error', function(e) {
|
||||||
|
logger.error('mqttConnect - doConnection - disconnect');
|
||||||
|
logger.error(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
isConnected: function() {
|
||||||
|
return this.connected;
|
||||||
|
},
|
||||||
|
sendCommand: function(deviceID, command) {
|
||||||
|
var payload = {
|
||||||
|
id: 'd',
|
||||||
|
text: command
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
projectorOn: function(callback) {
|
||||||
|
var packet;
|
||||||
|
console.log('projectorOn:');
|
||||||
|
var _callback = callback || {};
|
||||||
|
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
packet = {id: this.projector, status: true};
|
||||||
|
var destinationName = mqttConfig.prefix + this.projector + '/cmd/' + 'ON' + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'ON', _callback);
|
||||||
|
this.emitter.emit('sendSocket',packet);
|
||||||
|
logger.debug('Storing status...');
|
||||||
|
this.updateStatus('projector', packet);
|
||||||
|
},
|
||||||
|
projectorOff: function(callback) {
|
||||||
|
var packet;
|
||||||
|
var _callback = callback || {};
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
packet = {id: this.projector, status: false};
|
||||||
|
var destinationName = mqttConfig.prefix + this.projector + '/cmd/' + 'OFF' + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'OFF', _callback);
|
||||||
|
this.emitter.emit('sendSocket',packet);
|
||||||
|
console.log('Storing status...');
|
||||||
|
this.updateStatus('projector', packet);
|
||||||
|
|
||||||
|
},
|
||||||
|
projectorCmd: function(id, callback) {
|
||||||
|
var packet;
|
||||||
|
var _callback = callback || {};
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var destinationName = mqttConfig.prefix + this.projector + '/cmd/' + id + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'cmd', _callback);
|
||||||
|
},
|
||||||
|
heatingOn: function(callback) {
|
||||||
|
console.log('Turn heating on...');
|
||||||
|
var _callback = callback || null;
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
var destinationName = mqttConfig.prefix + this.heating + '/cmd/' + 'on' + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'ON', _callback);
|
||||||
|
this.emitter.emit('sendSocket',{id: this.heating, status: true});
|
||||||
|
},
|
||||||
|
heatingOff: function(callback) {
|
||||||
|
var _callback = callback || {};
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
var destinationName = mqttConfig.prefix + this.heating + '/cmd/' + 'off' + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'OFF', _callback);
|
||||||
|
this.emitter.emit('sendSocket',{id: this.heating, status: false});
|
||||||
|
},
|
||||||
|
lightingOn: function(id, callback) {
|
||||||
|
var packet;
|
||||||
|
|
||||||
|
console.log('lightingOn:' + id);
|
||||||
|
var _callback = callback || null;
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
var destinationName = mqttConfig.prefix + this.lighting + '/cmd/' + id + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'ON', _callback);
|
||||||
|
packet = {id: this.lighting, device: id, status: true};
|
||||||
|
this.emitter.emit('sendSocket',packet);
|
||||||
|
logger.debug('Storing status...');
|
||||||
|
this.updateStatus(this.lightList[id], packet);
|
||||||
|
},
|
||||||
|
lightingOff: function(id, callback) {
|
||||||
|
var packet;
|
||||||
|
var _callback = callback || null;
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
var destinationName = mqttConfig.prefix + this.lighting + '/cmd/' + id + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'OFF', _callback);
|
||||||
|
packet = {id: this.lighting, device: id, status: false};
|
||||||
|
this.emitter.emit('sendSocket', packet);
|
||||||
|
this.updateStatus(this.lightList[id], packet);
|
||||||
|
},
|
||||||
|
lightingCommand: function(id, callback) {
|
||||||
|
var packet;
|
||||||
|
var _callback = callback || null;
|
||||||
|
if (!this.client) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
var destinationName = mqttConfig.prefix + this.lighting + '/cmd/' + id + '/fmt/json';
|
||||||
|
this.client.publish(destinationName, 'cmd', _callback);
|
||||||
|
},
|
||||||
|
|
||||||
|
setupEvents: function() {
|
||||||
|
|
||||||
|
this.emitter.on('lightingOn', this.lightingOn);
|
||||||
|
this.emitter.on('lightingOff', this.lightingOff);
|
||||||
|
this.emitter.on('heatingOn', this.heatingOn);
|
||||||
|
this.emitter.on('heatingOff', this.heatingOff);
|
||||||
|
this.emitter.on('projectorOn', this.projectorOn);
|
||||||
|
this.emitter.on('projectorOff', this.projectorOff);
|
||||||
|
},
|
||||||
|
setupPing: function() {
|
||||||
|
logger.warn('Starting ping timer...');
|
||||||
|
|
||||||
|
this.pingTimer = setTimeout(function() {this.ping();}.bind(this), 10000);
|
||||||
|
},
|
||||||
|
ping: function() {
|
||||||
|
//Logger.error('Ping!');
|
||||||
|
this.sendRefresh();
|
||||||
|
var now = new Date;
|
||||||
|
var mod = 10000 - (now.getTime() % 10000);
|
||||||
|
|
||||||
|
setTimeout(function() {this.ping();}.bind(this),mod + 10);
|
||||||
|
|
||||||
|
},
|
||||||
|
sendRefresh: function() {
|
||||||
|
// logger.debug('+ Send refresh', this.statuses);
|
||||||
|
|
||||||
|
for (var item in this.statuses) {
|
||||||
|
if (this.statuses.hasOwnProperty(item)) {
|
||||||
|
console.log(this.statuses[item]);
|
||||||
|
this.emitter.emit('sendSocket', this.statuses[item]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// logger.debug('+ Send refresh');
|
||||||
|
},
|
||||||
|
preRestartConnection: function() {
|
||||||
|
logger.debug('Restart connection...');
|
||||||
|
//this.emitter.emit('restartMQTTSocket', this);
|
||||||
|
//logger.debug(this);
|
||||||
|
this.restartMQTTSocket();
|
||||||
|
},
|
||||||
|
startMQTTSocket:function() {
|
||||||
|
logger.warn('Restarting socket?');
|
||||||
|
this.connectWS();
|
||||||
|
},
|
||||||
|
restartMQTTSocket: function() {
|
||||||
|
this.wsClient.disconnect();
|
||||||
|
// setTimeout(this.startMQTTSocket.bind(this), 15000);
|
||||||
|
},
|
||||||
|
connectWS: function(connectCB) {
|
||||||
|
|
||||||
|
logger.debug('Going to connect WS');
|
||||||
|
var self = this;
|
||||||
|
var hostname = 'silvrtree.co.uk';
|
||||||
|
var clientId = 'a:' + 'qz0da4' + ':' + Date.now();
|
||||||
|
|
||||||
|
var api_key = 'martind2000';
|
||||||
|
var auth_token = 'MPReoa43';
|
||||||
|
|
||||||
|
this.wsClient =new Messaging.Client(hostname, 8883, clientId);
|
||||||
|
//var wsClient = new Messaging.Client(hostname, 8883, clientId);
|
||||||
|
var wsClient = this.wsClient;
|
||||||
|
var clientStatus = {connected: false, subscribed: false, deviceConnected: false};
|
||||||
|
var sensorData = {};
|
||||||
|
|
||||||
|
|
||||||
|
this.restartTimer = setTimeout(this.preRestartConnection.bind(this), 60000);
|
||||||
|
|
||||||
|
wsClient.onMessageArrived = function(msg) {
|
||||||
|
//logger.info("Message from :" + msg.destinationName);
|
||||||
|
clearTimeout(self.restartTimer);
|
||||||
|
self.restartTimer = setTimeout(self.preRestartConnection.bind(self), 60000);
|
||||||
|
clientStatus.deviceConnected = true;
|
||||||
|
sensorData = JSON.parse(msg.payloadString);
|
||||||
|
// Logger.debug(sensorData);
|
||||||
|
var temp = msg.destinationName.split('/');
|
||||||
|
if (self.watches.hasOwnProperty(temp[4])) {
|
||||||
|
|
||||||
|
// Logger.info('Emit: ' + JSON.stringify({id:self.watches[temp[4]],sensorData:sensorData}));
|
||||||
|
|
||||||
|
self.emitter.emit('sendSocket',{id: self.watches[temp[4]],sensorData: sensorData});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
wsClient.onConnectionLost = function(e) {
|
||||||
|
logger.error('+ wsClient.onConnectionLost');
|
||||||
|
logger.error(e);
|
||||||
|
logger.warn('Going to force a restart of the Socket.. Hold on.');
|
||||||
|
setTimeout(self.startMQTTSocket.bind(self), 15000);
|
||||||
|
//self.emitter.emit('sendSocket',{id: 'deviceLost',data: e});
|
||||||
|
//var wsReconnectTimer = setTimeout(function() {logger.debug('TRYING TO RECONNECT TO MQTT');self.emitter.emit('connectWS');}.bind(this),30000);
|
||||||
|
logger.error('- wsClient.onConnectionLost');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var connectOptions = {};
|
||||||
|
connectOptions.keepAliveInterval = 3600;
|
||||||
|
connectOptions.useSSL = true;
|
||||||
|
connectOptions.userName = api_key;
|
||||||
|
connectOptions.password = auth_token;
|
||||||
|
|
||||||
|
connectOptions.onSuccess = function() {
|
||||||
|
clientStatus.connected = true;
|
||||||
|
logger.info('MQTT connected to host: ' + wsClient.host + ' port : ' + wsClient.port + ' at ' + Date.now());
|
||||||
|
|
||||||
|
self.emitter.emit('clientStatusUpdated', clientStatus);
|
||||||
|
self.emitter.emit('clientConnected', self.sockets);
|
||||||
|
};
|
||||||
|
|
||||||
|
connectOptions.onFailure = function(e) {
|
||||||
|
self.emitter.emit('sendSocket',{id: 'deviceNotConnecting'});
|
||||||
|
logger.error('wsClient onFailure', e);
|
||||||
|
logger.error('MQTT connection failed at ' + Date.now() + '\nerror: ' + e.errorCode + ' : ' + e.errorMessage);
|
||||||
|
//var wsReconnectTimer = setTimeout(function() {logger.debug('TRYING TO RECONNECT TO MQTT');self.emitter.emit('connectWS');}.bind(this),30000);
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.debug('about to connect to ' + wsClient.host);
|
||||||
|
wsClient.connect(connectOptions);
|
||||||
|
|
||||||
|
this.sockets = {
|
||||||
|
|
||||||
|
getClientStatus: function() {
|
||||||
|
return clientStatus;
|
||||||
|
},
|
||||||
|
subscribe: function(deviceId, emitterId) {
|
||||||
|
logger.debug('trying to subscribe');
|
||||||
|
var subscribeTopic = 'iot-2/type/Ti-CC3200/id/' + deviceId + '/evt/+/fmt/json';
|
||||||
|
logger.debug(subscribeTopic);
|
||||||
|
|
||||||
|
var subscribeOptions = {
|
||||||
|
qos: 0,
|
||||||
|
onSuccess: function() {
|
||||||
|
logger.info('subscribed to ' + subscribeTopic);
|
||||||
|
clientStatus.subscribed = true;
|
||||||
|
// $rootScope.$broadcast("clientStatusUpdated", clientStatus);
|
||||||
|
|
||||||
|
self.emitter.emit('clientStatusUpdated', clientStatus);
|
||||||
|
self.watches[deviceId] = emitterId;
|
||||||
|
},
|
||||||
|
onFailure: function() {
|
||||||
|
logger.error('Failed to subscribe to ' + subscribeTopic);
|
||||||
|
logger.error('As messages are not available, visualization is not possible');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*If (IoTFconnector.prototype.clientStatus.subscribeTopic != "") {
|
||||||
|
console.log("Unsubscribing to " + subscribeTopic);
|
||||||
|
wsClient.unsubscribe(IoTFconnector.prototype.clientStatus.subscribeTopic);
|
||||||
|
};*/
|
||||||
|
|
||||||
|
wsClient.subscribe(subscribeTopic, subscribeOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return this.sockets;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
1791
lib/mqtt/mqttws31.js
Normal file
1791
lib/mqtt/mqttws31.js
Normal file
File diff suppressed because it is too large
Load Diff
79
package.json
Normal file
79
package.json
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"name": "sodashserver",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Smart Office Dashboard Server",
|
||||||
|
"main": "index.js",
|
||||||
|
"directories": {
|
||||||
|
"test": "test"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"body-parser": "^1.15.1",
|
||||||
|
"cookie-parser": "*",
|
||||||
|
"ejs": "*",
|
||||||
|
"errorhandler": "*",
|
||||||
|
"express": "^4.13.4",
|
||||||
|
"express-session": "*",
|
||||||
|
"htmlparser": "^1.7.7",
|
||||||
|
"method-override": "*",
|
||||||
|
"minibus": "^3.1.0",
|
||||||
|
"morgan": "*",
|
||||||
|
"mqtt": "^1.10.0",
|
||||||
|
"mqtt_over_websockets": "0.0.1",
|
||||||
|
"node-localstorage": "^1.1.2",
|
||||||
|
"request": "^2.72.0",
|
||||||
|
"websocket": "^1.0.22"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"after": "^0.8.1",
|
||||||
|
"apn": "^1.7.5",
|
||||||
|
"apns": "^0.1.0",
|
||||||
|
"basic-authentication": "^1.6.2",
|
||||||
|
"chai": "^3.5.0",
|
||||||
|
"cheerio": "^0.20.0",
|
||||||
|
"clone": "^1.0.2",
|
||||||
|
"del": "^2.2.0",
|
||||||
|
"elapsed": "0.0.7",
|
||||||
|
"gulp": "^3.9.1",
|
||||||
|
"gulp-autoprefixer": "^3.1.0",
|
||||||
|
"gulp-cache": "^0.4.5",
|
||||||
|
"gulp-concat": "^2.6.0",
|
||||||
|
"gulp-cssmin": "^0.1.7",
|
||||||
|
"gulp-cssnano": "^2.1.2",
|
||||||
|
"gulp-debug": "^2.1.2",
|
||||||
|
"gulp-google-webfonts": "0.0.12",
|
||||||
|
"gulp-html-replace": "^1.5.5",
|
||||||
|
"gulp-htmlmin": "^2.0.0",
|
||||||
|
"gulp-inject": "^4.0.0",
|
||||||
|
"gulp-jshint": "^2.0.1",
|
||||||
|
"gulp-jsmin": "^0.1.5",
|
||||||
|
"gulp-livereload": "^3.8.1",
|
||||||
|
"gulp-notify": "^2.2.0",
|
||||||
|
"gulp-rename": "^1.2.2",
|
||||||
|
"gulp-size": "^2.1.0",
|
||||||
|
"gulp-strip-debug": "^1.1.0",
|
||||||
|
"gulp-uglify": "^1.5.3",
|
||||||
|
"jshint": "^2.9.2",
|
||||||
|
"jsonfile": "^2.3.1",
|
||||||
|
"log4js": "^0.6.36",
|
||||||
|
"mocha": "^2.4.5",
|
||||||
|
"mqtt-ws": "^0.2.0",
|
||||||
|
"node-cron": "^1.1.1",
|
||||||
|
"require-dir": "^0.3.0",
|
||||||
|
"should": "^8.3.1",
|
||||||
|
"string": "^3.3.1",
|
||||||
|
"sugar": "^1.4.1",
|
||||||
|
"sugar-date": "^1.5.1",
|
||||||
|
"superagent": "^1.7.2",
|
||||||
|
"supertest": "^1.1.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha --recursive --reporter spec --bail --check-leaks --timeout 3000",
|
||||||
|
"start": "node app"
|
||||||
|
},
|
||||||
|
"author": "Martin Donnelly",
|
||||||
|
"license": "ISC",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+http://gitlab.silvrtree.co.uk/martind2000/SODashServer.git"
|
||||||
|
}
|
||||||
|
}
|
20
process.json
Normal file
20
process.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"apps": [
|
||||||
|
{
|
||||||
|
"name": "SODashServer",
|
||||||
|
"script": "app.js",
|
||||||
|
"cwd": "/home/azureuser/live",
|
||||||
|
"watch": true,
|
||||||
|
"instances": 1,
|
||||||
|
"exec_mode": "cluster",
|
||||||
|
"combine_logs": true,
|
||||||
|
"max_memory_restart": "150M",
|
||||||
|
"restart_delay": 5000,
|
||||||
|
"ignore_watch": [
|
||||||
|
"[\\/\\\\]\\./",
|
||||||
|
"node_modules",
|
||||||
|
"server/static"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user