Commit fbea5c907f98e4ce84155312d80a9681db8d873f

Authored by Adhidarma Hadiwinoto
1 parent 18c6f924d1
Exists in master

api near complete

Showing 12 changed files with 315 additions and 13 deletions Side-by-side Diff

1 1 /node_modules/
2 2 /config.json
3 3 /config.smstools.json
  4 +/smsd.conf.tmp
4 5 /tmp/
5 6 /logs/
6 7 config_*.json
bin/smstools-config-install
... ... @@ -0,0 +1,14 @@
  1 +#!/bin/bash
  2 +set -x
  3 +
  4 +DIRFILE=`dirname "$0"`
  5 +cd "$DIRFILE/.."
  6 +echo `pwd`
  7 +
  8 +TARGETFILE=$1
  9 +if [ -z "$TARGETFILE" ]; then
  10 + exit 0
  11 +fi
  12 +
  13 +sudo install smsd.conf.tmp "$TARGETFILE"
  14 +sudo systemctl restart sms3
... ... @@ -9,7 +9,7 @@ const config = require('komodo-sdk/config');
9 9 global.KOMODO_LOG_LABEL = `KOMODO-CENTER@${(config && typeof config.name === 'string') ? config.name.toUpperCase() : 'SMSTOOLS'}`;
10 10 process.title = global.KOMODO_LOG_LABEL;
11 11  
12   -require('./lib/smstools-configurator');
  12 +require('./lib/smstools-config');
13 13 require('./lib/apiserver');
14 14  
15 15 const messagingClient = require('komodo-center-messaging-client-lib');
lib/apiserver/index.js
... ... @@ -5,10 +5,13 @@ const config = require('komodo-sdk/config');
5 5 const logger = require('komodo-sdk/logger');
6 6  
7 7 const routerSmstools = require('./routers/smstools');
  8 +const routerSmstoolsConfig = require('./routers/smstools-config');
8 9  
9 10 const app = express();
10 11  
11 12 app.use('/smstools', routerSmstools);
  13 +app.use('/smstools-config', routerSmstoolsConfig);
  14 +
