Commit c07bd35b3dd6f91711e0d03a8022ba06892a3cf9

Authored by Adhidarma Hadiwinoto
1 parent 4e48bc12ef
Exists in master

Penanganan respon USSD OK duluan dan belakangan

Showing 1 changed file with 4 additions and 0 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 parser.on('data', () => { 276 parser.on('data', () => {
277 port.unpipe(parser); 277 port.unpipe(parser);
278 mutex.releaseLockWaitForSubCommand(); 278 mutex.releaseLockWaitForSubCommand();
279 }); 279 });
280 280
281 logger.verbose('Waiting for command lock to send message'); 281 logger.verbose('Waiting for command lock to send message');
282 await mutex.setLockWaitForCommand(); 282 await mutex.setLockWaitForCommand();
283 283
284 logger.info('Sending message', { destination, msg }); 284 logger.info('Sending message', { destination, msg });
285 // counters.increment('MESSAGE_SENT', modemInfo); 285 // counters.increment('MESSAGE_SENT', modemInfo);
286 286
287 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); 287 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+');
288 288
289 logger.verbose('Waiting for lock before set to text mode'); 289 logger.verbose('Waiting for lock before set to text mode');
290 await mutex.setLockWaitForSubCommand(); 290 await mutex.setLockWaitForSubCommand();
291 port.pipe(parser); 291 port.pipe(parser);
292 await writeToPort('AT+CMGF=1\r'); 292 await writeToPort('AT+CMGF=1\r');
293 293
294 logger.verbose('Waiting for lock before writing message'); 294 logger.verbose('Waiting for lock before writing message');
295 await mutex.setLockWaitForSubCommand(); 295 await mutex.setLockWaitForSubCommand();
296 port.pipe(parser); 296 port.pipe(parser);
297 await writeToPort(`AT+CMGS="${correctedDestination}"\r${msg}${Buffer.from([0x1A])}`); 297 await writeToPort(`AT+CMGS="${correctedDestination}"\r${msg}${Buffer.from([0x1A])}`);
298 298
299 await mutex.setLockWaitForSubCommand(); 299 await mutex.setLockWaitForSubCommand();
300 mutex.releaseLockWaitForSubCommand(); 300 mutex.releaseLockWaitForSubCommand();
301 301
302 logger.info('Message has been sent'); 302 logger.info('Message has been sent');
303 303
304 setTimeout(() => { 304 setTimeout(() => {
305 logger.verbose('Releasing command lock'); 305 logger.verbose('Releasing command lock');
306 mutex.releaseLockWaitForCommand(); 306 mutex.releaseLockWaitForCommand();
307 }, config.wait_for_release_lock_wait_for_command_ms || 2000); 307 }, config.wait_for_release_lock_wait_for_command_ms || 2000);
308 } 308 }
309 309
310 /** 310 /**
311 * Ekseksusi kode USSD. 311 * Ekseksusi kode USSD.
312 * 312 *
313 * Pilihan includeCUSD2: 313 * Pilihan includeCUSD2:
314 * -1: sebelum 314 * -1: sebelum
315 * 0: tidak (default) 315 * 0: tidak (default)
316 * 1: sesudah 316 * 1: sesudah
317 * 2: sebelum dan sesudah 317 * 2: sebelum dan sesudah
318 * 318 *
319 * @param {string} code - Kode USSD 319 * @param {string} code - Kode USSD
320 * @param {number} [includeCUSD2=0] - Apakah ingin otomatis memasukkan CUSD=2 320 * @param {number} [includeCUSD2=0] - Apakah ingin otomatis memasukkan CUSD=2
321 */ 321 */
322 function executeUSSD(code, includeCUSD2) { 322 function executeUSSD(code, includeCUSD2) {
323 return new Promise(async (resolve) => { 323 return new Promise(async (resolve) => {
324 const parserMain = new ParserReadline({ delimiter: '\r\n' }); 324 const parserMain = new ParserReadline({ delimiter: '\r\n' });
325 // const parserMain = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 325 // const parserMain = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
326 parserMain.on('data', (data) => { 326 parserMain.on('data', (data) => {
327 if (!data || !data.toString().trim()) return;
328
329 if (data.toString().trim() === 'OK') return;
330
327 port.unpipe(parserMain); 331 port.unpipe(parserMain);
328 mutex.releaseLockWaitForSubCommand(); 332 mutex.releaseLockWaitForSubCommand();
329 resolve(data); 333 resolve(data);
330 }); 334 });
331 335
332 const parserCUSD2 = new ParserReadline({ delimiter: '\r\n' }); 336 const parserCUSD2 = new ParserReadline({ delimiter: '\r\n' });
333 // const parserCUSD2 = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 337 // const parserCUSD2 = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
334 parserCUSD2.on('data', () => { 338 parserCUSD2.on('data', () => {
335 port.unpipe(parserCUSD2); 339 port.unpipe(parserCUSD2);
336 mutex.releaseLockWaitForSubCommand(); 340 mutex.releaseLockWaitForSubCommand();
337 }); 341 });
338 342
339 logger.verbose('Waiting for command lock to execute USSD'); 343 logger.verbose('Waiting for command lock to execute USSD');
340 await mutex.setLockWaitForCommand(); 344 await mutex.setLockWaitForCommand();
341 345
342 if (includeCUSD2 === -1 || includeCUSD2 === 2) { 346 if (includeCUSD2 === -1 || includeCUSD2 === 2) {
343 await mutex.setLockWaitForSubCommand(); 347 await mutex.setLockWaitForSubCommand();
344 logger.info('Terminating existing USSD session'); 348 logger.info('Terminating existing USSD session');
345 port.pipe(parserCUSD2); 349 port.pipe(parserCUSD2);
346 await writeToPort('AT+CUSD=2\r'); 350 await writeToPort('AT+CUSD=2\r');
347 } 351 }
348 352
349 await mutex.setLockWaitForSubCommand(); 353 await mutex.setLockWaitForSubCommand();
350 logger.info(`Executing USSD code "${code}"`); 354 logger.info(`Executing USSD code "${code}"`);
351 port.pipe(parserMain); 355 port.pipe(parserMain);
352 await writeToPort(`AT+CUSD=1,"${code}",15\r`); 356 await writeToPort(`AT+CUSD=1,"${code}",15\r`);
353 357
354 if (includeCUSD2 === 1 || includeCUSD2 === 2) { 358 if (includeCUSD2 === 1 || includeCUSD2 === 2) {
355 await mutex.setLockWaitForSubCommand(); 359 await mutex.setLockWaitForSubCommand();
356 logger.info('Terminating existing USSD session'); 360 logger.info('Terminating existing USSD session');
357 port.pipe(parserCUSD2); 361 port.pipe(parserCUSD2);
358 await writeToPort('AT+CUSD=2\r'); 362 await writeToPort('AT+CUSD=2\r');
359 } 363 }
360 364
361 await mutex.setLockWaitForSubCommand(); 365 await mutex.setLockWaitForSubCommand();
362 mutex.releaseLockWaitForSubCommand(); 366 mutex.releaseLockWaitForSubCommand();
363 367
364 mutex.releaseLockWaitForCommand(); 368 mutex.releaseLockWaitForCommand();
365 }); 369 });
366 } 370 }
367 371
368 function init() { 372 function init() {
369 port = new SerialPort(config.modem.device, { baudRate: 115200 }, (err) => { 373 port = new SerialPort(config.modem.device, { baudRate: 115200 }, (err) => {
370 if (err) { 374 if (err) {
371 logger.warn(`Error opening modem. ${err}. Terminating modem ${config.modem.device}.`); 375 logger.warn(`Error opening modem. ${err}. Terminating modem ${config.modem.device}.`);
372 process.exit(1); 376 process.exit(1);
373 } 377 }
374 378
375 registerModem(modemInfo); 379 registerModem(modemInfo);
376 }); 380 });
377 port.pipe(parserReadLine); 381 port.pipe(parserReadLine);
378 382
379 setInterval(() => { 383 setInterval(() => {
380 if ((new Date() - lastTs) > MAX_LAST_DATA_AGE_MS) { 384 if ((new Date() - lastTs) > MAX_LAST_DATA_AGE_MS) {
381 logger.warn(`No data for more than ${MAX_LAST_DATA_AGE_MS} ms. Modem might be unresponsive. Terminating modem ${config.modem.device}.`); 385 logger.warn(`No data for more than ${MAX_LAST_DATA_AGE_MS} ms. Modem might be unresponsive. Terminating modem ${config.modem.device}.`);
382 process.exit(0); 386 process.exit(0);
383 } 387 }
384 }, 30 * 1000); 388 }, 30 * 1000);
385 389
386 port.on('open', async () => { 390 port.on('open', async () => {
387 await mutex.setLockWaitForCommand(); 391 await mutex.setLockWaitForCommand();
388 392
389 logger.info('Modem opened'); 393 logger.info('Modem opened');
390 await writeToPort('\r'); 394 await writeToPort('\r');
391 await simpleSubCommand('AT\r'); 395 await simpleSubCommand('AT\r');
392 396
393 logger.info('Initializing modem to factory set'); 397 logger.info('Initializing modem to factory set');
394 await simpleSubCommand('AT&F\r'); 398 await simpleSubCommand('AT&F\r');
395 399
396 logger.info('Disabling echo'); 400 logger.info('Disabling echo');
397 await simpleSubCommand('ATE0\r'); 401 await simpleSubCommand('ATE0\r');
398 402
399 logger.info('Set to text mode'); 403 logger.info('Set to text mode');
400 await simpleSubCommand('AT+CMGF=1\r'); 404 await simpleSubCommand('AT+CMGF=1\r');
401 405
402 await readCOPS(); 406 await readCOPS();
403 407
404 await readManufacturer(); 408 await readManufacturer();
405 await readModel(); 409 await readModel();
406 await readIMEI(); 410 await readIMEI();
407 await readIMSI(); 411 await readIMSI();
408 412
409 if (!config.disable_delete_inbox_on_startup) { 413 if (!config.disable_delete_inbox_on_startup) {
410 logger.info('Deleting existing messages'); 414 logger.info('Deleting existing messages');
411 await deleteInbox(); 415 await deleteInbox();
412 } 416 }
413 417
414 mutex.releaseLockWaitForCommand(); 418 mutex.releaseLockWaitForCommand();
415 logger.verbose('Init completed'); 419 logger.verbose('Init completed');
416 420
417 registerModemToCenterPeriodically(); 421 registerModemToCenterPeriodically();
418 registerSignalStrengthBackgroundQuery(); 422 registerSignalStrengthBackgroundQuery();
419 }); 423 });
420 } 424 }
421 425
422 init(); 426 init();
423 427
424 exports.modemInfo = modemInfo; 428 exports.modemInfo = modemInfo;
425 exports.sendSMS = sendSMS; 429 exports.sendSMS = sendSMS;
426 exports.executeUSSD = executeUSSD; 430 exports.executeUSSD = executeUSSD;
427 431