Commit 9ad3c8d304bdba60eebc63809836e5629af59966
1 parent
7e9e3a6b3b
Exists in
master
MSISDN db
Showing 3 changed files with 18 additions and 0 deletions Inline Diff
.gitignore
1 | /node_modules/ | 1 | /node_modules/ |
2 | /config.json | 2 | /config.json |
3 | /tmp/ | 3 | /tmp/ |
4 | /logs/ | 4 | /logs/ |
5 | pid.txt | 5 | pid.txt |
6 | /db-msisdn.json | ||
7 | /db-msisdn.js |
lib/modem.js
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 dbCops = require('./db-cops'); | 16 | const dbCops = require('./db-cops'); |
17 | const reportSender = require('./report-sender'); | 17 | const reportSender = require('./report-sender'); |
18 | const msisdn = require('./msisdn'); | ||
18 | 19 | ||
19 | const modemInfo = { | 20 | const modemInfo = { |
20 | manufacturer: null, | 21 | manufacturer: null, |
21 | model: null, | 22 | model: null, |
22 | imei: null, | 23 | imei: null, |
23 | imsi: null, | 24 | imsi: null, |
25 | msisdn: null, | ||
24 | cops: null, | 26 | cops: null, |
25 | networkId: null, | 27 | networkId: null, |
26 | networkName: null, | 28 | networkName: null, |
27 | signalStrength: null, | 29 | signalStrength: null, |
28 | config: config.modem, | 30 | config: config.modem, |
29 | }; | 31 | }; |
30 | 32 | ||
31 | const port = new SerialPort(config.modem.device, { baudRate: 115200 }); | 33 | const port = new SerialPort(config.modem.device, { baudRate: 115200 }); |
32 | 34 | ||
33 | const parserReadLine = new ParserReadline(); | 35 | const parserReadLine = new ParserReadline(); |
34 | const parserWaitForOK = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 36 | const parserWaitForOK = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); |
35 | port.pipe(parserReadLine); | 37 | port.pipe(parserReadLine); |
36 | 38 | ||
37 | function writeToPort(data) { | 39 | function writeToPort(data) { |
38 | return new Promise((resolve) => { | 40 | return new Promise((resolve) => { |
39 | port.write(data, (err, bytesWritten) => { | 41 | port.write(data, (err, bytesWritten) => { |
40 | if (err) logger.warn(`ERROR: ${err.toString()}`); | 42 | if (err) logger.warn(`ERROR: ${err.toString()}`); |
41 | logger.verbose(`* OUT: ${data}`); | 43 | logger.verbose(`* OUT: ${data}`); |
42 | resolve(bytesWritten); | 44 | resolve(bytesWritten); |
43 | }); | 45 | }); |
44 | }); | 46 | }); |
45 | } | 47 | } |
46 | 48 | ||
47 | async function writeToPortAndWaitForOK(data) { | 49 | async function writeToPortAndWaitForOK(data) { |
48 | await mutex.setLockWaitForOK(); | 50 | await mutex.setLockWaitForOK(); |
49 | const result = await writeToPort(data); | 51 | const result = await writeToPort(data); |
50 | await mutex.setLockWaitForOK(); | 52 | await mutex.setLockWaitForOK(); |
51 | mutex.releaseLockWaitForOK(); | 53 | mutex.releaseLockWaitForOK(); |
52 | return result; | 54 | return result; |
53 | } | 55 | } |
54 | 56 | ||
55 | async function readSMS(slot) { | 57 | async function readSMS(slot) { |
56 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 58 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); |
57 | parser.on('data', async (data) => { | 59 | parser.on('data', async (data) => { |
58 | if (data) { | 60 | if (data) { |
59 | reportSender.incomingSMS(sms.extract(data.toString().trim())); | 61 | reportSender.incomingSMS(sms.extract(data.toString().trim())); |
60 | } | 62 | } |
61 | mutex.releaseLockWaitForOK(); | 63 | mutex.releaseLockWaitForOK(); |
62 | }); | 64 | }); |
63 | 65 | ||
64 | logger.info(`Reading SMS on slot ${slot}`); | 66 | logger.info(`Reading SMS on slot ${slot}`); |
65 | port.pipe(parser); | 67 | port.pipe(parser); |
66 | await writeToPortAndWaitForOK(`AT+CMGR=${slot}\r`); | 68 | await writeToPortAndWaitForOK(`AT+CMGR=${slot}\r`); |
67 | port.unpipe(parser); | 69 | port.unpipe(parser); |
68 | logger.verbose(`Finished reading SMS on slot ${slot}`); | 70 | logger.verbose(`Finished reading SMS on slot ${slot}`); |
69 | 71 | ||
70 | logger.info(`Deleting message on slot ${slot}`); | 72 | logger.info(`Deleting message on slot ${slot}`); |
71 | port.pipe(parserWaitForOK); | 73 | port.pipe(parserWaitForOK); |
72 | await writeToPortAndWaitForOK(`AT+CMGD=${slot}\r`); | 74 | await writeToPortAndWaitForOK(`AT+CMGD=${slot}\r`); |
73 | port.unpipe(parserWaitForOK); | 75 | port.unpipe(parserWaitForOK); |
74 | 76 | ||
75 | logger.info('Message processing has completed'); | 77 | logger.info('Message processing has completed'); |
76 | } | 78 | } |
77 | 79 | ||
78 | function onIncomingSMS(data) { | 80 | function onIncomingSMS(data) { |
79 | const value = common.extractValueFromReadLineData(data); | 81 | const value = common.extractValueFromReadLineData(data); |
80 | if (!value) return; | 82 | if (!value) return; |
81 | 83 | ||
82 | const chunks = value.split(','); | 84 | const chunks = value.split(','); |
83 | if (!chunks && !chunks[1]) return; | 85 | if (!chunks && !chunks[1]) return; |
84 | 86 | ||
85 | const slot = chunks[1]; | 87 | const slot = chunks[1]; |
86 | 88 | ||
87 | logger.info(`Incoming SMS on slot ${slot}`); | 89 | logger.info(`Incoming SMS on slot ${slot}`); |
88 | readSMS(slot); | 90 | readSMS(slot); |
89 | } | 91 | } |
90 | 92 | ||
91 | function onCOPS(data) { | 93 | function onCOPS(data) { |
92 | modemInfo.cops = common.extractValueFromReadLineData(data).trim(); | 94 | modemInfo.cops = common.extractValueFromReadLineData(data).trim(); |
93 | logger.info(`Connected Network: ${modemInfo.cops}`); | 95 | logger.info(`Connected Network: ${modemInfo.cops}`); |
94 | 96 | ||
95 | if (!modemInfo.cops) return; | 97 | if (!modemInfo.cops) return; |
96 | 98 | ||
97 | [, , modemInfo.networkId] = modemInfo.cops.split(','); | 99 | [, , modemInfo.networkId] = modemInfo.cops.split(','); |
98 | 100 | ||
99 | if (modemInfo.networkId) { | 101 | if (modemInfo.networkId) { |
100 | modemInfo.networkName = dbCops[modemInfo.networkId]; | 102 | modemInfo.networkName = dbCops[modemInfo.networkId]; |
101 | } | 103 | } |
102 | } | 104 | } |
103 | 105 | ||
104 | parserReadLine.on('data', (data) => { | 106 | parserReadLine.on('data', (data) => { |
105 | logger.verbose(`* IN: ${data}`); | 107 | logger.verbose(`* IN: ${data}`); |
106 | if (data) { | 108 | if (data) { |
107 | if (data.indexOf('+CSQ: ') === 0) { | 109 | if (data.indexOf('+CSQ: ') === 0) { |
108 | modemInfo.signalStrength = common.extractValueFromReadLineData(data).trim(); | 110 | modemInfo.signalStrength = common.extractValueFromReadLineData(data).trim(); |
109 | logger.info(`Signal strength: ${modemInfo.signalStrength}`); | 111 | logger.info(`Signal strength: ${modemInfo.signalStrength}`); |
110 | } else if (data.indexOf('+CMTI: ') === 0) { | 112 | } else if (data.indexOf('+CMTI: ') === 0) { |
111 | onIncomingSMS(data); | 113 | onIncomingSMS(data); |
112 | } else if (data.indexOf('+COPS: ') === 0) { | 114 | } else if (data.indexOf('+COPS: ') === 0) { |
113 | onCOPS(data); | 115 | onCOPS(data); |
114 | } | 116 | } |
115 | } | 117 | } |
116 | }); | 118 | }); |
117 | 119 | ||
118 | parserWaitForOK.on('data', () => { | 120 | parserWaitForOK.on('data', () => { |
119 | mutex.releaseLockWaitForOK(); | 121 | mutex.releaseLockWaitForOK(); |
120 | }); | 122 | }); |
121 | 123 | ||
122 | function simpleCommand(cmd, callback) { | 124 | function simpleCommand(cmd, callback) { |
123 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); | 125 | const parser = new ParserDelimiter({ delimiter: DELIMITER_WAIT_FOR_OK }); |
124 | parser.on('data', (data) => { | 126 | parser.on('data', (data) => { |
125 | port.unpipe(parser); | 127 | port.unpipe(parser); |
126 | mutex.releaseLockWaitForOK(); | 128 | mutex.releaseLockWaitForOK(); |
127 | 129 | ||
128 | if (data) { | 130 | if (data) { |
129 | callback(null, data.toString().trim()); | 131 | callback(null, data.toString().trim()); |
130 | } | 132 | } |
131 | }); | 133 | }); |
132 | 134 | ||
133 | port.pipe(parser); | 135 | port.pipe(parser); |
134 | writeToPortAndWaitForOK(cmd); | 136 | writeToPortAndWaitForOK(cmd); |
135 | } | 137 | } |
136 | 138 | ||
137 | function readManufacturer() { | 139 | function readManufacturer() { |
138 | return new Promise((resolve) => { | 140 | return new Promise((resolve) => { |
139 | simpleCommand('AT+CGMI\r', (err, result) => { | 141 | simpleCommand('AT+CGMI\r', (err, result) => { |
140 | modemInfo.manufacturer = result; | 142 | modemInfo.manufacturer = result; |
141 | logger.info(`Manufacturer: ${result}`); | 143 | logger.info(`Manufacturer: ${result}`); |
142 | resolve(result); | 144 | resolve(result); |
143 | }); | 145 | }); |
144 | }); | 146 | }); |
145 | } | 147 | } |
146 | 148 | ||
147 | function readModel() { | 149 | function readModel() { |
148 | return new Promise((resolve) => { | 150 | return new Promise((resolve) => { |
149 | simpleCommand('AT+CGMM\r', (err, result) => { | 151 | simpleCommand('AT+CGMM\r', (err, result) => { |
150 | modemInfo.model = result; | 152 | modemInfo.model = result; |
151 | logger.info(`Model: ${result}`); | 153 | logger.info(`Model: ${result}`); |
152 | resolve(result); | 154 | resolve(result); |
153 | }); | 155 | }); |
154 | }); | 156 | }); |
155 | } | 157 | } |
156 | 158 | ||
157 | function readIMEI() { | 159 | function readIMEI() { |
158 | return new Promise((resolve) => { | 160 | return new Promise((resolve) => { |
159 | simpleCommand('AT+CGSN\r', (err, result) => { | 161 | simpleCommand('AT+CGSN\r', (err, result) => { |
160 | modemInfo.imei = result; | 162 | modemInfo.imei = result; |
161 | logger.info(`IMEI: ${result}`); | 163 | logger.info(`IMEI: ${result}`); |
162 | resolve(result); | 164 | resolve(result); |
163 | }); | 165 | }); |
164 | }); | 166 | }); |
165 | } | 167 | } |
166 | 168 | ||
167 | function readIMSI() { | 169 | function readIMSI() { |
168 | return new Promise((resolve) => { | 170 | return new Promise((resolve) => { |
169 | simpleCommand('AT+CIMI\r', (err, result) => { | 171 | simpleCommand('AT+CIMI\r', (err, result) => { |
170 | modemInfo.imsi = result; | 172 | modemInfo.imsi = result; |
171 | logger.info(`IMSI: ${result}`); | 173 | logger.info(`IMSI: ${result}`); |
174 | |||
175 | if (result) { | ||
176 | modemInfo.msisdn = msisdn[result]; | ||
177 | if (modemInfo.msisdn) { | ||
178 | logger.info(`MSISDN: ${modemInfo.msisdn}`); | ||
179 | } | ||
180 | } | ||
172 | resolve(result); | 181 | resolve(result); |
173 | }); | 182 | }); |
174 | }); | 183 | }); |
175 | } | 184 | } |
176 | 185 | ||
177 | async function querySignalStrength() { | 186 | async function querySignalStrength() { |
178 | port.pipe(parserWaitForOK); | 187 | port.pipe(parserWaitForOK); |
179 | await writeToPortAndWaitForOK('AT+CSQ\r'); | 188 | await writeToPortAndWaitForOK('AT+CSQ\r'); |
180 | port.unpipe(parserWaitForOK); | 189 | port.unpipe(parserWaitForOK); |
181 | } | 190 | } |
182 | 191 | ||
183 | async function registerSignalStrengthBackgroundQuery() { | 192 | async function registerSignalStrengthBackgroundQuery() { |
184 | logger.info('Registering background signal strength query'); | 193 | logger.info('Registering background signal strength query'); |
185 | 194 | ||
186 | setInterval(() => { | 195 | setInterval(() => { |
187 | querySignalStrength(); | 196 | querySignalStrength(); |
188 | }, INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); | 197 | }, INTERVAL_BEETWEN_SIGNAL_STRENGTH_MS); |
189 | } | 198 | } |
190 | 199 | ||
191 | async function sendSMS(destination, msg) { | 200 | async function sendSMS(destination, msg) { |
192 | if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return; | 201 | if (typeof destination !== 'string' || typeof msg !== 'string' || !destination.trim() || !msg.trim()) return; |
193 | 202 | ||
194 | await mutex.setLockWaitForCommand(); | 203 | await mutex.setLockWaitForCommand(); |
195 | logger.info('Sending message', { destination, msg }); | 204 | logger.info('Sending message', { destination, msg }); |
196 | 205 | ||
197 | const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); | 206 | const correctedDestination = `+${destination}`.replace(/^0/, '62').replace(/^\++/, '+'); |
198 | 207 | ||
199 | port.pipe(parserWaitForOK); | 208 | port.pipe(parserWaitForOK); |
200 | await writeToPortAndWaitForOK('AT+CMGF=1\r'); | 209 | await writeToPortAndWaitForOK('AT+CMGF=1\r'); |
201 | await writeToPortAndWaitForOK(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`); | 210 | await writeToPortAndWaitForOK(`AT+CMGS="${correctedDestination}"\n${msg}${Buffer.from([0x1A])}`); |
202 | port.unpipe(parserWaitForOK); | 211 | port.unpipe(parserWaitForOK); |
203 | 212 | ||
204 | logger.info('Message has been sent'); | 213 | logger.info('Message has been sent'); |
205 | 214 | ||
206 | mutex.releaseLockWaitForCommand(); | 215 | mutex.releaseLockWaitForCommand(); |
207 | } | 216 | } |
208 | 217 | ||
209 | function init() { | 218 | function init() { |
210 | port.on('open', async () => { | 219 | port.on('open', async () => { |
211 | port.pipe(parserWaitForOK); | 220 | port.pipe(parserWaitForOK); |
212 | 221 | ||
213 | logger.info('Modem opened'); | 222 | logger.info('Modem opened'); |
214 | await writeToPortAndWaitForOK('AT\r'); | 223 | await writeToPortAndWaitForOK('AT\r'); |
215 | 224 | ||
216 | logger.info('Initializing modem to factory set'); | 225 | logger.info('Initializing modem to factory set'); |
217 | await writeToPortAndWaitForOK('AT&F\r'); | 226 | await writeToPortAndWaitForOK('AT&F\r'); |
218 | 227 | ||
219 | logger.info('Disabling echo'); | 228 | logger.info('Disabling echo'); |
220 | await writeToPortAndWaitForOK('ATE0\r'); | 229 | await writeToPortAndWaitForOK('ATE0\r'); |
221 | 230 | ||
222 | await writeToPortAndWaitForOK('AT+COPS?\r'); | 231 | await writeToPortAndWaitForOK('AT+COPS?\r'); |
223 | 232 | ||
224 | logger.info('Querying signal strength'); | 233 | logger.info('Querying signal strength'); |
225 | await writeToPortAndWaitForOK('AT+CSQ\r'); | 234 | await writeToPortAndWaitForOK('AT+CSQ\r'); |
226 | 235 | ||
227 | await readManufacturer(); | 236 | await readManufacturer(); |
228 | await readModel(); | 237 | await readModel(); |
229 | await readIMEI(); | 238 | await readIMEI(); |
230 | await readIMSI(); | 239 | await readIMSI(); |
231 | 240 | ||
232 | if (!config.disable_delete_inbox_on_startup) { | 241 | if (!config.disable_delete_inbox_on_startup) { |
233 | logger.info('Deleting existing messages'); | 242 | logger.info('Deleting existing messages'); |
234 | await writeToPortAndWaitForOK('AT+CMGD=0,4\r'); | 243 | await writeToPortAndWaitForOK('AT+CMGD=0,4\r'); |
235 | } | 244 | } |
236 | 245 | ||
237 | port.unpipe(parserWaitForOK); | 246 | port.unpipe(parserWaitForOK); |
238 | 247 | ||
239 | registerSignalStrengthBackgroundQuery(); | 248 | registerSignalStrengthBackgroundQuery(); |
240 | logger.verbose('Init completed'); | 249 | logger.verbose('Init completed'); |
241 | }); | 250 | }); |
242 | } | 251 | } |
243 | 252 | ||
244 | init(); | 253 | init(); |
245 | 254 | ||
246 | exports.modemInfo = modemInfo; | 255 | exports.modemInfo = modemInfo; |
247 | exports.sendSMS = sendSMS; | 256 | exports.sendSMS = sendSMS; |
248 | 257 |
lib/msisdn.js
File was created | 1 | 'use strict'; | |
2 | |||
3 | const fs = require('fs'); | ||
4 | |||
5 | const db = fs.existsSync('db-msisdn.json') || fs.existsSync('db-msisdn.js') ? require('../db-msisdn') : {}; | ||
6 | |||
7 | module.exports = db; | ||
8 |