Blame view

lib/modem.js 9.43 KB
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
1
2
3
  'use strict';
  
  const INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS = 60000;
2db546a87   Adhidarma Hadiwinoto   Regex parser
4
5
6
7
8
9
10
11
12
13
  // const DELIMITER_WAIT_FOR_OK = '
  OK\r
  ';
  
  const REGEX_WAIT_FOR_OK_OR_ERROR = /
  (?:OK|ERROR)\r
  /;
  // const REGEX_WAIT_FOR_OK_OR_ERROR = /
  OK\r
  /;
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
14

5a00ec06f   Adhidarma Hadiwinoto   DEBUG signalStrength
15
  const moment = require('moment');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
16
17
  const SerialPort = require('serialport');
  const ParserReadline = require('@serialport/parser-readline');
2db546a87   Adhidarma Hadiwinoto   Regex parser
18
19
20
  // const ParserDelimiter = require('@serialport/parser-delimiter');
  
  const ParserRegex = require('@serialport/parser-regex');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
21
22
23
  
  const config = require('komodo-sdk/config');
  const logger = require('komodo-sdk/logger');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
24

cba7eef40   Adhidarma Hadiwinoto   Separate locks fu...
25
  const mutex = require('./mutex');
67af4245e   Adhidarma Hadiwinoto   Refactor util men...
26
  const common = require('./common');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
27
  const sms = require('./sms');
7355ad895   Adhidarma Hadiwinoto   Network information
28
  const dbCops = require('./db-cops');
5ae543453   Adhidarma Hadiwinoto   Report via HTTP
29
  const reportSender = require('./report-sender');
9ad3c8d30   Adhidarma Hadiwinoto   MSISDN db
30
  const msisdn = require('./msisdn');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
31

bc541e414   Adhidarma Hadiwinoto   modemInfo
32
  const modemInfo = {
c428dcf05   Adhidarma Hadiwinoto   More information ...
33
34
      manufacturer: null,
      model: null,
3ec3e9eb3   Adhidarma Hadiwinoto   HTTP command serv...
35
      imei: null,
bc541e414   Adhidarma Hadiwinoto   modemInfo
36
      imsi: null,
9ad3c8d30   Adhidarma Hadiwinoto   MSISDN db
37
      msisdn: null,
7355ad895   Adhidarma Hadiwinoto   Network information
38
39
40
      cops: null,
      networkId: null,
      networkName: null,
bc541e414   Adhidarma Hadiwinoto   modemInfo
41
      signalStrength: null,
5a00ec06f   Adhidarma Hadiwinoto   DEBUG signalStrength
42
43
      signalStrengthTs: null,
      signalStrengthTsReadable: null,
0440fda97   Adhidarma Hadiwinoto   Include config on...
44
      config: config.modem,
bc541e414   Adhidarma Hadiwinoto   modemInfo
45
  };
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
46

49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
47
48
49
  const port = new SerialPort(config.modem.device, { baudRate: 115200 });
  
  const parserReadLine = new ParserReadline();
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
50

2db546a87   Adhidarma Hadiwinoto   Regex parser
51
  const parserWaitForOK = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
52
53
54
  parserWaitForOK.on('data', () => {
      mutex.releaseLockWaitForCommand();
  });
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
55
56
57
58
59
60
61
62
63
64
65
  port.pipe(parserReadLine);
  
  function writeToPort(data) {
      return new Promise((resolve) => {
          port.write(data, (err, bytesWritten) => {
              if (err) logger.warn(`ERROR: ${err.toString()}`);
              logger.verbose(`* OUT: ${data}`);
              resolve(bytesWritten);
          });
      });
  }
