Blame view

lib/modem-commands/index.js 10.1 KB
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
1
  const MUTEX_COMMAND = 'COMMAND';
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
2
  exports.MUTEX_COMMAND = MUTEX_COMMAND;
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
3
  const MUTEX_SUBCOMMAND = 'SUBCOMMAND';
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
4
  exports.MUTEX_SUBCOMMAND = MUTEX_SUBCOMMAND;
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
5

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
6
  const CTRLZ = '\u001a';
ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
7
  const pdu = require('node-pdu');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
8
  const uuidv1 = require('uuid/v1');
ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
9

8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
10
  const ParserReadline = require('@serialport/parser-readline');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
11
  const ParserRegex = require('@serialport/parser-regex');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
12
  const ParserReady = require('@serialport/parser-ready');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
13

e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
14
  const logger = require('komodo-sdk/logger');
ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
15
16
17
  const mutex = require('../mutex-common');
  const parsers = require('../serialport-parsers');
  const modemInfo = require('../modem-info');
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
18
19
20
21
22
  
  let port;
  
  function writeToPort(data) {
      return new Promise((resolve) => {
3522ae5bc   Adhidarma Hadiwinoto   MODEM-INFO: stuck...
23
          modemInfo.lastWriteTs = new Date();
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
24
25
          port.write(data, (err, bytesWritten) => {
              if (err) logger.warn(`ERROR: ${err.toString()}`);
9883a918f   Adhidarma Hadiwinoto   Urutan log
26
              logger.verbose('OUTGOING', { data: data.toString(), bytesWritten, err });
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
27
28
29
30
              resolve(bytesWritten);
          });
      });
  }
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
31
  exports.writeToPort = writeToPort;
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
32

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
33
  function writeToPortAndWaitForReadline(cmd, lockName) {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
34
      let resolved = false;
8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
35
36
37
      return new Promise(async (resolve) => {
          const parser = new ParserReadline({ delimiter: parsers.PARSER_READLINE_DELIMITER });
          parser.on('data', (data) => {
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
38
39
              port.unpipe(parser);
              mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
40
41
42
43
              if (!resolved) {
                  resolved = true;
                  resolve(data);
              }
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
44
45
46
47
48
49
          });
  
          await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
          port.pipe(parser);
          await writeToPort(cmd);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
50
51
  }
  exports.writeToPortAndWaitForReadline = writeToPortAndWaitForReadline;
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
52

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
53
  function writeToPortAndWaitForOkOrError(cmd, lockName) {
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
54
      return new Promise(async (resolve) => {
5b0551633   Adhidarma Hadiwinoto   Regex on writeToP...
55
56
          const parser = new ParserRegex({ regex: /(?:OK|ERROR)\r
  / });
afe1003d1   Adhidarma Hadiwinoto   Using modemComman...
57
          parser.on('data', (data) => {
8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
58
59
60
61
62
63
64
65
66
              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
67
68
  }
  exports.writeToPortAndWaitForOkOrError = writeToPortAndWaitForOkOrError;
8f7f6a139   Adhidarma Hadiwinoto   writeToPortAndWai...
69

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
70
  function sleep(ms) {
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
71
72
73
74
75
      return new Promise((resolve) => {
          setTimeout(() => {
              resolve();
          }, ms || 0);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
76
77
  }
  exports.sleep = sleep;
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
78

e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
79
80
81
  exports.setPort = function setPort(val) {
      port = val;
  };
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
82
  function querySignalQuality() {
e509607c5   Adhidarma Hadiwinoto   MODEM-COMMANDS: CSQ
83
84
85
86
87
88
89
90
91
92
      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
93
94
  }
  exports.querySignalQuality = querySignalQuality;
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
95

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
96
  function queryCOPS(lockName) {
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
97
      return new Promise(async (resolve) => {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
98
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryCOPS');
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
99
          await writeToPort('AT+COPS?\r');
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
100
101
102
          mutex.unlock(lockName || MUTEX_COMMAND, 'queryCOPS');
          resolve(true);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
103
104
  }
  exports.queryCOPS = queryCOPS;
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
105

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
106
  function queryCOPSAndSignalQuality(skipOnLocked) {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
107
      return new Promise(async (resolve) => {
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
108
109
110
          if (!skipOnLocked) {
              await mutex.lock(MUTEX_COMMAND);
          } else if (!mutex.tryLock(MUTEX_COMMAND, 'queryCOPSAndSignalQuality')) {
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
111
112
113
              resolve(false);
              return;
          }
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
114
115
          await writeToPortAndWaitForOkOrError('AT+COPS?\r', MUTEX_SUBCOMMAND);
          await writeToPortAndWaitForOkOrError('AT+CSQ\r', MUTEX_SUBCOMMAND);
47910cce6   Adhidarma Hadiwinoto   queryCOPSAndSigna...
116
117
  
          mutex.unlock(MUTEX_COMMAND, 'queryCopsAndSignalQuality');
dee2ba97a   Adhidarma Hadiwinoto   queryCOPS
118
119
          resolve(true);
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
120
121
  }
  exports.queryCOPSAndSignalQuality = queryCOPSAndSignalQuality;
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
122

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
123
  function queryIMEI(lockName) {
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
124
125
126
      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
127
              logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMEI' });
4cb2459b1   Adhidarma Hadiwinoto   queryIMEI unpipe ...
128
              port.unpipe(parser);
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
129
              mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMEI');
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
130
              modemInfo.imei = data.toString().trim() || null;
caac94e43   Adhidarma Hadiwinoto   modemInfo integrated
131
              logger.info('IMEI extracted', { imei: modemInfo.imei });
7f00b5aeb   Adhidarma Hadiwinoto   modemInfo.imei
132
              resolve(modemInfo.imei);
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
133
          });
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
134
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMEI');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
135
136
137
  
          port.pipe(parser);
          await writeToPort('AT+CGSN\r');
e77dfd454   Adhidarma Hadiwinoto   queryIMEI
138
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
139
140
  }
  exports.queryIMEI = queryIMEI;
b77537954   Adhidarma Hadiwinoto   queryIMSI
141

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
142
  function queryIMSI(lockName) {
b77537954   Adhidarma Hadiwinoto   queryIMSI
143
144
145
      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
146
              logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMSI' });
b77537954   Adhidarma Hadiwinoto   queryIMSI
147
              port.unpipe(parser);
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
148
              mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMSI');
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
149
              modemInfo.imsi = data.toString().trim() || null;
caac94e43   Adhidarma Hadiwinoto   modemInfo integrated
150
              logger.info('IMSI extracted', { imsi: modemInfo.imsi });
b77537954   Adhidarma Hadiwinoto   queryIMSI
151
152
              resolve(modemInfo.imsi);
          });
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
153
          await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMSI');
b77537954   Adhidarma Hadiwinoto   queryIMSI
154
155
156
157
  
          port.pipe(parser);
          await writeToPort('AT+CIMI\r');
      });
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
158
159
  }
  exports.queryIMSI = queryIMSI;
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
160
161
162
  
  exports.queryIMEIAndIMSI = async function queryIMEIAndIMSI() {
      await mutex.lock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
163
164
      const imei = await queryIMEI(MUTEX_SUBCOMMAND);
      const imsi = await queryIMSI(MUTEX_SUBCOMMAND);
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
165

08d2d23e1   Adhidarma Hadiwinoto   Perbaikan mutex u...
166
      await mutex.unlock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
caac94e43   Adhidarma Hadiwinoto   modemInfo integrated
167
      return { imei, imsi };
c5e93b5ea   Adhidarma Hadiwinoto   queryIMEIAndIMSI
168
  };
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
169

ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
170
171
172
173
174
175
176
177
178
179
180
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
  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
207
208
209
210
  async function sendCtrlZ() {
      await writeToPort(CTRLZ);
  }
  exports.sendCtrlZ = sendCtrlZ;
ea7f35320   Adhidarma Hadiwinoto   Refactor modem-co...
211

0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
212
  async function initATCommands() {
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
213
      await mutex.lock(MUTEX_COMMAND, 'INIT MODEM');
0ea228ab6   Adhidarma Hadiwinoto   sms and ussd
214
      await this.writeToPortAndWaitForOkOrError(`${CTRLZ}ATE0\r`, MUTEX_SUBCOMMAND);
fad855259   Adhidarma Hadiwinoto   Perbaikan waitFor...
215
216
217
      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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  }
  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) => {
          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);
          await writeToPort(`${submit.toString()}${CTRLZ}`);
  
          mutex.unlock(MUTEX_COMMAND, 'sendSMS');
          resolve(true);
      });
  };
  
  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...
297
  };