UNPKG

mgmt-iot-web

Version:

web platform to configure and interact with iot devices using mqtt

265 lines (205 loc) 8.21 kB
$ = {} const mqtt = require('mqtt') const FtpSrv = require('ftp-srv'); const crc = require('crc'); const fs = require('fs'); const path = require('path'); var web = require('./express-web'); var config = require('./config/env'); var device = require('./server/models/devices.js'); var user = require('./server/models/users'); mgmt_iot_version = ""; 'use strict'; const {Docker} = require('node-docker-api'); const docker = new Docker({ socketPath: '/var/run/docker.sock' }); const ftpPath = './server/public/' module.exports = { init : (settings)=>{ $.config = settings; // Setup global exception handlers to prevent application exit except in dev mode const isDev = settings?.environment === 'development'; process.on('uncaughtException', (error) => { console.error('Uncaught Exception:', error); if (isDev) { // In dev mode, let the application exit as normal process.exit(1); } else { // In production, prevent exit and continue running console.error('Application continuing despite uncaught exception...'); } }); process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Promise Rejection at:', promise, 'reason:', reason); if (isDev) { // In dev mode, let the application exit as normal process.exit(1); } else { // In production, prevent exit and continue running console.error('Application continuing despite unhandled promise rejection...'); } }); var db = require('./server/controllers/db'); db.connect(settings,() => { db_setup(); mgmt_iot_version = settings?.version ? settings.version : ""; web.listen(settings?.web?.port, () => { log.info('Web Server started and listening on port: ' +settings?.web?.port + ' ' + settings?.env); }); log.info("connected to DB"); }); var host = settings?.mqtt?.host; $.mqttClient = mqtt.connect({ protocolId: settings?.mqtt?.protocol, host: settings?.mqtt?.host, port:settings?.mqtt?.port, username:settings?.mqtt?.user, password:settings?.mqtt?.pwd, clientId: settings?.mqtt?.client }) docker.container.list() .then(containers =>{ containers.forEach(function (container) { let id = container.data.Image; console.log("id: ",id); container.status() .then(status => { status.stats() .then(stream => { stream.on('data', function (chunk) { const stats = JSON.parse(chunk.toString()); let topic = 'docker/container'+stats.name let rx_bytes = stats.networks?.eth0?.rx_bytes/1000 rx_bytes = Math.round((rx_bytes + Number.EPSILON) * 1000) / 1000 $.mqttClient.publish(topic+"/network/rx",String(rx_bytes)); $.mqttClient.publish(topic+"/network/rx/str",rx_bytes+" kB/s"); let tx_bytes = stats.networks?.eth0?.tx_bytes/1000; tx_bytes = Math.round((tx_bytes + Number.EPSILON) * 1000) / 1000 $.mqttClient.publish(topic+"/network/tx",String(tx_bytes)); $.mqttClient.publish(topic+"/network/tx/str",tx_bytes+" kB/s"); $.mqttClient.publish(topic+"/cpus/online",String(stats.cpu_stats.online_cpus)); let mem_usage = stats.memory_stats?.usage/1000000; mem_usage = Math.round((mem_usage + Number.EPSILON) * 1000) / 1000 $.mqttClient.publish(topic+"/memory/usage",String(mem_usage)); $.mqttClient.publish(topic+"/memory/usage/str",mem_usage+" MB"); let cpu_usage = stats.cpu_stats?.cpu_usage?.total_usage/stats.cpu_stats?.system_cpu_usage; cpu_usage = Math.round((cpu_usage + Number.EPSILON) * 1000) / 1000 $.mqttClient.publish(topic+"/cpu/usage",String(cpu_usage)); $.mqttClient.publish(topic+"/cpu/usage/str",cpu_usage+" %"); }); stream.on('error', function (err) { console.log(err); }); stream.on('end', function () { console.log('Stream ended'); }); }) }) }); }) .catch(error => console.log(error)); $.mqttClient.on('connect', function () { console.log("mqtt connected to: ",host); /* $.mqttClient.subscribe("#", function (err) { if(err) console.log(err); }) */ }) $.mqttClient.on('message', function (topic, message) { // message is Buffer console.log(topic.toString(),message.toString()) }) $.mqttClient.on('error', function (error) { console.log("error:",error) }) $.mqttClient.on('close', function () { console.log("mqtt closed") }) // --- FTP Server --- // Init ftp server const ftpServer = new FtpSrv({ url: "ftp://127.0.0.1:" + settings?.ftp?.port, anonymous: false, blacklist: ['STOR'], tls: false, pasv_url: settings?.ftp?.pasv_url, pasv_min: settings?.ftp?.pasv_min, pasv_max: settings?.ftp?.pasv_max, }); if( settings?.ftp && settings?.ftp?.enabled ){ ftpServer.listen().then(() => { console.log(`FTP Server is running on port: ${settings?.ftp?.port}`); }); } ftpServer.on('login', ({ ftpConnection, username, password }, resolve, reject) => { // You can implement your own user authentication here console.log('username:',username); console.log('password:',password); if(username !== settings?.ftp?.user_default && settings?.ftp?.pwd_default !== 'anonymous'){ return reject(new errors.GeneralError('Invalid username or password', 401)); } resolve({ root: path.join(__dirname, './server/public/') }); }); if( settings?.ftp?.upload){ ftpServer.on('STOR', async (conn) => { const filePath = path.join(__dirname, './server/public/', conn.args[0]); const fileStream = fs.createWriteStream(filePath); conn.stream.pipe(fileStream); fileStream.on('finish', () => { console.log(`File uploaded: ${filePath}`); }); conn.stream.on('data', (chunk) => { const crcValue = crc.crc16xmodem(chunk); console.log(`CRC16 for the received chunk: ${crcValue.toString(16)}`); }); }); } if( settings?.ftp?.download){ ftpServer.on('RETR', async (conn) => { const filePath = path.join(__dirname, ftpPath, conn.args[0]); const fileStream = fs.createReadStream(filePath); // Calculate CRC16 for the file content let fileCRC = crc.crc16xmodem(); fileStream.on('data', (chunk) => { fileCRC.update(chunk); }); fileStream.on('end', () => { console.log(`CRC16 for the file ${conn.args[0]}: ${fileCRC.digest().toString('hex')}`); }); conn.stream.pipe(fileStream); }); } ftpServer.on('client-error', ({connection, context, error}) => { console.log("client error: ",error); }); ftpServer.on('server-error', ({error}) => { console.log("server error: ",error); }); ftpServer.on('disconnect', ({connection, id, newConnectionCount}) => { console.log("disconnected id: ",id); }); // --- ----- --- }, path : ()=>{ return __dirname+'/server/public/views'; }, deviceInfo : (deviceID,cb)=>{ device.getInfo(deviceID,(err,rows)=>{ return cb(err,rows); }) }, deviceLastValues : (deviceID,cb)=>{ device.getLastValues(deviceID,(err,object)=>{ return cb(err,object); }) }, } function db_setup(){ let {user_type,user_pwd,user_lvl} = config.new_client; user.addIfNotRegistered(user_type,user_pwd,user_lvl,(err,res)=>{ if(err){ console.log(err); console.log("error registering user type:",user_type) } }); }