<!DOCTYPE html> <html> <head> <title>Dispatcher Configuration</title> <!-- <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"> --> <link href="css/materialdesignicons.min.css" rel="stylesheet"> <link href="css/vuetify.min.css" rel="stylesheet"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> </head> <body> <div id="app"> <v-app> <v-app-bar app> <v-toolbar-title>Dispatcher Configuration</v-toolbar-title> <v-spacer></v-spacer> <v-btn color="success" @click="storeConfig()">Store & Restart</v-btn> <v-checkbox label="Expert Mode" v-model="EXPERTMODE"></v-checkbox> </v-app-bar> <v-content> <v-form> <v-tabs v-model="configTab" next-icon="mdi-arrow-right-bold-box-outline" prev-icon="mdi-arrow-left-bold-box-outline" show-arrows> <v-tabs-slider></v-tabs-slider> <v-tab key="profiles">Profiles</v-tab> <v-tab key="gateways">Gateway Config</v-tab> <v-tab key="devices">Device Config</v-tab> <v-tab key="boskrypt"> <v-img src="boskrypt.gif" max-width="64px" max-height="32px"></v-img> </v-tab> <!-- <v-tab v-show="EXPERTMODE" key="notificationConfig">Notification Configuration</v-tab> --> </v-tabs> <v-tabs-items v-model="configTab"> <v-tab-item key="profiles"> <v-container> <v-row> <v-btn color="green" fab dark small icon @click="addProfile()"> <v-icon>mdi-plus</v-icon> </v-btn> </v-row> <v-row v-for="(deliveryPreset, index) in configData.deliveryPresets" :key="deliveryPreset._id" style="border-bottom: 2px solid black;"> <v-col cols="12" sm="12" md="12"> <pre>Index: {{ index }}</pre> <v-btn color="error" @click="deleteProfile(index)" icon> <v-icon>mdi-delete</v-icon> </v-btn> </v-col> <v-col cols="6" sm="6" md="4"> <v-text-field v-model="deliveryPreset.name" label="Name"></v-text-field> <v-select :items="pagerTypes" v-model="deliveryPreset.params.type" item-text="k" item-value="v" label="Delivery Type"></v-select> <v-select :items="deviceType" v-model="deliveryPreset.params.routing.device" item-text="k" item-value="v" label="Device"></v-select> </v-col> <v-col> <b>Delivery Targets:</b> <v-btn color="success" @click="addDeliveryTarget(index)">Add</v-btn> <v-row v-for="(connector, index) in deliveryPreset.params.routing.connectors" :key="index"> <v-col cols="6" sm="6" md="6"> <v-select :items="connectorTypes" v-model="connector[0]" item-text="k" item-value="v" label="Gateway"></v-select> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field v-model="connector[1]" label="Call ID"> <v-btn slot="append" color="error" @click="deliveryPreset.params.routing.connectors.splice(index, 1)" icon> <v-icon>mdi-delete</v-icon> </v-btn> </v-text-field> </v-col> </v-row> </v-col> </v-row> <v-row> </v-row> </v-container> </v-tab-item> <v-tab-item key="gateways"> <v-container> <v-list three-line> <v-list-item> <!-- Dummy--> <v-list-item-content> <v-list-item-title>Dummy</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.connectors.dummy.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.dummy.duplexTimeout"></v-text-field> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-divider></v-divider> <v-list-item> <!-- POCSAG-GW--> <v-list-item-content> <v-list-item-title>POCSAG-GW</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.connectors.pocsag.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.pocsag.duplexTimeout"></v-text-field> </v-row> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-divider></v-divider> <v-list-item> <!-- DAPNET--> <v-list-item-content> <v-list-item-title>DAPNET</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.connectors.dapnet.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.dapnet.duplexTimeout"></v-text-field> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field label="Username" v-model="configData.connectors.dapnet.username"></v-text-field> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field label="Password" type="password" v-model="configData.connectors.dapnet.password"></v-text-field> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field label="Endpoint" v-model="configData.connectors.dapnet.endpoint"></v-text-field> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-list-item> <!-- LoRaWAN--> <v-list-item-content> <v-list-item-title>LoRaWAN</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.connectors.lorawan.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.dapnet.duplexTimeout"></v-text-field> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field label="Username" v-model="configData.connectors.lorawan.username"></v-text-field> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field label="Password" type="password" v-model="configData.connectors.lorawan.password"></v-text-field> </v-col> <v-col cols="6" sm="6" md="6"> <v-text-field label="MQTT Server" v-model="configData.connectors.lorawan.mqttserver"></v-text-field> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-divider></v-divider> <v-list-item> <!-- e*Cityruf (inetgw) --> <v-list-item-content> <v-list-item-title>e*Cityruf (inetgw)</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6"> <v-switch v-model="configData.connectors.ecityruf.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.ecityruf.duplexTimeout"></v-text-field> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-divider></v-divider> <v-list-item> <!-- e*Message Puppeteering --> <v-list-item-content> <v-list-item-title>e*Message Puppeteering</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6"> <v-switch v-model="configData.connectors.emPuppettering.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.emPuppettering.duplexTimeout"></v-text-field> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-divider></v-divider> <v-list-item> <!-- e*Message alertManager --> <v-list-item-content> <v-list-item-title>e*Message alertManager</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6"> <v-switch v-model="configData.connectors.emessage.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.emessage.duplexTimeout"></v-text-field> </v-col> <v-col cols="6"> <v-text-field type="number" :rules="validNumberRules" label="Response Timeout in seconds" v-model="configData.connectors.emessage.responseTimeout"></v-text-field> </v-col> <v-col cols="6"> <v-text-field type="number" :rules="validNumberRules" label="Start Interval in seconds" v-model="configData.connectors.emessage.startInterval"></v-text-field> </v-col> <v-col cols="6"> <v-text-field label="Username" v-model="configData.connectors.emessage.username"></v-text-field> </v-col> <v-col cols="6"> <v-text-field label="Password" type="password" v-model="configData.connectors.emessage.password"></v-text-field> </v-col> <v-col cols="6"> <v-switch v-model="configData.connectors.emessage['2wayS_BackChannel']" label="2wayS BackChannel"></v-switch> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-divider></v-divider> <v-list-item> <!-- pagernetz.at --> <v-list-item-content> <v-list-item-title>pagernetz.at</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6"> <v-switch v-model="configData.connectors.pagernetzAT.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6"> <v-text-field type="number" :rules="validNumberRules" label="Duplex Timeout in seconds" v-model="configData.connectors.pagernetzAT.duplexTimeout"></v-text-field> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> <v-divider></v-divider> </v-list> </v-container> </v-tab-item> <v-tab-item key="devices"> <v-container> <v-list three-line> <v-list-item> <!-- Birdy Slim IoT --> <v-list-item-content> <v-list-item-title>Birdy Slim IoT</v-list-item-title> <v-list-item-action> <v-row cols="12"> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.pagers.birdyslim.enabled" label="Enabled"></v-switch> </v-col> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.pagers.birdyslim.rxchain.lorawan" label="RXChain LoRaWAN Enabled"></v-switch> </v-col> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.pagers.birdyslim.rxchain.events.mqtt" label="MQTT Events Enabled"></v-switch> </v-col> <v-col cols="6" sm="6" md="6"> <v-switch v-model="configData.pagers.birdyslim.rxchain.events.webhook" label="Webhook Enabled"></v-switch> </v-col> </v-row> </v-list-item-action> </v-list-item-content> </v-list-item> </v-list> </v-container> </v-tab-item> <v-tab-item key="boskrypt"> <v-container> <v-row> <v-btn color="green" fab dark small icon @click="addBOSKrypt()"> <v-icon>mdi-plus</v-icon> </v-btn> </v-row> <v-row v-for="(boskryptKey, index) in configData.boskrypt.keys" :key="index"> <v-col cols="6" sm="4" md="4"> <v-text-field v-model="boskryptKey.identifier" label="Identifier"></v-text-field> </v-col> <v-col cols="8" sm="8" md="8"> <v-text-field v-model="boskryptKey.value" label="Key"> <v-btn slot="append" color="error" @click="configData.boskrypt.keys.splice(index, 1)" icon> <v-icon>mdi-delete</v-icon> </v-btn> </v-text-field> </v-col> </v-row> </v-container> </v-tab-item> </v-tabs-items> </v-form> </v-content> </v-app> </div> <script src="js/vue/vue.js"></script> <script src="js/vue/vuetify.js"></script> <script src="js/vue/vue-resource_1.5.1.js"></script> <script> new Vue({ el: '#app', vuetify: new Vuetify(), http: { root: '/' }, data() { return { EXPERTMODE: false, configTab: null, validNumberRules: [ v => !isNaN(parseInt(v)) || 'is not a valid number' ], pagerTypes: [ { k: 'Simple', v: 'simple' }, { k: 'Duplex', v: 'duplex' }, ], deviceType: [ { k: 'Generic', v: 'generic' }, { k: 'Birdy Slim (IoT)', v: 'birdyslim' }, ], connectorTypes: [ { k: 'Dummy', v: 'dummy' }, { k: 'POCSAG GW', v: 'pocsag' }, { k: 'DAPNET', v: 'dapnet' }, { k: 'e*Cityruf inetgw', v: 'ecityruf' }, { k: 'e*Cityruf Puppeteer', v: 'em-p-cityruf' }, { k: 'e*Cityruf alarmManager', v: 'em-a-cityruf' }, { k: 'e*2wayS Puppeteer', v: 'em-p-twoways' }, { k: 'e*2wayS alarmManager', v: 'em-a-twoways' }, { k: 'LoRaWAN TTNv3', v: 'lorawan' }, ], configData: { boskrypt: { keys: [] }, pagers: { birdyslim: { enabled: true, rxchain: { lorawan: true, events: { webhook: false, mqtt: false } } } }, connectors: { dummy: { enabled: null, duplexTimeout: null, }, pocsag: { enabled: null, duplexTimeout: null, }, dapnet: { enabled: null, duplexTimeout: null, }, ecityruf: { enabled: null, duplexTimeout: null, }, emPuppettering: { enabled: null, duplexTimeout: null, }, } }, } }, created() { this.loadConfig() }, methods: { loadConfig() { this.$http.get(window.location.pathname + 'config').then(response => { const newConfig = response.body Object.keys(newConfig.deliveryPresets) .map(_key => { newConfig.deliveryPresets[_key]._id = btoa(JSON.stringify(newConfig.deliveryPresets[_key])) }) if (!!newConfig.boskrypt) newConfig.boskrypt.keys = Object.keys(newConfig.boskrypt.keys) .map(_key => { return { identifier: _key, value: newConfig.boskrypt.keys[_key] } }) this.configData = newConfig }, response => { }) }, storeConfig() { const storeConfig = JSON.parse(JSON.stringify(this.configData)) const oldBK = storeConfig.boskrypt.keys Object.keys(storeConfig.deliveryPresets) .map(_key => { delete storeConfig.deliveryPresets[_key]._id }) storeConfig.boskrypt.keys = Object.values(oldBK).reduce((total, keyData) => { total[ keyData.identifier ] = keyData.value return total }, {}) this.$http.post(window.location.pathname + 'config', storeConfig).then(response => { }) .then(this.$http.post(window.location.pathname + 'restart')) .then(() => { document.body.style = 'display:none' setTimeout(() => window.location.reload(), 1e3) }) }, addDeliveryTarget(index) { this.configData.deliveryPresets[index].params.routing.connectors.push(["dummy", "12345"]) }, addBOSKrypt() { this.configData.boskrypt.keys.push({ identifier: 'identifier', value: '' }) }, addProfile() { this.configData.deliveryPresets = Object.assign({}, this.configData.deliveryPresets, { [new Date().valueOf().toString(16)]: { name: "Name", params: { type: "simple", routing: { device: "generic", connectors: [] } } } }) }, deleteProfile(index) { delete this.configData.deliveryPresets[index] this.configData.deliveryPresets = Object.assign({}, this.configData.deliveryPresets) }, } }) </script> </body> </html>