如何使用 ruby 读取源源不断的 NMEA http 数据
How to read a constant stream of NMEA http data using ruby
我有一个名为 'gps2ip' 的 iPhone 应用程序,它会启动一个网络服务器,您可以访问该服务器以获取流式 NMEA 数据。
您可以使用 qgis 直接连接到此流以获取地图上的更新位置。我想以编程方式访问此流。
如果我在我的浏览器中输入这个 url window: 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 代码行解析为 latitude/longitude 对,我只需要能够在 ruby 环境中轻松访问 "the last one"。
我希望能够提取最后一两行并手动解析 NMEA 字符串,但我还没有找到一种方法来 "sip from the firehose" 数据而不生成错误消息。
当我尝试这个时:
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 Server Started. 'exit' to finish." 当然是响应的第一行。
我应该使用什么 ruby gem 来从这个数据流中抽取?显然 open-uri 想要 html headers 而我的流中有 none。我只需要显然地传输纯文本。
由于这不是 HTTP 协议,您需要更通用的 Socket。你可以这样做:
require 'socket'
s = TCPSocket.new '192.168.1.116', 11123
while line = s.gets
puts line
end
s.close
根据数据到达的速度和处理每一行所需的时间,您可能需要研究将每一行放入队列中,例如 Sidekiq 以便多个工作人员可以同时处理行。
由于您拥有的是永无止境的数据流,因此您不能只获取最后一条消息。您必须使用流,并决定何时收到足够的数据以开始处理。您或许可以利用 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 的行。
我有一个名为 'gps2ip' 的 iPhone 应用程序,它会启动一个网络服务器,您可以访问该服务器以获取流式 NMEA 数据。
您可以使用 qgis 直接连接到此流以获取地图上的更新位置。我想以编程方式访问此流。
如果我在我的浏览器中输入这个 url window: 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 代码行解析为 latitude/longitude 对,我只需要能够在 ruby 环境中轻松访问 "the last one"。
我希望能够提取最后一两行并手动解析 NMEA 字符串,但我还没有找到一种方法来 "sip from the firehose" 数据而不生成错误消息。
当我尝试这个时:
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 Server Started. 'exit' to finish." 当然是响应的第一行。
我应该使用什么 ruby gem 来从这个数据流中抽取?显然 open-uri 想要 html headers 而我的流中有 none。我只需要显然地传输纯文本。
由于这不是 HTTP 协议,您需要更通用的 Socket。你可以这样做:
require 'socket'
s = TCPSocket.new '192.168.1.116', 11123
while line = s.gets
puts line
end
s.close
根据数据到达的速度和处理每一行所需的时间,您可能需要研究将每一行放入队列中,例如 Sidekiq 以便多个工作人员可以同时处理行。
由于您拥有的是永无止境的数据流,因此您不能只获取最后一条消息。您必须使用流,并决定何时收到足够的数据以开始处理。您或许可以利用 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 的行。