Blame view

lib/modem-commands/index.js 10.8 KB
eb83d58a7   Adhidarma Hadiwinoto   jsdoc
1
2
3
4
5
  /**
   * Modul modem-commands
   *
   * @module
   */
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
6
  const MUTEX_COMMAND = 'COMMAND';
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
7
  exports.MUTEX_COMMAND = MUTEX_COMMAND;
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
8
  const MUTEX_SUBCOMMAND = 'SUBCOMMAND';
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
9
  exports.MUTEX_SUBCOMMAND = MUTEX_SUBCOMMAND;
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
10

eb83d58a7   Adhidarma Hadiwinoto   jsdoc
11
12
13
14
  /**
   * CTRL-Z string
   * @constant
   */
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
15
  const CTRLZ = '\u001a';
e49a56032   Adhidarma Hadiwinoto   Prototype of boot...
16
  exports.CTRLZ = CTRLZ;
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
17

ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
18
  const pdu = require('node-pdu');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
19
  const uuidv1 = require('uuid/v1');
ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
20

8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
21
  const ParserReadline = require('@serialport/parser-readline');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
22
  const ParserRegex = require('@serialport/parser-regex');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
23
  const ParserReady = require('@serialport/parser-ready');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
24

e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
25
  const logger = require('komodo-sdk/logger');
ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
26
27
28
  const mutex = require('../mutex-common');
  const parsers = require('../serialport-parsers');
  const modemInfo = require('../modem-info');
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
29
30
31
32
33
  
  let port;
  
  function writeToPort(data) {
      return new Promise((resolve) => {
3522ae5bc   Adhidarma Hadiwinoto   MODEM-INFO: stuck...
34
          modemInfo.lastWriteTs = new Date();
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
35
36
          port.write(data, (err, bytesWritten) => {
              if (err) logger.warn(`ERROR: ${err.toString()}`);
9883a918f   Adhidarma Hadiwinoto   Urutan log
37
              logger.verbose('OUTGOING', { data: data.toString(), bytesWritten, err });
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
38
39
40
41
              resolve(bytesWritten);
          });
      });
  }
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
42
  exports.writeToPort = writeToPort;
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
43

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
44
  function writeToPortAndWaitForReadline(cmd, lockName) {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
45
      let resolved = false;
8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
46
47
48
      return new Promise(async (resolve) => {
          const parser = new ParserReadline({ delimiter: parsers.PARSER_READLINE_DELIMITER });
          parser.on('data', (data) => {
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
49
50
              port.unpipe(parser);
              mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
51
52
53
54
              if (!resolved) {
                  resolved = true;
                  resolve(data);
              }
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
55
56
57
58
59
60
          });
  
          await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
          port.pipe(parser);
          await writeToPort(cmd);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
61
62
  }
  exports.writeToPortAndWaitForReadline = writeToPortAndWaitForReadline;
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
63

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
64
  function writeToPortAndWaitForOkOrError(cmd, lockName) {
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
65
      return new Promise(async (resolve) => {
5b0551633   Adhidarma Hadiwinoto   Regex on writeToP...
66
67
          const parser = new ParserRegex({ regex: /(?:OK|ERROR)\r
  / });
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
68
          parser.on('data', (data) => {
8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
69
70
71
72
73
74
75
76
77
              port.unpipe(parser);
              mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
              resolve(data);
          });
  
          await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
          port.pipe(parser);
          await writeToPort(cmd);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
78
79
  }
  exports.writeToPortAndWaitForOkOrError = writeToPortAndWaitForOkOrError;
8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
80

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
81
  function sleep(ms) {
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
82
83
84
85
86
      return new Promise((resolve) => {
          setTimeout(() => {
              resolve();
          }, ms || 0);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
87
88
  }
  exports.sleep = sleep;
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
89

e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
90
91
92
  exports.setPort = function setPort(val) {
      port = val;
  };
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
93
  function querySignalQuality() {
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
94
95
96
97
98
99
100
101
102
103
      return new Promise(async (resolve) => {
          if (!mutex.tryLock(MUTEX_COMMAND, 'querySignalQuality')) {
              resolve(false);
              return;
          }
  
          await writeToPort('AT+CSQ\r');
          mutex.unlock(MUTEX_COMMAND, 'querySignalQuality');
          resolve(true);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
104
105
  }
  exports.querySignalQuality = querySignalQuality;
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
106

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
107
  function queryCOPS(lockName) {
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
108
      return new Promise(async (resolve) => {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
109
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryCOPS');
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
110
          await writeToPort('AT+COPS?\r');
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
111
112
113
          mutex.unlock(lockName || MUTEX_COMMAND, 'queryCOPS');
          resolve(true);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
114
115
  }
  exports.queryCOPS = queryCOPS;
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
116

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
117
  function queryCOPSAndSignalQuality(skipOnLocked) {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
118
      return new Promise(async (resolve) => {
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
119
120
121
          if (!skipOnLocked) {
              await mutex.lock(MUTEX_COMMAND);
          } else if (!mutex.tryLock(MUTEX_COMMAND, 'queryCOPSAndSignalQuality')) {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
122
123
124
              resolve(false);
              return;
          }
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
125
126
          await writeToPortAndWaitForOkOrError('AT+COPS?\r', MUTEX_SUBCOMMAND);
          await writeToPortAndWaitForOkOrError('AT+CSQ\r', MUTEX_SUBCOMMAND);
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
127
128
  
          mutex.unlock(MUTEX_COMMAND, 'queryCopsAndSignalQuality');
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
129
130
          resolve(true);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
131
132
  }
  exports.queryCOPSAndSignalQuality = queryCOPSAndSignalQuality;
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
133

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
134
  function queryIMEI(lockName) {
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
135
136
137
      return new Promise(async (resolve) => {
          const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
          parser.on('data', (data) => {
9883a918f   Adhidarma Hadiwinoto   Urutan log
138
              logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMEI' });
4cb2459b1   Adhidarma Hadiwinoto   queryIMEI unpipe ...
139
              port.unpipe(parser);
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
140
              mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMEI');
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
141
              modemInfo.imei = data.toString().trim() || null;
caac94e43   Adhidarma Hadiwinoto   modemInfo integrated
142
              logger.info('IMEI extracted', { imei: modemInfo.imei });
7f00b5aeb   Adhidarma Hadiwinoto   modemInfo.imei
143
              resolve(modemInfo.imei);
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
144
          });
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
145
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMEI');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
146
147
148
  
          port.pipe(parser);
          await writeToPort('AT+CGSN\r');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
149
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
150
151
  }
  exports.queryIMEI = queryIMEI;
b77537954   Adhidarma Hadiwinoto   queryIMSI
152

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
153
  function queryIMSI(lockName) {
b77537954   Adhidarma Hadiwinoto   queryIMSI
154
155
156
      return new Promise(async (resolve) => {
          const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
          parser.on('data', (data) => {
9883a918f   Adhidarma Hadiwinoto   Urutan log
157
              logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMSI' });
b77537954   Adhidarma Hadiwinoto   queryIMSI
158
              port.unpipe(parser);
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
159
              mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMSI');
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
160
              modemInfo.imsi = data.toString().trim() || null;
caac94e43   Adhidarma Hadiwinoto   modemInfo integrated
161
              logger.info('IMSI extracted', { imsi: modemInfo.imsi });
b77537954   Adhidarma Hadiwinoto   queryIMSI
162
163
              resolve(modemInfo.imsi);
          });
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
164
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMSI');
b77537954   Adhidarma Hadiwinoto   queryIMSI
165
166
167
168
  
          port.pipe(parser);
          await writeToPort('AT+CIMI\r');
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
169
170
  }
  exports.queryIMSI = queryIMSI;
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
171
172
173
  
  exports.queryIMEIAndIMSI = async function queryIMEIAndIMSI() {
      await mutex.lock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
174
175
      const imei = await queryIMEI(MUTEX_SUBCOMMAND);
      const imsi = await queryIMSI(MUTEX_SUBCOMMAND);
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
176

08d2d23e1   Adhidarma Hadiwinoto   Perbaikan mutex u...
177
      await mutex.unlock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
caac94e43   Adhidarma Hadiwinoto   modemInfo integrated
178
      return { imei, imsi };
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
179
  };
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
180

ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  exports.queryManufacturer = function queryManufacturer(lockName) {
      return new Promise(async (resolve) => {
          const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
          parser.on('data', (data) => {
              logger.verbose('INCOMING', { data: data.toString(), parser: 'parserManufacturer' });
              port.unpipe(parser);
              mutex.unlock(lockName || MUTEX_COMMAND, 'parserManufacturer');
              modemInfo.manufacturer = data.toString().trim() || null;
              logger.info('Manufacturer extracted', { manufacturer: modemInfo.manufacturer });
              resolve(modemInfo.manufacturer);
          });
  
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryManufacturer');
  
          port.pipe(parser);
          await writeToPort('AT+CGMI\r');
      });
  };
  
  exports.queryModel = function queryModel(lockName) {
      return new Promise(async (resolve) => {
          const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
          parser.on('data', (data) => {
              logger.verbose('INCOMING', { data: data.toString(), parser: 'parserModel' });
              port.unpipe(parser);
              mutex.unlock(lockName || MUTEX_COMMAND, 'parserModel');
              modemInfo.model = data.toString().trim() || null;
              logger.info('Model extracted', { model: modemInfo.model });
              resolve(modemInfo.model);
          });
  
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryModel');
  
          port.pipe(parser);
          await writeToPort('AT+CGMM\r');
      });
  };
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
218
219
220
221
  async function sendCtrlZ() {
      await writeToPort(CTRLZ);
  }
  exports.sendCtrlZ = sendCtrlZ;
ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
222

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
223
  async function initATCommands() {
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
224
      await mutex.lock(MUTEX_COMMAND, 'INIT MODEM');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
225
      await this.writeToPortAndWaitForOkOrError(`${CTRLZ}ATE0\r`, MUTEX_SUBCOMMAND);
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
226
227
228
      await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND);
      await this.writeToPortAndWaitForOkOrError('AT+CNMI=1,2,0,1,0\r', MUTEX_SUBCOMMAND);
      mutex.unlock(MUTEX_COMMAND, 'INIT MODEM');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  }
  exports.initATCommands = initATCommands;
  
  function sendCMGSPdu(pduLength) {
      return new Promise((resolve) => {
          const parser = new ParserReady({ delimiter: '>' });
          parser.on('data', () => {
              logger.verbose('Got ">" message prompt, gonna to write PDU message');
              port.unpipe(parser);
              mutex.unlock(MUTEX_SUBCOMMAND, 'sendSmsPduCommand');
              resolve(true);
          });
  
          mutex.lock(MUTEX_SUBCOMMAND, 'sendSmsPduCommand');
          port.pipe(parser);
          writeToPort(`AT+CMGS=${pduLength}\r`);
      });
  }
  
  exports.sendSMS = function sendSMS(destination, msg) {
      return new Promise(async (resolve) => {
1d6334a9b   Adhidarma Hadiwinoto   Coba sms error
250
251
          async function responseHandler(data) {
              logger.verbose('SMS sent callback called', { data });
beba81d88   Adhidarma Hadiwinoto   SMS error
252
253
254
255
256
257
258
  
              if (data.indexOf('ERROR') >= 0 || data.indexOf('+CMS ERROR') >= 0 || data.indexOf('+CMGS') >= 0) {
                  logger.verbose('SMS sent');
                  parsers.setSmsSentCallback(null);
                  mutex.unlock(MUTEX_COMMAND, 'sendSMS');
                  resolve(data.indexOf('ERROR') >= 0 ? null : data.toString().trim());
              }
1d6334a9b   Adhidarma Hadiwinoto   Coba sms error
259
          }
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
          await mutex.lock(MUTEX_COMMAND, 'sendSMS');
  
          if (!destination || !destination.trim()) {
              resolve(false);
              return;
          }
  
          if (!msg || !msg.trim()) {
              resolve(false);
              return;
          }
  
          const correctedDestination = `+${destination.replace(/^0/, '62')}`.replace(/^\++/, '+');
          logger.verbose(`Sending sms to ${correctedDestination}`, { msg });
  
          await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND);
  
          const submit = pdu.Submit();
          submit.setAddress(correctedDestination);
          submit.setData(msg.trim());
          submit.getType().setSrr(0);
  
          await sendCMGSPdu(Math.floor(submit.toString().length / 2) - 1);
beba81d88   Adhidarma Hadiwinoto   SMS error
283
          // await writeToPortAndWaitForOkOrError(`${submit.toString()}${CTRLZ}`, MUTEX_SUBCOMMAND);
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
284

beba81d88   Adhidarma Hadiwinoto   SMS error
285
286
          parsers.setSmsSentCallback(responseHandler);
          await writeToPort(`${submit.toString()}${CTRLZ}`, MUTEX_SUBCOMMAND);
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
      });
  };
  
  exports.executeUSSD = function executeUSSD(code, _includeCUSD2, _sessionId) {
      return new Promise(async (resolve) => {
          const includeCUSD2 = _includeCUSD2 || 0;
          const sessionId = _sessionId || uuidv1();
  
          async function responseHandler(data) {
              logger.verbose('Processing USSD response', { data });
              parsers.setUssdCallback(null);
  
              if (includeCUSD2 === 1 || includeCUSD2 === 2) {
                  await writeToPortAndWaitForOkOrError('AT+CUSD=2\r', MUTEX_SUBCOMMAND);
              }
  
              mutex.unlock(MUTEX_COMMAND, `executeUSSD ${sessionId}`);
              resolve(data);
          }
  
          mutex.lock(MUTEX_COMMAND, `executeUSSD ${sessionId}`);
          parsers.setUssdCallback(responseHandler);
  
          await this.writeToPortAndWaitForOkOrError(`${CTRLZ}AT+CMGF=0\r`, MUTEX_SUBCOMMAND);
  
          if (includeCUSD2 === -1 || includeCUSD2 === 2) {
              await this.writeToPortAndWaitForOkOrError('AT+CUSD=2\r', MUTEX_SUBCOMMAND);
          }
  
          await writeToPort(`AT+CUSD=1,"${code}",15\r`, MUTEX_SUBCOMMAND);
      });
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
318
  };