Commit ea7f35320e9c40262d4a2b43e363153c050bbe25

Authored by Adhidarma Hadiwinoto
1 parent fad8552593
Exists in master

Refactor modem-commands

Showing 3 changed files with 223 additions and 171 deletions Side-by-side Diff

lib/modem-commands.js
... ... @@ -1,170 +0,0 @@
1   -const MUTEX_COMMAND = 'COMMAND';
2   -exports.MUTEX_COMMAND = MUTEX_COMMAND;
3   -
4   -const MUTEX_SUBCOMMAND = 'SUBCOMMAND';
5   -exports.MUTEX_SUBCOMMAND = MUTEX_SUBCOMMAND;
6   -
7   -const ParserReadline = require('@serialport/parser-readline');
8   -const ParserRegex = require('@serialport/parser-regex');
9   -
10   -const logger = require('komodo-sdk/logger');
11   -const mutex = require('./mutex-common');
12   -const parsers = require('./serialport-parsers');
13   -const modemInfo = require('./modem-info');
14   -
15   -let port;
16   -
17   -function writeToPort(data) {
18   - return new Promise((resolve) => {
19   - modemInfo.lastWriteTs = new Date();
20   - port.write(data, (err, bytesWritten) => {
21   - if (err) logger.warn(`ERROR: ${err.toString()}`);
22   -
23   - logger.verbose('OUTGOING', { data: data.toString(), bytesWritten, err });
24   - resolve(bytesWritten);
25   - });
26   - });
27   -}
28   -
29   -exports.writeToPortAndWaitForReadline = function writeToPortAndWaitForReadline(cmd, lockName) {
30   - let resolved = false;
31   -
32   - return new Promise(async (resolve) => {
33   - const parser = new ParserReadline({ delimiter: parsers.PARSER_READLINE_DELIMITER });
34   - parser.on('data', (data) => {
35   - port.unpipe(parser);
36   - mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
37   - if (!resolved) {
38   - resolved = true;
39   - resolve(data);
40   - }
41   - });
42   -
43   - await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
44   - port.pipe(parser);
45   - await writeToPort(cmd);
46   - });
47   -};
48   -
49   -exports.writeToPortAndWaitForOkOrError = function writeToPortAndWaitForOkOrError(cmd, lockName) {
50   - return new Promise(async (resolve) => {
51   - const parser = new ParserRegex({ regex: /(?:OK|ERROR)\r\n/ });
52   - parser.on('data', (data) => {
53   - port.unpipe(parser);
54   - mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
55   - resolve(data);
56   - });
57   -
58   - await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
59   - port.pipe(parser);
60   - await writeToPort(cmd);
61   - });
62   -};
63   -
64   -exports.sleep = function sleep(ms) {
65   - return new Promise((resolve) => {
66   - setTimeout(() => {
67   - resolve();
68   - }, ms || 0);
69   - });
70   -};
71   -
72   -
73   -exports.setPort = function setPort(val) {
74   - port = val;
75   -};
76   -
77   -exports.querySignalQuality = function querySignalQuality() {
78   - return new Promise(async (resolve) => {
79   - if (!mutex.tryLock(MUTEX_COMMAND, 'querySignalQuality')) {
80   - resolve(false);
81   - return;
82   - }
83   -
84   - await writeToPort('AT+CSQ\r');
85   - mutex.unlock(MUTEX_COMMAND, 'querySignalQuality');
86   - resolve(true);
87   - });
88   -};
89   -
90   -exports.queryCOPS = function queryCOPS(lockName) {
91   - return new Promise(async (resolve) => {
92   - await mutex.lock(lockName || MUTEX_COMMAND, 'queryCOPS');
93   - await writeToPort('AT+COPS?\r');
94   - mutex.unlock(lockName || MUTEX_COMMAND, 'queryCOPS');
95   - resolve(true);
96   - });
97   -};
98   -
99   -exports.queryCOPSAndSignalQuality = function queryCOPSAndSignalQuality(skipOnLocked) {
100   - return new Promise(async (resolve) => {
101   - if (!skipOnLocked) {
102   - await mutex.lock(MUTEX_COMMAND);
103   - } else if (!mutex.tryLock(MUTEX_COMMAND, 'queryCOPSAndSignalQuality')) {
104   - resolve(false);
105   - return;
106   - }
107   -
108   - await this.writeToPortAndWaitForOkOrError('AT+COPS?\r', MUTEX_SUBCOMMAND);
109   - await this.writeToPortAndWaitForOkOrError('AT+CSQ\r', MUTEX_SUBCOMMAND);
110   -
111   - mutex.unlock(MUTEX_COMMAND, 'queryCopsAndSignalQuality');
112   - resolve(true);
113   - });
114   -};
115   -
116   -exports.queryIMEI = function queryIMEI(lockName) {
117   - return new Promise(async (resolve) => {
118   - const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
119   - parser.on('data', (data) => {
120   - logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMEI' });
121   - port.unpipe(parser);
122   - mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMEI');
123   - modemInfo.imei = data.toString().trim() || null;
124   - logger.info('IMEI extracted', { imei: modemInfo.imei });
125   - resolve(modemInfo.imei);
126   - });
127   -
128   - await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMEI');
129   -
130   - port.pipe(parser);
131   - await writeToPort('AT+CGSN\r');
132   - });
133   -};
134   -
135   -exports.queryIMSI = function queryIMSI(lockName) {
136   - return new Promise(async (resolve) => {
137   - const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
138   - parser.on('data', (data) => {
139   - logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMSI' });
140   - port.unpipe(parser);
141   - mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMSI');
142   - modemInfo.imsi = data.toString().trim() || null;
143   - logger.info('IMSI extracted', { imsi: modemInfo.imsi });
144   - resolve(modemInfo.imsi);
145   - });
146   -
147   - await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMSI');
148   -
149   - port.pipe(parser);
150   - await writeToPort('AT+CIMI\r');
151   - });
152   -};
153   -
154   -exports.queryIMEIAndIMSI = async function queryIMEIAndIMSI() {
155   - await mutex.lock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
156   -
157   - const imei = await this.queryIMEI(MUTEX_SUBCOMMAND);
158   - const imsi = await this.queryIMSI(MUTEX_SUBCOMMAND);
159   -
160   - await mutex.unlock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
161   - return { imei, imsi };
162   -};
163   -
164   -exports.initATCommands = async function initATCommands() {
165   - await mutex.lock(MUTEX_COMMAND, 'INIT MODEM');
166   - await this.writeToPortAndWaitForOkOrError('ATE0\r', MUTEX_SUBCOMMAND);
167   - await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND);
168   - await this.writeToPortAndWaitForOkOrError('AT+CNMI=1,2,0,1,0\r', MUTEX_SUBCOMMAND);
169   - mutex.unlock(MUTEX_COMMAND, 'INIT MODEM');
170   -};
lib/modem-commands/index.js
... ... @@ -0,0 +1,216 @@
  1 +const MUTEX_COMMAND = 'COMMAND';
  2 +exports.MUTEX_COMMAND = MUTEX_COMMAND;
  3 +
  4 +const MUTEX_SUBCOMMAND = 'SUBCOMMAND';
  5 +exports.MUTEX_SUBCOMMAND = MUTEX_SUBCOMMAND;
  6 +
  7 +const pdu = require('node-pdu');
  8 +
  9 +const ParserReadline = require('@serialport/parser-readline');
  10 +const ParserRegex = require('@serialport/parser-regex');
  11 +
  12 +const logger = require('komodo-sdk/logger');
  13 +const mutex = require('../mutex-common');
  14 +const parsers = require('../serialport-parsers');
  15 +const modemInfo = require('../modem-info');
  16 +
  17 +let port;
  18 +
  19 +function writeToPort(data) {
  20 + return new Promise((resolve) => {
  21 + modemInfo.lastWriteTs = new Date();
  22 + port.write(data, (err, bytesWritten) => {
  23 + if (err) logger.warn(`ERROR: ${err.toString()}`);
  24 +
  25 + logger.verbose('OUTGOING', { data: data.toString(), bytesWritten, err });
  26 + resolve(bytesWritten);
  27 + });
  28 + });
  29 +}
  30 +
  31 +exports.writeToPortAndWaitForReadline = function writeToPortAndWaitForReadline(cmd, lockName) {
  32 + let resolved = false;
  33 +
  34 + return new Promise(async (resolve) => {
  35 + const parser = new ParserReadline({ delimiter: parsers.PARSER_READLINE_DELIMITER });
  36 + parser.on('data', (data) => {
  37 + port.unpipe(parser);
  38 + mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
  39 + if (!resolved) {
  40 + resolved = true;
  41 + resolve(data);
  42 + }
  43 + });
  44 +
  45 + await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
  46 + port.pipe(parser);
  47 + await writeToPort(cmd);
  48 + });
  49 +};
  50 +
  51 +exports.writeToPortAndWaitForOkOrError = function writeToPortAndWaitForOkOrError(cmd, lockName) {
  52 + return new Promise(async (resolve) => {
  53 + const parser = new ParserRegex({ regex: /(?:OK|ERROR)\r\n/ });
  54 + parser.on('data', (data) => {
  55 + port.unpipe(parser);
  56 + mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim());
  57 + resolve(data);
  58 + });
  59 +
  60 + await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim());
  61 + port.pipe(parser);
  62 + await writeToPort(cmd);
  63 + });
  64 +};
  65 +
  66 +exports.sleep = function sleep(ms) {
  67 + return new Promise((resolve) => {
  68 + setTimeout(() => {
  69 + resolve();
  70 + }, ms || 0);
  71 + });
  72 +};
  73 +
  74 +
  75 +exports.setPort = function setPort(val) {
  76 + port = val;
  77 +};
  78 +
  79 +exports.querySignalQuality = function querySignalQuality() {
  80 + return new Promise(async (resolve) => {
  81 + if (!mutex.tryLock(MUTEX_COMMAND, 'querySignalQuality')) {
  82 + resolve(false);
  83 + return;
  84 + }
  85 +
  86 + await writeToPort('AT+CSQ\r');
  87 + mutex.unlock(MUTEX_COMMAND, 'querySignalQuality');
  88 + resolve(true);
  89 + });
  90 +};
  91 +
  92 +exports.queryCOPS = function queryCOPS(lockName) {
  93 + return new Promise(async (resolve) => {
  94 + await mutex.lock(lockName || MUTEX_COMMAND, 'queryCOPS');
  95 + await writeToPort('AT+COPS?\r');
  96 + mutex.unlock(lockName || MUTEX_COMMAND, 'queryCOPS');
  97 + resolve(true);
  98 + });
  99 +};
  100 +
  101 +exports.queryCOPSAndSignalQuality = function queryCOPSAndSignalQuality(skipOnLocked) {
  102 + return new Promise(async (resolve) => {
  103 + if (!skipOnLocked) {
  104 + await mutex.lock(MUTEX_COMMAND);
  105 + } else if (!mutex.tryLock(MUTEX_COMMAND, 'queryCOPSAndSignalQuality')) {
  106 + resolve(false);
  107 + return;
  108 + }
  109 +
  110 + await this.writeToPortAndWaitForOkOrError('AT+COPS?\r', MUTEX_SUBCOMMAND);
  111 + await this.writeToPortAndWaitForOkOrError('AT+CSQ\r', MUTEX_SUBCOMMAND);
  112 +
  113 + mutex.unlock(MUTEX_COMMAND, 'queryCopsAndSignalQuality');
  114 + resolve(true);
  115 + });
  116 +};
  117 +
  118 +exports.queryIMEI = function queryIMEI(lockName) {
  119 + return new Promise(async (resolve) => {
  120 + const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
  121 + parser.on('data', (data) => {
  122 + logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMEI' });
  123 + port.unpipe(parser);
  124 + mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMEI');
  125 + modemInfo.imei = data.toString().trim() || null;
  126 + logger.info('IMEI extracted', { imei: modemInfo.imei });
  127 + resolve(modemInfo.imei);
  128 + });
  129 +
  130 + await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMEI');
  131 +
  132 + port.pipe(parser);
  133 + await writeToPort('AT+CGSN\r');
  134 + });
  135 +};
  136 +
  137 +exports.queryIMSI = function queryIMSI(lockName) {
  138 + return new Promise(async (resolve) => {
  139 + const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
  140 + parser.on('data', (data) => {
  141 + logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMSI' });
  142 + port.unpipe(parser);
  143 + mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMSI');
  144 + modemInfo.imsi = data.toString().trim() || null;
  145 + logger.info('IMSI extracted', { imsi: modemInfo.imsi });
  146 + resolve(modemInfo.imsi);
  147 + });
  148 +
  149 + await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMSI');
  150 +
  151 + port.pipe(parser);
  152 + await writeToPort('AT+CIMI\r');
  153 + });
  154 +};
  155 +
  156 +exports.queryIMEIAndIMSI = async function queryIMEIAndIMSI() {
  157 + await mutex.lock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
  158 +
  159 + const imei = await this.queryIMEI(MUTEX_SUBCOMMAND);
  160 + const imsi = await this.queryIMSI(MUTEX_SUBCOMMAND);
  161 +
  162 + await mutex.unlock(MUTEX_COMMAND, 'queryIMEIAndIMSI');
  163 + return { imei, imsi };
  164 +};
  165 +
  166 +exports.queryManufacturer = function queryManufacturer(lockName) {
  167 + return new Promise(async (resolve) => {
  168 + const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
  169 + parser.on('data', (data) => {
  170 + logger.verbose('INCOMING', { data: data.toString(), parser: 'parserManufacturer' });
  171 + port.unpipe(parser);
  172 + mutex.unlock(lockName || MUTEX_COMMAND, 'parserManufacturer');
  173 + modemInfo.manufacturer = data.toString().trim() || null;
  174 + logger.info('Manufacturer extracted', { manufacturer: modemInfo.manufacturer });
  175 + resolve(modemInfo.manufacturer);
  176 + });
  177 +
  178 + await mutex.lock(lockName || MUTEX_COMMAND, 'queryManufacturer');
  179 +
  180 + port.pipe(parser);
  181 + await writeToPort('AT+CGMI\r');
  182 + });
  183 +};
  184 +
  185 +exports.queryModel = function queryModel(lockName) {
  186 + return new Promise(async (resolve) => {
  187 + const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX });
  188 + parser.on('data', (data) => {
  189 + logger.verbose('INCOMING', { data: data.toString(), parser: 'parserModel' });
  190 + port.unpipe(parser);
  191 + mutex.unlock(lockName || MUTEX_COMMAND, 'parserModel');
  192 + modemInfo.model = data.toString().trim() || null;
  193 + logger.info('Model extracted', { model: modemInfo.model });
  194 + resolve(modemInfo.model);
  195 + });
  196 +
  197 + await mutex.lock(lockName || MUTEX_COMMAND, 'queryModel');
  198 +
  199 + port.pipe(parser);
  200 + await writeToPort('AT+CGMM\r');
  201 + });
  202 +};
  203 +
  204 +exports.sendSMS = function sendSMS(destination, msg) {
  205 + return new Promise(async (resolve) => {
  206 +
  207 + });
  208 +};
  209 +
  210 +exports.initATCommands = async function initATCommands() {
  211 + await mutex.lock(MUTEX_COMMAND, 'INIT MODEM');
  212 + await this.writeToPortAndWaitForOkOrError('\rATE0\r', MUTEX_SUBCOMMAND);
  213 + await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND);
  214 + await this.writeToPortAndWaitForOkOrError('AT+CNMI=1,2,0,1,0\r', MUTEX_SUBCOMMAND);
  215 + mutex.unlock(MUTEX_COMMAND, 'INIT MODEM');
  216 +};
