Commit e88bc6967ed82adc82e0dcce09e84b389fd88117

Authored by Adhidarma Hadiwinoto
1 parent e3bb6fdbab
Exists in master

Disable msisdn lookup

Showing 1 changed file with 3 additions and 1 deletions Inline Diff

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