flic 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +51 -49
  3. data/Rakefile +6 -1
  4. data/flic.gemspec +1 -0
  5. data/lib/flic.rb +1 -0
  6. data/lib/flic/blocker.rb +59 -0
  7. data/lib/flic/client.rb +12 -7
  8. data/lib/flic/client/scan_wizard.rb +4 -0
  9. data/lib/flic/protocol.rb +20 -6
  10. data/lib/flic/protocol/commands.rb +7 -0
  11. data/lib/flic/protocol/commands/cancel_scan_wizard.rb +1 -3
  12. data/lib/flic/protocol/commands/change_mode_parameters.rb +1 -3
  13. data/lib/flic/protocol/commands/command.rb +10 -4
  14. data/lib/flic/protocol/commands/create_connection_channel.rb +1 -3
  15. data/lib/flic/protocol/commands/create_scan_wizard.rb +1 -3
  16. data/lib/flic/protocol/commands/create_scanner.rb +1 -3
  17. data/lib/flic/protocol/commands/force_disconnect.rb +0 -2
  18. data/lib/flic/protocol/commands/get_button_uuid.rb +0 -2
  19. data/lib/flic/protocol/commands/get_info.rb +0 -1
  20. data/lib/flic/protocol/commands/ping.rb +1 -3
  21. data/lib/flic/protocol/commands/remove_connection_channel.rb +1 -3
  22. data/lib/flic/protocol/commands/remove_scanner.rb +1 -3
  23. data/lib/flic/protocol/connection.rb +22 -19
  24. data/lib/flic/protocol/events.rb +9 -2
  25. data/lib/flic/protocol/events/advertisement_packet.rb +2 -4
  26. data/lib/flic/protocol/events/bluetooth_controller_state_change.rb +0 -2
  27. data/lib/flic/protocol/events/button_click_or_hold.rb +2 -4
  28. data/lib/flic/protocol/events/button_single_or_double_click.rb +2 -4
  29. data/lib/flic/protocol/events/button_single_or_double_click_or_hold.rb +2 -4
  30. data/lib/flic/protocol/events/button_up_or_down.rb +2 -4
  31. data/lib/flic/protocol/events/connection_channel_removed.rb +1 -3
  32. data/lib/flic/protocol/events/connection_status_changed.rb +1 -3
  33. data/lib/flic/protocol/events/create_connection_channel_response.rb +1 -3
  34. data/lib/flic/protocol/events/event.rb +11 -5
  35. data/lib/flic/protocol/events/get_button_uuid_response.rb +0 -2
  36. data/lib/flic/protocol/events/get_info_response.rb +4 -6
  37. data/lib/flic/protocol/events/got_space_for_new_connection.rb +1 -3
  38. data/lib/flic/protocol/events/new_verified_button.rb +0 -2
  39. data/lib/flic/protocol/events/no_space_for_new_connection.rb +1 -3
  40. data/lib/flic/protocol/events/ping_response.rb +1 -3
  41. data/lib/flic/protocol/events/scan_wizard_button_connected.rb +1 -3
  42. data/lib/flic/protocol/events/scan_wizard_completed.rb +1 -3
  43. data/lib/flic/protocol/events/scan_wizard_found_private_button.rb +1 -3
  44. data/lib/flic/protocol/events/scan_wizard_found_public_button.rb +1 -3
  45. data/lib/flic/protocol/packet_header.rb +2 -2
  46. data/lib/flic/protocol/primitives.rb +1 -0
  47. data/lib/flic/protocol/primitives/bluetooth_address.rb +2 -1
  48. data/lib/flic/protocol/primitives/bluetooth_address_type.rb +3 -0
  49. data/lib/flic/protocol/primitives/bluetooth_controller_state.rb +7 -3
  50. data/lib/flic/protocol/primitives/boolean.rb +1 -0
  51. data/lib/flic/protocol/primitives/click_type.rb +13 -6
  52. data/lib/flic/protocol/primitives/connection_status.rb +7 -4
  53. data/lib/flic/protocol/primitives/create_connection_channel_error.rb +4 -2
  54. data/lib/flic/protocol/primitives/device_name.rb +2 -1
  55. data/lib/flic/protocol/primitives/disconnect_reason.rb +8 -4
  56. data/lib/flic/protocol/primitives/disconnect_time.rb +8 -9
  57. data/lib/flic/protocol/primitives/enum.rb +12 -1
  58. data/lib/flic/protocol/primitives/latency_mode.rb +7 -3
  59. data/lib/flic/protocol/primitives/removed_reason.rb +14 -7
  60. data/lib/flic/protocol/primitives/scan_wizard_result.rb +15 -8
  61. data/lib/flic/protocol/primitives/uuid.rb +13 -3
  62. data/lib/flic/simple_client.rb +116 -78
  63. data/lib/flic/version.rb +1 -1
  64. metadata +17 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30e6a6023c2fe3f2a83299ce7358050ef07195c8
