Commit 3ec3e9eb37d6c78f5816089fc549c63f48108d6b

Authored by Adhidarma Hadiwinoto
1 parent 56758af444
Exists in master

HTTP command server: router-info

Showing 3 changed files with 19 additions and 1 deletions Inline Diff

lib/http-command-server/index.js
1 'use strict'; 1 'use strict';
2 2
3 const express = require('express'); 3 const express = require('express');
4 4
5 const config = require('komodo-sdk/config'); 5 const config = require('komodo-sdk/config');
6 const logger = require('komodo-sdk/logger'); 6 const logger = require('komodo-sdk/logger');
7 7
8 const routerInfo = require('./router-info');
8 const routerSMS = require('./router-sms'); 9 const routerSMS = require('./router-sms');
9 10
10 const app = express(); 11 const app = express();
11 12
12 function middlewareCustomLog(req, res, next) { 13 function middlewareCustomLog(req, res, next) {
13 logger.info('Incoming request on HTTP command server', { ip: req.ip, url: req.url }); 14 logger.info('Incoming request on HTTP command server', { ip: req.ip, url: req.url });
14 next(); 15 next();
15 } 16 }
16 17
17 function middlewareCheckApikey(req, res, next) { 18 function middlewareCheckApikey(req, res, next) {
18 if (!req.query.apikey || (req.query.apikey !== config.http_command_server.apikey)) { 19 if (!req.query.apikey || (req.query.apikey !== config.http_command_server.apikey)) {
19 res.json({ 20 res.json({
20 status: 'NOT-OK', 21 status: 'NOT-OK',
21 error: 'INVALID_APIKEY', 22 error: 'INVALID_APIKEY',
22 message: 'Invalid apikey', 23 message: 'Invalid apikey',
23 }); 24 });
24 } else { 25 } else {
25 next(); 26 next();
26 } 27 }
27 } 28 }
28 29
29 app.use(middlewareCustomLog); 30 app.use(middlewareCustomLog);
30 app.use(middlewareCheckApikey); 31 app.use(middlewareCheckApikey);
32
33 app.use('/info', routerInfo);
31 app.use('/sms', routerSMS); 34 app.use('/sms', routerSMS);
32 35
33 36
34 app.listen(config.http_command_server.listen_port, () => { 37 app.listen(config.http_command_server.listen_port, () => {
35 logger.info(`HTTP command server listeing on port ${config.http_command_server.listen_port}`); 38 logger.info(`HTTP command server listeing on port ${config.http_command_server.listen_port}`);
36 }); 39 });
37 40
lib/http-command-server/router-info.js
File was created 1 'use strict';
2
3 const express = require('express');
4
5 const modem = require('../modem');
6
7 const router = express.Router();
8 module.exports = router;
9
10 function handlerMain(req, res) {
11 res.json(modem.modemInfo);
12 }
13
14 router.get('/', handlerMain);
15
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 DELIMITER_WAIT_FOR_OK = '\nOK\r\n'; 4 const DELIMITER_WAIT_FOR_OK = '\nOK\r\n';
5 5
6 const SerialPort = require('serialport'); 6 const SerialPort = require('serialport');
7 const ParserReadline = require('@serialport/parser-readline'); 7 const ParserReadline = require('@serialport/parser-readline');
8 const ParserDelimiter = require('@serialport/parser-delimiter'); 8 const ParserDelimiter = require('@serialport/parser-delimiter');
9 9
10 const config = require('komodo-sdk/config'); 10 const config = require('komodo-sdk/config');
11 const logger = require('komodo-sdk/logger'); 11 const logger = require('komodo-sdk/logger');
12 12
13 const mutex = require('./mutex'); 13 const mutex = require('./mutex');
14 const common = require('./common'); 14 const common = require('./common');
15 const sms = require('./sms'); 15 const sms = require('./sms');
16 const reportSender = require('./report-sender'); 16 const reportSender = require('./report-sender');
17 17
18 const modemInfo = { 18 const modemInfo = {
19 manufacturer: null, 19 manufacturer: null,
20 model: null, 20 model: null,
21 imei: null,
21 imsi: null, 22 imsi: null,
22 signalStrength: null, 23 signalStrength: null,
23 config: config.modem, 24 config: config.modem,
24 }; 25 };
25 26
26 const port = new SerialPort(config.modem.device, { baudRate: 115200 }); 27 const port = new SerialPort(config.modem.device, { baudRate: 115200 });
27 28
28 const parserReadLine = new ParserReadline(); 29 const parserReadLine = new ParserReadline();
29 const parserWaitForOK = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); 30 const parserWaitForOK = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK });
30 port.pipe(parserReadLine); 31 port.pipe(parserReadLine);
31 32
32 function writeToPort(data) { 33 function writeToPort(data) {
33 return new Promise((resolve) => { 34 return new Promise((resolve) => {
34 port.write(data, (err, bytesWritten) => { 35 port.write(data, (err, bytesWritten) => {
35 if (err) logger.warn(`ERROR: ${err.toString()}`); 36 if (err) logger.warn(`ERROR: ${err.toString()}`);
36 logger.verbose(`* OUT: ${data}`); 37 logger.verbose(`* OUT: ${data}`);
37 resolve(bytesWritten); 38 resolve(bytesWritten);
38 }); 39 });
39 }); 40 });
40 } 41 }
41 42
42 async function writeToPortAndWaitForOK(data) { 43 async function writeToPortAndWaitForOK(data) {
43 await mutex.setLockWaitForOK(); 44 await mutex.setLockWaitForOK();
44 const result = await writeToPort(data); 45 const result = await writeToPort(data);
45 await mutex.setLockWaitForOK(); 46 await mutex.setLockWaitForOK();
46 mutex.releaseLockWaitForOK(); 47 mutex.releaseLockWaitForOK();
47 return result; 48 return result;
48 } 49 }
49 50
50 async function readSMS(slot) { 51 async function readSMS(slot) {
51 const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); 52 const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK });
52 parser.on('data', async (data) => { 53 parser.on('data', async (data) => {
53 if (data) { 54 if (data) {
54 const smsObject = sms.extract(data.toString().trim()); 55 const smsObject = sms.extract(data.toString().trim());
55 // console.log('SMS', smsObject); // eslint-disable-line no-console 56 // console.log('SMS', smsObject); // eslint-disable-line no-console
56 reportSender.incomingSMS(smsObject); 57 reportSender.incomingSMS(smsObject);
57 } 58 }
58 mutex.releaseLockWaitForOK(); 59 mutex.releaseLockWaitForOK();
59 }); 60 });
60 61
61 logger.info(`Reading SMS on slot ${slot}`); 62 logger.info(`Reading SMS on slot ${slot}`);
62 port.pipe(parser); 63 port.pipe(parser);
63 await writeToPortAndWaitForOK(`AT+CMGR=${slot}\r`); 64 await writeToPortAndWaitForOK(`AT+CMGR=${slot}\r`);
64 port.unpipe(parser); 65 port.unpipe(parser);
65 logger.verbose(`Finished reading SMS on slot ${slot}`); 66 logger.verbose(`Finished reading SMS on slot ${slot}`);
66 67
67 logger.info(`Deleting message on slot ${slot}`); 68 logger.info(`Deleting message on slot ${slot}`);
68 port.pipe(parserWaitForOK); 69 port.pipe(parserWaitForOK);
69 await writeToPortAndWaitForOK(`AT+CMGD=${slot}\r`); 70 await writeToPortAndWaitForOK(`AT+CMGD=${slot}\r`);
70 port.unpipe(parserWaitForOK); 71 port.unpipe(parserWaitForOK);
71 72
72 logger.info('Message processing has completed'); 73 logger.info('Message processing has completed');
73 } 74 }
74 75
75 function onIncomingSMS(data) { 76 function onIncomingSMS(data) {
76 const value = common.extractValueFromReadLineData(data); 77 const value = common.extractValueFromReadLineData(data);
77 if (!value) return; 78 if (!value) return;
78 79
79 const chunks = value.split(','); 80 const chunks = value.split(',');
80 if (!chunks && !chunks[1]) return; 81 if (!chunks && !chunks[1]) return;
81 82
82 const slot = chunks[1]; 83 const slot = chunks[1];
83 84
84 logger.info(`Incoming SMS on slot ${slot}`); 85 logger.info(`Incoming SMS on slot ${slot}`);
85 readSMS(slot); 86 readSMS(slot);
86 } 87 }
87 88
88 parserReadLine.on('data', (data) => { 89 parserReadLine.on('data', (data) => {
89 logger.verbose(`* IN: ${data}`); 90 logger.verbose(`* IN: ${data}`);
90 if (data) { 91 if (data) {
91 if (data.indexOf('+CSQ: ') === 0) { 92 if (data.indexOf('+CSQ: ') === 0) {
92 modemInfo.signalStrength = common.extractValueFromReadLineData(data); 93 modemInfo.signalStrength = common.extractValueFromReadLineData(data).trim();
93 logger.info(`Signal strength: ${modemInfo.signalStrength}`); 94 logger.info(`Signal strength: ${modemInfo.signalStrength}`);
94 } else if (data.indexOf('+CMTI: ') === 0) { 95 } else if (data.indexOf('+CMTI: ') === 0) {
95 onIncomingSMS(data); 96 onIncomingSMS(data);
96 } 97 }
97 } 98 }
98 }); 99 });
99 100
100 parserWaitForOK.on('data', () => { 101 parserWaitForOK.on('data', () => {
101 mutex.releaseLockWaitForOK(); 102 mutex.releaseLockWaitForOK();
102 }); 103 });
103 104
104 function simpleCommand(cmd, callback) { 105 function simpleCommand(cmd, callback) {
105 const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); 106 const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK });
106 parser.on('data', (data) => { 107 parser.on('data', (data) => {
107 port.unpipe(parser); 108 port.unpipe(parser);
108 mutex.releaseLockWaitForOK(); 109 mutex.releaseLockWaitForOK();
109 110
110 if (data) { 111 if (data) {
111 callback(null, data.toString().trim()); 112 callback(null, data.toString().trim());
112 } 113 }
113 }); 114 });
114 115
115 port.pipe(parser); 116 port.pipe(parser);
116 writeToPortAndWaitForOK(cmd); 117 writeToPortAndWaitForOK(cmd);
117 } 118 }
118 119
119 function readManufacturer() { 120 function readManufacturer() {
120 return new Promise((resolve) => { 121 return new Promise((resolve) => {
121 simpleCommand('AT+CGMI\r', (err, result) => { 122 simpleCommand('AT+CGMI\r', (err, result) => {
122 modemInfo.manufacturer = result; 123 modemInfo.manufacturer = result;
123 logger.info(`Manufacturer: ${result}`); 124 logger.info(`Manufacturer: ${result}`);
124 resolve(result); 125 resolve(result);
125 }); 126 });
126 }); 127 });
127 } 128 }
128 129
129 function readModel() { 130 function readModel() {
130 return new Promise((resolve) => { 131 return new Promise((resolve) => {
131 simpleCommand('AT+CGMM\r', (err, result) => { 132 simpleCommand('AT+CGMM\r', (err, result) => {
132 modemInfo.model = result; 133 modemInfo.model = result;
133 logger.info(`Model: ${result}`); 134 logger.info(`Model: ${result}`);
134 resolve(result); 135 resolve(result);
135 }); 136 });
136 }); 137 });
137 } 138 }
138 139
139 function readIMEI() { 140 function readIMEI() {
140 return new Promise((resolve) => { 141 return new Promise((resolve) => {
141 simpleCommand('AT+CGSN\r', (err, result) => { 142 simpleCommand('AT+CGSN\r', (err, result) => {
142 modemInfo.imei = result; 143 modemInfo.imei = result;
143 logger.info(`IMEI: ${result}`); 144 logger.info(`IMEI: ${result}`);
144 resolve(result); 145 resolve(result);
145 }); 146 });
146 }); 147 });
147 } 148 }
148 149
149 function readIMSI() { 150 function readIMSI() {
150 return new Promise((resolve) => { 151 return new Promise((resolve) => {
151 simpleCommand('AT+CIMI\r', (err, result) => { 152 simpleCommand('AT+CIMI\r', (err, result) => {
152 modemInfo.imsi = result; 153 modemInfo.imsi = result;
153 logger.info(`IMSI: ${result}`); 154 logger.info(`IMSI: ${result}`);
154 resolve(result); 155 resolve(result);
155 }); 156 });
156 }); 157 });
157 } 158 }
158 159
159 async function querySignalStrength() { 160 async function querySignalStrength() {
160 port.pipe(parserWaitForOK); 161 port.pipe(parserWaitForOK);
161 await writeToPortAndWaitForOK('AT+CSQ\r'); 162 await writeToPortAndWaitForOK('AT+CSQ\r');
162 port.unpipe(parserWaitForOK); 163 port.unpipe(parserWaitForOK);
163 } 164 }
164 165
165 async function registerSignalStrengthBackgroundQuery() { 166 async function registerSignalStrengthBackgroundQuery() {
166 logger.info('Registering background signal strength query'); 167 logger.info('Registering background signal strength query');
167 168
168 setInterval(() => { 169 setInterval(() => {
169 querySignalStrength(); 170 querySignalStrength();
170 }, INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); 171 }, INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS);
171 } 172 }
172 173
173 async function sendSMS(destination, msg) { 174 async function sendSMS(destination, msg) {
174 await mutex.setLockWaitForCommand(); 175 await mutex.setLockWaitForCommand();
175 logger.info('Sending message', { destination, msg }); 176 logger.info('Sending message', { destination, msg });
176 177
177 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); 178 const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+');
178 179
179 port.pipe(parserWaitForOK); 180 port.pipe(parserWaitForOK);
180 await writeToPortAndWaitForOK('AT+CMGF=1\r'); 181 await writeToPortAndWaitForOK('AT+CMGF=1\r');
181 await writeToPortAndWaitForOK(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`); 182 await writeToPortAndWaitForOK(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`);
182 port.unpipe(parserWaitForOK); 183 port.unpipe(parserWaitForOK);
183 184
184 logger.info('Message has been sent'); 185 logger.info('Message has been sent');
185 186
186 mutex.releaseLockWaitForCommand(); 187 mutex.releaseLockWaitForCommand();
187 } 188 }
188 189
189 function init() { 190 function init() {
190 port.on('open', async () => { 191 port.on('open', async () => {
191 port.pipe(parserWaitForOK); 192 port.pipe(parserWaitForOK);
192 193
193 logger.info('Modem opened'); 194 logger.info('Modem opened');
194 await writeToPortAndWaitForOK('AT\r'); 195 await writeToPortAndWaitForOK('AT\r');
195 196
196 logger.info('Initializing modem to factory set'); 197 logger.info('Initializing modem to factory set');
197 await writeToPortAndWaitForOK('AT&F\r'); 198 await writeToPortAndWaitForOK('AT&F\r');
198 199
199 logger.info('Disabling echo'); 200 logger.info('Disabling echo');
200 await writeToPortAndWaitForOK('ATE0\r'); 201 await writeToPortAndWaitForOK('ATE0\r');
201 202
202 logger.info('Querying signal strength'); 203 logger.info('Querying signal strength');
203 await writeToPortAndWaitForOK('AT+CSQ\r'); 204 await writeToPortAndWaitForOK('AT+CSQ\r');
204 205
205 logger.info('Deleting existing messages'); 206 logger.info('Deleting existing messages');
206 // await writeToPortAndWaitForOK('AT+CMGD=0,4\r'); 207 // await writeToPortAndWaitForOK('AT+CMGD=0,4\r');
207 208
208 await readManufacturer(); 209 await readManufacturer();
209 await readModel(); 210 await readModel();
210 await readIMEI(); 211 await readIMEI();
211 await readIMSI(); 212 await readIMSI();
212 213
213 port.unpipe(parserWaitForOK); 214 port.unpipe(parserWaitForOK);
214 215
215 registerSignalStrengthBackgroundQuery(); 216 registerSignalStrengthBackgroundQuery();
216 logger.verbose('Init completed'); 217 logger.verbose('Init completed');
217 }); 218 });
218 } 219 }
219 220
220 init(); 221 init();
221 222
222 exports.modemInfo = modemInfo; 223 exports.modemInfo = modemInfo;
223 exports.sendSMS = sendSMS; 224 exports.sendSMS = sendSMS;
224 225