Source: plugins/inbound/katsys/base.js

const EventEmitter = require('events');
const Operation = require('../../../models/core/core_operation');
/**
 * Class for KatSys Cloud communication
 * @class plugins/inbound/katsys
 * @namespace plugins/inbound/katsys
 * @memberof plugins/inbound/katsys
  */
class katsys extends EventEmitter {

    /**
     * Constructor
     * 
     * Sets up everything, starts service and connects to katsys
     */
    constructor() {
        super();
        global.plgManager.logger.info('-------- PLUGIN KatSysCloud -----------');
        this.katsysProcess = null;
        this.registerForEvents();
        this.serviceProcId = null;
        this.loadConfig((success) => {
            if (success) {
                // set plugin as configured
                this.initializePlugin((initsuccess) => {
                    global.plgManager.logger.debug('PLUGIN | KATSYS | initialized Plugin: ' + initsuccess);
                    if (initsuccess) {
                        this.isConfigured = true;
                        this.prepareService();
                        this.wireServiceCommunication();
                        this.configService();
                        this.startService();
                    }
                })
            }
        })

    }

    /**
     * Registration of Events at the plugin manager (hook in to events provided by the plugin manager)
     */
    registerForEvents() {
        global.plgManager.logger.info('PLUGIN | KATSYS | Registering events');
        global.plgManager.on('event_pluginConfig_refreshed', (namespace) => {
            if (namespace === 'katsys') {
                // plugins config has changed --> refresh
                this.loadConfig((success) => {
                    if (success) {
                        global.plgManager.logger.info('PLUGIN | DIVERA247 | successfully reloaded plugin configuration');
                        this.restartService();
                    } else {
                        global.plgManager.logger.error('PLUGIN | DIVERA247 | could not reload plugin config!');
                    }
                });
            }
        })
    }

    /**
     * Plugin-specific implementation
     */
    newalarm(alarmInfo) {
        global.plgManager.logger.info('PLUGIN | KATSYS | Sending new Alarm to Plugin Manager for dispatching');
        global.plgManager.event_new_alarm(alarmInfo);
    }

    newStatus(statusInfo) {
        global.plgManager.logger.info('PLUGIN | KATSYS | Sending new State Info to Plugin Manager for dispatching');
        global.plgManager.event_new_state(statusInfo);
    }

    newZvei(zveiInfo) {
        global.plgManager.logger.info('PLUGIN | KATSYS | Sending new ZVEI Alarm to Plugin Manager for dispatching');
        global.plgManager.event_new_zveialarm(zveiInfo);
    }




    /**
     * Loads configuration for KatSys Service
     * @memberof plugins/inbound/katsys
     */
    loadConfig(callback) {
        global.plgManager.loadConfigFromStore('katsys', (configRows) => {
            if (configRows !== null) {
                this.config = configRows[0];
                this.config = JSON.parse(this.config.configstore);
                callback(true);
            } else {
                callback(false);
            }
            global.plgManager.logger.info('PLUGIN | KATSYS | Configuration loaded from core database');
        })
    }

    /**
     * returns config parameter for given fieldname
     * @param {string} fieldname 
     * @memberof plugins/inbound/katsys
     */
    getConfigValue(fieldname) {
        var retVal = null;
        this.config.fields.forEach((field) => {
            if (field.fieldname === fieldname) {
                retVal = field.value;
            }
        });
        return retVal;
    }

    /**
     * reconfigures divera plugin with new config settings
     * @param {function} callback success, true or false
     * @memberof plugins/inbound/katsys
     */
    initializePlugin(callback) {
        // LAU

        console.log(this.getConfigValue('subtoken'));
        this.katSysConfig = {
            masterToken: this.getConfigValue('mastertoken'),
            subToken: this.getConfigValue('subtoken'),
            pemFile: __dirname + '/uploads/' + this.getConfigValue('pemfile'),
            loglevel: 'debug'
        }

        if ((typeof this.katSysConfig.masterToken !== 'undefined') && (typeof this.katSysConfig.subToken !== 'undefined') && (typeof this.katSysConfig.pemFile !== 'undefined')) {
            global.plgManager.logger.info('PLUGIN | KATSYS | Properly inititlized settings');
            callback(true);
        } else {
            global.plgManager.logger.error('PLUGIN | KATSYS | could not initialize settings');
            callback(false);
        }
    }