2db546a87   Adhidarma Hadiwinoto   Regex parser
66
  // eslint-disable-next-line no-unused-vars
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
67
  async function writeToPortAndWaitForOK(data) {
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
68
      await mutex.setLockWaitForCommand();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
69
      const result = await writeToPort(data);
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
70
71
72
  
      await mutex.setLockWaitForCommand();
      mutex.releaseLockWaitForCommand();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
73
74
75
76
      return result;
  }
  
  async function readSMS(slot) {
2db546a87   Adhidarma Hadiwinoto   Regex parser
77
      const parserCMGR = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
78
      parserCMGR.on('data', (data) => {
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
79
          if (data) {
2db546a87   Adhidarma Hadiwinoto   Regex parser
80
              try {
343164ad5   Adhidarma Hadiwinoto   Repot modem info ...
81
                  reportSender.incomingSMS(sms.extract(data.toString().trim()), modemInfo);
2db546a87   Adhidarma Hadiwinoto   Regex parser
82
83
84
85
86
              } catch (e) {
                  logger.warn(`Exception on reporting new message. ${e.toString()}`, { smsObj: e.smsObj, dataFromModem: data });
  
                  process.exit(0);
              }
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
87
          }
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
88
89
90
          port.unpipe(parserCMGR);
          mutex.releaseLockWaitForCommand();
      });
2db546a87   Adhidarma Hadiwinoto   Regex parser
91
92
      // const parserCMGD = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK });
      const parserCMGD = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
93
94
95
      parserCMGD.on('data', () => {
          port.unpipe(parserCMGD);
          mutex.releaseLockWaitForCommand();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
96
97
98
      });
  
      logger.info(`Reading SMS on slot ${slot}`);
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
99
100
101
102
      await mutex.setLockWaitForCommand();
      port.pipe(parserCMGR);
      await writeToPort(`AT+CMGR=${slot}\r`);
      logger.info(`Finished reading SMS on slot ${slot}`);
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
103
104
  
      logger.info(`Deleting message on slot ${slot}`);
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
105
106
107
      await mutex.setLockWaitForCommand();
      port.pipe(parserCMGD);
      await writeToPort(`AT+CMGD=${slot}\r`);
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
      logger.info('Message processing has completed');
  }
  
  function onIncomingSMS(data) {
      const value = common.extractValueFromReadLineData(data);
      if (!value) return;
  
      const chunks = value.split(',');
      if (!chunks && !chunks[1]) return;
  
      const slot = chunks[1];
  
      logger.info(`Incoming SMS on slot ${slot}`);
      readSMS(slot);
  }
7355ad895   Adhidarma Hadiwinoto   Network information
123
124
125
126
127
128
129
130
131
132
133
134
  function onCOPS(data) {
      modemInfo.cops = common.extractValueFromReadLineData(data).trim();
      logger.info(`Connected Network: ${modemInfo.cops}`);
  
      if (!modemInfo.cops) return;
  
      [, , modemInfo.networkId] = modemInfo.cops.split(',');
  
      if (modemInfo.networkId) {
          modemInfo.networkName = dbCops[modemInfo.networkId];
      }
  }
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
135
136
137
138
  parserReadLine.on('data', (data) => {
      logger.verbose(`* IN: ${data}`);
      if (data) {
          if (data.indexOf('+CSQ: ') === 0) {
5a00ec06f   Adhidarma Hadiwinoto   DEBUG signalStrength
139
140
141
142
143
144
145
              const signalStrength = common.extractValueFromReadLineData(data).trim();
              if (signalStrength) {
                  modemInfo.signalStrength = signalStrength;
                  modemInfo.signalStrengthTs = new Date();
                  modemInfo.signalStrengthTsReadable = moment(modemInfo.signalStrengthTs).format('YYYY-MM-DD HH:mm:ss');
                  logger.info(`Signal strength: ${modemInfo.signalStrength}`);
              }
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
146
147
          } else if (data.indexOf('+CMTI: ') === 0) {
              onIncomingSMS(data);
7355ad895   Adhidarma Hadiwinoto   Network information
148
149
          } else if (data.indexOf('+COPS: ') === 0) {
              onCOPS(data);
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
150
151
152
          }
      }
  });
