class Syskit::Robot::MasterDeviceInstance

Subclass of DeviceInstance used to represent root devices

Constants

DRoby
KNOWN_PARAMETERS

Attributes

com_busses[R]

The communication busses this device is attached to

combus_client_in_srv[R]

The data service of {#task_model} that is used to receive data from the attached com bus for this device. If nil, the task is not expecting to receive any data from the communication bus (only send)

@return [BoundDataService,nil]

combus_client_out_srv[R]

The data service of {#task_model} that is used to send data to the attached com bus for this device. If nil, the task is not expecting to send any data from the communication bus (only receives)

@return [BoundDataService,nil]

configuration[R]

Configuration data structure

configuration_block[R]

Block given to configure to configure the device. It will be yield a data structure that represents the set of properties of the underlying task

Note that it is executed twice. Once at loading time to verify that the block is compatible with the data structure, and once at runtime to actually configure the task

device_model[R]

The device model, as a subclass of Device

driver_model[R]

The driver for this device @return [BoundDataService]

name[R]

The device name

requirements[R]

Additional specifications for deployment of the driver @return [Syskit::InstanceRequirements]

robot[R]

The RobotDefinition instance we are built upon

slaves[R]

The device slaves, as a mapping from the slave's name to the SlaveDeviceInstance object

Public Class Methods

new(robot, name, device_model, options, driver_model, task_arguments) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 46
def initialize(robot, name, device_model, options,
               driver_model, task_arguments)
    @robot, @name, @device_model, @task_arguments =
        robot, name, device_model, task_arguments
    @slaves      = Hash.new
    @conf = Array.new
    @com_busses = Array.new

    driver_model = driver_model.to_instance_requirements
    @driver_model = driver_model.service
    @requirements = driver_model.to_component_model
    requirements.with_arguments(:"#{driver_model.service.name}_dev" => self)
    requirements.with_arguments(**task_arguments)

    sample_size 1
    burst   0
end

Public Instance Methods

==(other) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 386
def ==(other)
    if other.kind_of?(MasterDeviceInstance)
        other.robot == robot &&
            other.name == name
    end
end
advanced() click to toggle source

Sets {#advanced?}

# File lib/syskit/robot/master_device_instance.rb, line 76
def advanced
    @advanced = true
    self
end
arguments() click to toggle source

The arguments passed to the underlying device driver

# File lib/syskit/robot/master_device_instance.rb, line 326
def arguments
    requirements.arguments
end
as_plan() click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 371
def as_plan; to_instance_requirements.as_plan end
attach_to(com_bus, bus_to_client: true, client_to_bus: true, **options) click to toggle source

Attaches this device on the given communication bus

@param [Boolean,String] bus_to_client whether the device expects a

connection from the bus. It can be set to a string, in which
case the string is used as the name of the service on the
client's device driver that should be used for connection

@param [Boolean,String] client_to_bus whether the device expects a

connection to the bus. It can be set to a string, in which
case the string is used as the name of the service on the client
device driver that should be used for connection
# File lib/syskit/robot/master_device_instance.rb, line 139
def attach_to(com_bus, bus_to_client: true, client_to_bus: true, **options)
    if com_bus.respond_to?(:to_str)
        com_bus, com_bus_name = robot.find_device(com_bus), com_bus
        if !com_bus
            raise ArgumentError, "no device declared with the name '#{com_bus_name}'"
        end
    end

    if srv_name = options.delete(:in)
        Roby.warn_deprecated "the in: option of MasterDeviceInstance#attach_to has been renamed to bus_to_client"
        bus_to_client = srv_name
    end
    if srv_name = options.delete(:out)
        Roby.warn_deprecated "the out: option of MasterDeviceInstance#attach_to has been renamed to client_to_bus"
        client_to_bus = srv_name
    end
    if !options.empty?
        raise ArgumentError, "unexpected options #{options}"
    end

    if bus_to_client && com_bus.model.bus_to_client?
        client_in_srv =
            if bus_to_client.respond_to?(:to_str)
                bus_to_client
            end
        client_in_srv_m  = com_bus.model.client_in_srv
        @combus_client_in_srv  =
            begin find_combus_client_srv(client_in_srv_m, client_in_srv)
            rescue AmbiguousServiceSelection
                raise ArgumentError, "#{driver_model.to_component_model} provides more than one input service to connect to the com bus, select one explicitely with the bus_to_client option"
            end
        if !combus_client_in_srv
            raise ArgumentError, "#{driver_model.to_component_model} does not provide an input service to connect to the com bus, and was expected to"
        end
    end

    if client_to_bus && com_bus.model.client_to_bus?
        client_out_srv =
            if client_to_bus.respond_to?(:to_str)
                client_to_bus
            end
        client_out_srv_m  = com_bus.model.client_out_srv
        @combus_client_out_srv  =
            begin find_combus_client_srv(client_out_srv_m, client_out_srv)
            rescue AmbiguousServiceSelection
                raise ArgumentError, "#{driver_model.to_component_model} provides more than one output service to connect to the com bus, select one explicitely with the client_to_bus option"
            end
        if !combus_client_out_srv
            raise ArgumentError, "#{driver_model.to_component_model} does not provide an output service to connect to the com bus, and was expected to"
        end
    end

    com_busses << com_bus
    com_bus.attached_devices << self
    com_bus.model.apply_attached_device_configuration_extensions(self)
    self
end
attached_to?(com_bus) click to toggle source

True if this device is attached to the given combus

# File lib/syskit/robot/master_device_instance.rb, line 95
def attached_to?(com_bus)
    com_busses.include?(com_bus)
end
bus_to_client?() click to toggle source

Whether this device sends messages to the bus it is attached to

It will return false if not attached to a bus

# File lib/syskit/robot/master_device_instance.rb, line 125
def bus_to_client?
    !!combus_client_in_srv
end
client_to_bus?() click to toggle source

Whether this device sends messages to the bus it is attached to

It will return false if not attached to a bus

# File lib/syskit/robot/master_device_instance.rb, line 118
def client_to_bus?
    !!combus_client_out_srv
end
droby_dump(peer) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 382
def droby_dump(peer)
    DRoby.new(name, peer.dump(device_model), peer.dump(driver_model))
end
each_fullfilled_model(&block) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 373
def each_fullfilled_model(&block)
    device_model.each_fullfilled_model(&block)
end
each_slave(&block) click to toggle source

Enumerates the slaves that are known for this device, as

slave_name, SlaveDeviceInstance object

pairs

# File lib/syskit/robot/master_device_instance.rb, line 250
def each_slave(&block)
    slaves.each_value(&block)
end
find_combus_client_srv(srv_m, srv_name) click to toggle source

Finds in {#driver_model}.component_model the data service that should be used to interface with a combus

@param [Model<DataService>] the data service model for the client

interface to the combus

@param [String,nil] the expected data service name, or nil if none

is given. In this case, one is searched by type
# File lib/syskit/robot/master_device_instance.rb, line 204
def find_combus_client_srv(srv_m, srv_name)
    driver_task_model = driver_model.to_component_model
    if srv_name
        result = driver_task_model.find_data_service(srv_name)
        if !result
            raise ArgumentError, "#{srv_name} is specified as a client service on device #{name} for combus #{com_bus.name}, but it is not a data service on #{driver_task_model}"
        elsif !result.fullfills?(srv_m)
            raise ArgumentError, "#{srv_name} is specified as a client service on device #{name} for combus #{com_bus.name}, but it does not provide the required service from #{com_bus.model}"
        end
        result
    else
        driver_task_model.find_data_service_from_type(srv_m)
    end
end
find_through_method_missing(m, args) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 311
def find_through_method_missing(m, args)
    MetaRuby::DSLs.find_through_method_missing(
        self, m, args, '_dev'.freeze => :slave) || super
end
full_name() click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 68
def full_name
    name
end
has_slave?(slave_service) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 254
def has_slave?(slave_service)
    return true if slaves[slave_service]

    slave_name = "#{driver_model.full_name}.#{slave_service}"
    !!task_model.find_data_service(slave_name)
end
has_through_method_missing?(m) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 306
def has_through_method_missing?(m)
    MetaRuby::DSLs.has_through_method_missing?(
        self, m, '_dev'.freeze => :has_slave?) || super
end
model() click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 20
def model; device_model end
prefer_deployed_tasks(hints) click to toggle source

Specify deployment selection hints for the device's driver

# File lib/syskit/robot/master_device_instance.rb, line 337
def prefer_deployed_tasks(hints)
    requirements.prefer_deployed_tasks(hints)
    self
end
pretty_print(pp) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 27
def pretty_print(pp)
    pp.text "MasterDeviceInstance(#{short_name}_dev)"
end
short_name() click to toggle source

Defined to be consistent with task and data service models

# File lib/syskit/robot/master_device_instance.rb, line 23
def short_name
    "#{name}[#{model.short_name}]"
end
slave(slave_service, options = Hash.new) click to toggle source

Gets the required slave device, or creates a dynamic one

@overload slave(slave_name)

@arg [String] slave_name the name of a slave service on the
  device's driver 
@return [Syskit::Robot::SlaveDeviceInstance]

@overload slave(dynamic_service_name, :as => slave_name)

@arg [String] dynamic_service_name the name of a dynamic service
  declared on the device's driver with #dynamic_service
@arg [String] slave_name the name of the slave as it should be
  created
@return [Syskit::Robot::SlaveDeviceInstance]
# File lib/syskit/robot/master_device_instance.rb, line 275
def slave(slave_service, options = Hash.new)
    options = Kernel.validate_options options, :as => nil
    if existing_slave = slaves[slave_service]
        return existing_slave
    end

    # If slave_service is a string, it should refer to an actual
    # service on +task_model+
    task_model = driver_model.to_component_model

    slave_name = "#{driver_model.full_name}.#{slave_service}"
    srv = task_model.find_data_service(slave_name)
    if !srv
        if options[:as]
            new_task_model = task_model.ensure_model_is_specialized
            srv = new_task_model.require_dynamic_service(slave_service, :as => options[:as])
        end
        if !srv
            raise ArgumentError, "there is no service #{slave_name} and no dynamic service in #{task_model.short_name}"
        end
        @driver_model = driver_model.attach(new_task_model)
    end

    device_instance = SlaveDeviceInstance.new(self, srv)
    slaves[srv.name] = device_instance
    if srv.model.respond_to?(:apply_device_configuration_extensions)
        srv.model.apply_device_configuration_extensions(device_instance)
    end
    robot.devices["#{name}.#{srv.name}"] = device_instance
end
to_action_model() click to toggle source

Create an action model that represent an instanciation of this device

@return [Actions::Model::Action]

# File lib/syskit/robot/master_device_instance.rb, line 361
def to_action_model
    profile = robot.profile
    req = to_instance_requirements
    profile.inject_di_context(req)
    action_model = Actions::Models::Action.
        new(req, doc || "device from profile #{profile.name}")
    action_model.name = "#{name}_dev"
    action_model
end
to_instance_requirements() click to toggle source

Returns the InstanceRequirements object that can be used to represent this device

# File lib/syskit/robot/master_device_instance.rb, line 350
def to_instance_requirements
    result = requirements.dup
    robot.inject_di_context(result)
    result.select_service(driver_model)
    result
end
to_s() click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 64
def to_s
    "device(#{device_model}, as: #{full_name})"
end
use(dependency_injection) click to toggle source

If this device's driver is a composition, allows to specify dependency injections for it

# File lib/syskit/robot/master_device_instance.rb, line 320
def use(dependency_injection)
    requirements.use(dependency_injection)
    self
end
use_conf(*conf) click to toggle source

@deprecated

# File lib/syskit/robot/master_device_instance.rb, line 82
def use_conf(*conf)
    Roby.warn_deprecated "MasterDeviceInstance#use_conf is deprecated. Use #with_conf instead"
    with_conf(*conf)
end
use_deployments(hints) click to toggle source
# File lib/syskit/robot/master_device_instance.rb, line 342
def use_deployments(hints)
    Roby.warn_deprecated "MasterDeviceInstance#use_deployments is deprecated. Use #prefer_deployed_tasks instead"
    prefer_deployed_tasks(hints)
    self
end
with_arguments(arguments = Hash.new) click to toggle source

Add arguments to the underlying device driver

# File lib/syskit/robot/master_device_instance.rb, line 331
def with_arguments(arguments = Hash.new)
    requirements.with_arguments(arguments)
    self
end
with_conf(*conf) click to toggle source

Declares that the following configuration chain should be used for this device

# File lib/syskit/robot/master_device_instance.rb, line 89
def with_conf(*conf)
    requirements.with_conf(*conf)
    self
end