Commit 3ec3e9eb37d6c78f5816089fc549c63f48108d6b
1 parent
56758af444
Exists in
master
HTTP command server: router-info
Showing 3 changed files with 19 additions and 1 deletions Inline Diff
lib/http-command-server/index.js
1 | 'use strict'; | 1 | 'use strict'; |
2 | 2 | ||
3 | const express = require('express'); | 3 | const express = require('express'); |
4 | 4 | ||
5 | const config = require('komodo-sdk/config'); | 5 | const config = require('komodo-sdk/config'); |
6 | const logger = require('komodo-sdk/logger'); | 6 | const logger = require('komodo-sdk/logger'); |
7 | 7 | ||
8 | const routerInfo = require('./router-info'); | ||
8 | const routerSMS = require('./router-sms'); | 9 | const routerSMS = require('./router-sms'); |
9 | 10 | ||
10 | const app = express(); | 11 | const app = express(); |
11 | 12 | ||
12 | function middlewareCustomLog(req, res, next) { | 13 | function middlewareCustomLog(req, res, next) { |
13 | logger.info('Incoming request on HTTP command server', { ip: req.ip, url: req.url }); | 14 | logger.info('Incoming request on HTTP command server', { ip: req.ip, url: req.url }); |
14 | next(); | 15 | next(); |
15 | } | 16 | } |
16 | 17 | ||
17 | function middlewareCheckApikey(req, res, next) { | 18 | function middlewareCheckApikey(req, res, next) { |
18 | if (!req.query.apikey || (req.query.apikey !== config.http_command_server.apikey)) { | 19 | if (!req.query.apikey || (req.query.apikey !== config.http_command_server.apikey)) { |
19 | res.json({ | 20 | res.json({ |
20 | status: 'NOT-OK', | 21 | status: 'NOT-OK', |
21 | error: 'INVALID_APIKEY', | 22 | error: 'INVALID_APIKEY', |
22 | message: 'Invalid apikey', | 23 | message: 'Invalid apikey', |
23 | }); | 24 | }); |
24 | } else { | 25 | } else { |
25 | next(); | 26 | next(); |
26 | } | 27 | } |
27 | } | 28 | } |
28 | 29 | ||
29 | app.use(middlewareCustomLog); | 30 | app.use(middlewareCustomLog); |
30 | app.use(middlewareCheckApikey); | 31 | app.use(middlewareCheckApikey); |
32 | |||
33 | app.use('/info', routerInfo); | ||
31 | app.use('/sms', routerSMS); | 34 | app.use('/sms', routerSMS); |
32 | 35 | ||
33 | 36 | ||
34 | app.listen(config.http_command_server.listen_port, () => { | 37 | app.listen(config.http_command_server.listen_port, () => { |
35 | logger.info(`HTTP command server listeing on port ${config.http_command_server.listen_port}`); | 38 | logger.info(`HTTP command server listeing on port ${config.http_command_server.listen_port}`); |
36 | }); | 39 | }); |
37 | 40 |
lib/http-command-server/router-info.js
File was created | 1 | 'use strict'; | |
2 | |||
3 | const express = require('express'); | ||
4 | |||
5 | const modem = require('../modem'); | ||
6 | |||
7 | const router = express.Router(); | ||
8 | module.exports = router; | ||
9 | |||
10 | function handlerMain(req, res) { | ||
11 | res.json(modem.modemInfo); | ||
12 | } | ||
13 | |||
14 | router.get('/', handlerMain); | ||
15 |
lib/modem.js
1 | 'use strict'; | 1 | 'use strict'; |
2 | 2 | ||
3 | const INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS = 60000; | 3 | const INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS = 60000; |
4 | const DELIMITER_WAIT_FOR_OK = '\nOK\r\n'; | 4 | const DELIMITER_WAIT_FOR_OK = '\nOK\r\n'; |
5 | 5 | ||
6 | const SerialPort = require('serialport'); | 6 | const SerialPort = require('serialport'); |
7 | const ParserReadline = require('@serialport/parser-readline'); | 7 | const ParserReadline = require('@serialport/parser-readline'); |
8 | const ParserDelimiter = require('@serialport/parser-delimiter'); | 8 | const ParserDelimiter = require('@serialport/parser-delimiter'); |
9 | 9 | ||
10 | const config = require('komodo-sdk/config'); | 10 | const config = require('komodo-sdk/config'); |
11 | const logger = require('komodo-sdk/logger'); | 11 | const logger = require('komodo-sdk/logger'); |
12 | 12 | ||
13 | const mutex = require('./mutex'); | 13 | const mutex = require('./mutex'); |
14 | const common = require('./common'); | 14 | const common = require('./common'); |
15 | const sms = require('./sms'); | 15 | const sms = require('./sms'); |
16 | const reportSender = require('./report-sender'); | 16 | const reportSender = require('./report-sender'); |
17 | 17 | ||
18 | const modemInfo = { | 18 | const modemInfo = { |
19 | manufacturer: null, | 19 | manufacturer: null, |
20 | model: null, | 20 | model: null, |
21 | imei: null, | ||
21 | imsi: null, | 22 | imsi: null, |
22 | signalStrength: null, | 23 | signalStrength: null, |
23 | config: config.modem, | 24 | config: config.modem, |
24 | }; | 25 | }; |
25 | 26 | ||
26 | const port = new SerialPort(config.modem.device, { baudRate: 115200 }); | 27 | const port = new SerialPort(config.modem.device, { baudRate: 115200 }); |
27 | 28 | ||
28 | const parserReadLine = new ParserReadline(); | 29 | const parserReadLine = new ParserReadline(); |
29 | const parserWaitForOK = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 30 | const parserWaitForOK = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); |
30 | port.pipe(parserReadLine); | 31 | port.pipe(parserReadLine); |
31 | 32 | ||
32 | function writeToPort(data) { | 33 | function writeToPort(data) { |
33 | return new Promise((resolve) => { | 34 | return new Promise((resolve) => { |
34 | port.write(data, (err, bytesWritten) => { | 35 | port.write(data, (err, bytesWritten) => { |
35 | if (err) logger.warn(`ERROR: ${err.toString()}`); | 36 | if (err) logger.warn(`ERROR: ${err.toString()}`); |
36 | logger.verbose(`* OUT: ${data}`); | 37 | logger.verbose(`* OUT: ${data}`); |
37 | resolve(bytesWritten); | 38 | resolve(bytesWritten); |
38 | }); | 39 | }); |
39 | }); | 40 | }); |
40 | } | 41 | } |
41 | 42 | ||
42 | async function writeToPortAndWaitForOK(data) { | 43 | async function writeToPortAndWaitForOK(data) { |
43 | await mutex.setLockWaitForOK(); | 44 | await mutex.setLockWaitForOK(); |
44 | const result = await writeToPort(data); | 45 | const result = await writeToPort(data); |
45 | await mutex.setLockWaitForOK(); | 46 | await mutex.setLockWaitForOK(); |
46 | mutex.releaseLockWaitForOK(); | 47 | mutex.releaseLockWaitForOK(); |
47 | return result; | 48 | return result; |
48 | } | 49 | } |
49 | 50 | ||
50 | async function readSMS(slot) { | 51 | async function readSMS(slot) { |
51 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 52 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); |
52 | parser.on('data', async (data) => { | 53 | parser.on('data', async (data) => { |
53 | if (data) { | 54 | if (data) { |
54 | const smsObject = sms.extract(data.toString().trim()); | 55 | const smsObject = sms.extract(data.toString().trim()); |
55 | // console.log('SMS', smsObject); // eslint-disable-line no-console | 56 | // console.log('SMS', smsObject); // eslint-disable-line no-console |
56 | reportSender.incomingSMS(smsObject); | 57 | reportSender.incomingSMS(smsObject); |
57 | } | 58 | } |
58 | mutex.releaseLockWaitForOK(); | 59 | mutex.releaseLockWaitForOK(); |
59 | }); | 60 | }); |
60 | 61 | ||
61 | logger.info(`Reading SMS on slot ${slot}`); | 62 | logger.info(`Reading SMS on slot ${slot}`); |
62 | port.pipe(parser); | 63 | port.pipe(parser); |
63 | await writeToPortAndWaitForOK(`AT+CMGR=${slot}\r`); | 64 | await writeToPortAndWaitForOK(`AT+CMGR=${slot}\r`); |
64 | port.unpipe(parser); | 65 | port.unpipe(parser); |
65 | logger.verbose(`Finished reading SMS on slot ${slot}`); | 66 | logger.verbose(`Finished reading SMS on slot ${slot}`); |
66 | 67 | ||
67 | logger.info(`Deleting message on slot ${slot}`); | 68 | logger.info(`Deleting message on slot ${slot}`); |
68 | port.pipe(parserWaitForOK); | 69 | port.pipe(parserWaitForOK); |
69 | await writeToPortAndWaitForOK(`AT+CMGD=${slot}\r`); | 70 | await writeToPortAndWaitForOK(`AT+CMGD=${slot}\r`); |
70 | port.unpipe(parserWaitForOK); | 71 | port.unpipe(parserWaitForOK); |
71 | 72 | ||
72 | logger.info('Message processing has completed'); | 73 | logger.info('Message processing has completed'); |
73 | } | 74 | } |
74 | 75 | ||
75 | function onIncomingSMS(data) { | 76 | function onIncomingSMS(data) { |
76 | const value = common.extractValueFromReadLineData(data); | 77 | const value = common.extractValueFromReadLineData(data); |
77 | if (!value) return; | 78 | if (!value) return; |
78 | 79 | ||
79 | const chunks = value.split(','); | 80 | const chunks = value.split(','); |
80 | if (!chunks && !chunks[1]) return; | 81 | if (!chunks && !chunks[1]) return; |
81 | 82 | ||
82 | const slot = chunks[1]; | 83 | const slot = chunks[1]; |
83 | 84 | ||
84 | logger.info(`Incoming SMS on slot ${slot}`); | 85 | logger.info(`Incoming SMS on slot ${slot}`); |
85 | readSMS(slot); | 86 | readSMS(slot); |
86 | } | 87 | } |
87 | 88 | ||
88 | parserReadLine.on('data', (data) => { | 89 | parserReadLine.on('data', (data) => { |
89 | logger.verbose(`* IN: ${data}`); | 90 | logger.verbose(`* IN: ${data}`); |
90 | if (data) { | 91 | if (data) { |
91 | if (data.indexOf('+CSQ: ') === 0) { | 92 | if (data.indexOf('+CSQ: ') === 0) { |
92 | modemInfo.signalStrength = common.extractValueFromReadLineData(data); | 93 | modemInfo.signalStrength = common.extractValueFromReadLineData(data).trim(); |
93 | logger.info(`Signal strength: ${modemInfo.signalStrength}`); | 94 | logger.info(`Signal strength: ${modemInfo.signalStrength}`); |
94 | } else if (data.indexOf('+CMTI: ') === 0) { | 95 | } else if (data.indexOf('+CMTI: ') === 0) { |
95 | onIncomingSMS(data); | 96 | onIncomingSMS(data); |
96 | } | 97 | } |
97 | } | 98 | } |
98 | }); | 99 | }); |
99 | 100 | ||
100 | parserWaitForOK.on('data', () => { | 101 | parserWaitForOK.on('data', () => { |
101 | mutex.releaseLockWaitForOK(); | 102 | mutex.releaseLockWaitForOK(); |
102 | }); | 103 | }); |
103 | 104 | ||
104 | function simpleCommand(cmd, callback) { | 105 | function simpleCommand(cmd, callback) { |
105 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 106 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); |
106 | parser.on('data', (data) => { | 107 | parser.on('data', (data) => { |
107 | port.unpipe(parser); | 108 | port.unpipe(parser); |
108 | mutex.releaseLockWaitForOK(); | 109 | mutex.releaseLockWaitForOK(); |
109 | 110 | ||
110 | if (data) { | 111 | if (data) { |
111 | callback(null, data.toString().trim()); | 112 | callback(null, data.toString().trim()); |
112 | } | 113 | } |
113 | }); | 114 | }); |
114 | 115 | ||
115 | port.pipe(parser); | 116 | port.pipe(parser); |
116 | writeToPortAndWaitForOK(cmd); | 117 | writeToPortAndWaitForOK(cmd); |
117 | } | 118 | } |
118 | 119 | ||
119 | function readManufacturer() { | 120 | function readManufacturer() { |
120 | return new Promise((resolve) => { | 121 | return new Promise((resolve) => { |
121 | simpleCommand('AT+CGMI\r', (err, result) => { | 122 | simpleCommand('AT+CGMI\r', (err, result) => { |
122 | modemInfo.manufacturer = result; | 123 | modemInfo.manufacturer = result; |
123 | logger.info(`Manufacturer: ${result}`); | 124 | logger.info(`Manufacturer: ${result}`); |
124 | resolve(result); | 125 | resolve(result); |
125 | }); | 126 | }); |
126 | }); | 127 | }); |
127 | } | 128 | } |
128 | 129 | ||
129 | function readModel() { | 130 | function readModel() { |
130 | return new Promise((resolve) => { | 131 | return new Promise((resolve) => { |
131 | simpleCommand('AT+CGMM\r', (err, result) => { | 132 | simpleCommand('AT+CGMM\r', (err, result) => { |
132 | modemInfo.model = result; | 133 | modemInfo.model = result; |
133 | logger.info(`Model: ${result}`); | 134 | logger.info(`Model: ${result}`); |
134 | resolve(result); | 135 | resolve(result); |
135 | }); | 136 | }); |
136 | }); | 137 | }); |
137 | } | 138 | } |
138 | 139 | ||
139 | function readIMEI() { | 140 | function readIMEI() { |
140 | return new Promise((resolve) => { | 141 | return new Promise((resolve) => { |
141 | simpleCommand('AT+CGSN\r', (err, result) => { | 142 | simpleCommand('AT+CGSN\r', (err, result) => { |
142 | modemInfo.imei = result; | 143 | modemInfo.imei = result; |
143 | logger.info(`IMEI: ${result}`); | 144 | logger.info(`IMEI: ${result}`); |
144 | resolve(result); | 145 | resolve(result); |
145 | }); | 146 | }); |
146 | }); | 147 | }); |
147 | } | 148 | } |
148 | 149 | ||
149 | function readIMSI() { | 150 | function readIMSI() { |
150 | return new Promise((resolve) => { | 151 | return new Promise((resolve) => { |
151 | simpleCommand('AT+CIMI\r', (err, result) => { | 152 | simpleCommand('AT+CIMI\r', (err, result) => { |
152 | modemInfo.imsi = result; | 153 | modemInfo.imsi = result; |
153 | logger.info(`IMSI: ${result}`); | 154 | logger.info(`IMSI: ${result}`); |
154 | resolve(result); | 155 | resolve(result); |
155 | }); | 156 | }); |
156 | }); | 157 | }); |
157 | } | 158 | } |
158 | 159 | ||
159 | async function querySignalStrength() { | 160 | async function querySignalStrength() { |
160 | port.pipe(parserWaitForOK); | 161 | port.pipe(parserWaitForOK); |
161 | await writeToPortAndWaitForOK('AT+CSQ\r'); | 162 | await writeToPortAndWaitForOK('AT+CSQ\r'); |
162 | port.unpipe(parserWaitForOK); | 163 | port.unpipe(parserWaitForOK); |
163 | } | 164 | } |
164 | 165 | ||
165 | async function registerSignalStrengthBackgroundQuery() { | 166 | async function registerSignalStrengthBackgroundQuery() { |
166 | logger.info('Registering background signal strength query'); | 167 | logger.info('Registering background signal strength query'); |
167 | 168 | ||
168 | setInterval(() => { | 169 | setInterval(() => { |
169 | querySignalStrength(); | 170 | querySignalStrength(); |
170 | }, INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); | 171 | }, INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); |
171 | } | 172 | } |
172 | 173 | ||
173 | async function sendSMS(destination, msg) { | 174 | async function sendSMS(destination, msg) { |
174 | await mutex.setLockWaitForCommand(); | 175 | await mutex.setLockWaitForCommand(); |
175 | logger.info('Sending message', { destination, msg }); | 176 | logger.info('Sending message', { destination, msg }); |
176 | 177 | ||
177 | const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); | 178 | const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); |
178 | 179 | ||
179 | port.pipe(parserWaitForOK); | 180 | port.pipe(parserWaitForOK); |
180 | await writeToPortAndWaitForOK('AT+CMGF=1\r'); | 181 | await writeToPortAndWaitForOK('AT+CMGF=1\r'); |
181 | await writeToPortAndWaitForOK(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`); | 182 | await writeToPortAndWaitForOK(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`); |
182 | port.unpipe(parserWaitForOK); | 183 | port.unpipe(parserWaitForOK); |
183 | 184 | ||
184 | logger.info('Message has been sent'); | 185 | logger.info('Message has been sent'); |
185 | 186 | ||
186 | mutex.releaseLockWaitForCommand(); | 187 | mutex.releaseLockWaitForCommand(); |
187 | } | 188 | } |
188 | 189 | ||
189 | function init() { | 190 | function init() { |
190 | port.on('open', async () => { | 191 | port.on('open', async () => { |
191 | port.pipe(parserWaitForOK); | 192 | port.pipe(parserWaitForOK); |
192 | 193 | ||
193 | logger.info('Modem opened'); | 194 | logger.info('Modem opened'); |
194 | await writeToPortAndWaitForOK('AT\r'); | 195 | await writeToPortAndWaitForOK('AT\r'); |
195 | 196 | ||
196 | logger.info('Initializing modem to factory set'); | 197 | logger.info('Initializing modem to factory set'); |
197 | await writeToPortAndWaitForOK('AT&F\r'); | 198 | await writeToPortAndWaitForOK('AT&F\r'); |
198 | 199 | ||
199 | logger.info('Disabling echo'); | 200 | logger.info('Disabling echo'); |
200 | await writeToPortAndWaitForOK('ATE0\r'); | 201 | await writeToPortAndWaitForOK('ATE0\r'); |
201 | 202 | ||
202 | logger.info('Querying signal strength'); | 203 | logger.info('Querying signal strength'); |
203 | await writeToPortAndWaitForOK('AT+CSQ\r'); | 204 | await writeToPortAndWaitForOK('AT+CSQ\r'); |
204 | 205 | ||
205 | logger.info('Deleting existing messages'); | 206 | logger.info('Deleting existing messages'); |
206 | // await writeToPortAndWaitForOK('AT+CMGD=0,4\r'); | 207 | // await writeToPortAndWaitForOK('AT+CMGD=0,4\r'); |
207 | 208 | ||
208 | await readManufacturer(); | 209 | await readManufacturer(); |
209 | await readModel(); | 210 | await readModel(); |
210 | await readIMEI(); | 211 | await readIMEI(); |
211 | await readIMSI(); | 212 | await readIMSI(); |
212 | 213 | ||
213 | port.unpipe(parserWaitForOK); | 214 | port.unpipe(parserWaitForOK); |
214 | 215 | ||
215 | registerSignalStrengthBackgroundQuery(); | 216 | registerSignalStrengthBackgroundQuery(); |
216 | logger.verbose('Init completed'); | 217 | logger.verbose('Init completed'); |
217 | }); | 218 | }); |
218 | } | 219 | } |
219 | 220 | ||
220 | init(); | 221 | init(); |
221 | 222 | ||
222 | exports.modemInfo = modemInfo; | 223 | exports.modemInfo = modemInfo; |
223 | exports.sendSMS = sendSMS; | 224 | exports.sendSMS = sendSMS; |
224 | 225 |