... ... @@ -20,23 +20,29 @@ const port = new SerialPort(config.modem.device, { baudRate: 115200 }, async (er
20 20 process.exit(1);
21 21 }
22 22  
23   - await modemCommands.writeToPortAndWaitForOkOrError('AT\r');
  23 + await modemCommands.writeToPortAndWaitForOkOrError('\rAT\r');
24 24 await modemCommands.writeToPortAndWaitForOkOrError('AT&FE0\r');
25 25 await modemCommands.writeToPortAndWaitForOkOrError('AT+CMGF=0\r');
26 26 await modemCommands.writeToPortAndWaitForOkOrError('AT+CNMI=1,2,0,1,0\r');
27 27  
  28 + await modemCommands.queryManufacturer();
  29 + await modemCommands.queryModel();
  30 +
28 31 await modemCommands.queryIMEIAndIMSI();
29 32 await modemCommands.queryCOPSAndSignalQuality();
30 33 logger.info('Modem state', modemInfo);
31 34  
32 35 setInterval(async () => {
33 36 await modemCommands.initATCommands();
  37 + await modemCommands.queryManufacturer();
  38 + await modemCommands.queryModel();
34 39 await modemCommands.queryIMEIAndIMSI();
35 40 await modemCommands.queryCOPSAndSignalQuality();
36 41 logger.info('Modem state', modemInfo);
37 42 }, (config && config.interval_beetwen_signal_strength_ms) || 30000);
38 43 });
39 44  
  45 +global.MODEM_PORT = port;
40 46 parsers.setPort(port);
41 47 modemCommands.setPort(port);
42 48