向 USB GSM 调制解调器发送“AT”命令在 Python 中返回空字符串

Posted

技术标签:

【中文标题】向 USB GSM 调制解调器发送“AT”命令在 Python 中返回空字符串【英文标题】:Sending 'AT' command to usb GSM modem return empty string in Python 【发布时间】:2019-06-05 20:50:05 【问题描述】:

问题

我正在 python 中设置一个脚本,以通过 AT 命令与我的 USB GSM 调制解调器通信。 因此,为了测试通信是否正常工作,我首先尝试发送一个简单的AT,期望收到一个OK,但是对于每个read 请求,我仍然只收到空字符串。 我遵循此处解释的 AT 标准:AT Commands

到目前为止

在 Linux Mint 18 上工作。 我通过mmcli找到了有关我的 GSM 的更多信息。 启动 mmcli -L 会导致:

$ mmcli -L
    /org/freedesktop/ModemManager1/Modem/0 [D-Link,Inc  ] D-Link DWM-157

然后是信息:

$ mmcli -m /org/freedesktop/ModemManager1/Modem/0 
  --------------------------
  General  |      dbus path: /org/freedesktop/ModemManager1/Modem/0
           |      device id: 741cce5b5eb40d9ac1c9a1dc0dfa2356f0abe3e7
  --------------------------
  Hardware |   manufacturer: D-Link,Inc  
           |          model: D-Link DWM-157
           |       revision: MOLY.WR8.W1231.DC.WG.MP.V3
           |   h/w revision: MTK2
           |      supported: gsm-umts
           |        current: gsm-umts
           |   equipment id: 355620059754511
  --------------------------
  System   |         device: /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-5
           |        drivers: cdc_mbim, option1
           |         plugin: Generic
           |   primary port: cdc-wdm2
           |          ports: ttyUSB0 (at), wwp0s29f7u5 (net), ttyUSB1 (at), 
           |                 cdc-wdm2 (mbim)
  --------------------------
  Numbers  |            own: 393515383117
  --------------------------
  Status   | unlock retries: unknown (0)
           |          state: registered
           |    power state: on
           |    access tech: hsdpa, hsupa
           | signal quality: 0% (cached)
  --------------------------
  Modes    |      supported: allowed: 2g, 3g; preferred: none
           |        current: allowed: 2g, 3g; preferred: none
  --------------------------
  IP       |      supported: ipv4, ipv6, ipv4v6
  --------------------------
  3GPP     |           imei: 355620059754511
           |  enabled locks: net-pers, net-sub-pers, provider-pers, corp-pers
           |    operator id: 22250
           |  operator name: 22250
           |   registration: home
  --------------------------
  SIM      |      dbus path: /org/freedesktop/ModemManager1/SIM/0

所以要检查我的 GSM 是否能够回复 AT,我使用了 socat:

$ sudo socat - /dev/ttyUSB0
AT

OK

最终目标

我的目标是创建一个脚本,允许我向一个号码列表发送多条短信。

完整的脚本

import serial, time

def initSerial() :
    print ('initialize...', end='')
    ser = serial.Serial()
    ser.port = "/dev/ttyUSB0"
    ser.baudrate = 115200
    ser.timeout = 5                     #timeout block read
    ser.writeTimeout = 2
    ser.bytesize = serial.EIGHTBITS     #number of bits per bytes
    ser.parity = serial.PARITY_NONE     #set parity check: no parity
    ser.stopbits = serial.STOPBITS_ONE  #number of stop bits
    ser.xonxoff = False                 #disable software flow control
    ser.rtscts = False                  #disable hardware (RTS/CTS) flow control
    ser.dsrdtr = False                  #disable hardware (DSR/DTR) flow control
    ser.open()
    print('done')
    return ser


def write_cmd(ser,cmd) :
    if ser.isOpen() :   
        print('writing: "  " in '.format(cmd, ser.name))
        ser.write(cmd.encode('utf-8'))  # Write the 'cmd' encoded with utf-8


def read_until(ser,terminator='\n'):
    print ('reading ...'.format(ser.name))
    resp = ''
    while not ( resp.endswith(terminator) or resp.endswith('\r') ) : # If the string is not terminated
        tmp = ser.read(1)   # Read and store in a temp variable
        if not tmp : return resp # timeout occured
        resp += tmp
    return resp  


if __name__ == '__main__' :
    ser = initSerial()          # Setup initial variables and configurations
    write_cmd(ser,'AT\r\n')         # Write a command to the serial pipe
    print(read_until(ser))      # Read from the serial pipe until 
    ser.close()

这是输出:

$ sudo python3 main.py 
  initialize...done
  writing: " AT " in /dev/ttyUSB0
  reading /dev/ttyUSB0...

那里有一个空行。

【问题讨论】:

【参考方案1】:

AT 命令根据特定的 sintaxis 工作。在这种情况下,我会说问题在于您发送的 AT 没有结尾行。您必须在末尾发送所有 AT 命令,并带有载波和结束行字符。所以在这种情况下是AT\r\n,你与设备通信的所有命令都应该以同样的方式完成。

if __name__ == '__main__' :
ser = initSerial()          # Setup initial variables and configurations
write_cmd(ser,'AT\r\n')     # Write a command to the serial pipe
print(read_until(ser))      # Read from the serial pipe until 
ser.close()

每个 AT 命令更改的响应取决于您使用的命令。我建议您使用另一个更详细的代码来接收 RX 信号。

【讨论】:

我尝试按照您的建议编写 'AT\r\n' 以及 'AT\r''AT\n'。不幸的是并没有改变结果。感谢您对接收代码的建议,解决通信问题后我会改进它。 你用什么在你的电脑和你的模块之间发送信息?你也测试过波特率吗?也许您正在为设备使用更高的波特率【参考方案2】:

似乎有什么东西阻止了您的代码返回错误。

对于 Python 3.x serial.read() 返回字节,所以你在哪里做:

resp += tmp

你应该得到一个错误(当我在我的笔记本电脑上运行你将两个串行端口连接在一起的代码时得到它)。

将该行更改为:

resp += tmp.decode()

更多详情请看这里:Why does pyserial for python3k return bytes while python2k returns strings?

我能想到的唯一原因是您没有收到此类型转换错误,因为您的端口上根本没有收到任何内容(您的代码在从端口读取空值时跳过该行)。如果是这种情况,我想您将不得不检查您的设置,因为您的 Python 代码可以正常工作。

【讨论】:

以上是关于向 USB GSM 调制解调器发送“AT”命令在 Python 中返回空字符串的主要内容,如果未能解决你的问题,请参考以下文章

使用 Android 模拟器测试来自外部应用程序的 COM 的 AT 命令

+CMS ERROR: 304, 使用 at 命令发送消息

如何使用python(pyserial)向华为E3272 Hilink发送AT命令?

如何通过USB GSM调制解调器从VB应用程序发送短信(华为E1731)

GSM之AT操作命令详解20160615

GSM调制解调器的反应太迟了