Ravn::HAL::Device::

SilvusRadio class

Silvus Radio adapter.

Responsible for generating the following events:

  • sys.gps.position

  • sys.gps.time

  • sys.radio.battery

Constants

FAKE_STATUS

A false status message used for testing and simulation mode, where a Silvus radio might not be present.

Attributes

radio R

The Silvus::Radio API.

timer R

A timer that discovers the Silvus radio IP and sends data across the event bus.

Public Class Methods

fake_radio_status()

Create a stubbed radio status message, for when you don’t have a real radio present. Randomizes position within ~500 meters. en.wikipedia.org/wiki/Decimal_degrees

# File lib/ravn/hal/device/silvus_radio.rb, line 49
def self::fake_radio_status
        lat = ( "39.09"  + "%02d" % rand(50) ).to_f
        lon = ( "-94.58" + "%02d" % rand(50) ).to_f

        status = FAKE_STATUS.merge(
                :battery_level => rand( 100 ),
                :gps_time      => Time.now.to_i,
        )
        status[ :gps_coordinates ].merge!(
                :latitude  => lat,
                :longitude => lon
        )

        return status
end
new( * )

Create a new device adapter for a Silvus radio.

# File lib/ravn/hal/device/silvus_radio.rb, line 92
def initialize( * )
        @radio = nil
        @timer = Concurrent::TimerTask.new do
                self.validate_radio
                self.send_status_messages
        end
        @timer.execution_interval = self.class.status_frequency
        @timer.add_observer( Ravn::LoggingTaskObserver.new( :silvus_timer) )

        if self.class.simulation_mode?
                self.log.warn "Radio operating in simulation mode!"
        end

        super
end

Public Instance Methods

gather_device_info()

Return a Hash that contains information describing this device for intra-device communication; overridden to set the correct vendor.

# File lib/ravn/hal/device/silvus_radio.rb, line 125
def gather_device_info
        return super.merge( vendor: 'silvus' )
end
send_battery_level( status )

Emit the radio battery level event.

# File lib/ravn/hal/device/silvus_radio.rb, line 171
def send_battery_level( status )
        msg = Ravn::HAL::Message.new( 'sys.radio.battery', data: { battery: status[:battery_level] } )
        self.filter_up( msg )
end
send_gps_position( status )

Emit the gps position event. Munge the GPS message to be more CoT-like before delivery.

# File lib/ravn/hal/device/silvus_radio.rb, line 164
def send_gps_position( status )
        msg  = self.build_gps_message( status )
        self.filter_up( msg ) if msg
end
send_gps_time( status )

Emit the gps time event.

# File lib/ravn/hal/device/silvus_radio.rb, line 154
def send_gps_time( status )
        time = status[ :gps_time ].to_i
        msg  = Ravn::HAL::Message.new( 'sys.gps.time', data: { time: time } )

        self.filter_up( msg )
end
send_mesh_state( status )

Emit the radio mesh state event.

# File lib/ravn/hal/device/silvus_radio.rb, line 178
def send_mesh_state( status )
        msg = Ravn::HAL::Message.new( 'sys.radio.mesh', data: {
                nodeid: status[ :nodeid ],
                mesh:   status[ :network_status ]
        })
        self.filter_up( msg )
end
send_status_messages()

Fetch the radio status, and send values up the message bus.

# File lib/ravn/hal/device/silvus_radio.rb, line 131
def send_status_messages
        if self.class.simulation_mode?
                status = self.class.fake_radio_status
        else
                return unless self.radio
                status = self.radio.status
        end

        self.send_gps_time( status ) if status[ :gps_time ]
        self.send_battery_level( status ) if status[ :battery_level ]
        self.send_gps_position( status )
        self.send_mesh_state( status )

rescue => err
        self.log.error "Exception during status_message: %s %s\n%s" % [
                err.class.to_s,
                err.message,
                err.full_message
        ]
end
start()

Fire up the interval timer for radio messages.

# File lib/ravn/hal/device/silvus_radio.rb, line 117
def start
        super
        self.timer.execute
end
validate_radio()

Find the local radio, based on a known private network and local interface. Instance a new radio API if interface found.

# File lib/ravn/hal/device/silvus_radio.rb, line 190
def validate_radio
        return if self.class.simulation_mode?

        zyre_int  = Zyre.interfaces[ Ravn::Net.interface ] or raise "No valid Ravn::Net interface."
        zyre_addr = zyre_int[ :address ]

        raise "Unable to find Silvus mesh network." unless
                zyre_addr.start_with?( self.class.network_prefix )

        radio_ip = IPAddr.new( "#{zyre_addr}#{self.class.network_mask}" ).succ
        self.log.info "Using radio at: %s" % [ radio_ip ] unless @radio
        @radio = Ravn::Silvus::API.new( radio_ip )

rescue => err
        self.log.error( err.message )
        @radio = nil
end

Protected Instance Methods

build_gps_message( status )

Construct and return a ‘sys.gps.position’ message.

# File lib/ravn/hal/device/silvus_radio.rb, line 214
def build_gps_message( status )
        return if status[ :gps_lock_level ] == :none
        gps = {
                pos: status[ :gps_coordinates ].values_at( :latitude, :longitude ),
                hae: status.dig( :gps_coordinates, :altitude ),
                ce:  status[ :gps_lock_level ] == :basic ? 15.0 : 3.0
        }
        return Ravn::HAL::Message.new( 'sys.gps.position', data: gps )
end