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