4
- data.tar.gz: f1ac706e5cfca806615de68e6bf147893225662e
3
+ metadata.gz: b313acdfde6b058cfba2f4d0c148b8937e6c2ab9
4
+ data.tar.gz: c5805fd3c6421a2b688e7f4b85b7594423dbe4a1
5
5
  SHA512:
6
- metadata.gz: a9bc7ad01daea014be21f5214cb15a5cd4d4a2cb0ae6a7cc69b8da408fed1153279475607d1267172f6f1a2bb6e13fe391829f596989189af3f449a3030b257b
7
- data.tar.gz: a1263c875e8c918b4cd100d65d91964dda1a3d08c3ea613468556ac1eb6dcad6d25ec3c9e8a8fb074d445249358646dd4c1a2ca8b945712ea6065048fb9e84d0
6
+ metadata.gz: 2e8dd3aa2feed080bf4d36af89dd3bf532ebf00842099d08aca5a3403974a83fcc859edae2b45760d5097db6b6308277d4f194f26bf22e5b7733586a8bb25b68
7
+ data.tar.gz: 934f32212c39ef034446a6d502ffd6a7fd611e1fd751a1dba8bceaee079fe4bb455038cf93ae305db0d04ef2a46f4550b2b51cbc8865e75c89ccbfd7a215cb04
data/README.md CHANGED
@@ -32,7 +32,7 @@ A button must be in public mode before it can be added. To put a button in publi
32
32
  Similarly, a button may be disconnected by passing `Flic::SimpleClient#disconnect_button` a button's bluetooth address.
33
33
 
34
34
  ### Listening for button events
35
- `Flic::SimpleClient#listen` accepts a latency mode (`:low`, `:normal`, or `:high`) as it's first argument and button bluetooth addresses as its other arguments. For each event that occurs to those buttons, it yields the bluetooth address of the button responsible for a given event, the type of click involved in the event (`:button_down`, `:button_up`, `:button_single_click`, `:button_double_click`, or `:button_hold`), the time in milliseconds since the event occured, and whether the event was queued. **It will block until the connection is closed or the block raises some other exception.**
35
+ `Flic::SimpleClient#listen` accepts a latency mode (`:low`, `:normal`, or `:high`) as it's first argument and button bluetooth addresses as its other arguments. For each event that occurs to those buttons, it yields the bluetooth address of the button responsible for a given event, the type of click involved in the event (`:button_down`, `:button_up`, `:button_single_click`, `:button_double_click`, or `:button_hold`), the time in seconds since the event occured, and whether the event was queued. **It will block until the connection is closed or the block raises some other exception.**
36
36
 
37
37
  ### Closing the connection to `flicd`
38
38
  To gracefully cleanup all connection channels and close the socket connection, call `Flic::SimpleClient#shutdown`. Once a `Flic::SimpleClient` has been shutdown it will close the underlying socket and cannot be used anymore.
@@ -40,6 +40,7 @@ To gracefully cleanup all connection channels and close the socket connection, c
40
40
  ### Example
41
41
  This is the script that I wrote to allow some of my Flic buttons to control Wink-enabled smart devices in home.