    /**
     * Wires messages from service to event model of plugin
     * All Messages in service need to be wired here to be recognised in plugin
     * @memberof plugins/inbound/katsys
     */
    wireServiceCommunication() {
        this.katsysProcess.on('message', function (msg) {
            var payload = null;
            try {
                payload = JSON.parse(msg);
            } catch (err) {
                payload = err.message;
            }
            if (typeof payload.error != 'undefined') {
                // child has sent an error
                // try restarting the whole service
                global.plgManager.event_new_admin_notification('KatSys Service meldet einen Fehler');
                this.restartService();
            }
            if (typeof payload.logmessage != 'undefined') {
                global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | ' + payload.logmessage);
            } else if (typeof payload.event != 'undefined') {
                // service send structured data
                if (payload.event.event === 'connectionStateChanged') {
                    // KatSys Cloud connection state has changed
                    global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | Connection Status has changed to ' + payload.event.newState);
                    if (payload.event.newState === true) {
                        global.plgManager.event_new_admin_notification('KatSys ist nun verbunden');
                    } else {
                        global.plgManager.event_new_admin_notification('Verbindung zu KatSys verloren');
                    }
                } else if (payload.event.event === 'statusParsed') {
                    var statusInfo = payload.event.statusInfo;
                    global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | NewStatusInfo: ' + statusInfo);
                    this.newStatus(statusInfo);
                } else if (payload.event.event === 'zveiParsed') {
                    var zveiInfo = payload.event.zveiInfo;
                    global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | zveiParsed: ' + zveiInfo);
                    this.newZvei(zveiInfo);
                } else if (payload.event.event === 'alarmParsed') {
                    var alarmInfo = payload.event.alarmInfo;
                    console.log('PLUGIN | KATSYS | SERVICE | alarmParsed');
                    global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | alarmParsed');
                    global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | Migrating IPC transferred alarminfo to operation object');

                    this.ipcOperationToObject(alarmInfo, (operationObj) => {
                        if (operationObj !== null) {
                            global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | successfully migrated -> Send Alarm now');
                            this.newalarm(operationObj);
                        } else {
                            global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | could not migrate object -> Send Alarm with ipcOperation Object now');
                            this.newalarm(alarmInfo);
                        }
                    })

                } else if (payload.event.event === 'katsys_try_reconnect') {
                    console.log('PLUGIN | KATSYS | SERVICE | katsys_try_reconnect');
                    global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | katsys_try_reconnect');
                    global.plgManager.event_new_admin_notification('KATSYS Cloud Verbindung verloren. Neuverbindung Versuch: ' + payload.event.tryCount);
                } else if (payload.event.event === 'katsys_error') {
                    console.log('PLUGIN | KATSYS | SERVICE | katsys_error');
                    global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | katsys_error ' + JSON.stringify(payload.event.error));
                    global.plgManager.event_new_admin_notification('KATSYS Cloud Fehler: ' + JSON.stringify(payload.event.error));
                    this.restartService();
                }
            } else {
                global.plgManager.logger.info('PLUGIN | KATSYS | SERVICE | UNSOLICITED MESSAGE: ' + msg);
            }
        }.bind(this));
    }

