const MUTEX_COMMAND = 'COMMAND'; exports.MUTEX_COMMAND = MUTEX_COMMAND; const MUTEX_SUBCOMMAND = 'SUBCOMMAND'; exports.MUTEX_SUBCOMMAND = MUTEX_SUBCOMMAND; const pdu = require('node-pdu'); const ParserReadline = require('@serialport/parser-readline'); const ParserRegex = require('@serialport/parser-regex'); const logger = require('komodo-sdk/logger'); const mutex = require('../mutex-common'); const parsers = require('../serialport-parsers'); const modemInfo = require('../modem-info'); let port; function writeToPort(data) { return new Promise((resolve) => { modemInfo.lastWriteTs = new Date(); port.write(data, (err, bytesWritten) => { if (err) logger.warn(`ERROR: ${err.toString()}`); logger.verbose('OUTGOING', { data: data.toString(), bytesWritten, err }); resolve(bytesWritten); }); }); } exports.writeToPortAndWaitForReadline = function writeToPortAndWaitForReadline(cmd, lockName) { let resolved = false; return new Promise(async (resolve) => { const parser = new ParserReadline({ delimiter: parsers.PARSER_READLINE_DELIMITER }); parser.on('data', (data) => { port.unpipe(parser); mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim()); if (!resolved) { resolved = true; resolve(data); } }); await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim()); port.pipe(parser); await writeToPort(cmd); }); }; exports.writeToPortAndWaitForOkOrError = function writeToPortAndWaitForOkOrError(cmd, lockName) { return new Promise(async (resolve) => { const parser = new ParserRegex({ regex: /(?:OK|ERROR)\r\n/ }); parser.on('data', (data) => { port.unpipe(parser); mutex.unlock(lockName || MUTEX_COMMAND, cmd.trim()); resolve(data); }); await mutex.lock(lockName || MUTEX_COMMAND, cmd.trim()); port.pipe(parser); await writeToPort(cmd); }); }; exports.sleep = function sleep(ms) { return new Promise((resolve) => { setTimeout(() => { resolve(); }, ms || 0); }); }; exports.setPort = function setPort(val) { port = val; }; exports.querySignalQuality = function querySignalQuality() { return new Promise(async (resolve) => { if (!mutex.tryLock(MUTEX_COMMAND, 'querySignalQuality')) { resolve(false); return; } await writeToPort('AT+CSQ\r'); mutex.unlock(MUTEX_COMMAND, 'querySignalQuality'); resolve(true); }); }; exports.queryCOPS = function queryCOPS(lockName) { return new Promise(async (resolve) => { await mutex.lock(lockName || MUTEX_COMMAND, 'queryCOPS'); await writeToPort('AT+COPS?\r'); mutex.unlock(lockName || MUTEX_COMMAND, 'queryCOPS'); resolve(true); }); }; exports.queryCOPSAndSignalQuality = function queryCOPSAndSignalQuality(skipOnLocked) { return new Promise(async (resolve) => { if (!skipOnLocked) { await mutex.lock(MUTEX_COMMAND); } else if (!mutex.tryLock(MUTEX_COMMAND, 'queryCOPSAndSignalQuality')) { resolve(false); return; } await this.writeToPortAndWaitForOkOrError('AT+COPS?\r', MUTEX_SUBCOMMAND); await this.writeToPortAndWaitForOkOrError('AT+CSQ\r', MUTEX_SUBCOMMAND); mutex.unlock(MUTEX_COMMAND, 'queryCopsAndSignalQuality'); resolve(true); }); }; exports.queryIMEI = function queryIMEI(lockName) { return new Promise(async (resolve) => { const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); parser.on('data', (data) => { logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMEI' }); port.unpipe(parser); mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMEI'); modemInfo.imei = data.toString().trim() || null; logger.info('IMEI extracted', { imei: modemInfo.imei }); resolve(modemInfo.imei); }); await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMEI'); port.pipe(parser); await writeToPort('AT+CGSN\r'); }); }; exports.queryIMSI = function queryIMSI(lockName) { return new Promise(async (resolve) => { const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); parser.on('data', (data) => { logger.verbose('INCOMING', { data: data.toString(), parser: 'parserIMSI' }); port.unpipe(parser); mutex.unlock(lockName || MUTEX_COMMAND, 'queryIMSI'); modemInfo.imsi = data.toString().trim() || null; logger.info('IMSI extracted', { imsi: modemInfo.imsi }); resolve(modemInfo.imsi); }); await mutex.lock(lockName || MUTEX_COMMAND, 'queryIMSI'); port.pipe(parser); await writeToPort('AT+CIMI\r'); }); }; exports.queryIMEIAndIMSI = async function queryIMEIAndIMSI() { await mutex.lock(MUTEX_COMMAND, 'queryIMEIAndIMSI'); const imei = await this.queryIMEI(MUTEX_SUBCOMMAND); const imsi = await this.queryIMSI(MUTEX_SUBCOMMAND); await mutex.unlock(MUTEX_COMMAND, 'queryIMEIAndIMSI'); return { imei, imsi }; }; exports.queryManufacturer = function queryManufacturer(lockName) { return new Promise(async (resolve) => { const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); parser.on('data', (data) => { logger.verbose('INCOMING', { data: data.toString(), parser: 'parserManufacturer' }); port.unpipe(parser); mutex.unlock(lockName || MUTEX_COMMAND, 'parserManufacturer'); modemInfo.manufacturer = data.toString().trim() || null; logger.info('Manufacturer extracted', { manufacturer: modemInfo.manufacturer }); resolve(modemInfo.manufacturer); }); await mutex.lock(lockName || MUTEX_COMMAND, 'queryManufacturer'); port.pipe(parser); await writeToPort('AT+CGMI\r'); }); }; exports.queryModel = function queryModel(lockName) { return new Promise(async (resolve) => { const parser = new ParserRegex({ regex: parsers.PARSER_WAIT_FOR_OK_OR_ERROR_REGEX }); parser.on('data', (data) => { logger.verbose('INCOMING', { data: data.toString(), parser: 'parserModel' }); port.unpipe(parser); mutex.unlock(lockName || MUTEX_COMMAND, 'parserModel'); modemInfo.model = data.toString().trim() || null; logger.info('Model extracted', { model: modemInfo.model }); resolve(modemInfo.model); }); await mutex.lock(lockName || MUTEX_COMMAND, 'queryModel'); port.pipe(parser); await writeToPort('AT+CGMM\r'); }); }; exports.sendSMS = function sendSMS(destination, msg) { return new Promise(async (resolve) => { }); }; exports.initATCommands = async function initATCommands() { await mutex.lock(MUTEX_COMMAND, 'INIT MODEM'); await this.writeToPortAndWaitForOkOrError('\rATE0\r', MUTEX_SUBCOMMAND); await this.writeToPortAndWaitForOkOrError('AT+CMGF=0\r', MUTEX_SUBCOMMAND); await this.writeToPortAndWaitForOkOrError('AT+CNMI=1,2,0,1,0\r', MUTEX_SUBCOMMAND); mutex.unlock(MUTEX_COMMAND, 'INIT MODEM'); };