【问题标题】:How to read a constant stream of NMEA http data using ruby如何使用 ruby​​ 读取恒定的 NMEA http 数据流
【发布时间】:2015-01-12 01:05:14
【问题描述】:

我有一个名为“gps2ip”的 iPhone 应用程序,它会启动一个网络服务器,您可以访问它来获取流式 NMEA 数据。

您可以使用 qgis 直接连接到此流,以获取地图上的更新位置。我想以编程方式访问此流。

如果我在浏览器 url 窗口中输入:http://192.168.1.116:11123 其中 192.168.1.116 是我的智能手机的 IP,如 gps2ip 应用程序所示

我在我的 safari/chrome/mozilla 浏览器屏幕上不断收到换行符分隔的 NMEA 字符串流,并在底部不断更新数据行。

    GPS 2 IP Server started. "exit" to finish.
    $GPGGA,005730,3403.415,N,07914.488,W,1,8,0.9,13.6,M,46.9,M,0,2*56
    $GPRMC,005730,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*66
    $GPGGA,005730,3403.415,N,07914.488,W,1,8,0.9,13.6,M,46.9,M,0,2*56
    $GPRMC,005730,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*66
    $GPGGA,005731,3403.415,N,07914.488,W,1,8,0.9,13.7,M,46.9,M,0,2*56
    $GPRMC,005731,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*67
    $GPGGA,005731,3403.415,N,07914.488,W,1,8,0.9,13.7,M,46.9,M,0,2*56
    $GPRMC,005731,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*67
    $GPGGA,005732,3403.415,N,07914.488,W,1,8,0.9,13.6,M,46.9,M,0,2*54
    $GPRMC,005732,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*64
    $GPGGA,005732,3403.415,N,07914.488,W,1,8,0.9,13.6,M,46.9,M,0,2*54
    $GPRMC,005732,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*64
    $GPGGA,005733,3403.415,N,07914.488,W,1,8,0.9,13.5,M,46.9,M,0,2*56
    $GPRMC,005733,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*65
    $GPGGA,005733,3403.415,N,07914.488,W,1,8,0.9,13.5,M,46.9,M,0,2*56
    $GPRMC,005733,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*65
    $GPGGA,005734,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*50
    $GPRMC,005734,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*62
    $GPGGA,005734,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*50
    $GPRMC,005734,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*62
    $GPGGA,005735,3403.415,N,07914.488,W,1,8,0.9,13.3,M,46.9,M,0,2*56
    $GPRMC,005735,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*63
    $GPGGA,005735,3403.415,N,07914.488,W,1,8,0.9,13.3,M,46.9,M,0,2*56
    $GPRMC,005735,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*63
    $GPGGA,005736,3403.415,N,07914.488,W,1,8,0.9,13.2,M,46.9,M,0,2*54
    $GPRMC,005736,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*60
    $GPGGA,005736,3403.415,N,07914.488,W,1,8,0.9,13.2,M,46.9,M,0,2*54
    $GPRMC,005736,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*60
    $GPGGA,005737,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*53
    $GPRMC,005737,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*61
    $GPGGA,005737,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*53
    $GPRMC,005737,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*61
    $GPGGA,005738,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*5C
    $GPRMC,005738,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*6E
    $GPGGA,005738,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*5C
    $GPRMC,005738,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*6E
    $GPGGA,005739,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*5D
    $GPRMC,005739,A,3403.415,N,07914.488,W,0.00,,120115,003.1,W*6F
    $GPGGA,005739,3403.415,N,07914.488,W,1,8,0.9,13.4,M,46.9,M,0,2*5D

我知道如何将这些 NMEA 代码行解析成纬度/经度对,我只需要能够在 ruby​​ 环境中轻松访问“最后一个”。

我希望能够提取最后一两行并手动解析 NMEA 字符串,但我还没有找到一种方法来“从消防软管中吸取”数据而不生成错误消息。

当我尝试这个时:

require 'open-uri'
open("http://192.168.1.116:11123")

我收到此错误:

Net::HTTPBadResponse: wrong status line: "GPS 2 IP Server started. \"exit\" to finish."

“GPS 2 IP 服务器已启动。‘退出’完成。”当然是响应的第一行。

我应该使用什么 ruby​​ gem 来从这些数据流中啜饮?显然 open-uri 想要 html 标头,而我的流没有。我显然只需要流式传输纯文本。

【问题讨论】:

  • 数据显然不是在HTTP协议中传输的。
  • 这个消防软管有多快? (例如每秒行数)
  • 1/s 也许我不确定....不完全是我的消防水管我想也许我只是想说

标签: ruby sockets stream gps


【解决方案1】:

由于这不是 HTTP 协议,因此您需要更通用的 Socket。你可以这样做:

require 'socket'

s = TCPSocket.new '192.168.1.116', 11123

while line = s.gets 
  puts line
end

s.close 

根据数据到达的速度以及处理每行所需的时间,您可能需要研究将每行放入队列中,例如Sidekiq,以便多个工作人员可以同时处理行。

【讨论】:

  • 这很好用。在这里达成交易所需要做的就是将我的 gps2ip 应用程序设置为仅广播 GPGLL 信号,然后在这里使用一些 ruby​​ 代码:github.com/jgillick/ruby-serialgps 来解析字符串。有一个非常糟糕的 protogem 来处理事务的最后一段,即为 lat & lng 返回简单的浮点值。 github.com/ddd1600/parse_nmea_from_ip
【解决方案2】:

由于您拥有的是永无止境的数据流,因此您不能只获取最后一条消息。您必须使用流,并决定何时收到足够的数据以开始处理。您可能可以利用GPRMC 消息来做到这一点。

nmea_plus(完全公开,我写的),你可以这样做:

require 'socket'
require 'nmea_plus'

allowable_delay = 3  # threshold to consider the stream as fresh
caught_up = false    # flag to say whether we've crossed the threshold

io_source = TCPSocket.new('192.168.1.116', 11123)
source_decoder = NMEAPlus::SourceDecoder.new(io_source)

source_decoder.each_message do |msg|
  case msg.data_type
  when 'GPRMC'
    if Time.now - msg.utc_time < allowable_delay
      caught_up = true
    end
  when 'GPGLL'
    if caught_up
      puts "Fix: #{msg.latitude}, #{msg.longitude}"
    end
  end
end

默认情况下,解码器会忽略任何不解析为 NMEA 的行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 2010-12-08
    • 2010-11-11
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    相关资源
    最近更新 更多