modem-commands.js 4.87 KB
const MUTEX_COMMAND = 'COMMAND';
const MUTEX_SUBCOMMAND = 'SUBCOMMAND';

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) => {
        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();
            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();
            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');

    await this.queryIMEI(MUTEX_SUBCOMMAND);
    await this.queryIMSI(MUTEX_SUBCOMMAND);

    await mutex.unlock(MUTEX_SUBCOMMAND, 'queryIMEIAndIMSI');
};