2db546a87   Adhidarma Hadiwinoto   Regex parser
153
154
  async function simpleSubCommand(cmd, callback) {
      const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
c428dcf05   Adhidarma Hadiwinoto   More information ...
155
156
      parser.on('data', (data) => {
          port.unpipe(parser);
2db546a87   Adhidarma Hadiwinoto   Regex parser
157
          mutex.releaseLockWaitForSubCommand();
c428dcf05   Adhidarma Hadiwinoto   More information ...
158
159
  
          if (data) {
2db546a87   Adhidarma Hadiwinoto   Regex parser
160
              if (callback) callback(null, data.toString().trim());
c428dcf05   Adhidarma Hadiwinoto   More information ...
161
162
          }
      });
2db546a87   Adhidarma Hadiwinoto   Regex parser
163
164
165
166
167
168
169
170
171
172
      return new Promise(async (resolve) => {
          await mutex.setLockWaitForSubCommand();
          port.pipe(parser);
          writeToPort(cmd);
  
          await mutex.setLockWaitForSubCommand();
          mutex.releaseLockWaitForSubCommand();
  
          resolve();
      });
c428dcf05   Adhidarma Hadiwinoto   More information ...
173
  }
c428dcf05   Adhidarma Hadiwinoto   More information ...
174
175
  function readManufacturer() {
      return new Promise((resolve) => {
2db546a87   Adhidarma Hadiwinoto   Regex parser
176
          simpleSubCommand('AT+CGMI\r', (err, result) => {
c428dcf05   Adhidarma Hadiwinoto   More information ...
177
178
179
180
181
182
183
184
185
              modemInfo.manufacturer = result;
              logger.info(`Manufacturer: ${result}`);
              resolve(result);
          });
      });
  }
  
  function readModel() {
      return new Promise((resolve) => {
2db546a87   Adhidarma Hadiwinoto   Regex parser
186
          simpleSubCommand('AT+CGMM\r', (err, result) => {
c428dcf05   Adhidarma Hadiwinoto   More information ...
187
188
189
190
191
192
193
194
195
              modemInfo.model = result;
              logger.info(`Model: ${result}`);
              resolve(result);
          });
      });
  }
  
  function readIMEI() {
      return new Promise((resolve) => {
2db546a87   Adhidarma Hadiwinoto   Regex parser
196
          simpleSubCommand('AT+CGSN\r', (err, result) => {
c428dcf05   Adhidarma Hadiwinoto   More information ...
197
198
199
200
201
202
203
204
205
              modemInfo.imei = result;
              logger.info(`IMEI: ${result}`);
              resolve(result);
          });
      });
  }
  
  function readIMSI() {
      return new Promise((resolve) => {
2db546a87   Adhidarma Hadiwinoto   Regex parser
206
          simpleSubCommand('AT+CIMI\r', (err, result) => {
c428dcf05   Adhidarma Hadiwinoto   More information ...
207
208
              modemInfo.imsi = result;
              logger.info(`IMSI: ${result}`);
9ad3c8d30   Adhidarma Hadiwinoto   MSISDN db
209
210
211
212
213
214
215
  
              if (result) {
                  modemInfo.msisdn = msisdn[result];
                  if (modemInfo.msisdn) {
                      logger.info(`MSISDN: ${modemInfo.msisdn}`);
                  }
              }
c428dcf05   Adhidarma Hadiwinoto   More information ...
216
217
218
219
              resolve(result);
          });
      });
  }
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
220

