Class: NXTBrick

Inherits:
Object
  • Object
show all
Includes:
NXT::Exceptions
Defined in:
lib/nxt/nxt_brick.rb

Overview

This class is the entry point for end-users creating their own list of commands to execute remotely on a Lego NXT brick.

An instance of this class provides all the endpoints necessary to:

  • educate the API on the connected input and output devices; and,

  • access these input and output devices and run commands using them.

Examples:

Creating an instance using a block, with one motor output.


NXTBrick.new(interface) do |nxt|
  nxt.add_motor_output(:a, :front_left)
end

Creating an instance without a block, with one motor and one light sensor.


nxt = NXTBrick.new(interface)
nxt.add_motor_output(:a, :front_left)
# ...
nxt.disconnect

Constant Summary collapse

PORTS =

An enumeration of possible ports, both input and output, that the NXT brick can have connectors attached to.

[:a, :b, :c, :one, :two, :three, :four]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(interface_type, *interface_args) ⇒ NXTBrick

Returns a new instance of NXTBrick.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/nxt/nxt_brick.rb', line 45

def initialize(interface_type, *interface_args)
  @port_identifiers = {}
  interface_type = interface_type.to_s.classify

  unless NXT::Interface.constants.include?(interface_type.to_sym)
    raise InvalidInterfaceError.new("There is no interface of type #{interface_type}.")
  end

  self.interface = NXT::Interface.const_get(interface_type).new(*interface_args)

  if block_given?
    begin
      self.connect
      yield(self)
    rescue Exception => e
      binding.pry
    ensure
      self.disconnect
    end
  end
end

Instance Attribute Details

#aObject (readonly)

Accessors for output ports on the NXT brick. These will be populated with the appropriate instances of their respective output connectors.



34
35
36
# File 'lib/nxt/nxt_brick.rb', line 34

def a
  @a
end

#bObject (readonly)

Accessors for output ports on the NXT brick. These will be populated with the appropriate instances of their respective output connectors.



34
35
36
# File 'lib/nxt/nxt_brick.rb', line 34

def b
  @b
end

#cObject (readonly)

Accessors for output ports on the NXT brick. These will be populated with the appropriate instances of their respective output connectors.



34
35
36
# File 'lib/nxt/nxt_brick.rb', line 34

def c
  @c
end

#fourObject (readonly)

Accessors for input ports on the NXT brick. These will be populated with the appropriate instances of their respective input connectors.



38
39
40
# File 'lib/nxt/nxt_brick.rb', line 38

def four
  @four
end

#interfaceObject

Get the instance of the interface that this runner class is using to connect to the NXT brick.



30
31
32
# File 'lib/nxt/nxt_brick.rb', line 30

def interface
  @interface
end

#oneObject (readonly)

Accessors for input ports on the NXT brick. These will be populated with the appropriate instances of their respective input connectors.



38
39
40
# File 'lib/nxt/nxt_brick.rb', line 38

def one
  @one
end

#port_identifiersObject (readonly)

We mandate that all added port connections have an identifier associated with it. This is so that code is not fragile when port swapping needs to be done.



43
44
45
# File 'lib/nxt/nxt_brick.rb', line 43

def port_identifiers
  @port_identifiers
end

#threeObject (readonly)

Accessors for input ports on the NXT brick. These will be populated with the appropriate instances of their respective input connectors.



38
39
40
# File 'lib/nxt/nxt_brick.rb', line 38

def three
  @three
end

#twoObject (readonly)

Accessors for input ports on the NXT brick. These will be populated with the appropriate instances of their respective input connectors.



38
39
40
# File 'lib/nxt/nxt_brick.rb', line 38

def two
  @two
end

Instance Method Details

#add(port, identifier, klass) ⇒ Object

Add a new connector instance, binding a specific identifier to the given port.

If the given port already is bound, an exception will be thrown. The instance given though can be of any class, presuming it talks the correct language.

Parameters:

  • Symbol

    port The port to bind to.

  • Symbol

    identifier The identifier to associate with this port.

  • Class

    klass The Class to instantiate as the instance of this port. There is no limitation on what type this can be, though it must be able to hook in correctly with the NXT library.

Raises:

  • (TypeError)


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/nxt/nxt_brick.rb', line 92

def add(port, identifier, klass)
  raise TypeError.new('Expected port to be a Symbol') unless port.is_a?(Symbol)
  raise TypeError.new('Expected identifier to be a Symbol') unless identifier.is_a?(Symbol)
  raise TypeError.new('Expected klass to be a Class') unless klass.is_a?(Class)

  unless PORTS.include?(port)
    raise TypeError.new("Expected port to be one of: :#{PORTS.join(', :')}")
  end

  port_variable = :"@#{port}"

  if !self.respond_to?(identifier)
    # Makes a new instance of the class and pushes it into our instance variable
    # for the given port.
    self.instance_variable_set(port_variable, klass.new(port, self.interface))

    # Given that that succeeded, all that remains is to add the identifier
    # to our lookup Hash. We'll use this Hash later on within method_missing.
    @port_identifiers[identifier] = port

    # Define a method on the eigenclass of this instance.
    (class << self; self; end).send(:define_method, identifier) do
      self.instance_variable_get(port_variable)
    end
  else
    if !self.instance_variable_get(port_variable).nil?
      raise PortTakenError.new("Port #{port} is already set, call remove first")
    else
      raise InvalidIdentifierError.new("Cannot use identifier #{identifier}, a method on #{self.class} is already using it.")
    end
  end
end

#connectObject

Connect using the given interface to the NXT brick.



68
69
70
# File 'lib/nxt/nxt_brick.rb', line 68

def connect
  self.interface.connect
end

#disconnectObject

Close the connection to the NXT brick, and dispose of any resources that this instance of NXTBrick is using. Any commands run against this runner after calling disconnect will fail.



75
76
77
# File 'lib/nxt/nxt_brick.rb', line 75

def disconnect
  self.interface.disconnect
end

#remove(identifier) ⇒ Object

Remove the assigned (if any) connector instance from the given identifier.

Parameters:

  • Symbol

    identifier The identifier to search for and remove.

Raises:

  • (TypeError)


129
130
131
132
# File 'lib/nxt/nxt_brick.rb', line 129

def remove(identifier)
  raise TypeError.new('Expected identifier to be a Symbol') unless identifier.is_a?(Symbol)
  !!@port_identifiers.delete(identifier)
end