Ravn::HAL::Device::
SilvusRadio
class
Silvus Radio adapter.
Responsible for generating the following events:
-
sys.gps.position
-
sys.gps.time
-
sys.radio.battery
- FAKE_STATUS
A false status message used for testing and simulation mode, where a Silvus radio might not be present.
- radio R
The Silvus::Radio API.
- timer R
A timer that discovers the Silvus radio IP and sends data across the event bus.
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
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
Create a new device adapter for a Silvus radio.
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
Return a Hash that contains information describing this device for intra-device communication; overridden to set the correct vendor
.
def gather_device_info
return super.merge( vendor: 'silvus' )
end
send_battery_level( status )
Emit the radio battery level event.
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.
def send_gps_position( status )
msg = self.build_gps_message( status )
self.filter_up( msg ) if msg
end
Emit the gps time event.
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.
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
Fetch the radio status, and send values up the message bus.
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
Fire up the interval timer for radio messages.
def start
super
self.timer.execute
end
Find the local radio, based on a known private network and local interface. Instance a new radio API if interface found.
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.
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