Ravn::BDE::

MissionController class

Main loop and workflow manager for the BDE. This object has two main jobs:

  • it serves as the trunk of the supervision tree, starting each of the pieces of the BDE beneath it.

  • it reflects events coming up the tree back down to the branches other than the sender.

Constants

CP_VERSION

The path to the hardware image’s version file.

Attributes

beacon_timer R

The object’s beacon timer

bolt_runner R

The Actor managing startup and running of Bolts

config R

The mission configuration

device_manager R

The Actor managing the Ravn::HAL::Manager

event_count RW

The number of events which have crossed the bus.

event_logger R

The Actor responsible for logging events to disk.

gateway_manager R

The Actor responsible for starting any configured gateways

net_broker R

The Actor managing the Ravn::Net::Broker for net-bound messages

start_time R

The monotonic time of the BDE’s startup

state_manager R

The Actor managing per-run state

Public Class Methods

new()

Create a new BDE::MissionController for the mission contained in mission_file.

# File lib/ravn/bde/mission_controller.rb, line 46
def initialize
        @start_time      = Ravn.monotonic_time
        @event_count     = 0
        @beacon_timer    = self.get_beacon_timer

        @config          = nil

        @state_manager   = nil
        @net_broker      = nil
        @device_manager  = nil
        @bolt_runner     = nil
        @event_logger    = nil
        @gateway_manager = nil

        super
end

Public Instance Methods

beacon_info()

Return an information hash for beacon messages.

# File lib/ravn/bde/mission_controller.rb, line 137
def beacon_info
        return { uptime: self.uptime, event_count: self.event_count }
end
emit_pois_event()

Issue an event with any static POIs that are preconfigured as part of the mission.

# File lib/ravn/bde/mission_controller.rb, line 220
def emit_pois_event
        pois = self.config[ :pois ] or return
        payload = pois.each_with_object( {} ) do |poi, acc|
                acc[ poi[:name] ] = poi.values_at( :latitude, :longitude )
        end

        msg = Ravn::BDE::Message.new( 'sys.pois', data: payload )
        self.tell( msg )
end
emit_startup_event()

Generate and issue an event indicating all controller components are instantiated and ready.

# File lib/ravn/bde/mission_controller.rb, line 185
def emit_startup_event
        startup_info = {
                callsign:       Ravn::BDE.callsign,
                system_time:    Ravn.time,
                monotonic_time: Ravn.monotonic_time,
                device_id:      Ravn.device_id,
                mission:        Ravn::BDE.mission,
                network: {
                        'interface'  => Ravn::Net.interface,
                        'ip_address' => Zyre.interfaces[ Ravn::Net.interface ]&.dig( :address )
                },
                versions: {
                        'ravn'       => Ravn::VERSION,
                        'ravn-bde'   => Ravn::BDE::VERSION,
                        'ravn-hal'   => Ravn::HAL::VERSION,
                        'ravn-net'   => Ravn::Net::VERSION,
                        'ruby'       => RbConfig::CONFIG[ 'ruby_version' ],
                        'concurrent' => Concurrent::VERSION,
                        'mdbx'       => MDBX::VERSION,
                        'libmdbx'    => MDBX::LIBRARY_VERSION,
                        'sqlite'     => SQLite3::VERSION,
                        'zyre'       => Zyre::VERSION,
                        'cp_image'   => CP_VERSION.readable? ? CP_VERSION.read : 'v?.?.?'
                },
        }

        Ravn::BDE::Beacon.send_message( type: 'startup', **startup_info )
        msg = Ravn::BDE::Message.new( 'sys.startup', data: startup_info )

        self.tell( msg )
end
filter_up( message )

Reflect messages coming up the tree back down.

# File lib/ravn/bde/mission_controller.rb, line 176
def filter_up( message )
        message.audit {}
        self.event_count += 1
        self.reflect_message( message )
end
get_beacon_timer()

Start a timer that will periodically send a status beacon

# File lib/ravn/bde/mission_controller.rb, line 253
def get_beacon_timer
        timer = Concurrent::TimerTask.new do
                self.tell( send_status_beacon: true )
        end
        timer.execution_interval = Ravn::BDE::Beacon.status_interval

        self.log.info "Created beacon timer: %p" % [ timer ]
        return timer
end
handle_send_status_beacon( * )

Send a periodic beacon with the BDE’s status.

# File lib/ravn/bde/mission_controller.rb, line 232
def handle_send_status_beacon( * )
        self.log.debug "Sending a status beacon: %p" % [ self ]

        info = self.beacon_info
        info[ :peers ] = self.net_broker.ask!( peer_map: true )

        Ravn::BDE::Beacon.send_message( type: 'status', **info )
rescue => err
        self.log.error "%p while building status beacon: %s" % [ err.class, err.message ]
        self.log.debug( err.full_message(order: :bottom) )
end
inspect_details()

Provide the details section of the inspect output.

# File lib/ravn/bde/mission_controller.rb, line 246
def inspect_details
        return " [%s] %d events, started: %0.3f" %
                [ Ravn::BDE.callsign, self.event_count || 0, self.start_time || 0.0 ]
end
on_event( message )

Actor lifecycle callback — handle some lifecycle +event+s.

# File lib/ravn/bde/mission_controller.rb, line 155
def on_event( message )
        event, _ = *message

        self.log.info "Got event: %p" % [ event ]

        case event
        when Exception
                info = self.beacon_info
                Ravn::BDE::Beacon.send_exception( event, type: 'shutdown', **info )
        when :terminated
                info = self.beacon_info
                Ravn::BDE::Beacon.send_message( type: 'shutdown', cause: "Terminated.", **info )
        else
                # no-op?
        end

        super
end
on_message( message )

Handle mesh.stop events explicitly.

# File lib/ravn/bde/mission_controller.rb, line 143
def on_message( message )
        if self.net_broker && message.respond_to?( :type ) && message.type == 'mesh.stop'
                self.net_broker&.ask!( :pause! )
                self.log.warn "Zyre shut down; restarting!"
                self.net_broker&.tell( :restart! )
        end

        super
end
start()

Start the mission controller.

# File lib/ravn/bde/mission_controller.rb, line 110
def start
        self.log.warn "Starting %p" % [ self ]

        @config = Ravn::BDE.load_mission_config

        @state_manager   = Ravn::BDE::StateManager.spawn!( :state_manager )
        @net_broker      = Ravn::BDE::NetBroker.spawn!( :net_broker, Ravn::BDE.callsign )
        @device_manager  = Ravn::BDE::DeviceManager.spawn!( :device_manager )
        @bolt_runner     = Ravn::BDE::BoltRunner.spawn!( :bolt_runner, @config )
        @event_logger    = Ravn::BDE::EventLogger.spawn!( :event_logger )
        @gateway_manager = Ravn::BDE::GatewayManager.spawn!( :gateway_manager )

        self.emit_startup_event
        self.emit_pois_event
        self.beacon_timer.execute
end
uptime()

Return the number of seconds since the MissionController started.

# File lib/ravn/bde/mission_controller.rb, line 129
def uptime
        self.log.debug "Start time is: %p" % [ self.start_time ]
        return 0 unless self.start_time
        return Ravn.monotonic_time - self.start_time
end