Commit 2db546a87026b1d0e04ec6edef14f3bec89d267e
1 parent
0bdac2f9c6
Exists in
master
Regex parser
Showing 4 changed files with 78 additions and 33 deletions Inline Diff
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 | |||
6 | const REGEX_WAIT_FOR_OK_OR_ERROR = /\n(?:OK|ERROR)\r\n/; | ||
7 | // const REGEX_WAIT_FOR_OK_OR_ERROR = /\nOK\r\n/; | ||
5 | 8 | ||
6 | const moment = require('moment'); | 9 | const moment = require('moment'); |
7 | const SerialPort = require('serialport'); | 10 | const SerialPort = require('serialport'); |
8 | const ParserReadline = require('@serialport/parser-readline'); | 11 | const ParserReadline = require('@serialport/parser-readline'); |
9 | const ParserDelimiter = require('@serialport/parser-delimiter'); | 12 | // const ParserDelimiter = require('@serialport/parser-delimiter'); |
13 | |||
14 | const ParserRegex = require('@serialport/parser-regex'); | ||
10 | 15 | ||
11 | const config = require('komodo-sdk/config'); | 16 | const config = require('komodo-sdk/config'); |
12 | const logger = require('komodo-sdk/logger'); | 17 | const logger = require('komodo-sdk/logger'); |
13 | 18 | ||
14 | const mutex = require('./mutex'); | 19 | const mutex = require('./mutex'); |
15 | const common = require('./common'); | 20 | const common = require('./common'); |
16 | const sms = require('./sms'); | 21 | const sms = require('./sms'); |
17 | const dbCops = require('./db-cops'); | 22 | const dbCops = require('./db-cops'); |
18 | const reportSender = require('./report-sender'); | 23 | const reportSender = require('./report-sender'); |
19 | const msisdn = require('./msisdn'); | 24 | const msisdn = require('./msisdn'); |
20 | 25 | ||
21 | const modemInfo = { | 26 | const modemInfo = { |
22 | manufacturer: null, | 27 | manufacturer: null, |
23 | model: null, | 28 | model: null, |
24 | imei: null, | 29 | imei: null, |
25 | imsi: null, | 30 | imsi: null, |
26 | msisdn: null, | 31 | msisdn: null, |
27 | cops: null, | 32 | cops: null, |
28 | networkId: null, | 33 | networkId: null, |
29 | networkName: null, | 34 | networkName: null, |
30 | signalStrength: null, | 35 | signalStrength: null, |
31 | signalStrengthTs: null, | 36 | signalStrengthTs: null, |
32 | signalStrengthTsReadable: null, | 37 | signalStrengthTsReadable: null, |
33 | config: config.modem, | 38 | config: config.modem, |
34 | }; | 39 | }; |
35 | 40 | ||
36 | const port = new SerialPort(config.modem.device, { baudRate: 115200 }); | 41 | const port = new SerialPort(config.modem.device, { baudRate: 115200 }); |
37 | 42 | ||
38 | const parserReadLine = new ParserReadline(); | 43 | const parserReadLine = new ParserReadline(); |
39 | 44 | ||
40 | const parserWaitForOK = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 45 | const parserWaitForOK = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); |
41 | parserWaitForOK.on('data', () => { | 46 | parserWaitForOK.on('data', () => { |
42 | mutex.releaseLockWaitForCommand(); | 47 | mutex.releaseLockWaitForCommand(); |
43 | }); | 48 | }); |
44 | 49 | ||
45 | 50 | ||
46 | port.pipe(parserReadLine); | 51 | port.pipe(parserReadLine); |
47 | 52 | ||
48 | function writeToPort(data) { | 53 | function writeToPort(data) { |
49 | return new Promise((resolve) => { | 54 | return new Promise((resolve) => { |
50 | port.write(data, (err, bytesWritten) => { | 55 | port.write(data, (err, bytesWritten) => { |
51 | if (err) logger.warn(`ERROR: ${err.toString()}`); | 56 | if (err) logger.warn(`ERROR: ${err.toString()}`); |
52 | logger.verbose(`* OUT: ${data}`); | 57 | logger.verbose(`* OUT: ${data}`); |
53 | resolve(bytesWritten); | 58 | resolve(bytesWritten); |
54 | }); | 59 | }); |
55 | }); | 60 | }); |
56 | } | 61 | } |
57 | 62 | ||
63 | // eslint-disable-next-line no-unused-vars | ||
58 | async function writeToPortAndWaitForOK(data) { | 64 | async function writeToPortAndWaitForOK(data) { |
59 | await mutex.setLockWaitForCommand(); | 65 | await mutex.setLockWaitForCommand(); |
60 | const result = await writeToPort(data); | 66 | const result = await writeToPort(data); |
61 | 67 | ||
62 | await mutex.setLockWaitForCommand(); | 68 | await mutex.setLockWaitForCommand(); |
63 | mutex.releaseLockWaitForCommand(); | 69 | mutex.releaseLockWaitForCommand(); |
64 | 70 | ||
65 | return result; | 71 | return result; |
66 | } | 72 | } |
67 | 73 | ||
68 | async function readSMS(slot) { | 74 | async function readSMS(slot) { |
69 | const parserCMGR = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 75 | const parserCMGR = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); |
70 | parserCMGR.on('data', (data) => { | 76 | parserCMGR.on('data', (data) => { |
71 | if (data) { | 77 | if (data) { |
72 | reportSender.incomingSMS(sms.extract(data.toString().trim())); | 78 | try { |
79 | reportSender.incomingSMS(sms.extract(data.toString().trim())); | ||
80 | } catch (e) { | ||
81 | logger.warn(`Exception on reporting new message. ${e.toString()}`, { smsObj: e.smsObj, dataFromModem: data }); | ||
82 | |||
83 | process.exit(0); | ||
84 | } | ||
73 | } | 85 | } |
74 | port.unpipe(parserCMGR); | 86 | port.unpipe(parserCMGR); |
75 | mutex.releaseLockWaitForCommand(); | 87 | mutex.releaseLockWaitForCommand(); |
76 | }); | 88 | }); |
77 | 89 | ||
78 | const parserCMGD = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 90 | // const parserCMGD = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); |
91 | const parserCMGD = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); | ||
79 | parserCMGD.on('data', () => { | 92 | parserCMGD.on('data', () => { |
80 | port.unpipe(parserCMGD); | 93 | port.unpipe(parserCMGD); |
81 | mutex.releaseLockWaitForCommand(); | 94 | mutex.releaseLockWaitForCommand(); |
82 | }); | 95 | }); |
83 | 96 | ||
84 | logger.info(`Reading SMS on slot ${slot}`); | 97 | logger.info(`Reading SMS on slot ${slot}`); |
85 | await mutex.setLockWaitForCommand(); | 98 | await mutex.setLockWaitForCommand(); |
86 | port.pipe(parserCMGR); | 99 | port.pipe(parserCMGR); |
87 | await writeToPort(`AT+CMGR=${slot}\r`); | 100 | await writeToPort(`AT+CMGR=${slot}\r`); |
88 | logger.info(`Finished reading SMS on slot ${slot}`); | 101 | logger.info(`Finished reading SMS on slot ${slot}`); |
89 | 102 | ||
90 | logger.info(`Deleting message on slot ${slot}`); | 103 | logger.info(`Deleting message on slot ${slot}`); |
91 | await mutex.setLockWaitForCommand(); | 104 | await mutex.setLockWaitForCommand(); |
92 | port.pipe(parserCMGD); | 105 | port.pipe(parserCMGD); |
93 | await writeToPort(`AT+CMGD=${slot}\r`); | 106 | await writeToPort(`AT+CMGD=${slot}\r`); |
94 | logger.info('Message processing has completed'); | 107 | logger.info('Message processing has completed'); |
95 | } | 108 | } |
96 | 109 | ||
97 | function onIncomingSMS(data) { | 110 | function onIncomingSMS(data) { |
98 | const value = common.extractValueFromReadLineData(data); | 111 | const value = common.extractValueFromReadLineData(data); |
99 | if (!value) return; | 112 | if (!value) return; |
100 | 113 | ||
101 | const chunks = value.split(','); | 114 | const chunks = value.split(','); |
102 | if (!chunks && !chunks[1]) return; | 115 | if (!chunks && !chunks[1]) return; |
103 | 116 | ||
104 | const slot = chunks[1]; | 117 | const slot = chunks[1]; |
105 | 118 | ||
106 | logger.info(`Incoming SMS on slot ${slot}`); | 119 | logger.info(`Incoming SMS on slot ${slot}`); |
107 | readSMS(slot); | 120 | readSMS(slot); |
108 | } | 121 | } |
109 | 122 | ||
110 | function onCOPS(data) { | 123 | function onCOPS(data) { |
111 | modemInfo.cops = common.extractValueFromReadLineData(data).trim(); | 124 | modemInfo.cops = common.extractValueFromReadLineData(data).trim(); |
112 | logger.info(`Connected Network: ${modemInfo.cops}`); | 125 | logger.info(`Connected Network: ${modemInfo.cops}`); |
113 | 126 | ||
114 | if (!modemInfo.cops) return; | 127 | if (!modemInfo.cops) return; |
115 | 128 | ||
116 | [, , modemInfo.networkId] = modemInfo.cops.split(','); | 129 | [, , modemInfo.networkId] = modemInfo.cops.split(','); |
117 | 130 | ||
118 | if (modemInfo.networkId) { | 131 | if (modemInfo.networkId) { |
119 | modemInfo.networkName = dbCops[modemInfo.networkId]; | 132 | modemInfo.networkName = dbCops[modemInfo.networkId]; |
120 | } | 133 | } |
121 | } | 134 | } |
122 | 135 | ||
123 | parserReadLine.on('data', (data) => { | 136 | parserReadLine.on('data', (data) => { |
124 | logger.verbose(`* IN: ${data}`); | 137 | logger.verbose(`* IN: ${data}`); |
125 | if (data) { | 138 | if (data) { |
126 | if (data.indexOf('+CSQ: ') === 0) { | 139 | if (data.indexOf('+CSQ: ') === 0) { |
127 | const signalStrength = common.extractValueFromReadLineData(data).trim(); | 140 | const signalStrength = common.extractValueFromReadLineData(data).trim(); |
128 | if (signalStrength) { | 141 | if (signalStrength) { |
129 | modemInfo.signalStrength = signalStrength; | 142 | modemInfo.signalStrength = signalStrength; |
130 | modemInfo.signalStrengthTs = new Date(); | 143 | modemInfo.signalStrengthTs = new Date(); |
131 | modemInfo.signalStrengthTsReadable = moment(modemInfo.signalStrengthTs).format('YYYY-MM-DD HH:mm:ss'); | 144 | modemInfo.signalStrengthTsReadable = moment(modemInfo.signalStrengthTs).format('YYYY-MM-DD HH:mm:ss'); |
132 | logger.info(`Signal strength: ${modemInfo.signalStrength}`); | 145 | logger.info(`Signal strength: ${modemInfo.signalStrength}`); |
133 | } | 146 | } |
134 | } else if (data.indexOf('+CMTI: ') === 0) { | 147 | } else if (data.indexOf('+CMTI: ') === 0) { |
135 | onIncomingSMS(data); | 148 | onIncomingSMS(data); |
136 | } else if (data.indexOf('+COPS: ') === 0) { | 149 | } else if (data.indexOf('+COPS: ') === 0) { |
137 | onCOPS(data); | 150 | onCOPS(data); |
138 | } | 151 | } |
139 | } | 152 | } |
140 | }); | 153 | }); |
141 | 154 | ||
142 | function simpleCommand(cmd, callback) { | 155 | async function simpleSubCommand(cmd, callback) { |
143 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 156 | const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); |
144 | parser.on('data', (data) => { | 157 | parser.on('data', (data) => { |
145 | port.unpipe(parser); | 158 | port.unpipe(parser); |
146 | mutex.releaseLockWaitForCommand(); | 159 | mutex.releaseLockWaitForSubCommand(); |
147 | 160 | ||
148 | if (data) { | 161 | if (data) { |
149 | callback(null, data.toString().trim()); | 162 | if (callback) callback(null, data.toString().trim()); |
150 | } | 163 | } |
151 | }); | 164 | }); |
152 | 165 | ||
153 | port.pipe(parser); | 166 | return new Promise(async (resolve) => { |
154 | writeToPortAndWaitForOK(cmd); | 167 | await mutex.setLockWaitForSubCommand(); |
168 | port.pipe(parser); | ||
169 | writeToPort(cmd); | ||
170 | |||
171 | await mutex.setLockWaitForSubCommand(); | ||
172 | mutex.releaseLockWaitForSubCommand(); | ||
173 | |||
174 | resolve(); | ||
175 | }); | ||
155 | } | 176 | } |
156 | 177 | ||
157 | function readManufacturer() { | 178 | function readManufacturer() { |
158 | return new Promise((resolve) => { | 179 | return new Promise((resolve) => { |
159 | simpleCommand('AT+CGMI\r', (err, result) => { | 180 | simpleSubCommand('AT+CGMI\r', (err, result) => { |
160 | modemInfo.manufacturer = result; | 181 | modemInfo.manufacturer = result; |
161 | logger.info(`Manufacturer: ${result}`); | 182 | logger.info(`Manufacturer: ${result}`); |
162 | resolve(result); | 183 | resolve(result); |
163 | }); | 184 | }); |
164 | }); | 185 | }); |
165 | } | 186 | } |
166 | 187 | ||
167 | function readModel() { | 188 | function readModel() { |
168 | return new Promise((resolve) => { | 189 | return new Promise((resolve) => { |
169 | simpleCommand('AT+CGMM\r', (err, result) => { | 190 | simpleSubCommand('AT+CGMM\r', (err, result) => { |
170 | modemInfo.model = result; | 191 | modemInfo.model = result; |
171 | logger.info(`Model: ${result}`); | 192 | logger.info(`Model: ${result}`); |
172 | resolve(result); | 193 | resolve(result); |
173 | }); | 194 | }); |
174 | }); | 195 | }); |
175 | } | 196 | } |
176 | 197 | ||
177 | function readIMEI() { | 198 | function readIMEI() { |
178 | return new Promise((resolve) => { | 199 | return new Promise((resolve) => { |
179 | simpleCommand('AT+CGSN\r', (err, result) => { | 200 | simpleSubCommand('AT+CGSN\r', (err, result) => { |
180 | modemInfo.imei = result; | 201 | modemInfo.imei = result; |
181 | logger.info(`IMEI: ${result}`); | 202 | logger.info(`IMEI: ${result}`); |
182 | resolve(result); | 203 | resolve(result); |
183 | }); | 204 | }); |
184 | }); | 205 | }); |
185 | } | 206 | } |
186 | 207 | ||
187 | function readIMSI() { | 208 | function readIMSI() { |
188 | return new Promise((resolve) => { | 209 | return new Promise((resolve) => { |
189 | simpleCommand('AT+CIMI\r', (err, result) => { | 210 | simpleSubCommand('AT+CIMI\r', (err, result) => { |
190 | modemInfo.imsi = result; | 211 | modemInfo.imsi = result; |
191 | logger.info(`IMSI: ${result}`); | 212 | logger.info(`IMSI: ${result}`); |
192 | 213 | ||
193 | if (result) { | 214 | if (result) { |
194 | modemInfo.msisdn = msisdn[result]; | 215 | modemInfo.msisdn = msisdn[result]; |
195 | if (modemInfo.msisdn) { | 216 | if (modemInfo.msisdn) { |
196 | logger.info(`MSISDN: ${modemInfo.msisdn}`); | 217 | logger.info(`MSISDN: ${modemInfo.msisdn}`); |
197 | } | 218 | } |
198 | } | 219 | } |
199 | resolve(result); | 220 | resolve(result); |
200 | }); | 221 | }); |
201 | }); | 222 | }); |
202 | } | 223 | } |
203 | 224 | ||
225 | function readCOPS() { | ||
226 | return new Promise((resolve) => { | ||
227 | simpleSubCommand('AT+COPS?\r', (err, result) => { | ||
228 | resolve(result); | ||
229 | }); | ||
230 | }); | ||
231 | } | ||
232 | |||
233 | function deleteInbox() { | ||
234 | return new Promise((resolve) => { | ||
235 | simpleSubCommand('AT+CMGD=0,4\r', (err, result) => { | ||
236 | resolve(result); | ||
237 | }); | ||
238 | }); | ||
239 | } | ||
240 | |||
204 | async function querySignalStrength() { | 241 | async function querySignalStrength() { |
205 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 242 | const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); |
206 | parser.on('data', () => { | 243 | parser.on('data', () => { |
207 | port.unpipe(parser); | 244 | port.unpipe(parser); |
208 | mutex.releaseLockWaitForCommand(); | 245 | mutex.releaseLockWaitForCommand(); |
209 | }); | 246 | }); |
210 | 247 | ||
211 | if (mutex.tryLockWaitForCommand()) { | 248 | if (mutex.tryLockWaitForCommand()) { |
212 | port.pipe(parser); | 249 | port.pipe(parser); |
213 | await writeToPort('AT+CSQ\r'); | 250 | await writeToPort('AT+CSQ\r'); |
214 | } | 251 | } |
215 | } | 252 | } |
216 | 253 | ||
217 | async function registerSignalStrengthBackgroundQuery() { | 254 | async function registerSignalStrengthBackgroundQuery() { |
218 | logger.info('Registering background signal strength query'); | 255 | logger.info('Registering background signal strength query'); |
219 | 256 | ||
220 | querySignalStrength(); | 257 | querySignalStrength(); |
221 | 258 | ||
222 | setInterval(() => { | 259 | setInterval(() => { |
223 | querySignalStrength(); | 260 | querySignalStrength(); |
224 | }, config.interval_beetwen_signal_strength_ms || INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); | 261 | }, config.interval_beetwen_signal_strength_ms || INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); |
225 | } | 262 | } |
226 | 263 | ||
227 | async function sendSMS(destination, msg) { | 264 | async function sendSMS(destination, msg) { |
228 | if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return; | 265 | if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return; |
229 | 266 | ||
230 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 267 | const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); |
231 | parser.on('data', () => { | 268 | parser.on('data', () => { |
232 | port.unpipe(parser); | 269 | port.unpipe(parser); |
233 | mutex.releaseLockWaitForSubCommand(); | 270 | mutex.releaseLockWaitForSubCommand(); |
234 | }); | 271 | }); |
235 | 272 | ||
236 | logger.verbose('Waiting for command lock to send message'); | 273 | logger.verbose('Waiting for command lock to send message'); |
237 | await mutex.setLockWaitForCommand(); | 274 | await mutex.setLockWaitForCommand(); |
238 | 275 | ||
239 | logger.info('Sending message', { destination, msg }); | 276 | logger.info('Sending message', { destination, msg }); |
240 | 277 | ||
241 | const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); | 278 | const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); |
242 | 279 | ||
243 | logger.verbose('Waiting for lock before set to text mode'); | 280 | logger.verbose('Waiting for lock before set to text mode'); |
244 | await mutex.setLockWaitForSubCommand(); | 281 | await mutex.setLockWaitForSubCommand(); |
245 | port.pipe(parser); | 282 | port.pipe(parser); |
246 | await writeToPort('AT+CMGF=1\r'); | 283 | await writeToPort('AT+CMGF=1\r'); |
247 | 284 | ||
248 | logger.verbose('Waiting for lock before writing message'); | 285 | logger.verbose('Waiting for lock before writing message'); |
249 | await mutex.setLockWaitForSubCommand(); | 286 | await mutex.setLockWaitForSubCommand(); |
250 | port.pipe(parser); | 287 | port.pipe(parser); |
251 | await writeToPort(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`); | 288 | await writeToPort(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`); |
252 | 289 | ||
253 | await mutex.setLockWaitForSubCommand(); | 290 | await mutex.setLockWaitForSubCommand(); |
254 | mutex.releaseLockWaitForSubCommand(); | 291 | mutex.releaseLockWaitForSubCommand(); |
255 | 292 | ||
256 | logger.info('Message has been sent'); | 293 | logger.info('Message has been sent'); |
257 | 294 | ||
258 | setTimeout(() => { | 295 | setTimeout(() => { |
259 | logger.verbose('Releasing command lock'); | 296 | logger.verbose('Releasing command lock'); |
260 | mutex.releaseLockWaitForCommand(); | 297 | mutex.releaseLockWaitForCommand(); |
261 | }, 2000); | 298 | }, 2000); |
262 | } | 299 | } |
263 | 300 | ||
264 | function init() { | 301 | function init() { |
265 | port.on('open', async () => { | 302 | port.on('open', async () => { |
266 | // await mutex.setLockWaitForCommand(); | 303 | await mutex.setLockWaitForCommand(); |
267 | port.pipe(parserWaitForOK); | ||
268 | 304 | ||
269 | logger.info('Modem opened'); | 305 | logger.info('Modem opened'); |
270 | await writeToPortAndWaitForOK('AT\r'); | 306 | await writeToPort('\r'); |
307 | await simpleSubCommand('AT\r'); | ||
271 | 308 | ||
272 | logger.info('Initializing modem to factory set'); | 309 | logger.info('Initializing modem to factory set'); |
273 | await writeToPortAndWaitForOK('AT&F\r'); | 310 | await simpleSubCommand('AT&F\r'); |
274 | 311 | ||
275 | logger.info('Disabling echo'); | 312 | logger.info('Disabling echo'); |
276 | await writeToPortAndWaitForOK('ATE0\r'); | 313 | await simpleSubCommand('ATE0\r'); |
277 | 314 | ||
278 | await writeToPortAndWaitForOK('AT+COPS?\r'); | 315 | await readCOPS(); |
279 | 316 | ||
280 | await readManufacturer(); | 317 | await readManufacturer(); |
281 | await readModel(); | 318 | await readModel(); |
282 | await readIMEI(); | 319 | await readIMEI(); |
283 | await readIMSI(); | 320 | await readIMSI(); |
284 | 321 | ||
285 | if (!config.disable_delete_inbox_on_startup) { | 322 | if (!config.disable_delete_inbox_on_startup) { |
286 | logger.info('Deleting existing messages'); | 323 | logger.info('Deleting existing messages'); |
287 | await writeToPortAndWaitForOK('AT+CMGD=0,4\r'); | 324 | await deleteInbox(); |
288 | } | 325 | } |
289 | 326 | ||
290 | port.unpipe(parserWaitForOK); | ||
291 | |||
292 | await mutex.setLockWaitForCommand(); | ||
293 | mutex.releaseLockWaitForCommand(); | 327 | mutex.releaseLockWaitForCommand(); |
328 | logger.verbose('Init completed'); | ||
294 | 329 | ||
295 | registerSignalStrengthBackgroundQuery(); | 330 | registerSignalStrengthBackgroundQuery(); |
296 | logger.verbose('Init completed'); | ||
297 | }); | 331 | }); |
298 | } | 332 | } |
299 | 333 |
lib/mutex.js
1 | 'use strict'; | 1 | 'use strict'; |
2 | 2 | ||
3 | const locks = require('locks'); | 3 | const locks = require('locks'); |
4 | 4 | ||
5 | const mutexWaitForOK = locks.createMutex(); | 5 | const mutexWaitForOK = locks.createMutex(); |
6 | const mutexCommand = locks.createMutex(); | 6 | const mutexCommand = locks.createMutex(); |
7 | 7 | ||
8 | const mutexSubCommand = locks.createMutex(); | 8 | const mutexSubCommand = locks.createMutex(); |
9 | 9 | ||
10 | function setLockWaitForOK() { | 10 | function setLockWaitForOK() { |
11 | return new Promise((resolve) => { | 11 | return new Promise((resolve) => { |
12 | mutexWaitForOK.lock(() => { | 12 | mutexWaitForOK.lock(() => { |
13 | resolve(true); | 13 | resolve(true); |
14 | }); | 14 | }); |
15 | }); | 15 | }); |
16 | } | 16 | } |
17 | 17 | ||
18 | function releaseLockWaitForOK() { | 18 | function releaseLockWaitForOK() { |
19 | try { | 19 | try { |
20 | mutexWaitForOK.unlock(); | 20 | mutexWaitForOK.unlock(); |
21 | } catch (e) { | 21 | } catch (e) { |
22 | // | 22 | // |
23 | } | 23 | } |
24 | } | 24 | } |
25 | 25 | ||
26 | function setLockWaitForCommand() { | 26 | function setLockWaitForCommand() { |
27 | return new Promise((resolve) => { | 27 | return new Promise((resolve) => { |
28 | mutexCommand.lock(() => { | 28 | mutexCommand.lock(() => { |
29 | resolve(true); | 29 | resolve(true); |
30 | }); | 30 | }); |
31 | }); | 31 | }); |
32 | } | 32 | } |
33 | 33 | ||
34 | function tryLockWaitForCommand() { | 34 | function tryLockWaitForCommand() { |
35 | return mutexCommand.tryLock(); | 35 | return mutexCommand.tryLock(); |
36 | } | 36 | } |
37 | 37 | ||
38 | 38 | ||
39 | function releaseLockWaitForCommand() { | 39 | function releaseLockWaitForCommand() { |
40 | try { | 40 | try { |
41 | mutexCommand.unlock(); | 41 | mutexCommand.unlock(); |
42 | } catch (e) { | 42 | } catch (e) { |
43 | // | 43 | // |
44 | } | 44 | } |
45 | } | 45 | } |
46 | 46 | ||
47 | function setLockWaitForSubCommand() { | 47 | function setLockWaitForSubCommand() { |
48 | return new Promise((resolve) => { | 48 | return new Promise((resolve) => { |
49 | mutexSubCommand.lock(() => { | 49 | mutexSubCommand.lock(() => { |
50 | resolve(true); | 50 | resolve(true); |
51 | }); | 51 | }); |
52 | }); | 52 | }); |
53 | } | 53 | } |
54 | 54 | ||
55 | function releaseLockWaitForSubCommand() { | 55 | function releaseLockWaitForSubCommand() { |
56 | mutexSubCommand.unlock(); | 56 | // mutexSubCommand.unlock(); |
57 | 57 | ||
58 | /* | ||
59 | try { | 58 | try { |
60 | mutexSubCommand.unlock(); | 59 | mutexSubCommand.unlock(); |
61 | } catch (e) { | 60 | } catch (e) { |
62 | // | 61 | // |
63 | } | 62 | } |
64 | */ | ||
65 | } | 63 | } |
66 | 64 | ||
67 | exports.setLockWaitForOK = setLockWaitForOK; | 65 | exports.setLockWaitForOK = setLockWaitForOK; |
68 | exports.releaseLockWaitForOK = releaseLockWaitForOK; | 66 | exports.releaseLockWaitForOK = releaseLockWaitForOK; |
69 | 67 | ||
70 | exports.setLockWaitForCommand = setLockWaitForCommand; | 68 | exports.setLockWaitForCommand = setLockWaitForCommand; |
71 | exports.releaseLockWaitForCommand = releaseLockWaitForCommand; | 69 | exports.releaseLockWaitForCommand = releaseLockWaitForCommand; |
72 | exports.tryLockWaitForCommand = tryLockWaitForCommand; | 70 | exports.tryLockWaitForCommand = tryLockWaitForCommand; |
73 | 71 | ||
74 | exports.setLockWaitForSubCommand = setLockWaitForSubCommand; | 72 | exports.setLockWaitForSubCommand = setLockWaitForSubCommand; |
75 | exports.releaseLockWaitForSubCommand = releaseLockWaitForSubCommand; | 73 | exports.releaseLockWaitForSubCommand = releaseLockWaitForSubCommand; |
76 | 74 |
lib/report-sender.js
1 | 'use strict'; | 1 | 'use strict'; |
2 | 2 | ||
3 | const request = require('request'); | 3 | const request = require('request'); |
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 | function incomingSMS(message) { | 8 | function incomingSMS(message) { |
9 | if (!config || !config.report_url || !config.report_url.incoming_sms) return; | 9 | if (!message || !config || !config.report_url || !config.report_url.incoming_sms) return; |
10 | |||
11 | if (!message.metadata) { | ||
12 | const e = new Error('Missing metadata on incoming sms'); | ||
13 | e.smsObj = message; | ||
14 | throw e; | ||
15 | } | ||
16 | |||
17 | if (!message.message) { | ||
18 | const e = new Error('Missing message on incoming sms'); | ||
19 | e.smsObj = message; | ||
20 | throw e; | ||
21 | } | ||
10 | 22 | ||
11 | const requestOptions = { | 23 | const requestOptions = { |
12 | url: config.report_url.incoming_sms, | 24 | url: config.report_url.incoming_sms, |
13 | qs: { | 25 | qs: { |
14 | modem: config.name, | 26 | modem: config.name, |
15 | ts: message.metadata.ts, | 27 | ts: message.metadata.ts, |
16 | status: message.metadata.status, | 28 | status: message.metadata.status, |
17 | number: message.metadata.from, | 29 | number: message.metadata.from, |
18 | msg: message.message, | 30 | msg: message.message, |
19 | }, | 31 | }, |
20 | }; | 32 | }; |
21 | 33 | ||
22 | logger.info('Sending report via HTTP', requestOptions); | 34 | logger.info('Sending report via HTTP', requestOptions); |
23 | request(requestOptions, (err, res, body) => { | 35 | request(requestOptions, (err, res, body) => { |
24 | if (err) { | 36 | if (err) { |
25 | logger.warn(`Error sending report via HTTP. ${err.toString()}`); | 37 | logger.warn(`Error sending report via HTTP. ${err.toString()}`); |
26 | return; | 38 | return; |
27 | } | 39 | } |
28 | 40 | ||
29 | if (res.statusCode !== 200) { | 41 | if (res.statusCode !== 200) { |
30 | logger.warn(`Error sending report via HTTP. Server respond with HTTP status code ${res.statusCode}`, { http_status_code: res.statusCode, body }); | 42 | logger.warn(`Error sending report via HTTP. Server respond with HTTP status code ${res.statusCode}`, { http_status_code: res.statusCode, body }); |
31 | } | 43 | } |
32 | }); | 44 | }); |
33 | } | 45 | } |
34 | 46 | ||
35 | exports.incomingSMS = incomingSMS; | 47 | exports.incomingSMS = incomingSMS; |
36 | 48 |
package.json
1 | { | 1 | { |
2 | "name": "komodo-modem-sms", | 2 | "name": "komodo-modem-sms", |
3 | "version": "0.10.4", | 3 | "version": "0.10.4", |
4 | "description": "Generic SMS modem driver", | 4 | "description": "Generic SMS modem driver", |
5 | "main": "index.js", | 5 | "main": "index.js", |
6 | "scripts": { | 6 | "scripts": { |
7 | "test": "mocha", | 7 | "test": "mocha", |
8 | "postversion": "git push && git push --tags" | 8 | "postversion": "git push && git push --tags" |
9 | }, | 9 | }, |
10 | "repository": { | 10 | "repository": { |
11 | "type": "git", | 11 | "type": "git", |
12 | "url": "http://gitlab.kodesumber.com/komodo/komodo-modem-sms.git" | 12 | "url": "http://gitlab.kodesumber.com/komodo/komodo-modem-sms.git" |
13 | }, | 13 | }, |
14 | "keywords": [ | 14 | "keywords": [ |
15 | "komodo", | 15 | "komodo", |
16 | "sms", | 16 | "sms", |
17 | "tektrans", | 17 | "tektrans", |
18 | "ppob" | 18 | "ppob" |
19 | ], | 19 | ], |
20 | "author": "Adhidarma Hadiwinoto <me@adhisimon.org>", | 20 | "author": "Adhidarma Hadiwinoto <me@adhisimon.org>", |
21 | "license": "ISC", | 21 | "license": "ISC", |
22 | "devDependencies": { | 22 | "devDependencies": { |
23 | "eslint": "^5.16.0", | 23 | "eslint": "^5.16.0", |
24 | "eslint-config-airbnb-base": "^13.2.0", | 24 | "eslint-config-airbnb-base": "^13.2.0", |
25 | "eslint-plugin-import": "^2.18.2", | 25 | "eslint-plugin-import": "^2.18.2", |
26 | "should": "^13.2.3" | 26 | "should": "^13.2.3" |
27 | }, | 27 | }, |
28 | "dependencies": { | 28 | "dependencies": { |
29 | "@serialport/parser-delimiter": "^2.0.2", | 29 | "@serialport/parser-delimiter": "^2.0.2", |
30 | "@serialport/parser-readline": "^2.0.2", | 30 | "@serialport/parser-readline": "^2.0.2", |
31 | "@serialport/parser-regex": "^2.0.2", | ||
31 | "express": "^4.17.1", | 32 | "express": "^4.17.1", |
32 | "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git", | 33 | "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git", |
33 | "locks": "^0.2.2", | 34 | "locks": "^0.2.2", |
34 | "moment": "^2.24.0", | 35 | "moment": "^2.24.0", |
35 | "request": "^2.88.0", | 36 | "request": "^2.88.0", |
36 | "serialport": "^7.1.5", | 37 | "serialport": "^7.1.5", |
37 | "serialport-gsm": "^3.2.0" | 38 | "serialport-gsm": "^3.2.0" |
38 | } | 39 | } |
39 | } | 40 | } |
40 | 41 |