    /**
     * Migrates an IPC transmitted operation to an Operation-Object.
     * @param {object} ipcOperation json from IPC holding operation information
     * @param {function} callback returns Operation - Object
     */
    ipcOperationToObject(ipcOperation, callback) {
        let alarmInfoOperation = new Operation();
        alarmInfoOperation.setUUID();
        global.plgManager.logger.info('PLUGIN | KATSYS | New alarm object recieved from Plugin-service. New GUID calculated: ' + alarmInfoOperation.uuid.value);
        alarmInfoOperation._alarmdate = ipcOperation._alarmdate;
        alarmInfoOperation._alarmtime = ipcOperation._alarmtime;
        alarmInfoOperation._alarmtimeCalc = ipcOperation._alarmtimeCalc;
        alarmInfoOperation._community = ipcOperation._community;
        alarmInfoOperation._district = ipcOperation._district;
        alarmInfoOperation._gear = ipcOperation._gear;
        alarmInfoOperation._gearCalc = ipcOperation._gearCalc;
        alarmInfoOperation._gkx = ipcOperation._gkx;
        alarmInfoOperation._gky = ipcOperation._gky;
        alarmInfoOperation._keywordCategory = ipcOperation._keywordCategory;
        alarmInfoOperation._keywordId = ipcOperation._keywordId;
        alarmInfoOperation._keywordName = ipcOperation._keywordName;
        alarmInfoOperation._keywordRaw = ipcOperation._keywordRaw;
        alarmInfoOperation._lat = ipcOperation._lat;
        alarmInfoOperation._location = ipcOperation._location;
        alarmInfoOperation._lon = ipcOperation._lon;
        alarmInfoOperation._message = ipcOperation._message;
        alarmInfoOperation._object = ipcOperation._object;
        alarmInfoOperation._operationSourceConnector = ipcOperation._operationSourceConnector;
        alarmInfoOperation._operationState = 1;
        alarmInfoOperation._operationnumber = ipcOperation._operationnumber;
        alarmInfoOperation._rawdata = ipcOperation._rawdata;
        alarmInfoOperation._section = ipcOperation._section;
        alarmInfoOperation._street = ipcOperation._street;
        alarmInfoOperation._subject = ipcOperation._subject;
        alarmInfoOperation._zveis = ipcOperation._zveis;
        alarmInfoOperation._zveisCalc = ipcOperation._zveisCalc;
        try {
            alarmInfoOperation._locationCalc = ipcOperation._locationCalc;
        } catch (err) {
            global.plgManager.logger.error('PLUGIN | KATSYS | error while ipcOperationToObject for _locationCalc: ' + err.message); 
        }
        alarmInfoOperation._floor = ipcOperation._floor;
        alarmInfoOperation._ils = ipcOperation._ils;

        return callback(alarmInfoOperation);

    }

    /**
     * Creates the service as a seperate node-process (fork)
     * sets the serviceProcId of the forked process
     * @memberof plugins/inbound/katsys
     */
    prepareService() {
        global.plgManager.logger.info('PLUGIN | KATSYS | Starting Service');
        const { fork } = require('child_process');
        this.katsysProcess = fork(__dirname + '/service.js');
        this.serviceProcId = this.katsysProcess.pid;
        this.katsysProcess.title = 'ALARMiator Plugin - KatSys Cloud Connector';
        global.plgManager.logger.info('PLUGIN | KATSYS | Service started with pid ' + this.serviceProcId);
        this.katsysProcess.on('exit', function (code) {
            this.katsysProcess = null;
            console.log("KATSYS Service EXITED " + code);
        });
    }

    /**
     * Send TESTALARM 
     * Only for testing purposes on development level
     */
    sendTestAlarm() {
        this.katsysProcess.send({ testalarm: true });
    }

    /**
     * Sends the service configuration to the katsys process
     */
    configService() {
        this.katsysProcess.send({ config: this.katSysConfig });
    }

    /**
     * tells the service to connect to the katsys cloud
     */
    startService() {
        this.katsysProcess.send({ start: 1 });
    }

    /**
     * restarts the KatSys Plugin Service
     */
    restartService() {
        global.plgManager.logger.info('PLUGIN | KATSYS | restart Service...');
        if (this.katsysProcess !== null) {
            global.plgManager.logger.info('PLUGIN | KATSYS | Killing Service...');
            this.katsysProcess.kill("SIGHUP");
        }
        this.initializePlugin((initsuccess) => {
            global.plgManager.logger.debug('PLUGIN | KATSYS | initialized Plugin: ' + initsuccess);
            if (initsuccess) {
                this.isConfigured = true;
                this.prepareService();
                this.wireServiceCommunication();
                this.configService();
                this.startService();
            }
        })
    }
}

module.exports = katsys;