【问题标题】:Parsing message parameters received by a GSM modem in python在python中解析GSM调制解调器收到的消息参数
【发布时间】:2013-03-28 17:52:15
【问题描述】:

我正在尝试在 python 中解析从 GSM 调制解调器接收到的消息。

我有很多消息需要解析。我每隔几个小时左右就会收到新消息。

这是我使用串行对象将数据从调制解调器读取到列表 x 后收到的数据示例。

AT+CMGL="ALL"


+CMGL: 1,"REC READ","+918884100421","","13/04/05,08:24:36+22"
here's message one 

+CMGL: 2,"REC READ","+918884100421","","13/04/05,09:40:38+22"
here's message two

+CMGL: 3,"REC READ","+918884100421","","13/04/05,09:41:04+22"
here's message three

+CMGL: 4,"REC READ","+918884100421","","13/04/05,10:04:18+22"
here's message four

+CMGL: 5,"REC READ","+918884100421","","13/04/05,10:04:32+22"
here's message five

.
.
.
.
.

还有很多消息,我这里只列出了五个。

我的主要目的是提取消息的内容,例如我收到的每条消息的“这里是消息一”等等。

这是我现在正在使用的代码。

def reading():
     print "Reading all the messages stored on SIM card"
     phone.write(b'AT+CMGL="ALL"\r')
     sleeps()
     x=phone.read(10000)
     sleeps()
     print x
     print "Now parsing the message!"
     k="".join(x)
     parse(k)
     k=""
def parse(k):
    m = re.search("\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\r\n(.+)\r\n",k)
    print "6="
    print m.group(6)

Phone 是我用来从 GSM 调制解调器读取的串行对象。

这里的m.group(6)是捕获第一条消息“这里是消息一”的消息内容

我怎样才能让它匹配所有消息的内容,而不仅仅是第一个。

我尝试设置多行标志,但没有奏效。也没有使用 re.findall() 代替 re.search()。

re.search 返回的匹配对象也是不可迭代的。

请帮忙。

【问题讨论】:

  • 能否请您将接收消息的 Python 程序添加到您的问题中?

标签: python regex parsing gsm at-command


【解决方案1】:

为此使用正则表达式并不是一个非常可靠的解决方案,因为它无法处理不同电话行为的变化。在您的示例中,响应的格式是

+CMGL: 1,"REC READ","+918884100421","","13/04/05,08:24:36+22"

但其他手机会给出类似的响应

+CMGL: 1,"REC READ","+31612123738",,"08/12/22,11:37:52+04"

注意第四个参数"" 与什么都没有的区别。 查看27.005,文本模式下的响应语法为

+CMGL: <index>,<stat>,<oa/da>,[<alpha>],[<scts>][,<tooa/toda>,<length>]<CR><LF>
<data><CR><LF>

&lt;alpha&gt; 确实是可选的。是的,可能会编写一个考虑到这一点的正则表达式,但随后您会进入two problems land


我建议您做的是切换到对响应进行正确解析,即:从第一个字符开始并根据预期的参数格式(和存在)分块前进。请参阅this answer 以获取一种快速而肮脏的方法来提取电话号码。它不如我在下面描述的算法那么健壮(例如comma + 2 假设太多)。

解析响应的绝对正确算法是:

匹配行首的前缀(例如+CMGL:)。然后开始解析区分以下标记:

  • 空白' ''\t'
  • 逗号','
  • 双引号'"'
  • 回车'\r'
  • 换行'\n'
  • 任何非空白非逗号非双引号非cr非lf字符

对于每个参数,首先忽略任何前导空格。 如果得到逗号,则参数不存在,继续解析下一个参数。 如果得到回车,下一个字符应该是换行符并到达行尾。如果得到一个非空白非...字符,这是一个数字参数的开始。收集此参数后面的所有非空白非...字符。在此之后,唯一的合法字符应该是零个或多个空格,后跟逗号或回车。 如果得到一个双引号字符前进到下一个双引号字符,那就是字符串的结尾(这是安全且正确的,因为即使字符串应该包含双引号字符,它们也会被转义但不是\")。在此之后,唯一的合法字符应该是零个或多个空格,后跟逗号或回车。

上面的内容一开始可能看起来有点不知所措,但是当你开始处理它时,它真的没有那么复杂。

【讨论】:

  • 哇,这真是太有见地了!会尽快测试一下,看看效果如何,谢谢:)
【解决方案2】:

由于我没有得到您的材料,所以我只是制作了一个样本。

'\xef\xbb\xbfAT+CMGL="ALL"\n\n+CMGL: 1,"REC READ","+918884100421","","13/04/05,08:24:36+22"\nhere\'s message one \n\n+CMGL: 2,"REC READ","+918884100421","","13/04/05,09:40:38+22"\nhere\'s message two\n\n+CMGL: 3,"REC READ","+918884100421","","13/04/05,09:41:04+22"\nhere\'s message three\n\n+CMGL: 4,"REC READ","+918884100421","","13/04/05,10:04:18+22"\nhere\'s message four\n\n+CMGL: 5,"REC READ","+918884100421","","13/04/05,10:04:32+22"\nhere\'s message five\n'

这来自您使用''.join() 提出的问题。然后我使用您的正则表达式模式,只需将\r\n 替换为\n,因为我使用的示例使用\n。我得到了结果。我不知道为什么 findall 不适合你。

def parse(x):
    res = []
    match = re.finditer("\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\n(.+)\n", x)
    for each in match:
        res.append(each.group(6))
    return res

我得到的结果是["here's message one ", "here's message two", "here's message three", "here's message four", "here's message five"]finditer 返回一个迭代器,findall 也可以正常工作。

 def parse(x):
        res = []
        match = re.findall("\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\n(.+)\n", x)
        for each in match:
            res.append(each[5])
        return res

【讨论】:

    【解决方案3】:

    如果消息总是在换行符上

    (?:[\n\r]+|^)\+CMGL.*?[\n\r]+(.*?)(?=[\n\r]+|$)
    

    第 1 组包含您所需的消息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      相关资源
      最近更新 更多