Initial commit
This commit is contained in:
371
main.js
Normal file
371
main.js
Normal file
@@ -0,0 +1,371 @@
|
||||
/**
|
||||
*
|
||||
* iobroker vis Adapter
|
||||
*
|
||||
* (c) 2014-2017 bluefox, hobbyquaker
|
||||
*
|
||||
* CC-NC-BY 4.0 License
|
||||
*
|
||||
*/
|
||||
/* jshint -W097 */
|
||||
/* jshint strict:false */
|
||||
/* jslint node: true */
|
||||
'use strict';
|
||||
|
||||
var adapterName = require(__dirname + '/package.json').name.split('.').pop();
|
||||
var isBeta = adapterName.indexOf('beta') !== -1;
|
||||
|
||||
var utils = require(__dirname + '/lib/utils'); // Get common adapter utils
|
||||
var adapter = new utils.Adapter(adapterName);
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var syncWidgetSets = require(__dirname + '/lib/install.js');
|
||||
var https = require('https');
|
||||
var jwt = require('jsonwebtoken');
|
||||
//var minify = require('html-minifier').minify;
|
||||
|
||||
adapter.on('ready', function () {
|
||||
main();
|
||||
});
|
||||
|
||||
function writeFile(fileName, callback) {
|
||||
var config = require(__dirname + '/www/js/config.js').config;
|
||||
var index;
|
||||
var srcFileNameParts = fileName.split('.');
|
||||
var ext = srcFileNameParts.pop();
|
||||
var srcFileName = srcFileNameParts.join('.') + '.src.' + ext;
|
||||
if (fs.existsSync(__dirname + '/www/' + srcFileName)) {
|
||||
index = fs.readFileSync(__dirname + '/www/' + srcFileName).toString();
|
||||
} else {
|
||||
index = fs.readFileSync(__dirname + '/www/' + fileName).toString();
|
||||
fs.writeFileSync(__dirname + '/www/' + srcFileName, index);
|
||||
}
|
||||
|
||||
// enable cache
|
||||
index = index.replace('<!--html manifest="cache.manifest" xmlns="http://www.w3.org/1999/html"--><html>',
|
||||
'<html manifest="cache.manifest" xmlns="http://www.w3.org/1999/html">');
|
||||
|
||||
var begin = '<!-- --------------------------------------- DO NOT EDIT INSIDE THIS LINE - BEGIN ------------------------------------------- -->';
|
||||
var end = '<!-- --------------------------------------- DO NOT EDIT INSIDE THIS LINE - END ------------------------------------------- -->';
|
||||
var bigInsert = '';
|
||||
for (var w in config.widgetSets) {
|
||||
if (!config.widgetSets.hasOwnProperty(w)) continue;
|
||||
var file;
|
||||
var name;
|
||||
|
||||
if (typeof config.widgetSets[w] === 'object') {
|
||||
name = config.widgetSets[w].name + '.html';
|
||||
} else {
|
||||
name = config.widgetSets[w] + '.html';
|
||||
}
|
||||
file = fs.readFileSync(__dirname + '/www/widgets/' + name);
|
||||
// extract all css and js
|
||||
|
||||
|
||||
bigInsert += '<!-- --------------' + name + '--- START -->\n' + file.toString() + '\n<!-- --------------' + name + '--- END -->\n';
|
||||
}
|
||||
var pos = index.indexOf(begin);
|
||||
if (pos !== -1) {
|
||||
var start = index.substring(0, pos + begin.length);
|
||||
pos = index.indexOf(end);
|
||||
if (pos !== -1) {
|
||||
var _end = index.substring(pos);
|
||||
index = start + '\n' + bigInsert + '\n' + _end;
|
||||
|
||||
/*index = minify(index, {
|
||||
removeAttributeQuotes: true,
|
||||
removeComments: true,
|
||||
collapseInlineTagWhitespace: true,
|
||||
collapseWhitespace: true,
|
||||
decodeEntities: true,
|
||||
minifyCSS: true,
|
||||
minifyJS: true,
|
||||
removeRedundantAttributes: true,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true
|
||||
});*/
|
||||
|
||||
adapter.readFile(adapterName, fileName, function (err, data) {
|
||||
if (data && data !== index) {
|
||||
fs.writeFileSync(__dirname + '/www/' + fileName, index);
|
||||
adapter.writeFile(adapterName, fileName, index, function () {
|
||||
if (callback) callback(true);
|
||||
});
|
||||
} else {
|
||||
if (callback) callback(false);
|
||||
}
|
||||
});
|
||||
} else if (callback) {
|
||||
callback(false);
|
||||
}
|
||||
} else if (callback) {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
|
||||
function upload(callback) {
|
||||
adapter.log.info('Upload ' + adapter.name + ' anew, while changes detected...');
|
||||
var file = utils.controllerDir + '/iobroker.js';
|
||||
var child = require('child_process').spawn('node', [file, 'upload', adapter.name, 'widgets']);
|
||||
var count = 0;
|
||||
child.stdout.on('data', function (data) {
|
||||
count++;
|
||||
adapter.log.debug(data.toString().replace('\n', ''));
|
||||
if ((count % 100) === 0) adapter.log.info(count + ' files uploaded...');
|
||||
});
|
||||
child.stderr.on('data', function (data) {
|
||||
adapter.log.error(data.toString().replace('\n', ''));
|
||||
});
|
||||
child.on('exit', function (exitCode) {
|
||||
adapter.log.info('Uploaded. ' + (exitCode ? 'Exit - ' + exitCode : 0));
|
||||
callback(exitCode);
|
||||
});
|
||||
}
|
||||
|
||||
function updateCacheManifest(callback) {
|
||||
adapter.log.info('Changes in index.html detected => update cache.manifest');
|
||||
var data = fs.readFileSync(__dirname + '/www/cache.manifest').toString();
|
||||
var build = data.match(/# dev build ([0-9]+)/);
|
||||
data = data.replace(/# dev build [0-9]+/, '# dev build ' + (parseInt(build[1] || 0, 10) + 1));
|
||||
fs.writeFileSync(__dirname + '/www/cache.manifest', data);
|
||||
|
||||
adapter.writeFile(adapterName, 'cache.manifest', data, function () {
|
||||
callback && callback();
|
||||
});
|
||||
}
|
||||
// Update index.html
|
||||
function checkFiles(configChanged, isBeta) {
|
||||
if (isBeta) {
|
||||
adapter.stop();
|
||||
return;
|
||||
}
|
||||
writeFile('index.html', function (indexChanged) {
|
||||
// Update edit.html
|
||||
writeFile('edit.html', function (editChanged) {
|
||||
if (indexChanged || editChanged || configChanged) {
|
||||
updateCacheManifest(function () {
|
||||
upload(function () {
|
||||
adapter.stop();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
adapter.stop();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyFiles(root, filesOrDirs, callback) {
|
||||
if (!filesOrDirs) {
|
||||
adapter.readDir('vis.0', root, function (err, filesOrDirs) {
|
||||
copyFiles(root, filesOrDirs || [], callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!filesOrDirs.length) {
|
||||
if (typeof callback === 'function') callback();
|
||||
return;
|
||||
}
|
||||
|
||||
var task = filesOrDirs.shift();
|
||||
if (task.isDir) {
|
||||
copyFiles(root + task.file + '/', null, function () {
|
||||
setTimeout(copyFiles, 0, root, filesOrDirs, callback);
|
||||
})
|
||||
} else {
|
||||
adapter.readFile('vis.0', root + task.file, function (err, data) {
|
||||
if (data || data === 0 || data === '') {
|
||||
adapter.writeFile(adapterName + '.0', root + task.file, data, function () {
|
||||
setTimeout(copyFiles, 0, root, filesOrDirs, callback);
|
||||
});
|
||||
} else {
|
||||
setTimeout(copyFiles, 0, root, filesOrDirs, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function generatePages(isLicenseError) {
|
||||
var count = 0;
|
||||
var changed = false;
|
||||
|
||||
if (!isBeta) {
|
||||
changed = syncWidgetSets(false, isLicenseError);
|
||||
|
||||
if (changed) {
|
||||
// upload config.js
|
||||
count++;
|
||||
var config = changed;
|
||||
adapter.readFile(adapterName, 'js/config.js', function (err, data) {
|
||||
if (data && data !== config) {
|
||||
adapter.log.info('config.js changed. Upload.');
|
||||
adapter.writeFile(adapterName, 'js/config.js', config, function () {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
});
|
||||
} else {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
}
|
||||
});
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
count++;
|
||||
// try to read vis-beta.0/files
|
||||
adapter.readDir(adapterName + '.0', '/', function (err, dirs) {
|
||||
if (!dirs || !dirs.length) {
|
||||
// copy all directories
|
||||
copyFiles('/', null, function () {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
})
|
||||
} else {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// create command variable
|
||||
count++;
|
||||
adapter.getObject('control.command', function (err, obj) {
|
||||
if (!obj) {
|
||||
adapter.setObject('control.command',
|
||||
{
|
||||
"type": "state",
|
||||
"common": {
|
||||
"name": "Command for vis",
|
||||
"type": "string",
|
||||
"desc": "Writing this variable akt as the trigger. Instance and data must be preset before 'command' will be written. 'changedView' will be signalled too",
|
||||
"states": {
|
||||
"alert": "alert",
|
||||
"changeView": "changeView",
|
||||
"refresh": "refresh",
|
||||
"reload": "reload",
|
||||
"dialog": "dialog",
|
||||
"popup": "popup",
|
||||
"playSound": "playSound",
|
||||
"changedView": "changedView",
|
||||
"tts": "tts"
|
||||
}
|
||||
},
|
||||
"native": {}
|
||||
},
|
||||
function () {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
}) ;
|
||||
} else {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
}
|
||||
});
|
||||
|
||||
// Create common user CSS file
|
||||
count++;
|
||||
adapter.readFile(adapterName, 'css/vis-common-user.css', function (err, data) {
|
||||
if (err || data === null || data === undefined) {
|
||||
adapter.writeFile(adapterName, 'css/vis-common-user.css', '', function () {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
});
|
||||
} else {
|
||||
if (!--count) checkFiles(changed, isBeta);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function indicateError(callback) {
|
||||
var data = fs.readFileSync(__dirname + '/www/js/config.js').toString();
|
||||
if (data.indexOf('license: false,') === -1) {
|
||||
data = data.replace('var visConfig = {', 'var visConfig = {license: false,');
|
||||
fs.writeFileSync(__dirname + '/www/js/config.js', data);
|
||||
|
||||
adapter.writeFile(adapterName, 'js/config.js', data, function () {
|
||||
updateCacheManifest(callback);
|
||||
});
|
||||
} else {
|
||||
callback && callback();
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
// Check if noConfig = false
|
||||
if (adapter.common.noConfig) {
|
||||
adapter.getForeignObject('system.adapter.' + adapter.namespace, function (err, obj) {
|
||||
obj.common.noConfig = false;
|
||||
adapter.setForeignObject(obj._id, obj, function () {
|
||||
adapter.stop();
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// first of all check license
|
||||
if (!adapter.config.license || typeof adapter.config.license !== 'string') {
|
||||
indicateError(function () {
|
||||
adapter.log.error('No license found for vis. Please get one on https://iobroker.net !');
|
||||
//adapter.stop();
|
||||
generatePages(true);
|
||||
});
|
||||
} else {
|
||||
// An object of options to indicate where to post to
|
||||
var postOptions = {
|
||||
host: 'iobroker.net',
|
||||
path: '/cert/',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'text/plain',
|
||||
'Content-Length': Buffer.byteLength(adapter.config.license)
|
||||
}
|
||||
};
|
||||
|
||||
// Set up the request
|
||||
var postReq = https.request(postOptions, function (res) {
|
||||
res.setEncoding('utf8');
|
||||
var result = '';
|
||||
res.on('data', function (chunk) {
|
||||
result += chunk;
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
try {
|
||||
var data = JSON.parse(result);
|
||||
if (data.result === 'OK') {
|
||||
adapter.log.info('vis license is OK.');
|
||||
generatePages();
|
||||
} else {
|
||||
indicateError(function () {
|
||||
adapter.log.error('License is invalid! Nothing updated. Error: ' + (data ? data.result: 'unknown'));
|
||||
//adapter.stop();
|
||||
generatePages(true);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
indicateError(function () {
|
||||
adapter.log.error('Cannot check license! Nothing updated. Error: ' + (data ? data.result: 'unknown'));
|
||||
//adapter.stop();
|
||||
generatePages(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
}).on('error', function (error) {
|
||||
jwt.verify(adapter.config.license, fs.readFileSync(__dirname + '/lib/cloudCert.crt'), function (err, decoded) {
|
||||
if (err) {
|
||||
adapter.log.error('Cannot check license: ' + error);
|
||||
//adapter.stop();
|
||||
generatePages(true);
|
||||
} else {
|
||||
if (decoded && decoded.expires * 1000 < new Date().getTime()) {
|
||||
adapter.log.error('Cannot check license: Expired on ' + new Date(decoded.expires * 1000).toString());
|
||||
adapter.stop();
|
||||
} else if (!decoded) {
|
||||
adapter.log.error('Cannot check license: License is empty');
|
||||
//adapter.stop();
|
||||
generatePages(true);
|
||||
} else {
|
||||
generatePages(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
postReq.write(adapter.config.license);
|
||||
postReq.end();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user