Class: Vissen::Input::Message::Base

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Vissen::Input::Message
Defined in:
lib/vissen/input/message/base.rb

Overview

This is the base message implementaion. This class should never be used directly, but rather be subclassed to create the various messages that the system understands.

The Base class keeps track of subclasses and can produce a message factory for all the implementations that it knows about (see .factory).

Constant Summary collapse

DATA_LENGTH =
3
STATUS =
0

Constants included from Vissen::Input::Message

CHANNEL_MASK, STATUS_MASK

Instance Attribute Summary

Attributes included from Vissen::Input::Message

#data, #timestamp

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Vissen::Input::Message

#channel, #fetch, #initialize, #status, #to_h

Class Method Details

.[](channel, number = nil) ⇒ Object

Alias to #matcher that swaps named arguments for positional ones.

See Also:

  • #matcher


98
99
100
# File 'lib/vissen/input/message/base.rb', line 98

def [](channel, number = nil)
  matcher channel: channel, number: number
end

.create(*bytes, status: self::STATUS, channel: 0, timestamp: Time.now.to_f) ⇒ Base

Build a new instance of Message::Base, or a subclass, using more intuitive arguments. Subclasses of Base can utilize the same functionality by simply redefining DATA_LENGTH to correspond to their message length.

Note that status and channel are masked using the default masks, and not the constants that may have been defined by a subclass.

Parameters:

  • bytes (Array<Integer>)

    the message data byte values. Unspecified values default to 0.

  • status (Integer) (defaults to: self::STATUS)

    the status to use for the new message.

  • channel (Integer) (defaults to: 0)

    the channel to use for the new message.

  • timestamp (Float) (defaults to: Time.now.to_f)

    the timestamp to use for the new message.

Returns:

  • (Base)

    a new instance of this class.

Raises:

  • (ArgumentError)


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/vissen/input/message/base.rb', line 116

def create(*bytes, status: self::STATUS,
           channel: 0,
           timestamp: Time.now.to_f)
  raise ArgumentError if bytes.length >= self::DATA_LENGTH

  validate_status status
  validate_channel channel

  data = Array.new self::DATA_LENGTH, 0

  # Note: this line line must reference
  #       STATUS_MASK and not self::STATUS_MASK
  data[0] = (status & STATUS_MASK) + (channel & CHANNEL_MASK)

  # Copy the bytes
  bytes.each_with_index { |value, index| data[index + 1] = value }

  new data, timestamp
end

.factoryMessageFactory

Creates a new factory with all the subclasses of base added to it as matchers.

Returns:

  • (MessageFactory)

    a factory configured to build all subclasses of Base.

Raises:

  • (RuntimeError)


87
88
89
90
# File 'lib/vissen/input/message/base.rb', line 87

def factory
  raise RuntimeError unless defined? @subclasses
  MessageFactory.new @subclasses.map(&:matcher)
end

.match(obj) ⇒ false, ...

Accessor to Matcher#match on the default class matcher.

Parameters:

  • obj (Hash, Message)

    the message to match.

Returns:

  • (false, Object, Message)

    (see Matcher#match)

See Also:



80
# File 'lib/vissen/input/message/base.rb', line 80

def_delegator :klass_matcher, :match, :match

.match?(obj) ⇒ true, false

Accessor to Matcher#match? on the default class matcher.

Parameters:

  • obj (#to_a)

    the message or data to match.

Returns:

  • (true, false)

    (see Matcher#match?)

See Also:



71
# File 'lib/vissen/input/message/base.rb', line 71

def_delegator :klass_matcher, :match?, :match?

.matcher(channel: nil, number: nil) ⇒ Matcher

Returns a new instance of a Matcher, configured to match this particular Message class. Subclasses of Base can utilize the same functionality by simply redefining STATUS and, if necessary, STATUS_MASK.

By supplying the optional named arguments channel and number

Raises a RangeError if the channel is given and is outside its valid range of (0..15). Raises a RangeError if number is given and is outside its valid range of (0..127).

Parameters:

  • channel (nil, Integer) (defaults to: nil)

    the channel to match, or nil to match all channels.

  • number (nil, Integer) (defaults to: nil)

    the second byte value to match, or nil to match all values.

Returns:

  • (Matcher)

    the matcher that fulfills the requirements.



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/vissen/input/message/base.rb', line 50

def matcher(channel: nil, number: nil)
  return klass_matcher unless channel || number
  val, mask = status_value_and_mask channel

  if number
    raise RangeError unless (0...128).cover? number
    Matcher.new(self) { |d| (d[0] & mask) == val && d[1] == number }
  else
    Matcher.new(self) { |d| (d[0] & mask) == val }
  end
end

Instance Method Details

#valid?true, false

Checks message data consistency with the class default matcher.

Returns:

  • (true, false)

    true if the message data matches the class matcher.



25
26
27
# File 'lib/vissen/input/message/base.rb', line 25

def valid?
  self.class.matcher.match? data
end