zabsalahid / serialport-gsm

SerialPort-GSM is a simplified plugin for communicating with gsm modems. (Primarily for sms) (Focused in PDU mode)
MIT License
90 stars 47 forks source link

Need help on initializeModem and setModemMode #14

Closed iamqinglong closed 5 years ago

iamqinglong commented 5 years ago

Hello Guys Need help. (Tulongan nyo naman ako pano paganahin) Thank you. serialport-gsm = 2.3.1 usb modem = globe tattoo huawei e359

broad

port

output

sms

code



let modem = serialportgsm.Modem()
let options = {
    baudRate: 9600,
    dataBits: 8,
    parity: 'none',
    stopBits: 1,
    flowControl: false,
    xon: false,
    rtscts: false,
    xoff: false,
    xany: false,
    buffersize: 0,
    autoDeleteOnReceive: true,
    enableConcatenation: true,
    incomingCallIndication: true

}
modem.open('COM5', options, (data,err,msg)=>{console.log('Opened ',data,err,msg)});
modem.on('open', () => {
    modem.initializeModem((msg,err,data) => {console.log('initialize msg:', msg, err)});
    modem.setModemMode((msg,err,data) => {console.log('set pdu msg:', msg, err,data)}, 'PDU');
});
modem.on('close', msg => console.log('on close msg:' , msg));

