Commit 2a4678f67a1c6d279a2d4b343eb0cd9edd0a8242

Authored by Adhidarma Hadiwinoto
1 parent e816f09945
Exists in master

global MODEM_PORT

Showing 1 changed file with 116 additions and 30 deletions Inline Diff

lib/modem-commands/index.js
1 /** 1 /**
2 * Modul modem-commands 2 * Modul modem-commands
3 * 3 *
4 * @module 4 * @module modem-commands
5 */ 5 */
6 6
7 7
8 /**
9 * Label mutex command
10 * @static
11 */
8 const MUTEX_COMMAND = 'COMMAND'; 12 const MUTEX_COMMAND = 'COMMAND';
9 exports.MUTEX_COMMAND = MUTEX_COMMAND;
10 13
14 /**
15 * Label mutex subcommand
16 * @static
17 */
11 const MUTEX_SUBCOMMAND = 'SUBCOMMAND'; 18 const MUTEX_SUBCOMMAND = 'SUBCOMMAND';
12 exports.MUTEX_SUBCOMMAND = MUTEX_SUBCOMMAND;
13 19
14 /** 20 /**
15 * CTRL-Z string 21 * CTRL-Z string
16 * @constant 22 * @static
17 */ 23 */
18 const CTRLZ = '\u001a'; 24 const CTRLZ = '\u001a';
19 exports.CTRLZ = CTRLZ; 25
20 26
21 const pdu = require('node-pdu'); 27 const pdu = require('node-pdu');
22 const uuidv1 = require('uuid/v1'); 28 const uuidv1 = require('uuid/v1');
23 29
24 const ParserReadline = require('@serialport/parser-readline'); 30 const ParserReadline = require('@serialport/parser-readline');
25 const ParserRegex = require('@serialport/parser-regex'); 31 const ParserRegex = require('@serialport/parser-regex');
26 const ParserReady = require('@serialport/parser-ready'); 32 const ParserReady = require('@serialport/parser-ready');
27 33
28 const logger = require('komodo-sdk/logger'); 34 const logger = require('komodo-sdk/logger');
29 const mutex = require('../mutex-common'); 35 const mutex = require('../mutex-common');
30 const parsers = require('../serialport-parsers'); 36 const parsers = require('../serialport-parsers');
31 const modemInfo = require('../modem-info'); 37 const modemInfo = require('../modem-info');
32 38
33 let port; 39 // let port;
34 40
35 function writeToPort(data) { 41 function writeToPort(data) {
36 return new Promise((resolve) => { 42 return new Promise((resolve) => {
43 const port = global.MODEM_PORT;
44
37 modemInfo.lastWriteTs = new Date(); 45 modemInfo.lastWriteTs = new Date();
38 port.write(data, (err, bytesWritten) => { 46 port.write(data, (err, bytesWritten) => {
39 if (err) logger.warn(`ERROR: ${err.toString()}`); 47 if (err) logger.warn(`ERROR: ${err.toString()}`);
40 48
41 logger.verbose('OUTGOING', { data: data.toString(), bytesWritten, err }); 49 logger.verbose('OUTGOING', { data: data.toString(), bytesWritten, err });
42 resolve(bytesWritten); 50 resolve(bytesWritten);
43 }); 51 });
44 }); 52 });
45 } 53 }
46 exports.writeToPort = writeToPort;
47 54
48 function writeToPortAndWaitForReadline(cmd, lockName) { 55 function writeToPortAndWaitForReadline(cmd, lockName) {
56 const port = global.MODEM_PORT;
49 let resolved = false; 57 let resolved = false;
50 58
51 return new Promise(async (resolve) => { 59 return new Promise(async (resolve) => {
52 const parser = new ParserReadline({ delimiter: parsers.PARSER_READLINE_DELIMITER }); 60 const parser = new ParserReadline({ delimiter: parsers.PARSER_READLINE_DELIMITER });
53 parser.on('data', (data) => { 61 parser.on('data', (data) => {
54 port.unpipe(parser); 62 port.unpipe(parser);
55 mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim()); 63 mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
56 if (!resolved) { 64 if (!resolved) {
57 resolved = true; 65 resolved = true;
58 resolve(data); 66 resolve(data);
59 } 67 }
60 }); 68 });
61 69
62 await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim()); 70 await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
63 port.pipe(parser); 71 port.pipe(parser);
64 await writeToPort(cmd); 72 await writeToPort(cmd);
65 }); 73 });
66 } 74 }
67 exports.writeToPortAndWaitForReadline = writeToPortAndWaitForReadline;
68 75
69 function writeToPortAndWaitForOkOrError(cmd, lockName) { 76 function writeToPortAndWaitForOkOrError(cmd, lockName) {
70 return new Promise(async (resolve) => { 77 return new Promise(async (resolve) => {
78 const port = global.MODEM_PORT;
71 const parser = new ParserRegex({ regex: /(?:OK|ERROR)\r\n/ }); 79 const parser = new ParserRegex({ regex: /(?:OK|ERROR)\r\n/ });
80
72 parser.on('data', (data) => { 81 parser.on('data', (data) => {
73 port.unpipe(parser); 82 port.unpipe(parser);
74 mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim()); 83 mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
75 resolve(data); 84 resolve(data);
76 }); 85 });
77 86
78 await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim()); 87 await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
79 port.pipe(parser); 88 port.pipe(parser);
80 await writeToPort(cmd); 89 await writeToPort(cmd);
81 }); 90 });
82 } 91 }
83 exports.writeToPortAndWaitForOkOrError = writeToPortAndWaitForOkOrError;
84 92
93 /**
94 * Sleep async
95 * @static
96 * @param {number} ms - Milliseconds to sleep
97 * @return {Promise}
98 */
85 function sleep(ms) { 99 function sleep(ms) {
86 return new Promise((resolve) => { 100 return new Promise((resolve) => {
87 setTimeout(() => { 101 setTimeout(() => {
88 resolve(); 102 resolve();
89 }, ms || 0); 103 }, ms || 0);
90 }); 104 });
91 } 105 }
92 exports.sleep = sleep;
93 106
94 exports.setPort = function setPort(val) { 107 /**
95 port = val; 108 * Set port
96 }; 109 * @static
110 * @param {SerialPort} val
111 */
112
113 /*
114 function setPort(val) {
115 // port = val || global.MODEM_PORT;
116 }
117 */
97 118
98 function querySignalQuality() { 119 function querySignalQuality() {
99 return new Promise(async (resolve) => { 120 return new Promise(async (resolve) => {
100 if (!mutex.tryLock(MUTEX_COMMAND, 'querySignalQuality')) { 121 if (!mutex.tryLock(MUTEX_COMMAND, 'querySignalQuality')) {
101 resolve(false); 122 resolve(false);
102 return; 123 return;
103 } 124 }
104 125
105 await writeToPort('AT+CSQ\r'); 126 await writeToPort('AT+CSQ\r');
106 mutex.unlock(MUTEX_COMMAND, 'querySignalQuality'); 127 mutex.unlock(MUTEX_COMMAND, 'querySignalQuality');
107 resolve(true); 128 resolve(true);
108 }); 129 });
109 } 130 }
110 exports.querySignalQuality = querySignalQuality;
111 131
112 function queryCOPS(lockName) { 132 function queryCOPS(lockName) {
113 return new Promise(async (resolve) => { 133 return new Promise(async (resolve) => {
114 await mutex.lock(lockName || MUTEX_COMMAND, 'queryCOPS'); 134 await mutex.lock(lockName || MUTEX_COMMAND, 'queryCOPS');
115 await writeToPort('AT+COPS?\r'); 135 await writeToPort('AT+COPS?\r');
116 mutex.unlock(lockName || MUTEX_COMMAND, 'queryCOPS'); 136 mutex.unlock(lockName || MUTEX_COMMAND, 'queryCOPS');
117 resolve(true); 137 resolve(true);
118 }); 138 });
119 } 139 }
120 exports.queryCOPS = queryCOPS;
121 140
122 function queryCOPSAndSignalQuality(skipOnLocked) { 141 function queryCOPSAndSignalQuality(skipOnLocked) {
123 return new Promise(async (resolve) => { 142 return new Promise(async (resolve) => {
124 if (!skipOnLocked) { 143 if (!skipOnLocked) {
125 await mutex.lock(MUTEX_COMMAND); 144 await mutex.lock(MUTEX_COMMAND);
126 } else if (!mutex.tryLock(MUTEX_COMMAND, 'queryCOPSAndSignalQuality')) { 145 } else if (!mutex.tryLock(MUTEX_COMMAND, 'queryCOPSAndSignalQuality')) {
127 resolve(false); 146 resolve(false);
128 return; 147 return;
129 } 148 }
130 149
131 await writeToPortAndWaitForOkOrError('AT+COPS?\r', MUTEX_SUBCOMMAND); 150 await writeToPortAndWaitForOkOrError('AT+COPS?\r', MUTEX_SUBCOMMAND);
132 await writeToPortAndWaitForOkOrError('AT+CSQ\r', MUTEX_SUBCOMMAND); 151 await writeToPortAndWaitForOkOrError('AT+CSQ\r', MUTEX_SUBCOMMAND);
133 152
134 mutex.unlock(MUTEX_COMMAND, 'queryCopsAndSignalQuality'); 153 mutex.unlock(MUTEX_COMMAND, 'queryCopsAndSignalQuality');
135 resolve(true); 154 resolve(true);
136 }); 155 });
137 } 156 }
138 exports.queryCOPSAndSignalQuality = queryCOPSAndSignalQuality;
139 157
140 function queryIMEI(lockName) { 158 function queryIMEI(lockName) {
141 return new Promise(async (resolve) => { 159 return new Promise(async (resolve) => {
160 const port = global.MODEM_PORT;
142 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); 161 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
162
143 parser.on('data', (data) => { 163 parser.on('data', (data) => {
144 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMEI' }); 164 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMEI' });
145 port.unpipe(parser); 165 port.unpipe(parser);
146 mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMEI'); 166 mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMEI');
147 modemInfo.imei = data.toString().trim() || null; 167 modemInfo.imei = data.toString().trim() || null;
148 logger.info('IMEI extracted', { imei: modemInfo.imei }); 168 logger.info('IMEI extracted', { imei: modemInfo.imei });
149 resolve(modemInfo.imei); 169 resolve(modemInfo.imei);
150 }); 170 });
151 171
152 await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMEI'); 172 await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMEI');
153 173
154 port.pipe(parser); 174 port.pipe(parser);
155 await writeToPort('AT+CGSN\r'); 175 await writeToPort('AT+CGSN\r');
156 }); 176 });
157 } 177 }
158 exports.queryIMEI = queryIMEI;
159 178
160 function queryIMSI(lockName) { 179 function queryIMSI(lockName) {
161 return new Promise(async (resolve) => { 180 return new Promise(async (resolve) => {
181 const port = global.MODEM_PORT;
162 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); 182 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
183
163 parser.on('data', (data) => { 184 parser.on('data', (data) => {
164 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMSI' }); 185 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMSI' });
165 port.unpipe(parser); 186 port.unpipe(parser);
166 mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMSI'); 187 mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMSI');
167 modemInfo.imsi = data.toString().trim() || null; 188 modemInfo.imsi = data.toString().trim() || null;
168 logger.info('IMSI extracted', { imsi: modemInfo.imsi }); 189 logger.info('IMSI extracted', { imsi: modemInfo.imsi });
169 resolve(modemInfo.imsi); 190 resolve(modemInfo.imsi);
170 }); 191 });
171 192
172 await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMSI'); 193 await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMSI');
173 194
174 port.pipe(parser); 195 port.pipe(parser);
175 await writeToPort('AT+CIMI\r'); 196 await writeToPort('AT+CIMI\r');
176 }); 197 });
177 } 198 }
178 exports.queryIMSI = queryIMSI;
179 199
180 exports.queryIMEIAndIMSI = async function queryIMEIAndIMSI() { 200 async function queryIMEIAndIMSI() {
181 await mutex.lock(MUTEX_COMMAND, 'queryIMEIAndIMSI'); 201 await mutex.lock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
182 202
183 const imei = await queryIMEI(MUTEX_SUBCOMMAND); 203 const imei = await queryIMEI(MUTEX_SUBCOMMAND);
184 const imsi = await queryIMSI(MUTEX_SUBCOMMAND); 204 const imsi = await queryIMSI(MUTEX_SUBCOMMAND);
185 205
186 await mutex.unlock(MUTEX_COMMAND, 'queryIMEIAndIMSI'); 206 await mutex.unlock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
187 return { imei, imsi }; 207 return { imei, imsi };
188 }; 208 }
189 209
190 exports.queryManufacturer = function queryManufacturer(lockName) { 210 function queryManufacturer(lockName) {
191 return new Promise(async (resolve) => { 211 return new Promise(async (resolve) => {
212 const port = global.MODEM_PORT;
192 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); 213 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
214
193 parser.on('data', (data) => { 215 parser.on('data', (data) => {
194 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserManufacturer' }); 216 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserManufacturer' });
195 port.unpipe(parser); 217 port.unpipe(parser);
196 mutex.unlock(lockName || MUTEX_COMMAND, 'parserManufacturer'); 218 mutex.unlock(lockName || MUTEX_COMMAND, 'parserManufacturer');
197 modemInfo.manufacturer = data.toString().trim() || null; 219 modemInfo.manufacturer = data.toString().trim() || null;
198 logger.info('Manufacturer extracted', { manufacturer: modemInfo.manufacturer }); 220 logger.info('Manufacturer extracted', { manufacturer: modemInfo.manufacturer });
199 resolve(modemInfo.manufacturer); 221 resolve(modemInfo.manufacturer);
200 }); 222 });
201 223
202 await mutex.lock(lockName || MUTEX_COMMAND, 'queryManufacturer'); 224 await mutex.lock(lockName || MUTEX_COMMAND, 'queryManufacturer');
203 225
204 port.pipe(parser); 226 port.pipe(parser);
205 await writeToPort('AT+CGMI\r'); 227 await writeToPort('AT+CGMI\r');
206 }); 228 });
207 }; 229 }
208 230
209 exports.queryModel = function queryModel(lockName) { 231 function queryModel(lockName) {
210 return new Promise(async (resolve) => { 232 return new Promise(async (resolve) => {
233 const port = global.MODEM_PORT;
211 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); 234 const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
235
212 parser.on('data', (data) => { 236 parser.on('data', (data) => {
213 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserModel' }); 237 logger.verbose('INCOMING', { data: data.toString(), parser: 'parserModel' });
214 port.unpipe(parser); 238 port.unpipe(parser);
215 mutex.unlock(lockName || MUTEX_COMMAND, 'parserModel'); 239 mutex.unlock(lockName || MUTEX_COMMAND, 'parserModel');
216 modemInfo.model = data.toString().trim() || null; 240 modemInfo.model = data.toString().trim() || null;
217 logger.info('Model extracted', { model: modemInfo.model }); 241 logger.info('Model extracted', { model: modemInfo.model });
218 resolve(modemInfo.model); 242 resolve(modemInfo.model);
219 }); 243 });
220 244
221 await mutex.lock(lockName || MUTEX_COMMAND, 'queryModel'); 245 await mutex.lock(lockName || MUTEX_COMMAND, 'queryModel');
222 246
223 port.pipe(parser); 247 port.pipe(parser);
224 await writeToPort('AT+CGMM\r'); 248 await writeToPort('AT+CGMM\r');
225 }); 249 });
226 }; 250 }
227 251
252 /**
253 * Menulis CTRL-Z ke port.
254 * @static
255 */
228 async function sendCtrlZ() { 256 async function sendCtrlZ() {
229 await writeToPort(CTRLZ); 257 await writeToPort(CTRLZ);
230 } 258 }
231 exports.sendCtrlZ = sendCtrlZ;
232 259
233 async function initATCommands() { 260 async function initATCommands() {
234 await mutex.lock(MUTEX_COMMAND, 'INIT MODEM'); 261 await mutex.lock(MUTEX_COMMAND, 'INIT MODEM');
235 await this.writeToPortAndWaitForOkOrError(`${CTRLZ}ATE0\r`, MUTEX_SUBCOMMAND); 262 await this.writeToPortAndWaitForOkOrError(`${CTRLZ}ATE0\r`, MUTEX_SUBCOMMAND);
236 await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND); 263 await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND);
237 await this.writeToPortAndWaitForOkOrError('AT+CNMI=1,2,0,1,0\r', MUTEX_SUBCOMMAND); 264 await this.writeToPortAndWaitForOkOrError('AT+CNMI=1,2,0,1,0\r', MUTEX_SUBCOMMAND);
238 mutex.unlock(MUTEX_COMMAND, 'INIT MODEM'); 265 mutex.unlock(MUTEX_COMMAND, 'INIT MODEM');
239 } 266 }
240 exports.initATCommands = initATCommands;
241 267
268 /**
269 * Menulis awal pesan PDU.
270 *
271 * @param {number} pduLength
272 */
242 function sendCMGSPdu(pduLength) { 273 function sendCMGSPdu(pduLength) {
243 return new Promise((resolve) => { 274 return new Promise((resolve) => {
275 const port = global.MODEM_PORT;
244 const parser = new ParserReady({ delimiter: '>' }); 276 const parser = new ParserReady({ delimiter: '>' });
277
245 parser.on('data', () => { 278 parser.on('data', () => {
246 logger.verbose('Got ">" message prompt, gonna to write PDU message'); 279 logger.verbose('Got ">" message prompt, gonna to write PDU message');
247 port.unpipe(parser); 280 port.unpipe(parser);
248 mutex.unlock(MUTEX_SUBCOMMAND, 'sendSmsPduCommand'); 281 mutex.unlock(MUTEX_SUBCOMMAND, 'sendSmsPduCommand');
249 resolve(true); 282 resolve(true);
250 }); 283 });
251 284
252 mutex.lock(MUTEX_SUBCOMMAND, 'sendSmsPduCommand'); 285 mutex.lock(MUTEX_SUBCOMMAND, 'sendSmsPduCommand');
253 port.pipe(parser); 286 port.pipe(parser);
254 writeToPort(`AT+CMGS=${pduLength}\r`); 287 writeToPort(`AT+CMGS=${pduLength}\r`);
255 }); 288 });
256 } 289 }
257 290
258 exports.sendSMS = function sendSMS(destination, msg) { 291 /**
292 * Mengirim sms
293 * @param {string} destination - nomor tujuan
294 * @param {string} msg - isi pesan
295 * @return {Promise}
296 * @static
297 */
298 function sendSMS(destination, msg) {
259 return new Promise(async (resolve) => { 299 return new Promise(async (resolve) => {
260 async function responseHandler(data) { 300 async function responseHandler(data) {
261 logger.verbose('SMS sent callback called', { data }); 301 logger.verbose('SMS sent callback called', { data });
262 302
263 if (data.indexOf('ERROR') >= 0 || data.indexOf('+CMS ERROR') >= 0 || data.indexOf('+CMGS') >= 0) { 303 if (data.indexOf('ERROR') >= 0 || data.indexOf('+CMS ERROR') >= 0 || data.indexOf('+CMGS') >= 0) {
264 logger.verbose('SMS sent'); 304 logger.verbose('SMS sent');
265 parsers.setSmsSentCallback(null); 305 parsers.setSmsSentCallback(null);
266 mutex.unlock(MUTEX_COMMAND, 'sendSMS'); 306 mutex.unlock(MUTEX_COMMAND, 'sendSMS');
267 resolve(data.indexOf('ERROR') >= 0 ? null : data.toString().trim()); 307 resolve(data.indexOf('ERROR') >= 0 ? null : data.toString().trim());
268 } 308 }
269 } 309 }
270 310
271 await mutex.lock(MUTEX_COMMAND, 'sendSMS'); 311 await mutex.lock(MUTEX_COMMAND, 'sendSMS');
272 312
273 if (!destination || !destination.trim()) { 313 if (!destination || !destination.trim()) {
274 resolve(false); 314 resolve(false);
275 return; 315 return;
276 } 316 }
277 317
278 if (!msg || !msg.trim()) { 318 if (!msg || !msg.trim()) {
279 resolve(false); 319 resolve(false);
280 return; 320 return;
281 } 321 }
282 322
283 const correctedDestination = `+${destination.replace(/^0/, '62')}`.replace(/^\++/, '+'); 323 const correctedDestination = `+${destination.replace(/^0/, '62')}`.replace(/^\++/, '+');
284 logger.verbose(`Sending sms to ${correctedDestination}`, { msg }); 324 logger.verbose(`Sending sms to ${correctedDestination}`, { msg });
285 325
286 await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND); 326 await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND);
287 327
288 const submit = pdu.Submit(); 328 const submit = pdu.Submit();
289 submit.setAddress(correctedDestination); 329 submit.setAddress(correctedDestination);
290 submit.setData(msg.trim()); 330 submit.setData(msg.trim());
291 submit.getType().setSrr(0); 331 submit.getType().setSrr(0);
292 332
293 await sendCMGSPdu(Math.floor(submit.toString().length / 2) - 1); 333 await sendCMGSPdu(Math.floor(submit.toString().length / 2) - 1);
294 // await writeToPortAndWaitForOkOrError(`${submit.toString()}${CTRLZ}`, MUTEX_SUBCOMMAND); 334 // await writeToPortAndWaitForOkOrError(`${submit.toString()}${CTRLZ}`, MUTEX_SUBCOMMAND);
295 335
296 parsers.setSmsSentCallback(responseHandler); 336 parsers.setSmsSentCallback(responseHandler);
297 await writeToPort(`${submit.toString()}${CTRLZ}`, MUTEX_SUBCOMMAND); 337 await writeToPort(`${submit.toString()}${CTRLZ}`, MUTEX_SUBCOMMAND);
298 }); 338 });
299 }; 339 }
300 340
301 exports.executeUSSD = function executeUSSD(code, _includeCUSD2, _sessionId) { 341 /**
342 * Ekseksusi kode USSD.
343 * <br>
344 * <br>Pilihan includeCUSD2:
345 * <br>-1: sebelum
346 * <br>0: tidak (default)
347 * <br>1: sesudah
348 * <br>2: sebelum dan sesudah
349 *
350 * @static
351 * @param {string} code - Kode USSD
352 * @param {number} [includeCUSD2=0] - Apakah ingin otomatis memasukkan CUSD=2
353 * @return {Promise}
354 */
355 function executeUSSD(code, _includeCUSD2, _sessionId) {
302 return new Promise(async (resolve) => { 356 return new Promise(async (resolve) => {
303 const includeCUSD2 = _includeCUSD2 || 0; 357 const includeCUSD2 = _includeCUSD2 || 0;
304 const sessionId = _sessionId || uuidv1(); 358 const sessionId = _sessionId || uuidv1();
305 359
306 async function responseHandler(data) { 360 async function responseHandler(data) {
307 logger.verbose('Processing USSD response', { data }); 361 logger.verbose('Processing USSD response', { data });
308 parsers.setUssdCallback(null); 362 parsers.setUssdCallback(null);
309 363
310 if (includeCUSD2 === 1 || includeCUSD2 === 2) { 364 if (includeCUSD2 === 1 || includeCUSD2 === 2) {
311 await writeToPortAndWaitForOkOrError('AT+CUSD=2\r', MUTEX_SUBCOMMAND); 365 await writeToPortAndWaitForOkOrError('AT+CUSD=2\r', MUTEX_SUBCOMMAND);
312 } 366 }
313 367
314 mutex.unlock(MUTEX_COMMAND, `executeUSSD ${sessionId}`); 368 mutex.unlock(MUTEX_COMMAND, `executeUSSD ${sessionId}`);
315 resolve(data); 369 resolve(data);
316 } 370 }
317 371
318 mutex.lock(MUTEX_COMMAND, `executeUSSD ${sessionId}`); 372 mutex.lock(MUTEX_COMMAND, `executeUSSD ${sessionId}`);
319 parsers.setUssdCallback(responseHandler); 373 parsers.setUssdCallback(responseHandler);
320 374
321 await this.writeToPortAndWaitForOkOrError(`${CTRLZ}AT+CMGF=0\r`, MUTEX_SUBCOMMAND); 375 await this.writeToPortAndWaitForOkOrError(`${CTRLZ}AT+CMGF=0\r`, MUTEX_SUBCOMMAND);
322 376
323 if (includeCUSD2 === -1 || includeCUSD2 === 2) { 377 if (includeCUSD2 === -1 || includeCUSD2 === 2) {
324 await this.writeToPortAndWaitForOkOrError('AT+CUSD=2\r', MUTEX_SUBCOMMAND); 378 await this.writeToPortAndWaitForOkOrError('AT+CUSD=2\r', MUTEX_SUBCOMMAND);
325 } 379 }
326 380
327 await writeToPort(`AT+CUSD=1,"${code}",15\r`, MUTEX_SUBCOMMAND); 381 await writeToPort(`AT+CUSD=1,"${code}",15\r`, MUTEX_SUBCOMMAND);
328 }); 382 });
329 }; 383 }
384
385 exports.MUTEX_COMMAND = MUTEX_COMMAND;
386 exports.MUTEX_SUBCOMMAND = MUTEX_SUBCOMMAND;
387 exports.CTRLZ = CTRLZ;
388
389 /**
390 * Modem info.
391 * @type {object}
392 */
393 exports.modemInfo = modemInfo;
394 // exports.setPort = setPort;
395
396 exports.writeToPort = writeToPort;
397 exports.writeToPortAndWaitForReadline = writeToPortAndWaitForReadline;
398 exports.writeToPortAndWaitForOkOrError = writeToPortAndWaitForOkOrError;
399 exports.sleep = sleep;
400
401 exports.querySignalQuality = querySignalQuality;
402 exports.queryCOPS = queryCOPS;
403 exports.queryCOPSAndSignalQuality = queryCOPSAndSignalQuality;