Commit 2a4678f67a1c6d279a2d4b343eb0cd9edd0a8242
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; |