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