Commit 063b2ec2fa1b965442f614c5dc114196c3bc9fea

Authored by Adhidarma Hadiwinoto
1 parent 16210aa33e
Exists in master

Split write sm

Showing 1 changed file with 3 additions and 1 deletions Inline Diff

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 MAX_LAST_DATA_AGE_MS = 3 * 60 * 1000; 4 const MAX_LAST_DATA_AGE_MS = 3 * 60 * 1000;
5 const REGEX_WAIT_FOR_OK_OR_ERROR = /\n(?:OK|ERROR)\r/; 5 const REGEX_WAIT_FOR_OK_OR_ERROR = /\n(?:OK|ERROR)\r/;
6 // const REGEX_WAIT_FOR_OK_OR_ERROR_USSD = /\n(?:OK|ERROR)\r/; 6 // const REGEX_WAIT_FOR_OK_OR_ERROR_USSD = /\n(?:OK|ERROR)\r/;
7 7
8 const moment = require('moment'); 8 const moment = require('moment');
9 const SerialPort = require('serialport'); 9 const SerialPort = require('serialport');
10 const ParserReadline = require('@serialport/parser-readline'); 10 const ParserReadline = require('@serialport/parser-readline');
11 // const ParserDelimiter = require('@serialport/parser-delimiter'); 11 // const ParserDelimiter = require('@serialport/parser-delimiter');
12 12
13 const ParserRegex = require('@serialport/parser-regex'); 13 const ParserRegex = require('@serialport/parser-regex');
14 14
15 const config = require('komodo-sdk/config'); 15 const config = require('komodo-sdk/config');
16 const logger = require('komodo-sdk/logger'); 16 const logger = require('komodo-sdk/logger');
17 17
18 const mutex = require('./mutex'); 18 const mutex = require('./mutex');
19 const common = require('./common'); 19 const common = require('./common');
20 const sms = require('./sms'); 20 const sms = require('./sms');
21 const dbCops = require('./db-cops'); 21 const dbCops = require('./db-cops');
22 const reportSender = require('./report-sender'); 22 const reportSender = require('./report-sender');
23 // const msisdn = require('./msisdn'); 23 // const msisdn = require('./msisdn');
24 const registerModem = require('./register-modem'); 24 const registerModem = require('./register-modem');
25 // const counters = require('./counters'); 25 // const counters = require('./counters');
26 26
27 const modemInfo = { 27 const modemInfo = {
28 device: config.modem.device, 28 device: config.modem.device,
29 manufacturer: null, 29 manufacturer: null,
30 model: null, 30 model: null,
31 imei: null, 31 imei: null,
32 imsi: null, 32 imsi: null,
33 msisdn: null, 33 msisdn: null,
34 cops: null, 34 cops: null,
35 networkId: null, 35 networkId: null,
36 networkName: null, 36 networkName: null,
37 signalStrength: null, 37 signalStrength: null,
38 signalStrengthTs: null, 38 signalStrengthTs: null,
39 signalStrengthTsReadable: null, 39 signalStrengthTsReadable: null,
40 // messageSentCounter: null, 40 // messageSentCounter: null,
41 // messageReceivedCounter: null, 41 // messageReceivedCounter: null,
42 }; 42 };
43 43
44 let lastTs = new Date(); 44 let lastTs = new Date();
45 45
46 let port; 46 let port;
47 47
48 const parserReadLine = new ParserReadline(); 48 const parserReadLine = new ParserReadline();
49 49
50 const parserWaitForOK = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 50 const parserWaitForOK = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
51 parserWaitForOK.on('data', () => { 51 parserWaitForOK.on('data', () => {
52 mutex.releaseLockWaitForCommand(); 52 mutex.releaseLockWaitForCommand();
53 }); 53 });
54 54
55 function writeToPort(data) { 55 function writeToPort(data) {
56 return new Promise((resolve) => { 56 return new Promise((resolve) => {
57 port.write(data, (err, bytesWritten) => { 57 port.write(data, (err, bytesWritten) => {
58 if (err) logger.warn(`ERROR: ${err.toString()}`); 58 if (err) logger.warn(`ERROR: ${err.toString()}`);
59 logger.verbose(`* OUT: ${data}`); 59 logger.verbose(`* OUT: ${data}`);
60 resolve(bytesWritten); 60 resolve(bytesWritten);
61 }); 61 });
62 }); 62 });
63 } 63 }
64 64
65 async function readSMS(slot) { 65 async function readSMS(slot) {
66 const parserCMGR = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 66 const parserCMGR = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
67 parserCMGR.on('data', (data) => { 67 parserCMGR.on('data', (data) => {
68 if (data) { 68 if (data) {
69 try { 69 try {
70 reportSender.incomingSMS(sms.extract(data.toString().trim()), modemInfo); 70 reportSender.incomingSMS(sms.extract(data.toString().trim()), modemInfo);
71 } catch (e) { 71 } catch (e) {
72 logger.warn(`Exception on reporting new message. ${e.toString()}`, { smsObj: e.smsObj, dataFromModem: data }); 72 logger.warn(`Exception on reporting new message. ${e.toString()}`, { smsObj: e.smsObj, dataFromModem: data });
73 73
74 process.exit(0); 74 process.exit(0);
75 } 75 }
76 } 76 }
77 port.unpipe(parserCMGR); 77 port.unpipe(parserCMGR);
78 mutex.releaseLockWaitForCommand(); 78 mutex.releaseLockWaitForCommand();
79 }); 79 });
80 80
81 // const parserCMGD = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); 81 // const parserCMGD = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK });
82 const parserCMGD = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 82 const parserCMGD = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
83 parserCMGD.on('data', () => { 83 parserCMGD.on('data', () => {
84 port.unpipe(parserCMGD); 84 port.unpipe(parserCMGD);
85 mutex.releaseLockWaitForCommand(); 85 mutex.releaseLockWaitForCommand();
86 }); 86 });
87 87
88 logger.info(`Reading SMS on slot ${slot}`); 88 logger.info(`Reading SMS on slot ${slot}`);
89 await mutex.setLockWaitForCommand(); 89 await mutex.setLockWaitForCommand();
90 port.pipe(parserCMGR); 90 port.pipe(parserCMGR);
91 await writeToPort(`AT+CMGR=${slot}\r`); 91 await writeToPort(`AT+CMGR=${slot}\r`);
92 logger.info(`Finished reading SMS on slot ${slot}`); 92 logger.info(`Finished reading SMS on slot ${slot}`);
93 93
94 logger.info(`Deleting message on slot ${slot}`); 94 logger.info(`Deleting message on slot ${slot}`);
95 await mutex.setLockWaitForCommand(); 95 await mutex.setLockWaitForCommand();
96 port.pipe(parserCMGD); 96 port.pipe(parserCMGD);
97 await writeToPort(`AT+CMGD=${slot}\r`); 97 await writeToPort(`AT+CMGD=${slot}\r`);
98 logger.info('Message processing has completed'); 98 logger.info('Message processing has completed');
99 } 99 }
100 100
101 function onIncomingSMS(data) { 101 function onIncomingSMS(data) {
102 const value = common.extractValueFromReadLineData(data); 102 const value = common.extractValueFromReadLineData(data);
103 if (!value) return; 103 if (!value) return;
104 104
105 const chunks = value.split(','); 105 const chunks = value.split(',');
106 if (!chunks && !chunks[1]) return; 106 if (!chunks && !chunks[1]) return;
107 107
108 const slot = chunks[1]; 108 const slot = chunks[1];
109 109
110 logger.info(`Incoming SMS on slot ${slot}`); 110 logger.info(`Incoming SMS on slot ${slot}`);
111 readSMS(slot); 111 readSMS(slot);
112 } 112 }
113 113
114 function onCOPS(data) { 114 function onCOPS(data) {
115 modemInfo.cops = common.extractValueFromReadLineData(data).trim(); 115 modemInfo.cops = common.extractValueFromReadLineData(data).trim();
116 logger.info(`Connected Network: ${modemInfo.cops}`); 116 logger.info(`Connected Network: ${modemInfo.cops}`);
117 117
118 if (!modemInfo.cops) return; 118 if (!modemInfo.cops) return;
119 119
120 [, , modemInfo.networkId] = modemInfo.cops.split(','); 120 [, , modemInfo.networkId] = modemInfo.cops.split(',');
121 121
122 if (modemInfo.networkId) { 122 if (modemInfo.networkId) {
123 modemInfo.networkName = dbCops[modemInfo.networkId] || modemInfo.networkId; 123 modemInfo.networkName = dbCops[modemInfo.networkId] || modemInfo.networkId;
124 } 124 }
125 } 125 }
126 126
127 parserReadLine.on('data', (data) => { 127 parserReadLine.on('data', (data) => {
128 logger.verbose(`* IN: ${data}`); 128 logger.verbose(`* IN: ${data}`);
129 if (data) { 129 if (data) {
130 lastTs = new Date(); 130 lastTs = new Date();
131 if (data.indexOf('+CSQ: ') === 0) { 131 if (data.indexOf('+CSQ: ') === 0) {
132 const signalStrength = common.extractValueFromReadLineData(data).trim(); 132 const signalStrength = common.extractValueFromReadLineData(data).trim();
133 if (signalStrength) { 133 if (signalStrength) {
134 modemInfo.signalStrength = signalStrength; 134 modemInfo.signalStrength = signalStrength;
135 modemInfo.signalStrengthTs = new Date(); 135 modemInfo.signalStrengthTs = new Date();
136 modemInfo.signalStrengthTsReadable = moment(modemInfo.signalStrengthTs).format('YYYY-MM-DD HH:mm:ss'); 136 modemInfo.signalStrengthTsReadable = moment(modemInfo.signalStrengthTs).format('YYYY-MM-DD HH:mm:ss');
137 logger.info(`Signal strength: ${modemInfo.signalStrength}`); 137 logger.info(`Signal strength: ${modemInfo.signalStrength}`);
138 registerModem(modemInfo); 138 registerModem(modemInfo);
139 } 139 }
140 } else if (data.indexOf('+CMTI: ') === 0) { 140 } else if (data.indexOf('+CMTI: ') === 0) {
141 // counters.increment('MESSAGE_RECEIVED', modemInfo); 141 // counters.increment('MESSAGE_RECEIVED', modemInfo);
142 onIncomingSMS(data); 142 onIncomingSMS(data);
143 } else if (data.indexOf('+COPS: ') === 0) { 143 } else if (data.indexOf('+COPS: ') === 0) {
144 onCOPS(data); 144 onCOPS(data);
145 } 145 }
146 } 146 }
147 }); 147 });
148 148
149 async function simpleSubCommand(cmd, callback) { 149 async function simpleSubCommand(cmd, callback) {
150 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 150 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
151 parser.on('data', (data) => { 151 parser.on('data', (data) => {
152 port.unpipe(parser); 152 port.unpipe(parser);
153 mutex.releaseLockWaitForSubCommand(); 153 mutex.releaseLockWaitForSubCommand();
154 154
155 if (data) { 155 if (data) {
156 if (callback) callback(null, data.toString().trim()); 156 if (callback) callback(null, data.toString().trim());
157 } 157 }
158 }); 158 });
159 159
160 return new Promise(async (resolve) => { 160 return new Promise(async (resolve) => {
161 await mutex.setLockWaitForSubCommand(); 161 await mutex.setLockWaitForSubCommand();
162 port.pipe(parser); 162 port.pipe(parser);
163 writeToPort(cmd); 163 writeToPort(cmd);
164 164
165 await mutex.setLockWaitForSubCommand(); 165 await mutex.setLockWaitForSubCommand();
166 mutex.releaseLockWaitForSubCommand(); 166 mutex.releaseLockWaitForSubCommand();
167 167
168 resolve(); 168 resolve();
169 }); 169 });
170 } 170 }
171 171
172 function readManufacturer() { 172 function readManufacturer() {
173 return new Promise((resolve) => { 173 return new Promise((resolve) => {
174 simpleSubCommand('AT+CGMI\r', (err, result) => { 174 simpleSubCommand('AT+CGMI\r', (err, result) => {
175 modemInfo.manufacturer = result; 175 modemInfo.manufacturer = result;
176 logger.info(`Manufacturer: ${result}`); 176 logger.info(`Manufacturer: ${result}`);
177 resolve(result); 177 resolve(result);
178 }); 178 });
179 }); 179 });
180 } 180 }
181 181
182 function readModel() { 182 function readModel() {
183 return new Promise((resolve) => { 183 return new Promise((resolve) => {
184 simpleSubCommand('AT+CGMM\r', (err, result) => { 184 simpleSubCommand('AT+CGMM\r', (err, result) => {
185 modemInfo.model = result; 185 modemInfo.model = result;
186 logger.info(`Model: ${result}`); 186 logger.info(`Model: ${result}`);
187 resolve(result); 187 resolve(result);
188 }); 188 });
189 }); 189 });
190 } 190 }
191 191
192 function readIMEI() { 192 function readIMEI() {
193 return new Promise((resolve) => { 193 return new Promise((resolve) => {
194 simpleSubCommand('AT+CGSN\r', (err, result) => { 194 simpleSubCommand('AT+CGSN\r', (err, result) => {
195 modemInfo.imei = result; 195 modemInfo.imei = result;
196 logger.info(`IMEI: ${result}`); 196 logger.info(`IMEI: ${result}`);
197 resolve(result); 197 resolve(result);
198 }); 198 });
199 }); 199 });
200 } 200 }
201 201
202 function readIMSI() { 202 function readIMSI() {
203 return new Promise((resolve) => { 203 return new Promise((resolve) => {
204 simpleSubCommand('AT+CIMI\r', (err, result) => { 204 simpleSubCommand('AT+CIMI\r', (err, result) => {
205 modemInfo.imsi = result; 205 modemInfo.imsi = result;
206 logger.info(`IMSI: ${result}`); 206 logger.info(`IMSI: ${result}`);
207 207
208 if (result) { 208 if (result) {
209 /* 209 /*
210 modemInfo.msisdn = msisdn[result]; 210 modemInfo.msisdn = msisdn[result];
211 if (modemInfo.msisdn) { 211 if (modemInfo.msisdn) {
212 logger.info(`MSISDN: ${modemInfo.msisdn}`); 212 logger.info(`MSISDN: ${modemInfo.msisdn}`);
213 registerModem(modemInfo); 213 registerModem(modemInfo);
214 } 214 }
215 */ 215 */
216 } else { 216 } else {
217 logger.warn(`IMSI not detected. Please insert a sim card to your modem. Terminating ${config.modem.device}.`); 217 logger.warn(`IMSI not detected. Please insert a sim card to your modem. Terminating ${config.modem.device}.`);
218 process.exit(2); 218 process.exit(2);
219 } 219 }
220 resolve(result); 220 resolve(result);
221 }); 221 });
222 }); 222 });
223 } 223 }
224 224
225 function readCOPS() { 225 function readCOPS() {
226 return new Promise((resolve) => { 226 return new Promise((resolve) => {
227 simpleSubCommand('AT+COPS?\r', (err, result) => { 227 simpleSubCommand('AT+COPS?\r', (err, result) => {
228 resolve(result); 228 resolve(result);
229 }); 229 });
230 }); 230 });
231 } 231 }
232 232
233 function deleteInbox() { 233 function deleteInbox() {
234 return new Promise((resolve) => { 234 return new Promise((resolve) => {
235 simpleSubCommand('AT+CMGD=0,4\r', (err, result) => { 235 simpleSubCommand('AT+CMGD=0,4\r', (err, result) => {
236 resolve(result); 236 resolve(result);
237 }); 237 });
238 }); 238 });
239 } 239 }
240 240
241 async function querySignalStrength() { 241 async function querySignalStrength() {
242 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 242 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
243 parser.on('data', () => { 243 parser.on('data', () => {
244 port.unpipe(parser); 244 port.unpipe(parser);
245 mutex.releaseLockWaitForCommand(); 245 mutex.releaseLockWaitForCommand();
246 }); 246 });
247 247
248 if (mutex.tryLockWaitForCommand()) { 248 if (mutex.tryLockWaitForCommand()) {
249 port.pipe(parser); 249 port.pipe(parser);
250 await writeToPort('AT+CSQ\r'); 250 await writeToPort('AT+CSQ\r');
251 } 251 }
252 } 252 }
253 253
254 function registerModemToCenterPeriodically() { 254 function registerModemToCenterPeriodically() {
255 registerModem(modemInfo); 255 registerModem(modemInfo);
256 256
257 setInterval(() => { 257 setInterval(() => {
258 registerModem(modemInfo); 258 registerModem(modemInfo);
259 }, 60 * 1000); 259 }, 60 * 1000);
260 } 260 }
261 261
262 async function registerSignalStrengthBackgroundQuery() { 262 async function registerSignalStrengthBackgroundQuery() {
263 logger.info('Registering background signal strength query'); 263 logger.info('Registering background signal strength query');
264 264
265 querySignalStrength(); 265 querySignalStrength();
266 266
267 setInterval(() => { 267 setInterval(() => {
268 querySignalStrength(); 268 querySignalStrength();
269 }, config.interval_beetwen_signal_strength_ms || INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); 269 }, config.interval_beetwen_signal_strength_ms || INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS);
270 } 270 }
271 271
272 async function sendSMS(destination, msg) { 272 async function sendSMS(destination, msg) {
273 if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return; 273 if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return;
274 274
275 // const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 275 // const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
276 const parser = new ParserReadline({ delimiter: '\r\n' }); 276 const parser = new ParserReadline({ delimiter: '\r\n' });
277 parser.on('data', () => { 277 parser.on('data', () => {
278 port.unpipe(parser); 278 port.unpipe(parser);
279 mutex.releaseLockWaitForSubCommand(); 279 mutex.releaseLockWaitForSubCommand();
280 }); 280 });
281 281
282 logger.verbose('Waiting for command lock to send message'); 282 logger.verbose('Waiting for command lock to send message');
283 await mutex.setLockWaitForCommand(); 283 await mutex.setLockWaitForCommand();
284 284
285 logger.info('Sending message', { destination, msg }); 285 logger.info('Sending message', { destination, msg });
286 // counters.increment('MESSAGE_SENT', modemInfo); 286 // counters.increment('MESSAGE_SENT', modemInfo);
287 287
288 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); 288 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+');
289 289
290 logger.verbose('Waiting for lock before set to text mode'); 290 logger.verbose('Waiting for lock before set to text mode');
291 await mutex.setLockWaitForSubCommand(); 291 await mutex.setLockWaitForSubCommand();
292 port.pipe(parser); 292 port.pipe(parser);
293 await writeToPort('AT+CMGF=1\r'); 293 await writeToPort('AT+CMGF=1\r');
294 294
295 logger.verbose('Waiting for lock before writing message'); 295 logger.verbose('Waiting for lock before writing message');
296 await mutex.setLockWaitForSubCommand(); 296 await mutex.setLockWaitForSubCommand();
297 port.pipe(parser); 297 port.pipe(parser);
298 await writeToPort(`AT+CMGS="${correctedDestination}"\r${msg}${Buffer.from([0x1A])}`); 298 await writeToPort(`AT+CMGS="${correctedDestination}"\r`);
299 await writeToPort(msg);
300 await writeToPort(Buffer.from([0x1A]));
299 301
300 await mutex.setLockWaitForSubCommand(); 302 await mutex.setLockWaitForSubCommand();
301 mutex.releaseLockWaitForSubCommand(); 303 mutex.releaseLockWaitForSubCommand();
302 304
303 logger.info('Message has been sent'); 305 logger.info('Message has been sent');
304 306
305 setTimeout(() => { 307 setTimeout(() => {
306 logger.verbose('Releasing command lock'); 308 logger.verbose('Releasing command lock');
307 mutex.releaseLockWaitForCommand(); 309 mutex.releaseLockWaitForCommand();
308 }, config.wait_for_release_lock_wait_for_command_ms || 2000); 310 }, config.wait_for_release_lock_wait_for_command_ms || 2000);
309 } 311 }
310 312
311 /** 313 /**
312 * Ekseksusi kode USSD. 314 * Ekseksusi kode USSD.
313 * 315 *
314 * Pilihan includeCUSD2: 316 * Pilihan includeCUSD2:
315 * -1: sebelum 317 * -1: sebelum
316 * 0: tidak (default) 318 * 0: tidak (default)
317 * 1: sesudah 319 * 1: sesudah
318 * 2: sebelum dan sesudah 320 * 2: sebelum dan sesudah
319 * 321 *
320 * @param {string} code - Kode USSD 322 * @param {string} code - Kode USSD
321 * @param {number} [includeCUSD2=0] - Apakah ingin otomatis memasukkan CUSD=2 323 * @param {number} [includeCUSD2=0] - Apakah ingin otomatis memasukkan CUSD=2
322 */ 324 */
323 function executeUSSD(code, includeCUSD2) { 325 function executeUSSD(code, includeCUSD2) {
324 return new Promise(async (resolve) => { 326 return new Promise(async (resolve) => {
325 const parserMain = new ParserReadline({ delimiter: '\r\n' }); 327 const parserMain = new ParserReadline({ delimiter: '\r\n' });
326 // const parserMain = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 328 // const parserMain = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
327 parserMain.on('data', (data) => { 329 parserMain.on('data', (data) => {
328 if (!data || !data.toString().trim()) return; 330 if (!data || !data.toString().trim()) return;
329 331
330 if (data.toString().trim() === 'OK') return; 332 if (data.toString().trim() === 'OK') return;
331 333
332 port.unpipe(parserMain); 334 port.unpipe(parserMain);
333 mutex.releaseLockWaitForSubCommand(); 335 mutex.releaseLockWaitForSubCommand();
334 resolve(data); 336 resolve(data);
335 }); 337 });
336 338
337 const parserCUSD2 = new ParserReadline({ delimiter: '\r\n' }); 339 const parserCUSD2 = new ParserReadline({ delimiter: '\r\n' });
338 // const parserCUSD2 = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 340 // const parserCUSD2 = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
339 parserCUSD2.on('data', () => { 341 parserCUSD2.on('data', () => {
340 port.unpipe(parserCUSD2); 342 port.unpipe(parserCUSD2);
341 mutex.releaseLockWaitForSubCommand(); 343 mutex.releaseLockWaitForSubCommand();
342 }); 344 });
343 345
344 logger.verbose('Waiting for command lock to execute USSD'); 346 logger.verbose('Waiting for command lock to execute USSD');
345 await mutex.setLockWaitForCommand(); 347 await mutex.setLockWaitForCommand();
346 348
347 if (includeCUSD2 === -1 || includeCUSD2 === 2) { 349 if (includeCUSD2 === -1 || includeCUSD2 === 2) {
348 await mutex.setLockWaitForSubCommand(); 350 await mutex.setLockWaitForSubCommand();
349 logger.info('Terminating existing USSD session'); 351 logger.info('Terminating existing USSD session');
350 port.pipe(parserCUSD2); 352 port.pipe(parserCUSD2);
351 await writeToPort('AT+CUSD=2\r'); 353 await writeToPort('AT+CUSD=2\r');
352 } 354 }
353 355
354 await mutex.setLockWaitForSubCommand(); 356 await mutex.setLockWaitForSubCommand();
355 logger.info(`Executing USSD code "${code}"`); 357 logger.info(`Executing USSD code "${code}"`);
356 port.pipe(parserMain); 358 port.pipe(parserMain);
357 await writeToPort(`AT+CUSD=1,"${code}",15\r`); 359 await writeToPort(`AT+CUSD=1,"${code}",15\r`);
358 360
359 if (includeCUSD2 === 1 || includeCUSD2 === 2) { 361 if (includeCUSD2 === 1 || includeCUSD2 === 2) {
360 await mutex.setLockWaitForSubCommand(); 362 await mutex.setLockWaitForSubCommand();
361 logger.info('Terminating existing USSD session'); 363 logger.info('Terminating existing USSD session');
362 port.pipe(parserCUSD2); 364 port.pipe(parserCUSD2);
363 await writeToPort('AT+CUSD=2\r'); 365 await writeToPort('AT+CUSD=2\r');
364 } 366 }
365 367
366 await mutex.setLockWaitForSubCommand(); 368 await mutex.setLockWaitForSubCommand();
367 mutex.releaseLockWaitForSubCommand(); 369 mutex.releaseLockWaitForSubCommand();
368 370
369 mutex.releaseLockWaitForCommand(); 371 mutex.releaseLockWaitForCommand();
370 }); 372 });
371 } 373 }
372 374
373 function init() { 375 function init() {
374 port = new SerialPort(config.modem.device, { baudRate: 115200 }, (err) => { 376 port = new SerialPort(config.modem.device, { baudRate: 115200 }, (err) => {
375 if (err) { 377 if (err) {
376 logger.warn(`Error opening modem. ${err}. Terminating modem ${config.modem.device}.`); 378 logger.warn(`Error opening modem. ${err}. Terminating modem ${config.modem.device}.`);
377 process.exit(1); 379 process.exit(1);
378 } 380 }
379 381
380 registerModem(modemInfo); 382 registerModem(modemInfo);
381 }); 383 });
382 port.pipe(parserReadLine); 384 port.pipe(parserReadLine);
383 385
384 setInterval(() => { 386 setInterval(() => {
385 if ((new Date() - lastTs) > MAX_LAST_DATA_AGE_MS) { 387 if ((new Date() - lastTs) > MAX_LAST_DATA_AGE_MS) {
386 logger.warn(`No data for more than ${MAX_LAST_DATA_AGE_MS} ms. Modem might be unresponsive. Terminating modem ${config.modem.device}.`); 388 logger.warn(`No data for more than ${MAX_LAST_DATA_AGE_MS} ms. Modem might be unresponsive. Terminating modem ${config.modem.device}.`);
387 process.exit(0); 389 process.exit(0);
388 } 390 }
389 }, 30 * 1000); 391 }, 30 * 1000);
390 392
391 port.on('open', async () => { 393 port.on('open', async () => {
392 await mutex.setLockWaitForCommand(); 394 await mutex.setLockWaitForCommand();
393 395
394 logger.info('Modem opened'); 396 logger.info('Modem opened');
395 await writeToPort('\r'); 397 await writeToPort('\r');
396 await simpleSubCommand('AT\r'); 398 await simpleSubCommand('AT\r');
397 399
398 logger.info('Initializing modem to factory set'); 400 logger.info('Initializing modem to factory set');
399 await simpleSubCommand('AT&F\r'); 401 await simpleSubCommand('AT&F\r');
400 402
401 logger.info('Disabling echo'); 403 logger.info('Disabling echo');
402 await simpleSubCommand('ATE0\r'); 404 await simpleSubCommand('ATE0\r');
403 405
404 logger.info('Set to text mode'); 406 logger.info('Set to text mode');
405 await simpleSubCommand('AT+CMGF=1\r'); 407 await simpleSubCommand('AT+CMGF=1\r');
406 408
407 logger.info('Set message indication'); 409 logger.info('Set message indication');
408 await simpleSubCommand('AT+CNMI=1,1,2,1,1\r'); 410 await simpleSubCommand('AT+CNMI=1,1,2,1,1\r');
409 411
410 await readCOPS(); 412 await readCOPS();
411 413
412 await readManufacturer(); 414 await readManufacturer();
413 await readModel(); 415 await readModel();
414 await readIMEI(); 416 await readIMEI();
415 await readIMSI(); 417 await readIMSI();
416 418
417 if (!config.disable_delete_inbox_on_startup) { 419 if (!config.disable_delete_inbox_on_startup) {
418 logger.info('Deleting existing messages'); 420 logger.info('Deleting existing messages');
419 await deleteInbox(); 421 await deleteInbox();
420 } 422 }
421 423
422 mutex.releaseLockWaitForCommand(); 424 mutex.releaseLockWaitForCommand();
423 logger.verbose('Init completed'); 425 logger.verbose('Init completed');
424 426
425 registerModemToCenterPeriodically(); 427 registerModemToCenterPeriodically();
426 registerSignalStrengthBackgroundQuery(); 428 registerSignalStrengthBackgroundQuery();
427 }); 429 });
428 } 430 }
429 431
430 init(); 432 init();
431 433
432 exports.modemInfo = modemInfo; 434 exports.modemInfo = modemInfo;
433 exports.sendSMS = sendSMS; 435 exports.sendSMS = sendSMS;
434 exports.executeUSSD = executeUSSD; 436 exports.executeUSSD = executeUSSD;
435 437