Class: Tamashii::Agent::Device::Keyboard::Base

Inherits:
DeviceBase
  • Object
show all
Defined in:
lib/tamashii/agent/device/keyboard/base.rb

Direct Known Subclasses

ButtonMatrix4x4, Dummy, TTP229Serial

Instance Method Summary collapse

Methods inherited from DeviceBase

#fetch_option, #fetch_option!, #unexport_pin

Methods included from Common::Loggable

#display_name, #logger, #progname

Constructor Details

#initialize(*args) ⇒ Base

Returns a new instance of Base.



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 10

def initialize(*args)
  super(*args)
  initialize_hardware
  @number_of_keys = number_of_keys
  @watcher_mode = fetch_option(:watch, default_watch)
  @watcher_stopping = Concurrent::AtomicBoolean.new(false)
  if @watcher_mode
    initialize_watcher
    start_watcher_thread
  end
end

Instance Method Details

#add_callback(event, callable) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 53

def add_callback(event, callable)
  if @watcher_mode
    @callbacks[event] = callable
  else
    puts "Callbacks are only available in watcher mode!"
  end
end

#default_number_of_keysObject

Raises:

  • (NotImplementedError)


26
27
28
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 26

def default_number_of_keys
  raise NotImplementedError
end

#default_watchObject



30
31
32
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 30

def default_watch
  true
end

#finalize_hardwareObject



42
43
44
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 42

def finalize_hardware
  logger.warn "Device #{@name} does not implement hardware finalize code"
end

#initialize_hardwareObject



38
39
40
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 38

def initialize_hardware
  logger.warn "Device #{@name} does not implement hardware initialize code"
end

#initialize_watcherObject



46
47
48
49
50
51
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 46

def initialize_watcher
  @last_keys_state = {}
  @current_keys_state = {}
  @current_key = Concurrent::AtomicFixnum.new(-1)
  @callbacks = {}
end

#mark_key_down(key) ⇒ Object



150
151
152
153
154
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 150

def mark_key_down(key)
  return unless @watcher_mode
  @current_key.value = key
  @current_keys_state[key] = true
end

#mark_key_up(key) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 141

def mark_key_up(key)
  return unless @watcher_mode
  if @current_key.value == key
    # remove current key
    @current_key.value = -1
  end
  @current_keys_state[key] = false
end

#number_of_keysObject



22
23
24
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 22

def number_of_keys
  fetch_option(:number_of_keys, default_number_of_keys)
end

#on_key_down(callable = nil, &block) ⇒ Object



61
62
63
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 61

def on_key_down(callable = nil, &block)
  add_callback(:down, callable || block)
end

#on_key_pressed(callable = nil, &block) ⇒ Object



69
70
71
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 69

def on_key_pressed(callable = nil, &block)
  add_callback(:pressed, callable || block)
end

#on_key_up(callable = nil, &block) ⇒ Object



65
66
67
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 65

def on_key_up(callable = nil, &block)
  add_callback(:up, callable || block)
end

#poll_keyObject



124
125
126
127
128
129
130
131
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 124

def poll_key
  if @watcher_mode
    @current_key.value >= 0 ? @current_key.value : nil
  else
    sleep polling_interval
    read_key
  end
end

#polling_intervalObject



34
35
36
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 34

def polling_interval
  0.1
end

#process_callbacksObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 95

def process_callbacks
  @number_of_keys.times do |key|
    if @current_keys_state[key]
      if @last_keys_state[key]
        @callbacks[:pressed]&.call(key)
      else
        @callbacks[:down]&.call(key)
      end
    else
      if @last_keys_state[key]
        @callbacks[:up]&.call(key)
      end
    end
  end
end

#read_keyObject

Raises:

  • (NotImplementedError)


156
157
158
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 156

def read_key
  raise NotImplementedError, "read_key"
end

#record_key_stateObject



111
112
113
114
115
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 111

def record_key_state
  @number_of_keys.times do |key|
    @last_keys_state[key] = @current_keys_state[key]
  end
end

#shutdownObject



133
134
135
136
137
138
139
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 133

def shutdown
  @watcher_stopping.make_true
  if @watcher_mode
    stop_watcher_thread
  end
  finalize_hardware
end

#start_watcher_threadObject



77
78
79
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 77

def start_watcher_thread
  @watcher_thread = Thread.new { watcher_loop }
end

#stop_watcher_threadObject



117
118
119
120
121
122
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 117

def stop_watcher_thread
  if !@watcher_thread.join(3)
    @watcher_thread.exit
    puts "watcher thread killed forcefully"
  end
end

#watcher_loopObject



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 81

def watcher_loop
  logger.debug "Watcher started"
  loop do
    if watcher_stopping?
      break
    end
    sleep polling_interval
    record_key_state
    read_key
    process_callbacks
  end
  puts "watcher thread terminated normally"
end

#watcher_stopping?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/tamashii/agent/device/keyboard/base.rb', line 73

def watcher_stopping?
  @watcher_stopping.true?
end