42
42
  ```ruby
43
+
43
44
  #!/usr/bin/env ruby
44
45
 
45
46
  require 'bundler/setup'
@@ -55,61 +56,62 @@ BEDROOM_BUTTON = 'XX:XX:XX:XX:XX:XX'
55
56
  NIGHTSTAND_BUTTON = 'XX:XX:XX:XX:XX:XX'
56
57
 
57
58
  begin
58
- puts "[*] Opening a connection to flicd..."
59
- client = Flic::SimpleClient.new
60
-
61
- puts "[*] Entering main loop"
62
- client.listen(:low, LIVING_ROOM_BUTTON, BEDROOM_BUTTON, NIGHTSTAND_BUTTON) do |button, event, latency_ms|
63
- if latency_ms > 2000
64
- puts "[*] [#{button}] Ignoring #{event} because the latency is #{latency_ms} ms"
65
- else
66
- puts "[*] [#{button}] Handling #{event}"
67
-
68
- case button
69
- when LIVING_ROOM_BUTTON
70
- case event
71
- when :button_single_click
72
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
73
- when :button_double_click
74
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
75
- when :button_hold
76
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
77
- end
78
-
79
- when BEDROOM_BUTTON
80
- case event
81
- when :button_single_click
82
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
83
- when :button_double_click
84
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
85
- when :button_hold
86
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
87
- end
88
-
89
- when NIGHTSTAND_BUTTON
90
- case event
91
- when :button_single_click
92
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
93
- when :button_double_click
94
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
95
- when :button_hold
96
- puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
97
- end
98
- end
99
- end
100
- end
59
+ puts "[*] Opening a connection to flicd..."
60
+ client = Flic::SimpleClient.new
61
+
62
+ puts "[*] Entering main loop"
63
+ client.listen(:low, LIVING_ROOM_BUTTON, BEDROOM_BUTTON, NIGHTSTAND_BUTTON) do |button, event, latency|
64
+ if latency > 10
65
+ puts "[*] [#{button}] Ignoring #{event} because the latency is #{latency} seconds"
66
+ else
67
+ puts "[*] [#{button}] Handling #{event}"
68
+
69
+ case button
70
+ when LIVING_ROOM_BUTTON
71
+ case event
72
+ when :button_single_click
73
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
74
+ when :button_double_click
75
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
76
+ when :button_hold
77
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
78
+ end
79
+
80
+ when BEDROOM_BUTTON
81
+ case event
82
+ when :button_single_click
83
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
84
+ when :button_double_click
85
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
86
+ when :button_hold
87
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
88
+ end
89
+
90
+ when NIGHTSTAND_BUTTON
91
+ case event
92
+ when :button_single_click
93
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
94
+ when :button_double_click
95
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
96
+ when :button_hold
97
+ puts HTTParty.post('https://api.wink.com/scenes/SCENE_ID/activate', headers: { Authorization: "Bearer #{WINK_ACCESS_TOKEN}" }).inspect
98
+ end
99
+ end
100
+ end
101
+ end
101
102
  rescue StandardError => error
102
- puts "[!] Whoops! #{error.inspect} occured. Wait for a second and restart everything."
103
- sleep 1
103
+ puts "[!] Whoops! #{error.inspect} occured. Wait for a second and restart everything."
104
+ sleep 1
104
105
 
105
- retry
106
+ retry
106
107
  rescue Interrupt
107
- puts "[*] Shutting down gracefully because of an interrupt"
108
+ puts "[*] Shutting down gracefully because of an interrupt"
108
109
 
109
- client.shutdown
110
+ client.shutdown
110
111
  end
111
112
 
112
113
  puts "[*] Goodbye cruel world!"
114
+
113
115
  ```
114
116
 
115
117
  ## Advanced Usage
data/Rakefile CHANGED
@@ -1,12 +1,17 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require 'yard'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
5
- task :default => :spec
6
6
  task :test => :spec
7
7
 
8
+ YARD::Rake::YardocTask.new(:yard)
9
+ task :doc => :yard
10
+
8
11
  task :console do
9
12
  require 'flic'
10
13
  require 'pry'
11
14
  Pry.start
12
15
  end
16
+
17
+ task :default => [:spec, :doc]
@@ -22,4 +22,5 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency 'rake', '~> 10.0'
23
23
  spec.add_development_dependency 'rspec', '~> 3.0'
24
24
  spec.add_development_dependency 'pry'
25
+ spec.add_development_dependency 'yard'
25
26
  end
@@ -1,6 +1,7 @@
1
1
  require 'flic/version'
2
2
 
3
3
  module Flic
4
+ autoload :Blocker, 'flic/blocker'
4
5
  autoload :Callbacks, 'flic/callbacks'
5
6
  autoload :Client, 'flic/client'
6
7
  autoload :Protocol, 'flic/protocol'
