Commit e07d18058ff73f7ad9e6a6fb53a2975727a99f01

Authored by Adhidarma Hadiwinoto
1 parent 9de643e330
Exists in master

Code cleanup

Showing 4 changed files with 5 additions and 31 deletions Inline Diff

1 { 1 {
2 "name": "SMS0", 2 "name": "SMS0",
3 "modem": { 3 "modem": {
4 "device": "/dev/ttyUSB0", 4 "device": "/dev/ttyUSB0",
5 "options": { 5 "options": {
6 "baudRate": 115200 6 "baudRate": 115200
7 } 7 }
8 }, 8 },
9 "report_url": { 9 "report_url": {
10 "incoming_sms": "http://localhost:16481/apikey/PLEASE_CHANGE_ME/on-sms", 10 "incoming_sms": "http://localhost:16481/apikey/PLEASE_CHANGE_ME/on-sms",
11 "register_modem": "http://localhost:16481/apikey/PLEASE_CHANGE_ME/modems/set" 11 "register_modem": "http://localhost:16481/apikey/PLEASE_CHANGE_ME/modems/set"
12 }, 12 },
13 "http_command_server": { 13 "http_command_server": {
14 "apikey": "PLEASE_CHANGE_ME", 14 "apikey": "PLEASE_CHANGE_ME",
15 "listen_port": "2110" 15 "listen_port": "2110"
16 }, 16 },
17 17
18 "interval_beetwen_signal_strength_ms": 60000, 18 "interval_beetwen_signal_strength_ms": 60000,
19 "wait_for_release_lock_wait_for_command_ms": 2000, 19 "sleep_after_send_sms_ms": 2000,
20 "disable_delete_inbox_on_startup": false 20 "disable_delete_inbox_on_startup": false
21 } 21 }
1 'use strict'; 1 'use strict';
2 2
3 const DEFAULT_SLEEP_AFTER_SEND_SMS_MS = 2000;
3 const INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS = 60000; 4 const INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS = 60000;
4 const MAX_LAST_DATA_AGE_MS = 3 * 60 * 1000; 5 const MAX_LAST_DATA_AGE_MS = 3 * 60 * 1000;
5 const REGEX_WAIT_FOR_OK_OR_ERROR = /\n(?:OK|ERROR)\r/; 6 const REGEX_WAIT_FOR_OK_OR_ERROR = /\n(?:OK|ERROR)\r/;
6 // const REGEX_WAIT_FOR_OK_OR_ERROR_USSD = /\n(?:OK|ERROR)\r/; 7 // const REGEX_WAIT_FOR_OK_OR_ERROR_USSD = /\n(?:OK|ERROR)\r/;
7 8
8 const moment = require('moment'); 9 const moment = require('moment');
9 const SerialPort = require('serialport'); 10 const SerialPort = require('serialport');
10 const ParserReadline = require('@serialport/parser-readline'); 11 const ParserReadline = require('@serialport/parser-readline');
11 // const ParserDelimiter = require('@serialport/parser-delimiter'); 12 // const ParserDelimiter = require('@serialport/parser-delimiter');
12 13
13 const ParserRegex = require('@serialport/parser-regex'); 14 const ParserRegex = require('@serialport/parser-regex');
14 15
15 const config = require('komodo-sdk/config'); 16 const config = require('komodo-sdk/config');
16 const logger = require('komodo-sdk/logger'); 17 const logger = require('komodo-sdk/logger');
17 18
18 const mutex = require('./mutex'); 19 const mutex = require('./mutex');
19 const common = require('./common'); 20 const common = require('./common');
20 const sms = require('./sms'); 21 const sms = require('./sms');
21 const dbCops = require('./db-cops'); 22 const dbCops = require('./db-cops');
22 const reportSender = require('./report-sender'); 23 const reportSender = require('./report-sender');
23 // const msisdn = require('./msisdn');
24 const registerModem = require('./register-modem'); 24 const registerModem = require('./register-modem');
25 // const counters = require('./counters');
26 25
27 const modemInfo = { 26 const modemInfo = {
28 device: config.modem.device, 27 device: config.modem.device,
29 manufacturer: null, 28 manufacturer: null,
30 model: null, 29 model: null,
31 imei: null, 30 imei: null,
32 imsi: null, 31 imsi: null,
33 msisdn: null, 32 msisdn: null,
34 cops: null, 33 cops: null,
35 networkId: null, 34 networkId: null,
36 networkName: null, 35 networkName: null,
37 signalStrength: null, 36 signalStrength: null,
38 signalStrengthTs: null, 37 signalStrengthTs: null,
39 signalStrengthTsReadable: null, 38 signalStrengthTsReadable: null,
40 // messageSentCounter: null,
41 // messageReceivedCounter: null,
42 }; 39 };
43 40
44 let lastTs = new Date(); 41 let lastTs = new Date();
45 42
46 let port; 43 let port;
47 44
48 const parserReadLine = new ParserReadline(); 45 const parserReadLine = new ParserReadline();
49 46
50 const parserWaitForOK = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 47 const parserWaitForOK = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
51 parserWaitForOK.on('data', () => { 48 parserWaitForOK.on('data', () => {
52 mutex.releaseLockWaitForCommand(); 49 mutex.releaseLockWaitForCommand();
53 }); 50 });
54 51
55 function writeToPort(data) { 52 function writeToPort(data) {
56 return new Promise((resolve) => { 53 return new Promise((resolve) => {
57 port.write(data, (err, bytesWritten) => { 54 port.write(data, (err, bytesWritten) => {
58 if (err) logger.warn(`ERROR: ${err.toString()}`); 55 if (err) logger.warn(`ERROR: ${err.toString()}`);
59 logger.verbose(`* OUT: ${data}`); 56 logger.verbose(`* OUT: ${data}`);
60 resolve(bytesWritten); 57 resolve(bytesWritten);
61 }); 58 });
62 }); 59 });
63 } 60 }
64 61
65 async function readSMS(slot) { 62 async function readSMS(slot) {
66 const parserCMGR = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 63 const parserCMGR = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
67 parserCMGR.on('data', (data) => { 64 parserCMGR.on('data', (data) => {
68 if (data) { 65 if (data) {
69 try { 66 try {
70 reportSender.incomingSMS(sms.extract(data.toString().trim()), modemInfo); 67 reportSender.incomingSMS(sms.extract(data.toString().trim()), modemInfo);
71 } catch (e) { 68 } catch (e) {
72 logger.warn(`Exception on reporting new message. ${e.toString()}`, { smsObj: e.smsObj, dataFromModem: data }); 69 logger.warn(`Exception on reporting new message. ${e.toString()}`, { smsObj: e.smsObj, dataFromModem: data });
73 70
74 process.exit(0); 71 process.exit(0);
75 } 72 }
76 } 73 }
77 port.unpipe(parserCMGR); 74 port.unpipe(parserCMGR);
78 mutex.releaseLockWaitForCommand(); 75 mutex.releaseLockWaitForCommand();
79 }); 76 });
80 77
81 // const parserCMGD = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); 78 // const parserCMGD = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK });
82 const parserCMGD = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 79 const parserCMGD = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
83 parserCMGD.on('data', () => { 80 parserCMGD.on('data', () => {
84 port.unpipe(parserCMGD); 81 port.unpipe(parserCMGD);
85 mutex.releaseLockWaitForCommand(); 82 mutex.releaseLockWaitForCommand();
86 }); 83 });
87 84
88 logger.info(`Reading SMS on slot ${slot}`); 85 logger.info(`Reading SMS on slot ${slot}`);
89 await mutex.setLockWaitForCommand(); 86 await mutex.setLockWaitForCommand();
90 port.pipe(parserCMGR); 87 port.pipe(parserCMGR);
91 await writeToPort(`AT+CMGR=${slot}\r`); 88 await writeToPort(`AT+CMGR=${slot}\r`);
92 logger.info(`Finished reading SMS on slot ${slot}`); 89 logger.info(`Finished reading SMS on slot ${slot}`);
93 90
94 logger.info(`Deleting message on slot ${slot}`); 91 logger.info(`Deleting message on slot ${slot}`);
95 await mutex.setLockWaitForCommand(); 92 await mutex.setLockWaitForCommand();
96 port.pipe(parserCMGD); 93 port.pipe(parserCMGD);
97 await writeToPort(`AT+CMGD=${slot}\r`); 94 await writeToPort(`AT+CMGD=${slot}\r`);
98 logger.info('Message processing has completed'); 95 logger.info('Message processing has completed');
99 } 96 }
100 97
101 function onIncomingSMS(data) { 98 function onIncomingSMS(data) {
102 const value = common.extractValueFromReadLineData(data); 99 const value = common.extractValueFromReadLineData(data);
103 if (!value) return; 100 if (!value) return;
104 101
105 const chunks = value.split(','); 102 const chunks = value.split(',');
106 if (!chunks && !chunks[1]) return; 103 if (!chunks && !chunks[1]) return;
107 104
108 const slot = chunks[1]; 105 const slot = chunks[1];
109 106
110 logger.info(`Incoming SMS on slot ${slot}`); 107 logger.info(`Incoming SMS on slot ${slot}`);
111 readSMS(slot); 108 readSMS(slot);
112 } 109 }
113 110
114 function onCOPS(data) { 111 function onCOPS(data) {
115 modemInfo.cops = common.extractValueFromReadLineData(data).trim(); 112 modemInfo.cops = common.extractValueFromReadLineData(data).trim();
116 logger.info(`Connected Network: ${modemInfo.cops}`); 113 logger.info(`Connected Network: ${modemInfo.cops}`);
117 114
118 if (!modemInfo.cops) return; 115 if (!modemInfo.cops) return;
119 116
120 [, , modemInfo.networkId] = modemInfo.cops.split(','); 117 [, , modemInfo.networkId] = modemInfo.cops.split(',');
121 118
122 if (modemInfo.networkId) { 119 if (modemInfo.networkId) {
123 modemInfo.networkName = dbCops[modemInfo.networkId] || modemInfo.networkId; 120 modemInfo.networkName = dbCops[modemInfo.networkId] || modemInfo.networkId;
124 } 121 }
125 } 122 }
126 123
127 parserReadLine.on('data', (data) => { 124 parserReadLine.on('data', (data) => {
128 logger.verbose(`* IN: ${data}`); 125 logger.verbose(`* IN: ${data}`);
129 if (data) { 126 if (data) {
130 lastTs = new Date(); 127 lastTs = new Date();
131 if (data.indexOf('+CSQ: ') === 0) { 128 if (data.indexOf('+CSQ: ') === 0) {
132 const signalStrength = common.extractValueFromReadLineData(data).trim(); 129 const signalStrength = common.extractValueFromReadLineData(data).trim();
133 if (signalStrength) { 130 if (signalStrength) {
134 modemInfo.signalStrength = signalStrength; 131 modemInfo.signalStrength = signalStrength;
135 modemInfo.signalStrengthTs = new Date(); 132 modemInfo.signalStrengthTs = new Date();
136 modemInfo.signalStrengthTsReadable = moment(modemInfo.signalStrengthTs).format('YYYY-MM-DD HH:mm:ss'); 133 modemInfo.signalStrengthTsReadable = moment(modemInfo.signalStrengthTs).format('YYYY-MM-DD HH:mm:ss');
137 logger.info(`Signal strength: ${modemInfo.signalStrength}`); 134 logger.info(`Signal strength: ${modemInfo.signalStrength}`);
138 registerModem(modemInfo); 135 registerModem(modemInfo);
139 } 136 }
140 } else if (data.indexOf('+CMTI: ') === 0) { 137 } else if (data.indexOf('+CMTI: ') === 0) {
141 // counters.increment('MESSAGE_RECEIVED', modemInfo);
142 onIncomingSMS(data); 138 onIncomingSMS(data);
143 } else if (data.indexOf('+COPS: ') === 0) { 139 } else if (data.indexOf('+COPS: ') === 0) {
144 onCOPS(data); 140 onCOPS(data);
145 } 141 }
146 } 142 }
147 }); 143 });
148 144
149 async function simpleSubCommand(cmd, callback) { 145 async function simpleSubCommand(cmd, callback) {
150 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 146 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
151 parser.on('data', (data) => { 147 parser.on('data', (data) => {
152 port.unpipe(parser); 148 port.unpipe(parser);
153 mutex.releaseLockWaitForSubCommand(); 149 mutex.releaseLockWaitForSubCommand();
154 150
155 if (data) { 151 if (data) {
156 if (callback) callback(null, data.toString().trim()); 152 if (callback) callback(null, data.toString().trim());
157 } 153 }
158 }); 154 });
159 155
160 return new Promise(async (resolve) => { 156 return new Promise(async (resolve) => {
161 await mutex.setLockWaitForSubCommand(); 157 await mutex.setLockWaitForSubCommand();
162 port.pipe(parser); 158 port.pipe(parser);
163 writeToPort(cmd); 159 writeToPort(cmd);
164 160
165 await mutex.setLockWaitForSubCommand(); 161 await mutex.setLockWaitForSubCommand();
166 mutex.releaseLockWaitForSubCommand(); 162 mutex.releaseLockWaitForSubCommand();
167 163
168 resolve(); 164 resolve();
169 }); 165 });
170 } 166 }
171 167
172 function readManufacturer() { 168 function readManufacturer() {
173 return new Promise((resolve) => { 169 return new Promise((resolve) => {
174 simpleSubCommand('AT+CGMI\r', (err, result) => { 170 simpleSubCommand('AT+CGMI\r', (err, result) => {
175 modemInfo.manufacturer = result; 171 modemInfo.manufacturer = result;
176 logger.info(`Manufacturer: ${result}`); 172 logger.info(`Manufacturer: ${result}`);
177 resolve(result); 173 resolve(result);
178 }); 174 });
179 }); 175 });
180 } 176 }
181 177
182 function readModel() { 178 function readModel() {
183 return new Promise((resolve) => { 179 return new Promise((resolve) => {
184 simpleSubCommand('AT+CGMM\r', (err, result) => { 180 simpleSubCommand('AT+CGMM\r', (err, result) => {
185 modemInfo.model = result; 181 modemInfo.model = result;
186 logger.info(`Model: ${result}`); 182 logger.info(`Model: ${result}`);
187 resolve(result); 183 resolve(result);
188 }); 184 });
189 }); 185 });
190 } 186 }
191 187
192 function readIMEI() { 188 function readIMEI() {
193 return new Promise((resolve) => { 189 return new Promise((resolve) => {
194 simpleSubCommand('AT+CGSN\r', (err, result) => { 190 simpleSubCommand('AT+CGSN\r', (err, result) => {
195 modemInfo.imei = result; 191 modemInfo.imei = result;
196 logger.info(`IMEI: ${result}`); 192 logger.info(`IMEI: ${result}`);
197 resolve(result); 193 resolve(result);
198 }); 194 });
199 }); 195 });
200 } 196 }
201 197
202 function readIMSI() { 198 function readIMSI() {
203 return new Promise((resolve) => { 199 return new Promise((resolve) => {
204 simpleSubCommand('AT+CIMI\r', (err, result) => { 200 simpleSubCommand('AT+CIMI\r', (err, result) => {
205 modemInfo.imsi = result; 201 modemInfo.imsi = result;
206 logger.info(`IMSI: ${result}`); 202 logger.info(`IMSI: ${result}`);
207 203
208 if (result) { 204 if (result) {
209 /* 205 /*
210 modemInfo.msisdn = msisdn[result]; 206 modemInfo.msisdn = msisdn[result];
211 if (modemInfo.msisdn) { 207 if (modemInfo.msisdn) {
212 logger.info(`MSISDN: ${modemInfo.msisdn}`); 208 logger.info(`MSISDN: ${modemInfo.msisdn}`);
213 registerModem(modemInfo); 209 registerModem(modemInfo);
214 } 210 }
215 */ 211 */
216 } else { 212 } else {
217 logger.warn(`IMSI not detected. Please insert a sim card to your modem. Terminating ${config.modem.device}.`); 213 logger.warn(`IMSI not detected. Please insert a sim card to your modem. Terminating ${config.modem.device}.`);
218 process.exit(2); 214 process.exit(2);
219 } 215 }
220 resolve(result); 216 resolve(result);
221 }); 217 });
222 }); 218 });
223 } 219 }
224 220
225 function readCOPS() { 221 function readCOPS() {
226 return new Promise((resolve) => { 222 return new Promise((resolve) => {
227 simpleSubCommand('AT+COPS?\r', (err, result) => { 223 simpleSubCommand('AT+COPS?\r', (err, result) => {
228 resolve(result); 224 resolve(result);
229 }); 225 });
230 }); 226 });
231 } 227 }
232 228
233 function deleteInbox() { 229 function deleteInbox() {
234 return new Promise((resolve) => { 230 return new Promise((resolve) => {
235 simpleSubCommand('AT+CMGD=0,4\r', (err, result) => { 231 simpleSubCommand('AT+CMGD=0,4\r', (err, result) => {
236 resolve(result); 232 resolve(result);
237 }); 233 });
238 }); 234 });
239 } 235 }
240 236
241 async function querySignalStrength() { 237 async function querySignalStrength() {
242 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 238 const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
243 parser.on('data', () => { 239 parser.on('data', () => {
244 port.unpipe(parser); 240 port.unpipe(parser);
245 mutex.releaseLockWaitForCommand(); 241 mutex.releaseLockWaitForCommand();
246 }); 242 });
247 243
248 if (mutex.tryLockWaitForCommand()) { 244 if (mutex.tryLockWaitForCommand()) {
249 port.pipe(parser); 245 port.pipe(parser);
250 await writeToPort('AT+CSQ\r'); 246 await writeToPort('AT+CSQ\r');
251 } 247 }
252 } 248 }
253 249
254 function registerModemToCenterPeriodically() { 250 function registerModemToCenterPeriodically() {
255 registerModem(modemInfo); 251 registerModem(modemInfo);
256 252
257 setInterval(() => { 253 setInterval(() => {
258 registerModem(modemInfo); 254 registerModem(modemInfo);
259 }, 60 * 1000); 255 }, 60 * 1000);
260 } 256 }
261 257
262 async function registerSignalStrengthBackgroundQuery() { 258 async function registerSignalStrengthBackgroundQuery() {
263 logger.info('Registering background signal strength query'); 259 logger.info('Registering background signal strength query');
264 260
265 querySignalStrength(); 261 querySignalStrength();
266 262
267 setInterval(() => { 263 setInterval(() => {
268 querySignalStrength(); 264 querySignalStrength();
269 }, config.interval_beetwen_signal_strength_ms || INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); 265 }, config.interval_beetwen_signal_strength_ms || INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS);
270 } 266 }
271 267
272 async function sendSMS(destination, msg) { 268 async function sendSMS(destination, msg) {
273 if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return; 269 if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return;
274 270
275 // const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 271 // const parser = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
276 const parser = new ParserReadline({ delimiter: '\r\n' }); 272 const parser = new ParserReadline({ delimiter: '\r\n' });
277 parser.on('data', () => { 273 parser.on('data', () => {
278 port.unpipe(parser); 274 port.unpipe(parser);
279 mutex.releaseLockWaitForSubCommand(); 275 mutex.releaseLockWaitForSubCommand();
280 }); 276 });
281 277
282 logger.verbose('Waiting for command lock to send message'); 278 logger.verbose('Waiting for command lock to send message');
283 await mutex.setLockWaitForCommand(); 279 await mutex.setLockWaitForCommand();
284 280
285 logger.info('Sending message', { destination, msg }); 281 logger.info('Preparing to send message', { destination, msg });
286 // counters.increment('MESSAGE_SENT', modemInfo);
287 282
288 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); 283 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+');
289 284
290 logger.verbose('Waiting for lock before set to text mode'); 285 logger.verbose('Waiting for lock before set SMS to text mode');
291 await mutex.setLockWaitForSubCommand(); 286 await mutex.setLockWaitForSubCommand();
292 port.pipe(parser); 287 port.pipe(parser);
293 await writeToPort('AT+CMGF=1\r'); 288 await writeToPort('AT+CMGF=1\r');
294 289
295 logger.verbose('Waiting for lock before writing message'); 290 logger.verbose('Waiting for lock before writing message');
296 await mutex.setLockWaitForSubCommand(); 291 await mutex.setLockWaitForSubCommand();
297 port.pipe(parser); 292 port.pipe(parser);
298 await writeToPort(`AT+CMGS="${correctedDestination}"\r`); 293 await writeToPort(`AT+CMGS="${correctedDestination}"\r`);
299 await writeToPort(msg); 294 await writeToPort(msg);
300 await writeToPort(Buffer.from([0x1A])); 295 await writeToPort(Buffer.from([0x1A]));
301 296
302 await mutex.setLockWaitForSubCommand(); 297 await mutex.setLockWaitForSubCommand();
303 mutex.releaseLockWaitForSubCommand(); 298 mutex.releaseLockWaitForSubCommand();
304 299
305 logger.info('Message has been sent'); 300 logger.info('Message has been sent');
306 301
307 setTimeout(() => { 302 setTimeout(() => {
308 logger.verbose('Releasing command lock'); 303 logger.verbose('Releasing command lock');
309 mutex.releaseLockWaitForCommand(); 304 mutex.releaseLockWaitForCommand();
310 }, config.wait_for_release_lock_wait_for_command_ms || 2000); 305 }, config.sleep_after_send_sms_ms || DEFAULT_SLEEP_AFTER_SEND_SMS_MS);
311 } 306 }
312 307
313 /** 308 /**
314 * Ekseksusi kode USSD. 309 * Ekseksusi kode USSD.
315 * 310 *
316 * Pilihan includeCUSD2: 311 * Pilihan includeCUSD2:
317 * -1: sebelum 312 * -1: sebelum
318 * 0: tidak (default) 313 * 0: tidak (default)
319 * 1: sesudah 314 * 1: sesudah
320 * 2: sebelum dan sesudah 315 * 2: sebelum dan sesudah
321 * 316 *
322 * @param {string} code - Kode USSD 317 * @param {string} code - Kode USSD
323 * @param {number} [includeCUSD2=0] - Apakah ingin otomatis memasukkan CUSD=2 318 * @param {number} [includeCUSD2=0] - Apakah ingin otomatis memasukkan CUSD=2
324 */ 319 */
325 function executeUSSD(code, includeCUSD2) { 320 function executeUSSD(code, includeCUSD2) {
326 return new Promise(async (resolve) => { 321 return new Promise(async (resolve) => {
327 const parserMain = new ParserReadline({ delimiter: '\r\n' }); 322 const parserMain = new ParserReadline({ delimiter: '\r\n' });
328 // const parserMain = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 323 // const parserMain = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
329 parserMain.on('data', (data) => { 324 parserMain.on('data', (data) => {
330 if (!data || !data.toString().trim()) return; 325 if (!data || !data.toString().trim()) return;
331 326
332 if (data.toString().trim() === 'OK') return; 327 if (data.toString().trim() === 'OK') return;
333 328
334 port.unpipe(parserMain); 329 port.unpipe(parserMain);
335 mutex.releaseLockWaitForSubCommand(); 330 mutex.releaseLockWaitForSubCommand();
336 resolve(data); 331 resolve(data);
337 }); 332 });
338 333
339 const parserCUSD2 = new ParserReadline({ delimiter: '\r\n' }); 334 const parserCUSD2 = new ParserReadline({ delimiter: '\r\n' });
340 // const parserCUSD2 = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR }); 335 // const parserCUSD2 = new ParserRegex({ regex: REGEX_WAIT_FOR_OK_OR_ERROR });
341 parserCUSD2.on('data', () => { 336 parserCUSD2.on('data', () => {
342 port.unpipe(parserCUSD2); 337 port.unpipe(parserCUSD2);
343 mutex.releaseLockWaitForSubCommand(); 338 mutex.releaseLockWaitForSubCommand();
344 }); 339 });
345 340
346 logger.verbose('Waiting for command lock to execute USSD'); 341 logger.verbose('Waiting for command lock to execute USSD');
347 await mutex.setLockWaitForCommand(); 342 await mutex.setLockWaitForCommand();
348 343
349 if (includeCUSD2 === -1 || includeCUSD2 === 2) { 344 if (includeCUSD2 === -1 || includeCUSD2 === 2) {
350 await mutex.setLockWaitForSubCommand(); 345 await mutex.setLockWaitForSubCommand();
351 logger.info('Terminating existing USSD session'); 346 logger.info('Terminating existing USSD session');
352 port.pipe(parserCUSD2); 347 port.pipe(parserCUSD2);
353 await writeToPort('AT+CUSD=2\r'); 348 await writeToPort('AT+CUSD=2\r');
354 } 349 }
355 350
356 await mutex.setLockWaitForSubCommand(); 351 await mutex.setLockWaitForSubCommand();
357 logger.info(`Executing USSD code "${code}"`); 352 logger.info(`Executing USSD code "${code}"`);
358 port.pipe(parserMain); 353 port.pipe(parserMain);
359 await writeToPort(`AT+CUSD=1,"${code}",15\r`); 354 await writeToPort(`AT+CUSD=1,"${code}",15\r`);
360 355
361 if (includeCUSD2 === 1 || includeCUSD2 === 2) { 356 if (includeCUSD2 === 1 || includeCUSD2 === 2) {
362 await mutex.setLockWaitForSubCommand(); 357 await mutex.setLockWaitForSubCommand();
363 logger.info('Terminating existing USSD session'); 358 logger.info('Terminating existing USSD session');
364 port.pipe(parserCUSD2); 359 port.pipe(parserCUSD2);
365 await writeToPort('AT+CUSD=2\r'); 360 await writeToPort('AT+CUSD=2\r');
366 } 361 }
367 362
368 await mutex.setLockWaitForSubCommand(); 363 await mutex.setLockWaitForSubCommand();
369 mutex.releaseLockWaitForSubCommand(); 364 mutex.releaseLockWaitForSubCommand();
370 365
371 mutex.releaseLockWaitForCommand(); 366 mutex.releaseLockWaitForCommand();
372 }); 367 });
373 } 368 }
374 369
375 function init() { 370 function init() {
376 port = new SerialPort(config.modem.device, { baudRate: 115200 }, (err) => { 371 port = new SerialPort(config.modem.device, { baudRate: 115200 }, (err) => {
377 if (err) { 372 if (err) {
378 logger.warn(`Error opening modem. ${err}. Terminating modem ${config.modem.device}.`); 373 logger.warn(`Error opening modem. ${err}. Terminating modem ${config.modem.device}.`);
379 process.exit(1); 374 process.exit(1);
380 } 375 }
381 376
382 registerModem(modemInfo); 377 registerModem(modemInfo);
383 }); 378 });
384 port.pipe(parserReadLine); 379 port.pipe(parserReadLine);
385 380
386 setInterval(() => { 381 setInterval(() => {
387 if ((new Date() - lastTs) > MAX_LAST_DATA_AGE_MS) { 382 if ((new Date() - lastTs) > MAX_LAST_DATA_AGE_MS) {
388 logger.warn(`No data for more than ${MAX_LAST_DATA_AGE_MS} ms. Modem might be unresponsive. Terminating modem ${config.modem.device}.`); 383 logger.warn(`No data for more than ${MAX_LAST_DATA_AGE_MS} ms. Modem might be unresponsive. Terminating modem ${config.modem.device}.`);
389 process.exit(0); 384 process.exit(0);
390 } 385 }
391 }, 30 * 1000); 386 }, 30 * 1000);
392 387
393 port.on('open', async () => { 388 port.on('open', async () => {
394 await mutex.setLockWaitForCommand(); 389 await mutex.setLockWaitForCommand();
395 390
396 logger.info('Modem opened'); 391 logger.info('Modem opened');
397 await writeToPort('\r'); 392 await writeToPort('\r');
398 await simpleSubCommand('AT\r'); 393 await simpleSubCommand('AT\r');
399 394
400 logger.info('Initializing modem to factory set'); 395 logger.info('Initializing modem to factory set');
401 await simpleSubCommand('AT&F\r'); 396 await simpleSubCommand('AT&F\r');
402 397
403 logger.info('Disabling echo'); 398 logger.info('Disabling echo');
404 await simpleSubCommand('ATE0\r'); 399 await simpleSubCommand('ATE0\r');
405 400
406 logger.info('Set to text mode'); 401 logger.info('Set to text mode');
407 await simpleSubCommand('AT+CMGF=1\r'); 402 await simpleSubCommand('AT+CMGF=1\r');
408 403
409 logger.info('Set message indication'); 404 logger.info('Set message indication');
410 await simpleSubCommand('AT+CNMI=1,1,2,1,1\r'); 405 await simpleSubCommand('AT+CNMI=1,1,2,1,1\r');
411 406
412 await readCOPS(); 407 await readCOPS();
413 408
414 await readManufacturer(); 409 await readManufacturer();
415 await readModel(); 410 await readModel();
416 await readIMEI(); 411 await readIMEI();
417 await readIMSI(); 412 await readIMSI();
418 413
419 if (!config.disable_delete_inbox_on_startup) { 414 if (!config.disable_delete_inbox_on_startup) {
420 logger.info('Deleting existing messages'); 415 logger.info('Deleting existing messages');
421 await deleteInbox(); 416 await deleteInbox();
422 } 417 }
423 418
424 mutex.releaseLockWaitForCommand(); 419 mutex.releaseLockWaitForCommand();
425 logger.verbose('Init completed'); 420 logger.verbose('Init completed');
426 421
427 registerModemToCenterPeriodically(); 422 registerModemToCenterPeriodically();
428 registerSignalStrengthBackgroundQuery(); 423 registerSignalStrengthBackgroundQuery();
429 }); 424 });
430 } 425 }
431 426
432 init(); 427 init();
433 428
434 exports.modemInfo = modemInfo; 429 exports.modemInfo = modemInfo;
435 exports.sendSMS = sendSMS; 430 exports.sendSMS = sendSMS;
436 exports.executeUSSD = executeUSSD; 431 exports.executeUSSD = executeUSSD;
lib/msisdn.js
1 'use strict'; File was deleted
2
3 const fs = require('fs');
4 const logger = require('komodo-sdk/logger');
5
6 const db = fs.existsSync('db-msisdn.json') || fs.existsSync('db-msisdn.js') ? require('../db-msisdn') : {};
7
8 logger.info(`MSISDN database loaded with ${Object.keys(db).length}.`);
9
10 module.exports = db;
11 1 'use strict';
lib/register-modem.js
1 'use strict'; 1 'use strict';
2 2
3 const path = require('path'); 3 const path = require('path');
4 const request = require('request'); 4 const request = require('request');
5 5
6 const locks = require('locks'); 6 const locks = require('locks');
7 7
8 const config = require('komodo-sdk/config'); 8 const config = require('komodo-sdk/config');
9 const logger = require('komodo-sdk/logger'); 9 const logger = require('komodo-sdk/logger');
10 10
11 // const counters = require('./counters');
12
13 const mutex = locks.createMutex(); 11 const mutex = locks.createMutex();
14 12
15 function reportUrl() { 13 function reportUrl() {
16 if (config.report_url.register_modem) { 14 if (config.report_url.register_modem) {
17 return config.report_url.register_modem; 15 return config.report_url.register_modem;
18 } 16 }
19 17
20 const baseUrl = path.dirname(config.report_url.incoming_sms); 18 const baseUrl = path.dirname(config.report_url.incoming_sms);
21 return `${baseUrl}/modems/set`; 19 return `${baseUrl}/modems/set`;
22 } 20 }
23 21
24 function sender(modemInfo) { 22 function sender(modemInfo) {
25 if (mutex.tryLock()) { 23 if (mutex.tryLock()) {
26 // logger.info('Getting message counters before registering modem');
27
28 // eslint-disable-next-line no-param-reassign
29 // modemInfo.messageSentCounter = await counters.get('MESSAGE_SENT', modemInfo);
30 // eslint-disable-next-line no-param-reassign
31 // modemInfo.messageReceivedCounter = await counters.get('MESSAGE_RECEIVED', modemInfo);
32
33 const requestOptions = { 24 const requestOptions = {
34 url: reportUrl(), 25 url: reportUrl(),
35 qs: { 26 qs: {
36 modem: config.name, 27 modem: config.name,
37 modem_device: config.modem.device, 28 modem_device: config.modem.device,
38 modem_imsi: modemInfo.imsi, 29 modem_imsi: modemInfo.imsi,
39 modem_msisdn: modemInfo.msisdn, 30 modem_msisdn: modemInfo.msisdn,
40 modem_network_id: modemInfo.networkId, 31 modem_network_id: modemInfo.networkId,
41 modem_network_name: modemInfo.networkName, 32 modem_network_name: modemInfo.networkName,
42 modem_signal_strength: modemInfo.signalStrength, 33 modem_signal_strength: modemInfo.signalStrength,
43 uptime: Math.floor(process.uptime()), 34 uptime: Math.floor(process.uptime()),
44 report_port: config.http_command_server.listen_port, 35 report_port: config.http_command_server.listen_port,
45 report_apikey: config.http_command_server.apikey, 36 report_apikey: config.http_command_server.apikey,
46 report_path_sms: '/sms', 37 report_path_sms: '/sms',
47 // counter_sent: modemInfo.messageSentCounter,
48 // counter_received: modemInfo.messageReceivedCounter,
49 }, 38 },
50 }; 39 };
51 40
52 logger.info('Sending modem registration to center'); 41 logger.info('Sending modem registration to center');
53 request(requestOptions, (err, res) => { 42 request(requestOptions, (err, res) => {
54 mutex.unlock(); 43 mutex.unlock();
55 44
56 if (err) { 45 if (err) {
57 logger.warn(`Error registering modem. ${err.toString()}`); 46 logger.warn(`Error registering modem. ${err.toString()}`);
58 } else if (res.statusCode !== 200) { 47 } else if (res.statusCode !== 200) {
59 logger.warn(`SMS center respond with HTTP status code ${res.statusCode}.`); 48 logger.warn(`SMS center respond with HTTP status code ${res.statusCode}.`);
60 } 49 }
61 }); 50 });
62 } 51 }
63 } 52 }
64 53
65 module.exports = sender; 54 module.exports = sender;
66 55