Commit c8812a9bfb82c4cb4c6c94b3c623a2794d24a379
1 parent
eab32ea271
Exists in
master
Modem port based on config
Showing 1 changed file with 1 additions and 1 deletions Inline Diff
lib/modem/index.js
1 | "use strict"; | 1 | "use strict"; |
2 | 2 | ||
3 | const fs = require('fs'); | 3 | const fs = require('fs'); |
4 | const EventEmitter = require('events'); | 4 | const EventEmitter = require('events'); |
5 | const os = require('os'); | 5 | const os = require('os'); |
6 | 6 | ||
7 | const moment = require('moment'); | 7 | const moment = require('moment'); |
8 | 8 | ||
9 | const SerialPort = require('serialport'); | 9 | const SerialPort = require('serialport'); |
10 | const Readline = require('@serialport/parser-readline'); | 10 | const Readline = require('@serialport/parser-readline'); |
11 | const Delimiter = require('@serialport/parser-delimiter'); | 11 | const Delimiter = require('@serialport/parser-delimiter'); |
12 | const jsesc = require('jsesc'); | 12 | const jsesc = require('jsesc'); |
13 | 13 | ||
14 | const logger = require('komodo-sdk/logger'); | 14 | const logger = require('komodo-sdk/logger'); |
15 | 15 | ||
16 | const smsParser = require('./sms-parser'); | 16 | const smsParser = require('./sms-parser'); |
17 | 17 | ||
18 | const SIGNAL_STRENGTH_INTERVAL_MS = 60 * 1000; | 18 | const SIGNAL_STRENGTH_INTERVAL_MS = 60 * 1000; |
19 | 19 | ||
20 | fs.existsSync('logs/') || fs.mkdirSync('logs/'); | 20 | fs.existsSync('logs/') || fs.mkdirSync('logs/'); |
21 | const debugLogWriter = process.env.KOMODO_DEBUG_MODEM ? fs.createWriteStream('logs/log-debug-modem.txt', { flags: 'a' }) : null; | 21 | const debugLogWriter = process.env.KOMODO_DEBUG_MODEM ? fs.createWriteStream('logs/log-debug-modem.txt', { flags: 'a' }) : null; |
22 | 22 | ||
23 | function debugLog(msg) { | 23 | function debugLog(msg) { |
24 | if (debugLogWriter) { | 24 | if (debugLogWriter) { |
25 | debugLogWriter.write(msg + os.EOL); | 25 | debugLogWriter.write(msg + os.EOL); |
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | 29 | ||
30 | class Modem extends EventEmitter { | 30 | class Modem extends EventEmitter { |
31 | constructor(portName) { | 31 | constructor(portName) { |
32 | super(); | 32 | super(); |
33 | this.portName = portName; | 33 | this.portName = portName; |
34 | } | 34 | } |
35 | 35 | ||
36 | open(cb) { | 36 | open(cb) { |
37 | const self = this; | 37 | const self = this; |
38 | 38 | ||
39 | this.port = new SerialPort('/home/adhisimon/ttyUSB0ksa'); | 39 | this.port = new SerialPort(this.portName); |
40 | 40 | ||
41 | this.port.on('error', function(err) { | 41 | this.port.on('error', function(err) { |
42 | if (cb) cb(err); | 42 | if (cb) cb(err); |
43 | }); | 43 | }); |
44 | 44 | ||
45 | this.port.on('open', function() { | 45 | this.port.on('open', function() { |
46 | self.resetModem(function() { | 46 | self.resetModem(function() { |
47 | self.getIMSI(function() { | 47 | self.getIMSI(function() { |
48 | self.emit('open'); | 48 | self.emit('open'); |
49 | self.getSignalStrength(cb); | 49 | self.getSignalStrength(cb); |
50 | 50 | ||
51 | setInterval(function() { | 51 | setInterval(function() { |
52 | self.getSignalStrength(); | 52 | self.getSignalStrength(); |
53 | }, SIGNAL_STRENGTH_INTERVAL_MS) | 53 | }, SIGNAL_STRENGTH_INTERVAL_MS) |
54 | 54 | ||
55 | }) | 55 | }) |
56 | }); | 56 | }); |
57 | 57 | ||
58 | }); | 58 | }); |
59 | 59 | ||
60 | 60 | ||
61 | } | 61 | } |
62 | 62 | ||
63 | resetParserToDefault() { | 63 | resetParserToDefault() { |
64 | const self = this; | 64 | const self = this; |
65 | //this.port.unpipe(this.parser); | 65 | //this.port.unpipe(this.parser); |
66 | if (this.parser) { this.port.unpipe(this.parser)}; | 66 | if (this.parser) { this.port.unpipe(this.parser)}; |
67 | this.parser = this.port.pipe(new Readline()); | 67 | this.parser = this.port.pipe(new Readline()); |
68 | 68 | ||
69 | this.parser.on('data', function(data) { | 69 | this.parser.on('data', function(data) { |
70 | if (!data) return; | 70 | if (!data) return; |
71 | 71 | ||
72 | debugLog('PARSER-DEFAULT: ' + data); | 72 | debugLog('PARSER-DEFAULT: ' + data); |
73 | 73 | ||
74 | if (data.indexOf('+CMTI:') === 0) { | 74 | if (data.indexOf('+CMTI:') === 0) { |
75 | self.onSMS(data); | 75 | self.onSMS(data); |
76 | } | 76 | } |
77 | else if (data.indexOf('+CUSD:') === 0) { | 77 | else if (data.indexOf('+CUSD:') === 0) { |
78 | self.onUSSDResponse(data); | 78 | self.onUSSDResponse(data); |
79 | } | 79 | } |
80 | if (data.indexOf('+CSQ:') === 0) { | 80 | if (data.indexOf('+CSQ:') === 0) { |
81 | debugLog('*** Got CSQ signal strength response'); | 81 | debugLog('*** Got CSQ signal strength response'); |
82 | self.onSignalStrength(data); | 82 | self.onSignalStrength(data); |
83 | } | 83 | } |
84 | 84 | ||
85 | }); | 85 | }); |
86 | } | 86 | } |
87 | 87 | ||
88 | _write(...args) { | 88 | _write(...args) { |
89 | debugLog('COMMAND: ' + args[0]); | 89 | debugLog('COMMAND: ' + args[0]); |
90 | this.port.write(...args); | 90 | this.port.write(...args); |
91 | this.port.drain(); | 91 | this.port.drain(); |
92 | } | 92 | } |
93 | 93 | ||
94 | write(data) { | 94 | write(data) { |
95 | debugLog('COMMAND: ' + data); | 95 | debugLog('COMMAND: ' + data); |
96 | this.port.write(data); | 96 | this.port.write(data); |
97 | this.port.drain(); | 97 | this.port.drain(); |
98 | } | 98 | } |
99 | 99 | ||
100 | getPort() { | 100 | getPort() { |
101 | return this.port; | 101 | return this.port; |
102 | } | 102 | } |
103 | 103 | ||
104 | onUSSDResponse(data) { | 104 | onUSSDResponse(data) { |
105 | debugLog('USSD-RESPONSE: ' + data); | 105 | debugLog('USSD-RESPONSE: ' + data); |
106 | this.emit('ussd response', data); | 106 | this.emit('ussd response', data); |
107 | } | 107 | } |
108 | 108 | ||
109 | onSMS(data) { | 109 | onSMS(data) { |
110 | const self = this; | 110 | const self = this; |
111 | const port = this.port; | 111 | const port = this.port; |
112 | 112 | ||
113 | const matches = data.match(/,(\d+)\s*$/); | 113 | const matches = data.match(/,(\d+)\s*$/); |
114 | if (!matches || matches.length < 2) { | 114 | if (!matches || matches.length < 2) { |
115 | return; | 115 | return; |
116 | } | 116 | } |
117 | 117 | ||
118 | const slot = matches[1]; | 118 | const slot = matches[1]; |
119 | //console.log('*** Ada SMS masuk di slot ' + slot); | 119 | //console.log('*** Ada SMS masuk di slot ' + slot); |
120 | 120 | ||
121 | if (!slot) { | 121 | if (!slot) { |
122 | debugLog('*** Gagal deteksi slot sms') | 122 | debugLog('*** Gagal deteksi slot sms') |
123 | return; | 123 | return; |
124 | } | 124 | } |
125 | 125 | ||
126 | if (this.parser) { this.port.unpipe(this.parser)}; | 126 | if (this.parser) { this.port.unpipe(this.parser)}; |
127 | const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) | 127 | const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) |
128 | 128 | ||
129 | parser.on('data', function(data) { | 129 | parser.on('data', function(data) { |
130 | self.parseSMS(data); | 130 | self.parseSMS(data); |
131 | self.port.unpipe(parser); | 131 | self.port.unpipe(parser); |
132 | self.resetParserToDefault(); | 132 | self.resetParserToDefault(); |
133 | 133 | ||
134 | self.write('AT+CMGD=' + slot + '\r'); | 134 | self.write('AT+CMGD=' + slot + '\r'); |
135 | }) | 135 | }) |
136 | 136 | ||
137 | this.write('AT+CMGR=' + slot + '\r'); | 137 | this.write('AT+CMGR=' + slot + '\r'); |
138 | } | 138 | } |
139 | 139 | ||
140 | parseSMS(data) { | 140 | parseSMS(data) { |
141 | data = data.toString().trim(); | 141 | data = data.toString().trim(); |
142 | //debugLog(jsesc(data, {wrap: true})); | 142 | //debugLog(jsesc(data, {wrap: true})); |
143 | debugLog('SMS-READ: ' + data); | 143 | debugLog('SMS-READ: ' + data); |
144 | const sms = smsParser.parseModemResponse(data); | 144 | const sms = smsParser.parseModemResponse(data); |
145 | this.emit('incoming sms', sms); | 145 | this.emit('incoming sms', sms); |
146 | } | 146 | } |
147 | 147 | ||
148 | resetModem(cb) { | 148 | resetModem(cb) { |
149 | const self = this; | 149 | const self = this; |
150 | 150 | ||
151 | if (this.parser) { this.port.unpipe(this.parser)}; | 151 | if (this.parser) { this.port.unpipe(this.parser)}; |
152 | const parser = this.port.pipe(new Delimiter({ delimiter: '\nOK\r\n' })); | 152 | const parser = this.port.pipe(new Delimiter({ delimiter: '\nOK\r\n' })); |
153 | 153 | ||
154 | parser.on('data', function(data) { | 154 | parser.on('data', function(data) { |
155 | const value = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); | 155 | const value = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); |
156 | 156 | ||
157 | debugLog('PARSER-RESETMODEM: modem reseted'); | 157 | debugLog('PARSER-RESETMODEM: modem reseted'); |
158 | 158 | ||
159 | self.port.unpipe(parser); | 159 | self.port.unpipe(parser); |
160 | self.resetParserToDefault(); | 160 | self.resetParserToDefault(); |
161 | 161 | ||
162 | if (cb) { | 162 | if (cb) { |
163 | cb(null, value); | 163 | cb(null, value); |
164 | } | 164 | } |
165 | }) | 165 | }) |
166 | 166 | ||
167 | this.write('AT &F Z E0\r'); | 167 | this.write('AT &F Z E0\r'); |
168 | } | 168 | } |
169 | 169 | ||
170 | getIMSI(cb) { | 170 | getIMSI(cb) { |
171 | const self = this; | 171 | const self = this; |
172 | const port = this.port; | 172 | const port = this.port; |
173 | 173 | ||
174 | if (this.parser) { this.port.unpipe(this.parser)}; | 174 | if (this.parser) { this.port.unpipe(this.parser)}; |
175 | const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) | 175 | const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) |
176 | 176 | ||
177 | parser.on('data', function(data) { | 177 | parser.on('data', function(data) { |
178 | self.imsi = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); | 178 | self.imsi = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); |
179 | debugLog('PARSER-IMSI: ' + self.imsi); | 179 | debugLog('PARSER-IMSI: ' + self.imsi); |
180 | 180 | ||
181 | self.port.unpipe(parser); | 181 | self.port.unpipe(parser); |
182 | self.resetParserToDefault(); | 182 | self.resetParserToDefault(); |
183 | 183 | ||
184 | self.emit('imsi', self.imsi); | 184 | self.emit('imsi', self.imsi); |
185 | 185 | ||
186 | if (cb) { | 186 | if (cb) { |
187 | cb(null, self.imsi); | 187 | cb(null, self.imsi); |
188 | } | 188 | } |
189 | }) | 189 | }) |
190 | 190 | ||
191 | this.write('AT+CIMI\r'); | 191 | this.write('AT+CIMI\r'); |
192 | } | 192 | } |
193 | 193 | ||
194 | getCOPS(cb) { | 194 | getCOPS(cb) { |
195 | const self = this; | 195 | const self = this; |
196 | 196 | ||
197 | /* | 197 | /* |
198 | const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) | 198 | const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) |
199 | 199 | ||
200 | parser.on('data', function(data) { | 200 | parser.on('data', function(data) { |
201 | const value = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); | 201 | const value = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); |
202 | debugLog('PARSER-COPS: ' + value); | 202 | debugLog('PARSER-COPS: ' + value); |
203 | self.port.unpipe(parser); | 203 | self.port.unpipe(parser); |
204 | if (cb) { | 204 | if (cb) { |
205 | cb(null, value); | 205 | cb(null, value); |
206 | } | 206 | } |
207 | }) | 207 | }) |
208 | */ | 208 | */ |
209 | 209 | ||
210 | //console.log('MODEM: sending AT+COPS?'); | 210 | //console.log('MODEM: sending AT+COPS?'); |
211 | this.write('AT+COPS?\r'); | 211 | this.write('AT+COPS?\r'); |
212 | } | 212 | } |
213 | 213 | ||
214 | sendUSSD(cmd, cb) { | 214 | sendUSSD(cmd, cb) { |
215 | const self = this; | 215 | const self = this; |
216 | const port = this.port; | 216 | const port = this.port; |
217 | 217 | ||
218 | //console.log('MODEM: ' + moment().format('HH:mm:ss') + ' *** Sending USSD command ' + cmd); | 218 | //console.log('MODEM: ' + moment().format('HH:mm:ss') + ' *** Sending USSD command ' + cmd); |
219 | this.write('AT+CUSD=1,"' + cmd + '",15\r'); | 219 | this.write('AT+CUSD=1,"' + cmd + '",15\r'); |
220 | } | 220 | } |
221 | 221 | ||
222 | onSignalStrength(data) { | 222 | onSignalStrength(data) { |
223 | if (typeof data !== 'string') { | 223 | if (typeof data !== 'string') { |
224 | debugLog('*** onSignalStrength data is not a string'); | 224 | debugLog('*** onSignalStrength data is not a string'); |
225 | return; | 225 | return; |
226 | } | 226 | } |
227 | const matches = data.match(/: (\d+),/); | 227 | const matches = data.match(/: (\d+),/); |
228 | if (matches.length < 2) return; | 228 | if (matches.length < 2) return; |
229 | 229 | ||
230 | this.emit('signal strength', Number(matches[1])); | 230 | this.emit('signal strength', Number(matches[1])); |
231 | } | 231 | } |
232 | 232 | ||
233 | getSignalStrength(cb) { | 233 | getSignalStrength(cb) { |
234 | this.write('AT+CSQ\r'); | 234 | this.write('AT+CSQ\r'); |
235 | 235 | ||
236 | if (cb) { cb() }; | 236 | if (cb) { cb() }; |
237 | } | 237 | } |
238 | } | 238 | } |
239 | 239 | ||
240 | module.exports = Modem; | 240 | module.exports = Modem; |
241 | 241 |