112 lines
3.1 KiB
Ruby
112 lines
3.1 KiB
Ruby
# Represents a provider of GPS fixes and a dispatcher of event callbacks for applications needing
|
|
# such fixes.
|
|
module Gps
|
|
class Receiver
|
|
include Fix
|
|
|
|
def initialize(options = {})
|
|
super
|
|
@last_latitude = @last_longitude = 0
|
|
@position_change_threshold = 0
|
|
@last_speed = 0
|
|
@last_course = 0
|
|
@last_altitude = 0
|
|
@last_satellites = 0
|
|
end
|
|
|
|
# Factory for creating a +Receiver+.
|
|
# Accepts an implementation and a hash of options, both optional. If no
|
|
# implementation is provided, the first is used by default. Implementations are in
|
|
# the module +Gps::Receivers+.
|
|
def self.create(arg = nil, args = {})
|
|
implementation = arg.respond_to?(:capitalize)? Receivers.const_get(arg.capitalize): Receivers.const_get(Receivers.constants[0])
|
|
options = arg.kind_of?(Hash)? arg: args
|
|
implementation.new(options)
|
|
end
|
|
|
|
# Sets the position from an array of the form [latitude, longitude], calling the
|
|
# _on_position_change_ callback if necessary.
|
|
def position=(value)
|
|
@latitude = value[0]
|
|
@longitude = value[1]
|
|
call_position_change_if_necessary
|
|
end
|
|
|
|
# Called on position change, but only if the change is greater than +threshold+ degrees.
|
|
# The block receives the amount of change in degrees.
|
|
def on_position_change(threshold = 0, &block)
|
|
@position_change_threshold = threshold
|
|
@on_position_change = block
|
|
end
|
|
|
|
# Called on speed change.
|
|
def on_speed_change(&block)
|
|
@on_speed_change = block
|
|
end
|
|
|
|
# Called on course change.
|
|
def on_course_change(&block)
|
|
@on_course_change = block
|
|
end
|
|
|
|
# Called when the altitude changes.
|
|
def on_altitude_change(&block)
|
|
@on_altitude_change = block
|
|
end
|
|
|
|
# Called when the number of visible satellites changes.
|
|
def on_satellites_change(&block)
|
|
@on_satellites_change = block
|
|
end
|
|
|
|
# Override this in children. Opens the connection, device, etc.
|
|
def start
|
|
@thread = Thread.new do
|
|
while true
|
|
update
|
|
end
|
|
end
|
|
end
|
|
|
|
# Override this in children. Closes the device, connection, etc. and stops updating.
|
|
def stop
|
|
@thread.kill if @thread
|
|
@thread = nil
|
|
end
|
|
|
|
# Returns _true_ if started, _false_ otherwise.
|
|
def started?
|
|
!@thread.nil? && @thread.alive?
|
|
end
|
|
|
|
# Override this in children, setting fix variables from the GPS receiver.
|
|
# Here we dispatch to callbacks if necessary.
|
|
def update
|
|
call_position_change_if_necessary
|
|
@on_speed_change.call if @on_speed_change and @speed != @last_speed
|
|
@last_speed = @speed
|
|
@on_course_change.call if @on_course_change and @course != @last_course
|
|
@last_course = @course
|
|
@on_altitude_change.call if @on_altitude_change and @altitude != @last_altitude
|
|
@last_altitude = @altitude
|
|
@on_satellites_change.call if @on_satellites_change and @satellites != @last_satellites
|
|
@last_satellites = @satellites
|
|
end
|
|
|
|
private
|
|
def call_position_change_if_necessary
|
|
if position_change > @position_change_threshold
|
|
@on_position_change.call(position_change) if @on_position_change
|
|
@last_latitude = @latitude
|
|
@last_longitude = @longitude
|
|
end
|
|
end
|
|
|
|
def position_change
|
|
(@latitude-@last_latitude).abs+(@longitude-@last_longitude).abs
|
|
end
|
|
end
|
|
|
|
module Receivers
|
|
end
|
|
end |