From b53db5e8b65ce8c11129b086cc6c818f3a21c1f4 Mon Sep 17 00:00:00 2001
From: Adhidarma Hadiwinoto <me@adhisimon.org>
Date: Wed, 16 Oct 2019 15:27:06 +0700
Subject: [PATCH] Migrated to modem-commands. I hope so

---
 index.js                              |  4 ++-
 lib/bootstrap.js                      | 47 +++++++++++++++++++++++++++++------
 lib/http-command-server/router-sms.js |  3 ++-
 lib/modem-commands/index.js           |  4 +--
 lib/modem-commands/ussd-codes.js      |  1 +
 lib/modem.js                          | 22 ++++++----------
 lib/register-modem.js                 |  4 ++-
 lib/report-sender2.js                 | 45 +++++++++++++++++++++++++++++++++
 lib/serialport-parsers.js             | 11 ++++++--
 modem-tester.js                       | 15 +++++------
 package.json                          |  3 ++-
 11 files changed, 123 insertions(+), 36 deletions(-)
 create mode 100644 lib/modem-commands/ussd-codes.js
 create mode 100644 lib/report-sender2.js

diff --git a/index.js b/index.js
index 5463af4..4065208 100644
--- a/index.js
+++ b/index.js
@@ -25,4 +25,6 @@ global.KOMODO_LOG_LABEL = (typeof config.name === 'string' && config.name.trim()
     : `KOMODO-MODEM@${path.basename(config.modem.device).replace('tty', '').toUpperCase()}`;
 
 require('./lib/http-command-server');
-require('./lib/modem');
+
+// require('./lib/modem');
+require('./lib/bootstrap');
diff --git a/lib/bootstrap.js b/lib/bootstrap.js
index 045e531..c8fd9d0 100644
--- a/lib/bootstrap.js
+++ b/lib/bootstrap.js
@@ -1,9 +1,12 @@
 /**
  * Modul modem bootstrap
- * @module bootstrap
+ * @module
  * @since 2019-09-25
  */
 
+const DEFAULT_BAUDRATE = 115200;
+
+const fs = require('fs');
 const SerialPort = require('serialport');
 
 const config = require('komodo-sdk/config');
@@ -11,14 +14,32 @@ const logger = require('komodo-sdk/logger');
 
 const parsers = require('./serialport-parsers');
 const modemCommands = require('./modem-commands');
+const ussdCodes = require('./modem-commands/ussd-codes');
+
 const modemInfo = require('./modem-info');
+const registerModem = require('./register-modem');
+
+logger.info('Bootstraping modem');
 
-const port = new SerialPort(config.modem.device, { baudRate: 115200 }, async (err) => {
+if (!fs.existsSync(config.modem.device)) {
+    logger.error(`Modem not found on ${config.modem.device}. Terminating.`);
+    process.exit(1);
+}
+
+const port = new SerialPort(config.modem.device, {
+    baudRate: (config.modem && config.modem.options && config.modem.options.baudRate)
+        || DEFAULT_BAUDRATE,
+}, async (err) => {
     if (err) {
         logger.warn(`Error opening modem. ${err}. Terminating modem ${config.modem.device}.`);
         process.exit(1);
     }
 
+    global.MODEM_PORT = port;
+    parsers.setPort(port);
+    // modemCommands.setPort(port);
+    port.pipe(parsers.parserReadline);
+
     await modemCommands.writeToPortAndWaitForOkOrError(`${modemCommands.CTRLZ}AT&FE0\r`);
     await modemCommands.initATCommands();
     await modemCommands.queryManufacturer();
@@ -27,6 +48,22 @@ const port = new SerialPort(config.modem.device, { baudRate: 115200 }, async (er
     await modemCommands.queryCOPSAndSignalQuality();
 
     logger.info('Modem state', modemInfo);
+    registerModem();
+
+    if (config.debug_sms_destination_on_start) {
+        await modemCommands.sendSMS(config.debug_sms_destination_on_start,
+            `${config.name} (${modemInfo.imsi || 'UNKNOWN'}) started on ${new Date()}`);
+    }
+
+    if (config.debug_ussd_code_on_start) {
+        const ussdResponse = await modemCommands.executeUSSD(config.debug_ussd_code_on_start, 2);
+        logger.info('USSD RESPONSE', { command: config.debug_ussd_code_on_start, ussdResponse });
+    }
+
+    if ((modemInfo.networkName && modemInfo.networkName === 'TELKOMSEL') || config.bootstrap_tsel_sms_quota_check) {
+        const ussdResponse = await modemCommands.executeUSSD(ussdCodes.TSEL_SMS_QUOTA_CHECK, 1);
+        logger.info('USSD RESPONSE', { command: config.debug_ussd_code_on_start, ussdResponse });
+    }
 
     setInterval(async () => {
         await modemCommands.initATCommands();
@@ -35,10 +72,6 @@ const port = new SerialPort(config.modem.device, { baudRate: 115200 }, async (er
         await modemCommands.queryIMEIAndIMSI();
         await modemCommands.queryCOPSAndSignalQuality();
         logger.info('Modem state', modemInfo);
+        registerModem();
     }, config.interval_beetwen_signal_strength_ms || 30000);
 });
-
-global.MODEM_PORT = port;
-parsers.setPort(port);
-modemCommands.setPort(port);
-port.pipe(parsers.parserReadline);
diff --git a/lib/http-command-server/router-sms.js b/lib/http-command-server/router-sms.js
index 00e8c32..4585d0b 100644
--- a/lib/http-command-server/router-sms.js
+++ b/lib/http-command-server/router-sms.js
@@ -2,7 +2,8 @@
 
 const express = require('express');
 
-const modem = require('../modem');
+// const modem = require('../modem');
+const modem = require('../modem-commands');
 
 const router = express.Router();
 module.exports = router;
diff --git a/lib/modem-commands/index.js b/lib/modem-commands/index.js
index 293d291..e765d30 100644
--- a/lib/modem-commands/index.js
+++ b/lib/modem-commands/index.js
@@ -301,7 +301,7 @@ function sendSMS(destination, msg) {
             logger.verbose('SMS sent callback called', { data });
 
             if (data.indexOf('ERROR') >= 0 || data.indexOf('+CMS ERROR') >= 0 || data.indexOf('+CMGS') >= 0) {
-                logger.verbose('SMS sent');
+                logger.info('SMS sent', { data });
                 parsers.setSmsSentCallback(null);
                 mutex.unlock(MUTEX_COMMAND, 'sendSMS');
                 resolve(data.indexOf('ERROR') >= 0 ? null : data.toString().trim());
@@ -321,7 +321,7 @@ function sendSMS(destination, msg) {
         }
 
         const correctedDestination = `+${destination.replace(/^0/, '62')}`.replace(/^\++/, '+');
-        logger.verbose(`Sending sms to ${correctedDestination}`, { msg });
+        logger.info(`Sending sms to ${correctedDestination}`, { msg, length: msg.length });
 
         await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND);
 
diff --git a/lib/modem-commands/ussd-codes.js b/lib/modem-commands/ussd-codes.js
new file mode 100644
index 0000000..d331913
--- /dev/null
+++ b/lib/modem-commands/ussd-codes.js
@@ -0,0 +1 @@
+exports.TSEL_SMS_QUOTA_CHECK = '*888*2*2*4#';
diff --git a/lib/modem.js b/lib/modem.js
index 97bd969..d36e877 100644
--- a/lib/modem.js
+++ b/lib/modem.js
@@ -5,6 +5,7 @@
  *
  * @module
  * @deprecated going to move to module:bootstrap
+ * @see module:bootstrap
  */
 
 const DEFAULT_SLEEP_AFTER_SEND_SMS_MS = 2000;
@@ -13,6 +14,7 @@ const MAX_LAST_DATA_AGE_MS = 3 * 60 * 1000;
 const REGEX_WAIT_FOR_OK_OR_ERROR = /\n(?:OK|ERROR)\r/;
 // const REGEX_WAIT_FOR_OK_OR_ERROR_USSD = /\n(?:OK|ERROR)\r/;
 
+const path = require('path');
 const moment = require('moment');
 const SerialPort = require('serialport');
 const ParserReadline = require('@serialport/parser-readline');
@@ -23,6 +25,11 @@ const ParserRegex = require('@serialport/parser-regex');
 const config = require('komodo-sdk/config');
 const logger = require('komodo-sdk/logger');
 
+// const stack = new Error().stack;
+logger.warn(`'${path.basename(__filename, '.js')}' is DEPRECATED, please use 'modem-commands'!`);
+// eslint-disable-next-line no-console
+console.trace(`'${path.basename(__filename, '.js')}' is DEPRECATED, please use 'modem-commands'!`);
+
 const mutex = require('./mutex');
 const common = require('./common');
 const sms = require('./sms');
@@ -30,20 +37,7 @@ const dbCops = require('./db-cops');
 const reportSender = require('./report-sender');
 const registerModem = require('./register-modem');
 
-const modemInfo = {
-    device: config.modem.device,
-    manufacturer: null,
-    model: null,
-    imei: null,
-    imsi: null,
-    msisdn: null,
-    cops: null,
-    networkId: null,
-    networkName: null,
-    signalStrength: null,
-    signalStrengthTs: null,
-    signalStrengthTsReadable: null,
-};
+const modemInfo = require('./modem-info');
 
 let lastTs = new Date();
 
diff --git a/lib/register-modem.js b/lib/register-modem.js
index d58c0d8..dda773c 100644
--- a/lib/register-modem.js
+++ b/lib/register-modem.js
@@ -8,6 +8,8 @@ const locks = require('locks');
 const config = require('komodo-sdk/config');
 const logger = require('komodo-sdk/logger');
 
+const modemInfo = require('./modem-info');
+
 const mutex = locks.createMutex();
 
 function reportUrl() {
@@ -19,7 +21,7 @@ function reportUrl() {
     return `${baseUrl}/modems/set`;
 }
 
-function sender(modemInfo) {
+function sender() {
     if (mutex.tryLock()) {
         const requestOptions = {
             url: reportUrl(),
diff --git a/lib/report-sender2.js b/lib/report-sender2.js
new file mode 100644
index 0000000..e50d3ea
--- /dev/null
+++ b/lib/report-sender2.js
@@ -0,0 +1,45 @@
+const request = require('request');
+
+const config = require('komodo-sdk/config');
+const logger = require('komodo-sdk/logger');
+const modemInfo = require('./modem-info');
+
+function incomingSMS(ts, from, msg) {
+    if (!ts || !from || !msg
+        || !config || !config.report_url || !config.report_url.incoming_sms) return;
+
+    const requestOptions = {
+        url: config.report_url.incoming_sms,
+        qs: {
+            ts,
+            // status: message.metadata.status,
+            number: from,
+            msg,
+            modem: config.name,
+            modem_imsi: modemInfo.imsi,
+            modem_msisdn: modemInfo.msisdn,
+            modem_device: config.modem.device,
+            modem_network_id: modemInfo.networkId,
+            modem_network_name: modemInfo.networkName,
+            modem_signal_strength: modemInfo.signalStrength,
+            uptime: Math.floor(process.uptime()),
+            report_port: config.http_command_server.listen_port,
+            report_apikey: config.http_command_server.apikey,
+            report_path_sms: '/sms',
+        },
+    };
+
+    logger.info('Sending report via HTTP', requestOptions);
+    request(requestOptions, (err, res, body) => {
+        if (err) {
+            logger.warn(`Error sending report via HTTP. ${err.toString()}`);
+            return;
+        }
+
+        if (res.statusCode !== 200) {
+            logger.warn(`Error sending report via HTTP. Server respond with HTTP status code ${res.statusCode}`, { http_status_code: res.statusCode, body });
+        }
+    });
+}
+
+exports.incomingSMS = incomingSMS;
diff --git a/lib/serialport-parsers.js b/lib/serialport-parsers.js
index 719ccae..5f5a5a4 100644
--- a/lib/serialport-parsers.js
+++ b/lib/serialport-parsers.js
@@ -11,6 +11,7 @@ const logger = require('komodo-sdk/logger');
 
 const dbCops = require('./db-cops');
 const modemInfo = require('./modem-info');
+const reportSender = require('./report-sender2');
 
 let port;
 
@@ -88,7 +89,7 @@ function onPduDeliver(data, parsedData) {
     const ts = new Date(parsedData.getScts().getIsoString());
 
     logger.verbose('PDU processed', { ts, from, msg });
-    return { from, msg };
+    return { ts, from, msg };
 }
 
 function onCOPS(data) {
@@ -149,7 +150,13 @@ parserReadline.on('data', (data) => {
     if (pduParsed && pduParsed.constructor.name === 'Deliver' && pduParsed.getData().getSize()) {
         const pduType = pduParsed.getType();
         logger.verbose('Got a PDU SMS-DELIVER', { pduType });
-        onPduDeliver(data, pduParsed);
+        const parsedData = onPduDeliver(data, pduParsed);
+
+        if (parsedData.ts && parsedData.from && parsedData.msg) {
+            reportSender.incomingSMS(parsedData.ts, parsedData.from, parsedData.msg);
+        } else {
+            logger.warn('Got a PDU SMS-DELIVER but failed on parsing PDU message');
+        }
     } else if (data.toString().trim() === 'ERROR') {
         if (typeof smsSentCallback === 'function') smsSentCallback(data.toString());
     } else if (isResultCodeIs(data, 'CSQ')) {
diff --git a/modem-tester.js b/modem-tester.js
index bf9bb00..ebba906 100644
--- a/modem-tester.js
+++ b/modem-tester.js
@@ -33,13 +33,14 @@ const port = new SerialPort(config.modem.device, { baudRate: 115200 }, async (er
     await modemCommands.queryCOPSAndSignalQuality();
     logger.info('Modem state', modemInfo);
 
-    // await modemCommands.sendSMS('628128364883', `coba pakai pdu ${new Date()}`);
-    // await modemCommands.sendSMS('+6282210008543', `coba pakai pdu ${new Date()}`);
-    // await modemCommands.sendSMS('6281809903333', `coba pakai pdu ${new Date()}`);
-    await modemCommands.sendSMS('999', `coba pakai pdu ${new Date()}`);
+    if (config.debug_sms_destination_on_start) {
+        await modemCommands.sendSMS(config.debug_sms_destination_on_start, `${modemInfo.imsi || 'UNKNOWN'}: coba pakai pdu ${new Date()}`);
+    }
 
-    // const ussdResponse = await modemCommands.executeUSSD('*888#', 2);
-    // logger.info('USSD RESPONSE', { ussdResponse });
+    if (config.debug_ussd_code_on_start) {
+        const ussdResponse = await modemCommands.executeUSSD(config.debug_ussd_code_on_start, 2);
+        logger.info('USSD RESPONSE', { command: config.debug_ussd_code_on_start, ussdResponse });
+    }
 
     setInterval(async () => {
         await modemCommands.initATCommands();
@@ -53,7 +54,7 @@ const port = new SerialPort(config.modem.device, { baudRate: 115200 }, async (er
 
 global.MODEM_PORT = port;
 parsers.setPort(port);
-modemCommands.setPort(port);
+// modemCommands.setPort(port);
 
 if (config && config.modem_tester && config.modem_tester.parser === 'regex') {
     logger.info('Using parserWaitForOkOrError');
diff --git a/package.json b/package.json
index b18a827..47e4bf6 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,8 @@
   "main": "index.js",
   "scripts": {
     "test": "mocha",
-    "postversion": "git push && git push --tags"
+    "postversion": "git push && git push --tags",
+    "jsdoc": "./generate-jsdoc.sh"
   },
   "repository": {
     "type": "git",
-- 
1.9.0