"use strict"; const fs = require('fs'); const EventEmitter = require('events'); const os = require('os'); const moment = require('moment'); const SerialPort = require('serialport'); const Readline = require('@serialport/parser-readline'); const Delimiter = require('@serialport/parser-delimiter'); const jsesc = require('jsesc'); const logger = require('komodo-sdk/logger'); const smsParser = require('./sms-parser'); const SIGNAL_STRENGTH_INTERVAL_MS = 60 * 1000; fs.existsSync('logs/') || fs.mkdirSync('logs/'); const debugLogWriter = process.env.KOMODO_DEBUG_MODEM ? fs.createWriteStream('logs/log-debug-modem.txt', { flags: 'a' }) : null; function debugLog(msg) { if (debugLogWriter) { debugLogWriter.write(msg + os.EOL); } } class Modem extends EventEmitter { constructor(portName) { super(); this.portName = portName; } open(cb) { const self = this; this.port = new SerialPort('/home/adhisimon/ttyUSB0ksa'); this.port.on('error', function(err) { if (cb) cb(err); }); this.port.on('open', function() { self.disableEcho(function() { self.getIMSI(function() { self.emit('open'); self.getSignalStrength(cb); setInterval(function() { self.getSignalStrength(); }, SIGNAL_STRENGTH_INTERVAL_MS) }) }); }); } resetParserToDefault() { const self = this; //this.port.unpipe(this.parser); if (this.parser) { this.port.unpipe(this.parser)}; this.parser = this.port.pipe(new Readline()); this.parser.on('data', function(data) { if (!data) return; debugLog('PARSER-DEFAULT: ' + data); if (data.indexOf('+CMTI:') === 0) { self.onSMS(data); } else if (data.indexOf('+CUSD:') === 0) { self.onUSSDResponse(data); } if (data.indexOf('+CSQ:') === 0) { debugLog('*** Got CSQ signal strength response'); self.onSignalStrength(data); } }); } _write(...args) { debugLog('COMMAND: ' + args[0]); this.port.write(...args); this.port.drain(); } write(data) { debugLog('COMMAND: ' + data); this.port.write(data); this.port.drain(); } getPort() { return this.port; } onUSSDResponse(data) { debugLog('USSD-RESPONSE: ' + data); this.emit('ussd response', data); } onSMS(data) { const self = this; const port = this.port; const matches = data.match(/,(\d+)\s*$/); if (!matches || matches.length < 2) { return; } const slot = matches[1]; //console.log('*** Ada SMS masuk di slot ' + slot); if (!slot) { debugLog('*** Gagal deteksi slot sms') return; } if (this.parser) { this.port.unpipe(this.parser)}; const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) parser.on('data', function(data) { self.parseSMS(data); self.port.unpipe(parser); self.resetParserToDefault(); self.write('AT+CMGD=' + slot + '\r'); }) this.write('AT+CMGR=' + slot + '\r'); } parseSMS(data) { data = data.toString().trim(); //debugLog(jsesc(data, {wrap: true})); debugLog('SMS-READ: ' + data); const sms = smsParser.parseModemResponse(data); this.emit('incoming sms', sms); } disableEcho(cb) { const self = this; if (this.parser) { this.port.unpipe(this.parser)}; const parser = this.port.pipe(new Delimiter({ delimiter: '\nOK\r\n' })); parser.on('data', function(data) { const value = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); debugLog('PARSER-DISABLEECHO: echo disabled'); self.port.unpipe(parser); self.resetParserToDefault(); if (cb) { cb(null, value); } }) this.write('ATE0\r'); } getIMSI(cb) { const self = this; const port = this.port; if (this.parser) { this.port.unpipe(this.parser)}; const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) parser.on('data', function(data) { self.imsi = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); debugLog('PARSER-IMSI: ' + self.imsi); self.port.unpipe(parser); self.resetParserToDefault(); self.emit('imsi', self.imsi); if (cb) { cb(null, self.imsi); } }) this.write('AT+CIMI\r'); } getCOPS(cb) { const self = this; /* const parser = this.port.pipe(new Delimiter({ delimiter: '\r\nOK\r\n' })) parser.on('data', function(data) { const value = data.toString().replace(/^\s+/, '').replace(/\s+$/, ''); debugLog('PARSER-COPS: ' + value); self.port.unpipe(parser); if (cb) { cb(null, value); } }) */ //console.log('MODEM: sending AT+COPS?'); this.write('AT+COPS?\r'); } sendUSSD(cmd, cb) { const self = this; const port = this.port; //console.log('MODEM: ' + moment().format('HH:mm:ss') + ' *** Sending USSD command ' + cmd); this.write('AT+CUSD=1,"' + cmd + '",15\r'); } onSignalStrength(data) { if (typeof data !== 'string') { debugLog('*** onSignalStrength data is not a string'); return; } const matches = data.match(/: (\d+),/); if (matches.length < 2) return; this.emit('signal strength', Number(matches[1])); } getSignalStrength(cb) { this.write('AT+CSQ\r'); if (cb) { cb() }; } } module.exports = Modem;