65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Python 和 Telit 蜂窝模块实现 SMS

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (7投票s)

2010 年 10 月 9 日

CPOL

5分钟阅读

viewsIcon

42694

使用 Python 和 Telit 蜂窝模块实现 SMS

引言

这是关于如何使用嵌入式 Python 解释器控制 Telit GC864-PY 或 Telit 生产的其他支持 Python 的蜂窝模块的系列文章的续篇。在本文中,我们将介绍如何使用 Python 和 AT 命令发送和接收 SMS 消息。

安装

要设置 SMS 消息,脚本在初始阶段需要包含一些内容。

#AT+CMGF mode 1 = text mode 0 = PDU mode (Default)
#Set Text Mode
a = MDM.send('AT+CMGF=1\r', 2)
#clear Receive buffer
res = MDM.receive(5)
#ATE0 sets the modem to echo commands
a = MDM.send('ate0\r', 2)
#clear Receive buffer
res = MDM.receive(5)
#CNMI sets up the new SMS message indicator
#AT+CNMI=mode,Message_Format,Broadcast_Reporting,SMS-Status-Report,Buffer-Handling
#Settings used
#Mode = Buffer and Forward to terminal
#Message_Format = '+CMTI: <memr>,<index>'
#Broadcast_Reporting = No messages
#SMS-Status-Report = No Reporting
#Buffer Handling = Buffer Flushed to terminal
a = MDM.send('AT+CNMI=2,1,0,0,0\r', 2)
#clear Receive buffer
res = MDM.receive(5)

Telit 设备的默认模式是使用 PDU 格式。除非您了解 PDU 的含义并希望使用它,否则此模式不适合使用。第二种模式是 Text 模式。这是一种详细的设置,允许您在无需解码的情况下读取消息。您的第一步是设置此模式。

#AT+CMGF mode 1 = text mode 0 = PDU mode (Default)
#Set Text Mode
a = MDM.send('AT+CMGF=1\r', 2)
#clear Receive buffer
res = MDM.receive(5)

有关 Telit 模块附带的自定义 Python 库的说明,请参阅上一篇文章。其中解释了 MDM.send()MDM.receive()

下一个命令是 ATE 命令。这会禁用输入回显,以便接收缓冲区仅包含来自模块的响应,无需查看您发送给设备的命令。

CNMI 命令非常重要,它决定了模块在收到消息时显示的内容。

#CNMI sets up the new SMS message indicator
#AT+CNMI=mode,Message_Format,Broadcast_Reporting,SMS-Status-Report,Buffer-Handling
#Settings used
#Mode = Buffer and Forward to terminal
#Message_Format = '+CMTI: <memr>,<index>'
#Broadcast_Reporting = No messages
#SMS-Status-Report = No Reporting
#Buffer Handling = Buffer Flushed to terminal
a = MDM.send('AT+CNMI=2,1,0,0,0\r', 2)
#clear Receive buffer
res = MDM.receive(5)

我们将在稍后介绍如何读取消息,但在收到消息时,您将看到类似以下内容的内容:

+CMTI: “SE”,2

在此阶段,格式和模式最为重要。模块的AT 命令参考指南更深入地介绍了其他选项,以防您的场景需要不同的设置。

接收 SMS

使用上述设置,可以轻松识别和提取收到的任何 SMS 消息的正文以及发送号码。首先,您需要等待 SMS 消息到达,这可以通过不同的方法处理。此处使用了无限循环来持续检查终端是否有新消息。

while 1:
        #Read buffer for new messages
        res = MDM.receive(5)
        #Identify if a SMS was received
        a = res.find('+CMTI: "SM",')
        #Process Received SMS Message
        if (a != -1):
                #Identify the position of memory location
                firstdigit_pos = a + 12
                #Extract Memory location as string
                pos = res[firstdigit_pos:-2]
                #Retrieve Sending Number
                SMSnumber = getSMSnumber(pos)
                #Retrieve Message
                SMSmessage = getSMSmessage(pos)

如果 string 包含 '+CMTI: "SM"',则变量 a 被设置为该字符串的第一个位置。这使我们能够识别是否收到了消息,并排除可能被捕获在缓冲区中的任何其他消息。现在我们需要隔离消息的确切索引号。

firstdigit_pos = a + 12

现在我们知道第一个索引号的起始位置,然后从字符串的右侧取剩余的 -2 个字符以消除一些尾随的空格。我们获得了 pos 值,将在接下来的两个函数中使用。