@@ -0,0 +1,59 @@
1
+ require 'flic'
2
+
3
+ require 'thread'
4
+
5
+ module Flic
6
+ class Blocker
7
+ attr_reader :rejection_value
8
+
9
+ def initialize
10
+ @semaphore = Mutex.new
11
+ @queues = []
12
+ @rejection_value = nil
13
+ end
14
+
15
+ def block_until_callback
16
+ queue = Queue.new
17
+
18
+ begin
19
+ @semaphore.synchronize do
20
+ if @queues.frozen?
21
+ raise *rejection_value
22
+ else
23
+ @queues << queue
24
+ end
25
+ end
26
+
27
+ yield proc { |value| queue << [:resolve, value] }
28
+
29
+ control, value = queue.pop
30
+
31
+ case control
32
+ when :resolve
33
+ value
34
+ when :reject
35
+ raise *rejection_value
36
+ end
37
+ ensure
38
+ @semaphore.synchronize do
39
+ unless @queues.frozen?
40
+ @queues.delete queue
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ def unblock_all!(*rejection_value)
47
+ @semaphore.synchronize do
48
+ unless @queues.frozen?
49
+ @rejection_value = rejection_value
50
+
51
+ @queues.each { |queue| queue << [:reject, *rejection_value] }.clear
52
+ @queues.freeze
53
+
54
+ freeze
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -6,7 +6,7 @@ require 'socket'
6
6
  module Flic
7
7
  class Client
8
8
  class Error < StandardError; end
9
- class ClientShutdownError < Error; end
9
+ class Shutdown < Error; end
10
10
 
11
11
  autoload :ConnectionChannel, 'flic/client/connection_channel'
12
12
  autoload :Features, 'flic/client/features'
@@ -41,27 +41,32 @@ module Flic
41
41
  define_callbacks :new_button_verified, :bluetooth_controller_state_changed,
42
42
  :connections_exhausted, :connection_available
43
43
 
44
-
45
44
  def initialize(host = 'localhost', port = 5551)
46
45
  @host, @port = host, port
47
46
  @handle_next_event_semaphore = Mutex.new
48
47
  @socket = TCPSocket.new(host, port)
49
48
  @connection = Protocol::Connection.new(socket)
49
+ @is_shutdown = false
50
50
  yield self if block_given?
51
51
  end
52
52
 
53
+ def shutdown?
54
+ @is_shutdown
55
+ end
56
+
53
57
  def shutdown
54
- connection.close
58
+ socket.close
59
+ @is_shutdown = true
55
60
  end
56
61
 
57
62
  def handle_next_event
58
63
  @handle_next_event_semaphore.synchronize do
59
64
  begin
60
65
  handle_event connection.recv_event
61
- rescue Protocol::Connection::ConnectionClosedError
66
+ rescue Protocol::Connection::UnderlyingSocketClosedError
62
67
  shutdown
63
68
 
64
- raise ClientShutdownError, 'The connection has been closed'
69
+ raise Shutdown, 'The connection has been closed'
65
70
  end
66
71
  end
67
72
  end
@@ -74,10 +79,10 @@ module Flic
74
79
 
75
80
  def send_command(command)
76
81
  connection.send_command(command)
77
- rescue Protocol::Connection::ConnectionClosedError
82
+ rescue Protocol::Connection::UnderlyingSocketClosedError
78
83
  shutdown
79
84
 
80
- raise ClientShutdownError, 'The connection has been closed'
85
+ raise Shutdown, 'The connection has been closed'
81
86
  end
82
87
 
83
88
  def handle_event(event)
@@ -9,6 +9,10 @@ module Flic
9
9
 
10
10
  define_callbacks :added, :removed,
11
11
  :found_private_button, :found_public_button, :button_connected
12
+
13
+ def successful?
14
+ result == :success
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -1,7 +1,11 @@
1
1
  require 'flic'
2
2
 
3
3
  module Flic
4
+ # This module contains an implementation of the Flic binary protocol. Of particular external interest is
5
+ # `Flic::Protocol::Connection` which provides a wrapper for the binary protocol around a socket instance.
4
6
  module Protocol
7
+ extend self
8
+
5
9
  class Error < StandardError; end
6
10
 
7
11
  autoload :Commands, 'flic/protocol/commands'
@@ -10,9 +14,10 @@ module Flic
10
14
  autoload :PacketHeader, 'flic/protocol/packet_header'
11
15
  autoload :Primitives, 'flic/protocol/primitives'
12
16
 
13
- INVALID_BUTTON_UUID = '00000000-0000-0000-0000-000000000000'.freeze
14
-
15
- def self.serialize_command(command)
17
+ # Serializes an instance of a protocol command class to a binary string
18
+ # @param command [Flic::Protocol::Commands::Command]
19
+ # @return [String] binary string
20
+ def serialize_command(command)
16
21
  case command
17
22
  when Commands::Command
18
23
  command.to_binary_s
@@ -23,7 +28,10 @@ module Flic
23
28
  raise Error, "Cannot serialize command `#{command.inspect}`"