modem.on('error',  msg => console.log('on error msg:' , msg));```
psmass commented 5 years ago

Hi Qing long? Your code looks good to me for basic intialization. Looking at your output, the timeout message for ATZ indicates your modem is not responding 'OK' to ATZ command issued (this is issued by the modem.js code (found in ../node_modules/serialport-gsm/lib/functions/). Can you via a serial interface direct with your modem verify that it correctly responds to ATZ. I found it extremelyl informative to 'instrument the modem.dataReceived (). by placing a 'console.log(`_dataReceived ${newpart}`) right after the newparts.forEach(newpart => { line. You can then see all the low level AT commands and responses directly from the modem. This not only allowed me to understand the code, but also see what it was seeing (or not seeing in a case I had - the Quectel module was diverting URC to a different port (i had to add a ATQURCCFG command to a private version of the modem.js to allow me to configure the correct port). Also note that if you add any commands and call the modem.executeCommand() directly you need to add code to the modem.dataReceived() to fill out the result and call the callback (i.e. you can't just use the modem.executeCommand() directly without some thought (and work).

Please differ to Zab on this but this is basicallly what I understand the modem.js code does. Three basic things... 1) sends the underlying AT messages using modem.executeCommand() depending on what API you are using. Example: you'll note that the modem.initializeModem sends via 'executeCommand()' an ATZ command. 2) it then pushes the command to the head of the queue (queue[0] and sets a timer (usually 30 seconds). This timer is cancelled when the expected response occurs and 'OK'. This is much more time than needed so something is drastically wrong if this times out. 3) It has a function called modem.dataReceived that is invoked when data comes from the modem. This function parses the responses , poping the queue to correlate what command it is getting a response from. If it gets a interim response it places it in the results and waits for an 'OK' or 'Error' or timeout. If it gets an OK it cancels the timer and calls back your function with the results. If it gets an Error it does the same with 'Error'. If the timer fires because it never got a response to a command you get the response you are seeing in your output trace.

Hope this helps...even though I had to do a bit of work to make a specific modem to work (the AT command standard is good but not perfect), this gsm code is well writen, and easily modifiable. I really appreciated the work Zab & Karianpour did and how much time it saved me. In fact i'm using the same 'like scheme' in a C library for the embedded controller side (that has no RTOS:-( )

Here is a final version that worked for me. In my case I created an openModem function that rolled a bunch of intialization together: (note I do a lot of my dev on my mac, test it and push it to my headless Raspberry server).


in my gsmModem.js file

//const serialPort="/dev/ttyUSB3"; // serialport for gsm Modem 'AT' commands Rpi
const serialPort="/dev/tty.Repleo-CP2102-0001"; // serial port for mac

var gsmModem = serialportgsm.Modem();
let options = {
    baudRate: 115200,
    dataBits: 8,
    parity: 'none',
    stopBits: 1,
    flowControl: false,
    xon: false,
    rtscts: false,
    xoff: false,
    xany: false,
    autoDeleteOnReceive: true,
    enableConcatenation: true,
    incomingCallIndication: true
}

unction sendSMS(phoneNum, message) {
    gsmModem.sendSMS(phoneNum, message, false, (result) => {
        if (result.status==="Error") {
            //console.log (`Failed to send message: ${result.error}`);
            logEvent("Gateway", `Failed to send message: ${result.error}`);
        } else {
            // note that per message this will get call back is called twice
            // once to enque the message and once to actually send it.
            console.log(`Msg ID: ${result.data.messageId},` +
            `${result.data.response} To: ${result.data.recipient}`);
        }
    });
}

function openModem () { // and configure it for Quectel init + PDU mode
    gsmModem.open(serialPort, options, (err) => {
        if (err) {
            //console.log(`Error opening modem ${err}`);
            logEvent("Gateway", `Error opening modem`);
        }
        // Quectel GSM Module requires the port to be "usbmodem" to get URC's
            gsmModem.setURCPort((result, err) => {
            if (err) {
                // console.log(`Initialize URC port failed: ${err}`);
                logEvent("Gateway", `Initialize URC port failed`);
            } else {
                console.log (`${result.request}`);
            }
        }, false, "usbmodem");

        // gsmModem add at+qnwinfo (carrier info), and at+qspn (service provider name)  for debug logs
        gsmModem.setModemMode((msg,err) => {
            if (err) {
                //console.log(`Error Setting Modem Mode - ${err}`);
                logEvent("Gateway", `Error Setting Modem Mode`);
            } else {
                console.log(`Set Mode: ${msg.data}`);
            }   
        }, "PDU");

        // capture signal strength for the logs
        gsmModem.getNetworkSignal((sigStrength, err) => {
            if (err) {
                //console.log(`Error retrieving Signal Strength - ${err}`);
                logEvent("Gateway", `Error retrieving Signal Strength`);
            } else {
                console.log(`Signal Strength = ${sigStrength.data.signalQuality}`);
            }
        });

    });
}

Over in my app.js file

const _gsmModem = require('./js/gsmModem');
const gsmModem = _gsmModem.gsmModem;
const _fs = require('./js/fileSys.js');
const logEvent = _fs.logEvent;

const port = 3000;

app.set('view engine', 'ejs');

_gsmModem.openModem(); // configures it as well for our situation

gsmModem.on('open', () => {
    //console.log(`Modem Sucessfully Opened`);
    gsmModem.initializeModem((msg, err) => {
            if (err) {
                    //console.log(`Error Initializing Modem - ${err}`);
                    logEvent("Gateway", "Error Initializing Modem");
            } else {
                    //console.log(`${msg.data}`);
                    logEvent("Gateway", msg.data);
            }
    });

    gsmModem.on('onNewMessage', data => {
            console.log(`New Message From: ${data.sender} At time: ${data.dateTimeSent}`);
            try { // looks for either a status or alert message
                    var newMsg=(JSON.parse(data.message));
        //      console.log(newMsg);
                    if (newMsg.msg=="status") {
                        (updateStatus(data.sender, newMsg));
                    } else if (newMsg.msg=="alert") {
                        //console.log(`ALERT being sent ${newMsg.alertSev} ${newMsg.alert}`);
                        (sendEmergencyText(data.sender, newMsg.alert)); // function also logs the event
                    }
            }
            catch(err) { // log foreign message and drop it
                    data.message = data.message.substring(0,100); // trim to 100 chars max
                    //console.log(`Can\'t Parse. Not a MM controller Message: ${data.message}`);
                    logEvent("Gateway", `Can\'t Parse. Not a MM controller Message: ${data.message}`);
            }
    });

    gsmModem.on('error', (err) => {
            //console.log(`Modem threw error: ${err}`);
            logEvent("Gateway", `Modem threw error: ${err}`);
            gsmModem.getNetworkSignal((sigStrength, err) => {
                    if (err) {
                        //console.log(`Error retrieving Signal Strength - ${err}`);
                        logEvent("Gateway", `Error retrieving Signal Strength`);
                    } else {
                        //console.log(`Signal Strength = ${sigStrength.data.signalQuality}`);
                        logEvent("Gateway", `Signal Strength = ${sigStrength.data.signalQuality}`);
                    }
            });
    });
psmass commented 5 years ago

Oh one thing I did note is that you call all the functions expecting to get 'data', 'err', and 'msg' back. The API as near as I can tell only provides ('msg', 'err') where data is msg.data. See my code above. Good luck!

iamqinglong commented 5 years ago

Hello Mr @psmass . Thank you for your time, I do really appreciate it. I just resolved my problem just by changing the port. It took me a lot of time just to solved this problem because I rely on the output based on serialportgsm.list() method.

So to those people out there who wants to try this great library using USB modem, If your using Windows try to check the port on your Device Manager > Modems > Click Available Modem Properties > Modem(tab) > Port : X (mine Port : 4) I hope it could help. modem