2db546a87   Adhidarma Hadiwinoto   Regex parser
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  function readCOPS() {
      return new Promise((resolve) => {
          simpleSubCommand('AT+COPS?\r', (err, result) => {
              resolve(result);
          });
      });
  }
  
  function deleteInbox() {
      return new Promise((resolve) => {
          simpleSubCommand('AT+CMGD=0,4\r', (err, result) => {
              resolve(result);
          });
      });
  }
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
236
  async function querySignalStrength() {
2db546a87   Adhidarma Hadiwinoto   Regex parser
237
      const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
238
239
240
241
242
243
244
245
246
      parser.on('data', () => {
          port.unpipe(parser);
          mutex.releaseLockWaitForCommand();
      });
  
      if (mutex.tryLockWaitForCommand()) {
          port.pipe(parser);
          await writeToPort('AT+CSQ\r');
      }
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
247
248
249
250
  }
  
  async function registerSignalStrengthBackgroundQuery() {
      logger.info('Registering background signal strength query');
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
251
      querySignalStrength();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
252
253
      setInterval(() => {
          querySignalStrength();
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
254
      }, config.interval_beetwen_signal_strength_ms || INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS);
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
255
256
257
  }
  
  async function sendSMS(destination, msg) {
3023245c4   Adhidarma Hadiwinoto   Pengamanan tambahan
258
      if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return;
2db546a87   Adhidarma Hadiwinoto   Regex parser
259
      const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
260
261
262
263
264
265
      parser.on('data', () => {
          port.unpipe(parser);
          mutex.releaseLockWaitForSubCommand();
      });
  
      logger.verbose('Waiting for command lock to send message');
cba7eef40   Adhidarma Hadiwinoto   Separate locks fu...
266
      await mutex.setLockWaitForCommand();
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
267

49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
268
269
270
      logger.info('Sending message', { destination, msg });
  
      const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+');
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
271
272
273
274
275
276
277
278
279
280
281
282
283
      logger.verbose('Waiting for lock before set to text mode');
      await mutex.setLockWaitForSubCommand();
      port.pipe(parser);
      await writeToPort('AT+CMGF=1\r');
  
      logger.verbose('Waiting for lock before writing message');
      await mutex.setLockWaitForSubCommand();
      port.pipe(parser);
      await writeToPort(`AT+CMGS="${correctedDestination}"
  ${msg}${Buffer.from([0x1A])}`);
  
      await mutex.setLockWaitForSubCommand();
      mutex.releaseLockWaitForSubCommand();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
284
285
  
      logger.info('Message has been sent');
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
286
287
288
289
      setTimeout(() => {
          logger.verbose('Releasing command lock');
          mutex.releaseLockWaitForCommand();
      }, 2000);
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
290
291
292
293
  }
  
  function init() {
      port.on('open', async () => {
2db546a87   Adhidarma Hadiwinoto   Regex parser
294
          await mutex.setLockWaitForCommand();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
295
296
  
          logger.info('Modem opened');
2db546a87   Adhidarma Hadiwinoto   Regex parser
297
298
          await writeToPort('\r');
          await simpleSubCommand('AT\r');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
299
300
  
          logger.info('Initializing modem to factory set');
2db546a87   Adhidarma Hadiwinoto   Regex parser
301
          await simpleSubCommand('AT&F\r');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
302
303
  
          logger.info('Disabling echo');
2db546a87   Adhidarma Hadiwinoto   Regex parser
304
          await simpleSubCommand('ATE0\r');
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
305

2db546a87   Adhidarma Hadiwinoto   Regex parser
306
          await readCOPS();
7355ad895   Adhidarma Hadiwinoto   Network information
307

c428dcf05   Adhidarma Hadiwinoto   More information ...
308
309
310
          await readManufacturer();
          await readModel();
          await readIMEI();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
311
          await readIMSI();
2253f95a7   Adhidarma Hadiwinoto   config.disable_de...
312
313
          if (!config.disable_delete_inbox_on_startup) {
              logger.info('Deleting existing messages');
2db546a87   Adhidarma Hadiwinoto   Regex parser
314
              await deleteInbox();
2253f95a7   Adhidarma Hadiwinoto   config.disable_de...
315
          }
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
316
          mutex.releaseLockWaitForCommand();
2db546a87   Adhidarma Hadiwinoto   Regex parser
317
          logger.verbose('Init completed');
0bdac2f9c   Adhidarma Hadiwinoto   Bersih kirim sms ...
318

49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
319
          registerSignalStrengthBackgroundQuery();
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
320
321
322
323
      });
  }
  
  init();
bc541e414   Adhidarma Hadiwinoto   modemInfo
324
  exports.modemInfo = modemInfo;
49eaf19a3   Adhidarma Hadiwinoto   SMS is ok
325
  exports.sendSMS = sendSMS;