Commit fbea5c907f98e4ce84155312d80a9681db8d873f
1 parent
18c6f924d1
Exists in
master
api near complete
Showing 12 changed files with 315 additions and 13 deletions Side-by-side Diff
- .gitignore
- bin/smstools-config-install
- index.js
- lib/apiserver/index.js
- lib/apiserver/routers/smstools-config.js
- lib/smstools-config/config-file.js
- lib/smstools-config/creator.js
- lib/smstools-config/index.js
- lib/smstools-config/setter.js
- lib/smstools-configurator/index.js
- lib/smstools-status-parsed.js
- package.json
.gitignore
bin/smstools-config-install
index.js
... | ... | @@ -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'); |
package.json