24
29
  end
25
30
 
26
- def self.parse_command(serialized_command)
31
+ # Deserializes an instance of a protocol command class from a binary string
32
+ # @param serialized_command [String] binary string
33
+ # @return [Flic::Protocol::Commands::Command]
34
+ def parse_command(serialized_command)
27
35
  command = Commands::Command.read(serialized_command)
28
36
  opcode = command.opcode
29
37
  command_class = Commands::Command.command_class_for_opcode(opcode)
@@ -37,7 +45,10 @@ module Flic
37
45
  raise Error, "Cannot parse event `#{serialized_command.inspect}`"
38
46
  end
39
47
 
40
- def self.serialize_event(event)
48
+ # Serializes an instance of a protocol event class to a binary string
49
+ # @param event [Flic::Protocol::Events::Event]
50
+ # @return [String] binary string
51
+ def serialize_event(event)
41
52
  case event
42
53
  when Commands::Event
43
54
  event.to_binary_s
@@ -48,7 +59,10 @@ module Flic
48
59
  raise Error, "Cannot serialize event `#{event.inspect}`"
49
60
  end
50
61
 
51
- def self.parse_event(serialized_event)
62
+ # Deserializes an instance of a protocol event class from a binary string
63
+ # @param serialized_event [String] binary string
64
+ # @return [Flic::Protocol::Events::Event]
65
+ def parse_event(serialized_event)
52
66
  event = Events::Event.read(serialized_event)
53
67
  opcode = event.opcode
54
68
  event_class = Events.event_class_for_opcode(opcode)
@@ -2,6 +2,7 @@ require 'flic/protocol'
2
2
 
3
3
  module Flic
4
4
  module Protocol
5
+ # A namespace module for all of the command classes
5
6
  module Commands
6
7
  autoload :CancelScanWizard, 'flic/protocol/commands/cancel_scan_wizard'
7
8
  autoload :ChangeModeParameters, 'flic/protocol/commands/change_mode_parameters'
@@ -32,10 +33,16 @@ module Flic
32
33
 
33
34
  OPCODE_COMMAND_CLASS = COMMAND_CLASS_OPCODE.invert.freeze
34
35
 
36
+ # Finds the command class for a given opcode
37
+ # @param opcode [Integer]
38
+ # @return [Class]
35
39
  def self.command_class_for_opcode(opcode)
36
40
  OPCODE_COMMAND_CLASS[opcode]
37
41
  end
38
42
 
43
+ # Finds the opcode for a given command class
44
+ # @param command_class [Class]
45
+ # @return [Integer]
39
46
  def self.opcode_for_command_class(command_class)
40
47
  COMMAND_CLASS_OPCODE[command_class]
41
48
  end
@@ -6,9 +6,7 @@ module Flic
6
6
  module Protocol
7
7
  module Commands
8
8
  class CancelScanWizard < Command
9
- endian :little
10
-
11
- uint32 :scan_wizard_id
9
+ uint32le :scan_wizard_id
12
10
  end
13
11
  end
14
12
  end
@@ -7,9 +7,7 @@ module Flic
7
7
  module Protocol
8
8
  module Commands
9
9
  class ChangeModeParameters < Command
10
- endian :little
11
-
12
- uint32 :connection_channel_id
10
+ uint32le :connection_channel_id
13
11
  latency_mode :latency_mode
14
12
  disconnect_time :auto_disconnect_time
15
13
  end
@@ -6,15 +6,21 @@ module Flic
6
6
  module Protocol
7
7
  module Commands
8
8
  class Command < BinData::Record
9
- endian :little
10
-
11
- uint8 :opcode, initial_value: -> { init_opcode }
9
+ uint8le :opcode, initial_value: :class_opcode, assert: :opcode_matcher
12
10
 
13
11
  private
14
12
 
15
- def init_opcode
13
+ def class_opcode
16
14
  Commands.opcode_for_command_class(self.class)
17
15
  end
16
+
17
+ def opcode_matcher
18
+ if class_opcode
19
+ class_opcode
20
+ else
21
+ true
22
+ end
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -8,9 +8,7 @@ module Flic
8
8
  module Protocol
9
9
  module Commands
10
10
  class CreateConnectionChannel < Command
11
- endian :little
12
-
13
- uint32 :connection_channel_id
11
+ uint32le :connection_channel_id
14
12
  bluetooth_address :bluetooth_address
15
13
 
16
14
  latency_mode :latency_mode