两个物联网应用程序可以同时访问一个蜂窝调制解调器,这样我就不必杀死ModemManager并断开互联网连接了吗?

问题描述

我一直无法从调制解调器中获取GPS数据。通常,我可以使用以下代码在Python中获取GPS:

import time
from serial import Serial

# If a "port" is given,then the port will be opened immediately.
ser = Serial(port="/dev/ttyUSB3",timeout=2,write_timeout=2)

# The following prints as "True"
print(ser.is_open)

def read_until_timeout(ser,timeout=5):
    """Turn GPS on and read until either we find the line we want,or the timeout occurs
    """

    # Turn GPS on
    ser.write(b"AT+CGPS=1,1\r\n")

    # Request GPS
    ser.write(b"AT+CGPSINFO=1\r\n")

    # Start the loop
    time_start = time.time()
    while ((time.time() - time_start) < timeout):        
        print("Trying ser.readline().decode('ascii',errors='replace')...")
        try:
            # Read from the serial port
            line = ser.readline().decode('ascii',errors='replace')
        except serial.serialutil.SerialException as err:
            print(f"Problem reading data: {err}")

        if "+CGPSINFO:" in line:
            print(f"Found '+CGPSINFO:' in line: {line}")
            break

在工作网关上,最后一条打印语句将返回如下所示的行,其中包含GPS纬度和经度:

print(read_until_timeout(ser,timeout=5))
>>> '+CGPSINFO: 5100.506298,N,11404.432885,W,031120,234519.0,1080.1,0.0,204.6\r\n'

有时运行此功能输出如下,我认为这只是意味着GPS无法获得“修复”:

print(read_until_timeout(ser,timeout=5))
>>> Found '+CGPSINFO:' in line: +CGPSINFO:,

但是有时它会说它很“忙”,如下所示:

print(read_until_timeout(ser,timeout=5))
>>> Problem reading data: read Failed: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

以上是因为两个以上的应用程序无法同时访问串行端口吗?

如果我尝试从Linux Bash向调制解调器发送AT消息,则表明调制解调器“忙” ...

$ echo 'AT+CGPSINFO=1' | socat - /dev/ttyUSB3,crnl
>>> 2020/11/20 19:18:24 socat[3251] E open("/dev/ttyUSB3",02002,0666): Device or resource busy

所以我检查哪些设备正在使用调制解调器:

$ sudo lsof /dev/ttyUSB3
>>> COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
Modemmana  800 root   12u   CHR  188,3      0t0  449 /dev/ttyUSB3
python    1706 root    3u   CHR  188,3      0t0  449 /dev/ttyUSB3