pos = res[firstdigit_pos:-2]

当发出 read 命令时,getSMSnumber 函数从生成的 string 中提取号码。我们还没有介绍这一点,但会边讲边解释。

def getSMSnumber(SMSpos):
    #setup command for reading message
    SMS_read_command = 'AT+CMGR='+str(SMSpos)+'\r'
    #clear receive buffer
    MDM.receive(10)
    MDM.send(SMS_read_command,5)      #send the read message command
    SMScontent = MDM.receive(15)        #collect the contents of the message
    b = SMScontent.find('+1')           #Identify the start of the number
    c = b+12
    SMSnumber = SMScontent[b:c]         #Extract the number
    return(SMSnumber)

此函数相当简单。它仅识别由 +CMGR 命令生成的 string 中的号码。CMGR 仅需要内存中的 <index> 位置,它将以类似以下格式检索消息:

+CMGR: "REC READ","+15291234567",,"07/02/18,00:12:05+32"
Insert SMS message here

此函数仅适用于美国号码,因为我搜索的是“+1”。对于国际消息,需要采用不同的方法。一旦识别出号码的起始位置,就可以轻松解析出号码并将其返回到主函数。

检索消息正文也使用相同的过程。

def getSMSmessage(SMSpos):
        #setup command for reading message
        newSMSread_command = 'AT+CMGR='+str(SMSpos)+'\r'
        #clear receive buffer
        MDM.receive(10)
        MDM.send(newSMSread_command,5)      #read the new SMS arrived
        SMScontent = MDM.receive(15)        #collect the full message with header
        a = SMScontent.find('\n',4) + 1     #Find the end of the first line
        b = len(SMScontent)
        SMSmessage = SMScontent[a:b]        #extract message from response
        return(SMSmessage)

与上面类似,您只需要删除消息的标头,只保留消息的正文。最大的障碍是正确设置调制解调器,其余的都是 string 操作。

发送短信

发送 SMS 消息比接收它们更容易。

def sendSMS( number, smstext):
        #Send command for sending message
        a = MDM.send('AT+CMGS="' + number + '"\r', 2)
        #clear receive buffer
        res = MDM.receive(10)           
        a = MDM.send(smstext, 2)        #Send body of message
        #this terminates the message and sends it
        a = MDM.sendbyte(0x1A, 2)       #terminating the message require ctrl-z
        return()

这里需要使用 CMGS 命令。它只需目的地号码。模块会显示一个提示,然后接受发送给它的任何内容作为消息正文。最后,发送 Ctrl-Z 给模块表示消息已完成并发送。

删除 SMS

要删除 SMS,您只需要知道其在内存中的位置。您也可以删除所有消息,而不是只删除一条。

AT+CMGD=<index>[,<delflag>]

<delflag> 是可选的,允许在删除所有消息时进行多种不同的选项。如果省略或为 0,则仅删除 <index> 位置的消息。

<delflag> 选项包括:

  1. 删除所有消息,保留未读和已发送/未发送的消息
  2. 删除所有已读和已发送的消息,保留未读和未发送的消息
  3. 删除所有消息(除了未读消息,甚至会删除未发送的消息)
  4. 删除所有消息

此函数将从内存中删除所有消息。

def del_all_SMS(SMSpos = 1):
        delSMS_command = 'AT+CMGD='+str(SMSpos)+',4\r'
        MDM.send(delSMS_command,5)     #delete all messages
        return()

拨打语音电话

接听和拨打语音电话不是一个很大的话题,所以我决定在这里涵盖它,而不是专门写一篇文章。接听电话需要检查 MDM 接口上的 stringRING’。这将允许您发送以下命令。

ATA

ATA 接听电话,并使用设备上的麦克风和扬声器输入。这可用于远程监控某个位置或音频源,或创建远程呼叫箱。拨打电话同样简单。

ATD<number>

只需插入要拨打的号码,它就会自动将对方电话连接到麦克风和扬声器连接。使用 Python 中的 MDM.send()MDM.receive() 命令可以非常简单地实现呼叫控制。这是一个接听电话的脚本示例。

#Check for Phone CAll
p = res.find('RING')
if (p != -1):
       q = MDM.send('ATA\r',5)

结论

SMS 消息是与项目之间来回发送信息并允许从几乎任何方式进行控制的绝佳方式。在未来的文章中,我们将介绍其他主题,例如数据呼叫和 GPIO 使用。

历史

  • 2010 年 10 月 8 日:初始版本
© . All rights reserved.