12 15 app.get('/cwd', (req, res) => {
13 16 res.json({
14 17 cwd: process.cwd(),
lib/apiserver/routers/smstools-config.js
... ... @@ -0,0 +1,120 @@
  1 +const childProcess = require('child_process');
  2 +
  3 +const express = require('express');
  4 +const bodyParser = require('body-parser');
  5 +
  6 +const config = require('komodo-sdk/config');
  7 +const smstoolsConfig = require('../../smstools-config');
  8 +const smstoolsConfigCreator = require('../../smstools-config/creator');
  9 +const smstoolsConfigSetter = require('../../smstools-config/setter');
  10 +const smstoolsConfigData = require('../../smstools-config/config-file');
  11 +
  12 +const router = express.Router();
  13 +module.exports = router;
  14 +
  15 +function pageIndex(req, res) {
  16 + const configString = smstoolsConfigCreator();
  17 + res.json({
  18 + dirty: smstoolsConfig.config.dirty,
  19 + config: smstoolsConfig.config,
  20 + configStringLength: configString.length,
  21 + configStringNrLines: (configString.match(/\n/g) || []).length,
  22 + configString,
  23 + });
  24 +}
  25 +
  26 +function pageGenerate(req, res) {
  27 + res.end(smstoolsConfigCreator());
  28 +}
  29 +
  30 +async function pageModemList(req, res) {
  31 + const modems = [];
  32 + // eslint-disable-next-line no-restricted-syntax
  33 + for (const [key, value] of Object.entries(smstoolsConfigData.modems || {})) {
  34 + modems.push({
  35 + label: `${key}: ${value.device}, INCOMING${value.outgoing ? ' and OUTGOING' : ''}`,
  36 + value: key,
  37 + data: value,
  38 + });
  39 + }
  40 +
  41 + res.json(modems);
  42 +}
  43 +
  44 +async function pageSet(req, res) {
  45 + const keyword = (req.params.keyword || req.query.keyword || '').trim();
  46 + const value = (req.query.value || '').trim();
  47 +
  48 + if (!keyword) {
  49 + res.end('Invalid keyword');
  50 + return;
  51 + }
  52 +
  53 + const result = await smstoolsConfigSetter.set(keyword, value);
  54 + res.json({
  55 + dirty: !!smstoolsConfigData.dirty,
  56 + result,
  57 + });
  58 +}
  59 +
  60 +async function pageModemSet(req, res) {
  61 + if (!req.body) {
  62 + res.json({
  63 + status: 'NOT OK',
  64 + message: 'Empty body',
  65 + });
  66 + return;
  67 + }
  68 +
  69 + const modemName = (req.params.modemName || '').trim();
  70 + if (!modemName) {
  71 + res.json({
  72 + status: 'NOT OK',
  73 + message: 'Invalid modem name',
  74 + });
  75 + return;
  76 + }
  77 +
  78 + const result = await smstoolsConfigSetter.setModem(modemName, req.body);
  79 + res.json({
  80 + dirty: !!smstoolsConfigData.dirty,
  81 + result,
  82 + });
  83 +}
  84 +
  85 +async function pageModemDelete(req, res) {
  86 + const modemName = (req.params.modemName || '').trim();
  87 + if (!modemName) {
  88 + res.json({
  89 + status: 'NOT OK',
  90 + message: 'Invalid modem name',
  91 + });
  92 + return;
  93 + }
  94 +
  95 + const result = await smstoolsConfigSetter.delModem(modemName);
  96 + res.json({
  97 + dirty: !!smstoolsConfigData.dirty,
  98 + result,
  99 + });
  100 +}
  101 +
  102 +function pageInstallConfig(req, res) {
  103 + const fileToExec = `${process.cwd()}/bin/smstools-config-install`;
  104 + childProcess.execFile(fileToExec, [config.smstools_config_file], (err, stdout, stderr) => {
  105 + res.json({
  106 + err,
  107 + stdout,
  108 + stderr,
  109 + });
  110 + });
  111 +}
  112 +
  113 +router.get('/', pageIndex);
  114 +router.get('/generate', pageGenerate);
  115 +router.get('/modems', pageModemList);
  116 +
  117 +router.get('/set/:keyword', pageSet);
  118 +router.post('/modem/set/:modemName', bodyParser.json({ type: '*/json' }), pageModemSet);
  119 +router.get('/modem/delete/:modemName', pageModemDelete);
  120 +router.get('/install-config', pageInstallConfig);
lib/smstools-config/config-file.js
... ... @@ -0,0 +1 @@
  1 +module.exports = require('../../config.smstools.json');
lib/smstools-config/creator.js
... ... @@ -0,0 +1,67 @@
  1 +const path = require('path');
  2 +const moment = require('moment');
  3 +const config = require('komodo-sdk/config');
  4 +const smstoolsConfig = require('./config-file');
  5 +
  6 +function modemNames() {
  7 + const modems = [];
  8 +
  9 + // eslint-disable-next-line no-restricted-syntax
  10 + for (const [key, value] of Object.entries(smstoolsConfig.modems || {})) {
  11 + if (value && !value.disabled) modems.push(key);
  12 + }
  13 +
  14 + return modems;
  15 +}
  16 +
  17 +function modemEntries() {
  18 + const modems = modemNames();
  19 + const retval = [];
  20 +
  21 + modems.forEach((modemName) => {
  22 + const modem = smstoolsConfig.modems[modemName];
  23 +
  24 + const modemEntry = `
  25 +[${modemName}]
  26 +device = ${modem.device}
  27 +outgoing = ${modem.outgoing ? 'yes' : 'no'}
  28 + `.trim();
  29 +
  30 + retval.push(modemEntry);
  31 + });
  32 +
  33 + return retval;
  34 +}
  35 +
  36 +module.exports = () => {
  37 + const newContent = `
  38 +# Generated by komodo-center-smstools based on config timestamp ${moment(smstoolsConfig.ts).format('YYYY-MM-DD HH:mm:ss')}
  39 +# Do not edit this file manually
  40 +
  41 +devices = ${modemNames().join(',')}
  42 +logfile = ${config.smstools_logfile || config.smstools_log_file || '/var/log/smsd/smsd.log'}
  43 +loglevel = ${smstoolsConfig.loglevel || 5}
  44 +smartlogging = yes
  45 +autosplit = ${(config.smstools_autosplit !== undefined && config.smstools_autosplit !== null) ? config.smstools_autosplit : 1}
  46 +user = ${smstoolsConfig.user || 'smstools'}
  47 +group = ${smstoolsConfig.group || 'smstools'}
  48 +eventhandler = ${config.smstools_eventhandler || '/var/lib/smstools/centers/smstools/bin/smstools-eventhandler.js'}
  49 +stats_interval = ${config.smstools_stats_interval || 60}
  50 +stats = ${path.dirname(config.smstools_status_file) || '/var/log/smsd/smsd_stats'}
  51 +sent = /var/spool/sms/sent
  52 +${smstoolsConfig.customConfig || ''}
  53 +
  54 +[default]
  55 +incoming = yes
  56 +regular_run_interval = 60
  57 +regular_run_cmd = AT+CGSN
  58 +regular_run_cmd = AT+CIMI
  59 +regular_run_cmd = AT+COPS?
  60 +regular_run_statfile = /var/spool/sms/regular_run/modemname
  61 +
  62 +${modemEntries().join('\n\n')}
  63 +
  64 +# end of configuration file
  65 + `;
  66 + return `${newContent.trim()}\n`;
  67 +};
lib/smstools-config/index.js
... ... @@ -0,0 +1,14 @@
  1 +const fs = require('fs');
  2 +const logger = require('komodo-sdk/logger');
  3 +
  4 +
  5 +if (!fs.existsSync('config.smstools.json')) {
  6 + logger.info('config.smstools.json does not exists, creating it');
  7 + fs.writeFileSync('config.smstools.json', JSON.stringify({ dirty: true }, 0, 4));
  8 +}
  9 +
  10 +const smstoolsConfigData = require('./config-file');
  11 +
  12 +exports.config = smstoolsConfigData;
  13 +
  14 +logger.info('Current SMSTOOLS config', { smstoolsConfig: smstoolsConfigData });
lib/smstools-config/setter.js
... ... @@ -0,0 +1,92 @@
  1 +const fs = require('fs');
  2 +const logger = require('komodo-sdk/logger');
  3 +const smstoolsConfigData = require('./config-file');
  4 +const creator = require('./creator');
  5 +
  6 +async function writeConfig() {
  7 + const data = smstoolsConfigData;
  8 + data.ts = new Date();
  9 + const configFilename = 'config.smstools.json';
  10 + try {
  11 + await fs.promises.writeFile(configFilename, JSON.stringify(data || {}, 0, 4));
  12 + } catch (e) {
  13 + logger.warn('SMSTOOLS-CONFIG/setter: Exception on writeConfig', { filename: configFilename, e });
  14 + return e;
  15 + }
  16 +
  17 + const newSmsdConfFilename = 'smsd.conf.tmp';
  18 + const newSmsdConf = await creator();
  19 + try {
  20 + await fs.promises.writeFile(newSmsdConfFilename, newSmsdConf);
  21 + } catch (e) {
  22 + logger.warn('SMSTOOLS-CONFIG/setter: Exception on writeConfig', { filename: newSmsdConfFilename, e });
  23 + return e;
  24 + }
  25 +
  26 + return null;
  27 +}
  28 +
  29 +exports.set = async (keyword, value) => {
  30 + if (!keyword) return smstoolsConfigData;
  31 + smstoolsConfigData[keyword] = value;
  32 + smstoolsConfigData.dirty = true;
  33 + await writeConfig();
  34 + return smstoolsConfigData;
  35 +};
  36 +
  37 +function getModemByDevice(device) {
  38 + let modemName = null;
  39 + if (!device) return modemName;
  40 +
  41 + // eslint-disable-next-line no-restricted-syntax
  42 + for (const [key, value] of Object.entries(smstoolsConfigData.modems || {})) {
  43 + if (value.device === device) {
  44 + modemName = key;
  45 + }
  46 + }
  47 +
  48 + return modemName;
  49 +}
  50 +
  51 +
  52 +exports.setModem = async (modemName, data) => {
  53 + if (!modemName) return smstoolsConfigData;
  54 +
  55 + if (data.device) {
  56 + const modemWithSameDevice = getModemByDevice(data.device);
  57 + if (modemWithSameDevice && modemWithSameDevice !== modemName) {
  58 + return smstoolsConfigData;
  59 + }
  60 + }
  61 +
  62 + if (!smstoolsConfigData.modems) {
  63 + smstoolsConfigData.modems = {};
  64 + }
  65 +
  66 + if (!smstoolsConfigData.modems[modemName]) {
  67 + smstoolsConfigData.modems[modemName] = {};
  68 + }
  69 +
  70 + smstoolsConfigData.modems[modemName] = data;
  71 + smstoolsConfigData.dirty = true;
  72 + await writeConfig();
  73 + return smstoolsConfigData;
  74 +};
  75 +
  76 +
  77 +exports.delModem = async (modemName) => {
  78 + if (!modemName) return smstoolsConfigData;
  79 +
  80 + if (!smstoolsConfigData.modems) {
  81 + return smstoolsConfigData;
  82 + }
  83 +
  84 + if (!smstoolsConfigData.modems[modemName]) {
  85 + return smstoolsConfigData;
  86 + }
  87 +
  88 + delete smstoolsConfigData.modems[modemName];
  89 + smstoolsConfigData.dirty = true;
  90 + await writeConfig();
  91 + return smstoolsConfigData;
  92 +};
lib/smstools-configurator/index.js
... ... @@ -1,11 +0,0 @@
1   -const fs = require('fs');
2   -const logger = require('komodo-sdk/logger');
3   -
4   -if (!fs.existsSync('config.smstools.json')) {
5   - logger.info('config.smstools.json does not exists, creating it');
6   - fs.writeFileSync('config.smstools.json', JSON.stringify({}, 0, 4));
7   -}
8   -
9   -const smstoolsConfig = require('../../config.smstools.json');
10   -
11   -logger.info('Our SMSTOOLS config read', { smstoolsConfig });
lib/smstools-status-parsed.js
... ... @@ -7,7 +7,7 @@ const smstoolsStatus = require('./smstools-status');
7 7 const modemInfo = require('./smstools-modem-info');
8 8  
9 9 module.exports = async (statsFilename) => {
10   - const smstoolsLogfile = config.smstools_log_file || '/var/log/smsd/smsd.log';
  10 + const smstoolsLogfile = config.smstools_logfile || config.smstools_log_file || '/var/log/smsd/smsd.log';
11 11 logger.verbose('ROUTER-SMSTOOLS-STATUS-PARSED: Executing', { smstoolsLogfile });
12 12 const contents = await smstoolsStatus(statsFilename);
13 13 const contentsSplitted = (contents || '').trim().split('\n');
... ... @@ -29,6 +29,7 @@
29 29 "should": "^13.2.3"
30 30 },
31 31 "dependencies": {
  32 + "body-parser": "^1.19.0",
32 33 "express": "^4.17.1",
33 34 "get-stdin": "^7.0.0",
34 35 "komodo-center-messaging-client-lib": "git+http://gitlab.kodesumber.com/komodo/komodo-center-messaging-client-lib.git",