如何检测GSM调制解调器响应的最后一个字符

时间:2014-02-09 22:15:51

标签: c embedded gsm modem

我正在使用GSM调制解调器“SIM900” 我用超级终端测试了它,主命令没问题。

然后我烧掉代码发送AT命令,使用UART将微控制器上的号码拨到GSM调制解调器,工作正常。

但是我的回答有问题。 GSM以字符流回复,但不以Null'\ 0'结束!

如何在数组中获取整个响应以便稍后解析?而且,我怎样才能检测到响应的结束?

AT \ r \ n响应是==>行

AT + CMGR = 1响应是==> + CMGR:“REC UNREAD”,“+ 2347060580383”,“10/10 / 27,18:54:32 + 04”

提前致谢。

2 个答案:

答案 0 :(得分:1)

测试新行,通常为\n\r\n

NUL0'\0')仅在C中用于终止字符数组,即“字符串”。

答案 1 :(得分:1)

您可以使用\r\nOK作为结尾,因为手机仅对NewLine使用\n。但是有一种更可靠的方法(我做过一次)以确保你没有得到错误的结局,例如当传入的短信中有确切的\r\nOK时。为了做到这一点,我建议您将字符集更改为UCS2,这样您将获得UnicodeArray中的消息文本和发件人编号(就像它被转义一样。)

这是我用于我的目的的类(额外的检查模块(AT \ r \ n命令)用于防止卡在错误中,以防出现意外错误或类似的事情!而且我有时没有响应的模块,所以有了这个,我可以让它再次响应!看起来不合逻辑,但救了我!现在对我来说很完美!):

public class SMSController
{
    public event EventHandler StatusChanged;
    protected virtual void OnStatusChanged()
    {
        if (StatusChanged != null)
        {
            StatusChanged(this, EventArgs.Empty);
        }
    }

    SerialPort serial;
    public SMSController(SerialPort serialPort)
    {
        this.serial = serialPort;
    }

    string readLine(int timeout = -1)
    {
        int oldTo = serial.ReadTimeout;
        serial.ReadTimeout = timeout;
        string str = serial.ReadTo("\n").Replace("\n", "").Replace("\r", "");
        serial.ReadTimeout = oldTo;
        return str;
    }

    void writeLine(string str)
    {
        serial.Write(str + "\r\n");
    }

    bool waitForString(string str, int timeout = -1)
    {
        if (readLine(timeout).Contains(str))
        {
            return true;
        }
        return false;
    }

    bool waitForOK(int timeout = -1, bool repeat = true)
    {
        if (repeat)
        {
            readUntilFind("OK", timeout);
            return true;
        }
        else
            return waitForString("OK", timeout);
    }

    void readUntilFind(string str, int timeout = -1)
    {
        while (!waitForString(str, timeout)) ;
    }

    void writeCommand(string command)
    {
        serial.DiscardInBuffer();
        writeLine(command);
    }

    bool applyCommand(string command, int timeout = -1)
    {
        writeCommand(command);
        return waitForOK(timeout);
    }

    private string lastStatus = "Ready";
    public string LastStatus
    {
        get { return lastStatus; }
        private set
        {
            lastStatus = value;
            OnStatusChanged();
        }
    }

    public void InitModule()
    {
        try
        {
            LastStatus = "Checking SIM900...";
            applyCommand("ATE0", 2000); //Disable echo
            applyCommand("AT", 5000); //Check module

            LastStatus = "Initializing SIM900...";
            applyCommand("AT+CMGF=1", 1000); //Set SMS format to text mode

            LastStatus = "Operation successful!";
        }
        catch (TimeoutException)
        {
            LastStatus = "Operation timed-out";
        }
        catch (Exception ex)
        {
            LastStatus = ex.Message;
        }
    }

    public static string ConvertToUnicodeArray(string str)
    {
        byte[] byt = Encoding.Unicode.GetBytes(str);           
        string res = "";
        for (int i = 0; i < byt.Length; i+=2)
        {
            res += byt[i + 1].ToString("X2");
            res += byt[i].ToString("X2");
        }
        return res;
    }

    public void SendMessage(string destinationNumber, string text, bool isUnicode = false)
    {
        try
        {
            LastStatus = "Initiating to send...";
            applyCommand("AT+CSMP=17,167,2,25", 1000);
            if (isUnicode)
            {
                if (!applyCommand("AT+CSCS=\"UCS2\"", 5000))
                    throw new Exception("Operation failed!");
                writeCommand("AT+CMGS=\"" + ConvertToUnicodeArray(destinationNumber) + "\"");
            }
            else
            {
                if (!applyCommand("AT+CSCS=\"GSM\"", 5000))
                    throw new Exception("Operation failed!");
                writeCommand("AT+CMGS=\"" + destinationNumber + "\"");
            }

            waitForString("> ", 5000);

            LastStatus = "Sending...";
            serial.DiscardInBuffer();
            serial.Write(isUnicode ? ConvertToUnicodeArray(text) : text);
            serial.Write(new byte[] { 0x1A }, 0, 1);

            if (waitForOK(30000))
            {
                LastStatus = "Message sent!";
            }
            else
                LastStatus = "Sending failed!";
        }
        catch (TimeoutException)
        {
            LastStatus = "Operation timed-out";
        }
        catch (Exception ex)
        {
            LastStatus = ex.Message;
        }
    }

    private string readTo(string str, int timeout)
    {
        int to = serial.ReadTimeout;
        serial.ReadTimeout = timeout;
        string strread = serial.ReadTo(str);
        serial.ReadTimeout = to;
        return strread;
    }

    public static byte[] StringToByteArray(string hex)
    {
        return Enumerable.Range(0, hex.Length)
                 .Where(x => x % 2 == 0)
                 .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                 .ToArray();
    }

    public static string ConvertUnicodeToText(string bytes)
    {
        byte[] bt = StringToByteArray(bytes);
        for (int i = 0; i < bt.Length; i+=2)
        {
            byte swap = bt[i];
            bt[i] = bt[i + 1];
            bt[i + 1] = swap;
        }
        return Encoding.Unicode.GetString(bt);
    }

    public SMS[] GetUnreadMessages()
    {
        List<SMS> lst = new List<SMS>();
        try
        {
            LastStatus = "Initializing...";
            applyCommand("AT+CSMP=17,167,2,25", 1000);
            applyCommand("AT+CSCS=\"UCS2\"", 2000);

            LastStatus = "Fetching text messages...";
            writeCommand("AT+CMGL=\"REC UNREAD\"");
            string texts = readTo("OK\r\n", 10000);
            string[] packets = texts.Split(new string[] { "\r\n\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < packets.Length; i++)
            {
                if (!packets[i].Contains("+CMGL"))
                    continue;
                string num = packets[i].Split(new string[] { "," },
                    StringSplitOptions.RemoveEmptyEntries)[2].Replace("\"", "");
                string txt = packets[i].Split(new string[] { "\r\n" },
                    StringSplitOptions.RemoveEmptyEntries)[1].Replace("\"", "");
                lst.Add(new SMS(ConvertUnicodeToText(num), ConvertUnicodeToText(txt)));
            }

            applyCommand("AT+CMGDA=\"DEL READ\"", 10000);
            LastStatus = "Operation successful!";
        }
        catch (TimeoutException)
        {
            LastStatus = "Operation timed-out";
        }
        catch (Exception ex)
        {
            LastStatus = ex.Message;
        }

        return lst.ToArray();
    }
}