Commit 17ea7e3e941811085455aaf01fadf0ac1271372c

Authored by Adhidarma Hadiwinoto
1 parent af2522550c
Exists in master

JSDOC

Showing 2 changed files with 13 additions and 1 deletions Inline Diff

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