但是,如果我用sudo kill 800关闭ModemManager,那么蜂窝互联网连接就会死掉,而我就不会那样做,因为它们是在旷野的远程IoT设备(我大约有50个北美各地的行动。

是否可以通过Modemmanager 共享调制解调器,以便在通过蜂窝Internet连接时可以通过Python或外壳访问GPS结果? >

这个问题是相关的,所以我也对它悬赏: https://superuser.com/questions/1455327/trying-to-read-a-serial-port-device-or-resource-busy

更新2020年11月22日:

@GitFront有助于suggested直接使用Modemmanager。很棒的建议。 gi库也很巧妙。

从Ubuntu Bash中获得以下内容,当我尝试直接从Modemmanager获取GPS时:

user@user-Default-string:~$ mmcli -m 0 --location-status

/org/freedesktop/Modemmanager1/Modem/0
  ----------------------------
  Location |   capabilities: '3gpp-lac-ci'
           |        enabled: '3gpp-lac-ci'
           |        signals: 'no'

关于定位功能通知,由于某种原因,没有显示gps-raw,gps-nmea,agps,只有3gpp-lac-ci出现,但是我知道此网关/ SIMCom 7600调制解调器具有GPS / GNSS功能,并且连接了无源天线正确。

有人知道为什么gps-raw,agps没有显示功能吗?

与我办公室中完全相同的网关/调制解调器/天线组合确实具有gps-raw,agps功能,并且一切工作正常……唯一的区别是SIM卡,这没关系。相比之下,我办公室中的网关报告以下功能

user@ax1000008:~$ mmcli -m 0 --location-status
  ------------------------
  Location | capabilities: 3gpp-lac-ci,gps-raw,agps
           |      enabled: 3gpp-lac-ci
           |      signals: no
  ------------------------
  GPS      | refresh rate: 30 seconds

我请求启用gps-raw,gps-nmea

user@ax1000008:~$ sudo mmcli -m 0 --location-enable-gps-raw --location-enable-gps-nmea
successfully setup location gathering

然后我通过以下方式成功请求GPS(在我办公室的网关/调制解调器上):

user@ax1000008:~$ sudo mmcli -m 0 --location-get
  --------------------------
  3GPP |      operator code: 302
       |      operator name: 220
       | location area code: 2BC4
       | tracking area code: 0000
       |            cell id: 04B68931
  --------------------------
  GPS  |               nmea:
       |                     $GPGGA,183553.00,5100.511216,11404.429721,1,06,1.7,1078.0,M,-16.0,*6C
       |                     $GPRMC,183552.00,A,5100.511138,11404.429729,341.3,221120,15.4,E,A*10
       |                     $GPGSA,2,01,03,21,22,31,32,2.0,0.9*3C
       |                     $GPGSV,4,15,45,295,34,11,291,29,10,109,20,36*4F
       |                     $GPGSV,12,08,056,19,53,258,35,33,292,23,02,111,15*79
       |                     $GPGSV,3,25,092,163,70,066,236,*7C
       |                     $GPGSV,17,04,344,24,*48
       |                     $GPVTG,T,325.9,K,A*2B
       |                     $PQXFI,183553.0,9.61,5.64,0.13*4E
       |                utc: 183553.00
       |          longitude: -114.073829
       |           latitude: 51.008520
       |           altitude: 1078.000000

在该字段的非工作网关上,这是我尝试启用gps-rawgps-nmea时得到的信息:

user@user-Default-string:~$ sudo mmcli -m 0 --location-enable-gps-raw --location-enable-gps-nmea
error: Couldn't setup location gathering: 'GDBus.Error:org.freedesktop.Modemmanager1.Error.Core.Unsupported: Cannot enable unsupported location sources: 'gps-raw,gps-nmea''

解决方法

您应该能够利用ModemManager来获取GPS位置,而不是直接获取它。这样,您可以避免在两个服务中使用相同的串行端口。

在ModemManager联机帮助页中,有使用public class Battery { public enum BatteryType { NotSet,LiLon,NiMH,NiCd } public BatteryType IsBatteryType { get; private set;} = BatteryType.NotSet; public ushort HoursIdle { get; private set; } public ushort HoursTalk { get; private set; } public Battery(ushort hoursIdle,ushort hoursTalk,BatteryType batteryType) { this.HoursIdle = hoursIdle; this.HoursTalk = hoursTalk; this.IsBatteryType = batteryType; } } 工具从命令行执行此操作的文档: https://www.freedesktop.org/software/ModemManager/man/1.0.0/mmcli.8.html#lbBC

还有一个mmcli库,您应该可以通过GObject Introspection从Python使用它,而无需运行命令行工具。

libmm-glib

请记住,当数据会话处于活动状态(from the documentation)时,设备可能无法提供位置:

位置接口允许设备向客户端应用程序提供位置信息。并非所有设备都可以提供此信息,或者即使提供了信息,在数据会话处于活动状态时也可能无法提供此信息。

,

我认为我现在基本上已经解决了这个问题,而不必杀死ModemManager(这有可能会杀死IoT远程网关上的Internet连接)。

主要答案是我根本无法获得GPS定位(除了许可问题)。

我在Python代码中没有做任何错误,有时ModemManager使用的是我向(/dev/ttyUSB2/dev/ttyUSB3)发送命令的AT端口...将ModemManager升级到v1。 10.0也可能有效,但我不愿意在现场工作的实时网关上进行。

@ rm5248建议在像我的SIMCom 7600上的/dev/ttyUSB1上使用专用的NMEA端口,我认为他是正确的。

我使用此documentation安装了GPSD(GPSDaemon)及其各种客户端(例如cgps和gpsmon)。如果GPS已修复,则GPSD及其客户非常适合获取GPS信息。

如何测试GPSD软件: https://gpsd.gitlab.io/gpsd/installation.html#_how_to_test_the_software

# Start GPSD on /dev/ttyUSB1 with debug level 5,# -N (don't daemonize),and -n (don't wait for 
# client to connect to poll GPS)

# no daemon,for debugging
$ sudo gpsd -D 5 -N -n /dev/ttyUSB1

# daemonized to run in background
$ sudo gpsd -D 5 -n /dev/ttyUSB1

然后运行以下两个客户端之一,并观察/dev/ttyUSB1上专用的NMEA端口,而不是/dev/ttyUSB2/dev/ttyUSB3上的“ AT”端口:

$ cgps
$ gpsmon /dev/ttyUSB1

在工作网关cgps上的工作方式如下: working gps on gateway with cgps

gpsmon /dev/ttyUSB1的工作方式如下: working gps on gateway with gpsmon

但是在不起作用的网关上,cgps看起来像这样,显示NO FIXnon-working gateway,no fix