flic 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/lib/flic.rb +2 -1
- data/lib/flic/callbacks.rb +36 -0
- data/lib/flic/client.rb +52 -203
- data/lib/flic/client/connection_channel.rb +21 -0
- data/lib/flic/client/features.rb +15 -0
- data/lib/flic/client/features/connection_channel.rb +175 -0
- data/lib/flic/client/features/force_disconnect.rb +13 -0
- data/lib/flic/client/features/get_button_uuid.rb +43 -0
- data/lib/flic/client/features/get_info.rb +52 -0
- data/lib/flic/client/features/ping.rb +55 -0
- data/lib/flic/client/features/scan.rb +112 -0
- data/lib/flic/client/features/scan_wizard.rb +131 -0
- data/lib/flic/client/scan_wizard.rb +14 -0
- data/lib/flic/client/scanner.rb +12 -0
- data/lib/flic/client/server_info.rb +16 -0
- data/lib/flic/protocol.rb +1 -0
- data/lib/flic/protocol/commands/change_mode_parameters.rb +3 -2
- data/lib/flic/protocol/commands/create_connection_channel.rb +3 -2
- data/lib/flic/protocol/commands/remove_connection_channel.rb +1 -1
- data/lib/flic/{client → protocol}/connection.rb +20 -26
- data/lib/flic/protocol/events/button_click_or_hold.rb +1 -1
- data/lib/flic/protocol/events/button_single_or_double_click.rb +1 -1
- data/lib/flic/protocol/events/button_single_or_double_click_or_hold.rb +1 -1
- data/lib/flic/protocol/events/button_up_or_down.rb +1 -1
- data/lib/flic/protocol/events/connection_channel_removed.rb +2 -2
- data/lib/flic/protocol/events/connection_status_changed.rb +1 -1
- data/lib/flic/protocol/events/create_connection_channel_response.rb +1 -1
- data/lib/flic/protocol/events/get_info_response.rb +3 -2
- data/lib/flic/protocol/primitives.rb +1 -0
- data/lib/flic/protocol/primitives/disconnect_time.rb +29 -0
- data/lib/flic/simple_client.rb +116 -0
- data/lib/flic/version.rb +1 -1
- metadata +18 -6
- data/lib/flic/event_bus.rb +0 -81
- data/lib/flic/event_bus/driver.rb +0 -23
- data/lib/flic/event_bus/subscription.rb +0 -66
data/lib/flic/protocol.rb
CHANGED
@@ -5,6 +5,7 @@ module Flic
|
|
5
5
|
class Error < StandardError; end
|
6
6
|
|
7
7
|
autoload :Commands, 'flic/protocol/commands'
|
8
|
+
autoload :Connection, 'flic/protocol/connection'
|
8
9
|
autoload :Events, 'flic/protocol/events'
|
9
10
|
autoload :PacketHeader, 'flic/protocol/packet_header'
|
10
11
|
autoload :Primitives, 'flic/protocol/primitives'
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'flic/protocol/commands'
|
2
2
|
require 'flic/protocol/commands/command'
|
3
3
|
require 'flic/protocol/primitives/latency_mode'
|
4
|
+
require 'flic/protocol/primitives/disconnect_time'
|
4
5
|
|
5
6
|
module Flic
|
6
7
|
module Protocol
|
@@ -8,9 +9,9 @@ module Flic
|
|
8
9
|
class ChangeModeParameters < Command
|
9
10
|
endian :little
|
10
11
|
|
11
|
-
uint32 :
|
12
|
+
uint32 :connection_channel_id
|
12
13
|
latency_mode :latency_mode
|
13
|
-
|
14
|
+
disconnect_time :auto_disconnect_time
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -2,6 +2,7 @@ require 'flic/protocol/commands'
|
|
2
2
|
require 'flic/protocol/commands/command'
|
3
3
|
require 'flic/protocol/primitives/bluetooth_address'
|
4
4
|
require 'flic/protocol/primitives/latency_mode'
|
5
|
+
require 'flic/protocol/primitives/disconnect_time'
|
5
6
|
|
6
7
|
module Flic
|
7
8
|
module Protocol
|
@@ -9,11 +10,11 @@ module Flic
|
|
9
10
|
class CreateConnectionChannel < Command
|
10
11
|
endian :little
|
11
12
|
|
12
|
-
uint32 :
|
13
|
+
uint32 :connection_channel_id
|
13
14
|
bluetooth_address :bluetooth_address
|
14
15
|
|
15
16
|
latency_mode :latency_mode
|
16
|
-
|
17
|
+
disconnect_time :auto_disconnect_time
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -1,32 +1,15 @@
|
|
1
|
-
require 'flic'
|
2
|
-
require 'flic/client'
|
3
1
|
require 'flic/protocol'
|
4
2
|
|
5
|
-
require 'socket'
|
6
|
-
|
7
3
|
module Flic
|
8
|
-
|
4
|
+
module Protocol
|
9
5
|
class Connection
|
10
|
-
class Error < StandardError; end
|
11
6
|
class ConnectionClosedError < Error; end
|
7
|
+
class NilResponse < Error; end
|
12
8
|
|
13
|
-
|
14
|
-
def open(*args)
|
15
|
-
client = new(*args)
|
16
|
-
|
17
|
-
begin
|
18
|
-
yield client
|
19
|
-
ensure
|
20
|
-
client.close
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
attr_reader :hostname, :port
|
9
|
+
attr_reader :socket
|
26
10
|
|
27
|
-
def initialize(
|
28
|
-
@
|
29
|
-
@socket = TCPSocket.new(hostname, port, *additional_socket_args)
|
11
|
+
def initialize(socket)
|
12
|
+
@socket = socket
|
30
13
|
@read_semaphore = Mutex.new
|
31
14
|
@write_semaphore = Mutex.new
|
32
15
|
end
|
@@ -35,12 +18,16 @@ module Flic
|
|
35
18
|
send_packet Protocol.serialize_command(command)
|
36
19
|
end
|
37
20
|
|
38
|
-
def
|
39
|
-
Protocol.parse_event(
|
21
|
+
def recv_command
|
22
|
+
Protocol.parse_event(recv_command)
|
40
23
|
end
|
41
24
|
|
42
|
-
def
|
43
|
-
|
25
|
+
def send_event(event)
|
26
|
+
send_packet Protocol.serialize_event(event)
|
27
|
+
end
|
28
|
+
|
29
|
+
def recv_event
|
30
|
+
Protocol.parse_event(recv_packet)
|
44
31
|
end
|
45
32
|
|
46
33
|
def closed?
|
@@ -71,10 +58,17 @@ module Flic
|
|
71
58
|
@read_semaphore.synchronize do
|
72
59
|
packet_header = Protocol::PacketHeader.new
|
73
60
|
packet_header_bytes = @socket.read packet_header.num_bytes
|
61
|
+
|
62
|
+
raise NilResponse unless packet_header_bytes
|
63
|
+
|
74
64
|
packet_header.read(packet_header_bytes)
|
75
65
|
|
76
66
|
@socket.read(packet_header.byte_length)
|
77
67
|
end
|
68
|
+
rescue NilResponse
|
69
|
+
@socket.close
|
70
|
+
|
71
|
+
retry
|
78
72
|
rescue IOError
|
79
73
|
if closed?
|
80
74
|
raise ConnectionClosedError
|
@@ -9,7 +9,7 @@ module Flic
|
|
9
9
|
class ConnectionStatusChanged < Event
|
10
10
|
endian :little
|
11
11
|
|
12
|
-
uint32 :
|
12
|
+
uint32 :connection_channel_id
|
13
13
|
connection_status :connection_status
|
14
14
|
|
15
15
|
disconnect_reason :disconnect_reason # only relevant when connection_status is :disconnected
|
@@ -19,9 +19,10 @@ module Flic
|
|
19
19
|
uint8 :current_pending_connections
|
20
20
|
boolean :currently_no_space_for_new_connection
|
21
21
|
|
22
|
-
uint16 :
|
23
|
-
array :
|
22
|
+
uint16 :verified_buttons_bluetooth_addresses_length
|
23
|
+
array :verified_buttons_bluetooth_addresses, type: :bluetooth_address, initial_length: :verified_buttons_bluetooth_addresses_length
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
|
+
|
@@ -12,6 +12,7 @@ module Flic
|
|
12
12
|
autoload :CreateConnectionChannelError, 'flic/protocol/primitives/create_connection_channel_error'
|
13
13
|
autoload :DeviceName, 'flic/protocol/primitives/device_name'
|
14
14
|
autoload :DisconnectReason, 'flic/protocol/primitives/disconnect_reason'
|
15
|
+
autoload :DisconnectTime, 'flic/protocol/primitives/disconnect_time'
|
15
16
|
autoload :Enum, 'flic/protocol/primitives/enum'
|
16
17
|
autoload :LatencyMode, 'flic/protocol/primitives/latency_mode'
|
17
18
|
autoload :RemovedReason, 'flic/protocol/primitives/removed_reason'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'flic/protocol/primitives'
|
2
|
+
|
3
|
+
module Flic
|
4
|
+
module Primitives
|
5
|
+
class DisconnectTime < BinData::Primitive
|
6
|
+
endian :little
|
7
|
+
|
8
|
+
uint16 :time, initial_value: 512
|
9
|
+
|
10
|
+
def get
|
11
|
+
if time == 512
|
12
|
+
nil
|
13
|
+
else
|
14
|
+
time
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def set(value)
|
19
|
+
if value == 512
|
20
|
+
raise RangeError, '512 is a special value that cannot be used for disconnect_time'
|
21
|
+
elsif value
|
22
|
+
self.time = value
|
23
|
+
else
|
24
|
+
self.time = 512
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'flic'
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
module Flic
|
6
|
+
class SimpleClient
|
7
|
+
class Error < StandardError; end
|
8
|
+
class ConnectionChannelRemoved; end
|
9
|
+
|
10
|
+
attr_reader :client
|
11
|
+
|
12
|
+
def initialize(*client_args)
|
13
|
+
@client = Client.new(*client_args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def shutdown
|
17
|
+
client.shutdown
|
18
|
+
event_dispatch_thread.join
|
19
|
+
end
|
20
|
+
|
21
|
+
def buttons
|
22
|
+
server_info = process_events_until do |callback|
|
23
|
+
client.get_info(&callback)
|
24
|
+
end
|
25
|
+
|
26
|
+
server_info.verified_buttons_bluetooth_addresses
|
27
|
+
end
|
28
|
+
|
29
|
+
def connect_button
|
30
|
+
begin
|
31
|
+
scan_wizard = Client::ScanWizard.new
|
32
|
+
|
33
|
+
process_events_until do |callback|
|
34
|
+
scan_wizard.removed do |result, bluetooth_address, *|
|
35
|
+
if result == :success
|
36
|
+
callback.call(bluetooth_address)
|
37
|
+
else
|
38
|
+
callback.call(nil)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
client.add_scan_wizard(scan_wizard)
|
43
|
+
end
|
44
|
+
ensure
|
45
|
+
client.remove_scan_wizard(scan_wizard)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def disconnect_button(button_bluetooth_address)
|
50
|
+
client.force_disconnect(button_bluetooth_address)
|
51
|
+
end
|
52
|
+
|
53
|
+
def listen(latency_mode, *button_bluetooth_addresses)
|
54
|
+
connection_channels = []
|
55
|
+
button_events = []
|
56
|
+
broken = false
|
57
|
+
|
58
|
+
begin
|
59
|
+
button_bluetooth_addresses.each do |button_bluetooth_addresses|
|
60
|
+
connection_channel = Client::ConnectionChannel.new(button_bluetooth_addresses, latency_mode)
|
61
|
+
|
62
|
+
connection_channel.button_up_or_down do |click_type, latency|
|
63
|
+
button_events << [button_bluetooth_addresses, click_type, latency]
|
64
|
+
end
|
65
|
+
|
66
|
+
connection_channel.button_single_click_or_double_click_or_hold do |click_type, latency|
|
67
|
+
button_events << [button_bluetooth_addresses, click_type, latency]
|
68
|
+
end
|
69
|
+
|
70
|
+
connection_channel.removed do
|
71
|
+
broken = true
|
72
|
+
end
|
73
|
+
|
74
|
+
connection_channels << connection_channel
|
75
|
+
|
76
|
+
client.add_connection_channel connection_channel
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
loop do
|
81
|
+
client.handle_next_event while !broken && button_events.empty?
|
82
|
+
|
83
|
+
button_events.each do |button_event|
|
84
|
+
yield *button_event
|
85
|
+
end
|
86
|
+
|
87
|
+
button_events.clear
|
88
|
+
|
89
|
+
raise ConnectionChannelRemoved, 'A connection channel was removed' if broken
|
90
|
+
end
|
91
|
+
ensure
|
92
|
+
connection_channels.each do |connection_channel|
|
93
|
+
client.remove_connection_channel connection_channel
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def process_events_until
|
101
|
+
done = false
|
102
|
+
result = nil
|
103
|
+
|
104
|
+
callback = proc do |_result|
|
105
|
+
done = true
|
106
|
+
result = _result
|
107
|
+
end
|
108
|
+
|
109
|
+
yield callback
|
110
|
+
|
111
|
+
client.handle_next_event until done
|
112
|
+
|
113
|
+
result
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/flic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alec Larsen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bindata
|
@@ -96,11 +96,20 @@ files:
|
|
96
96
|
- Rakefile
|
97
97
|
- flic.gemspec
|
98
98
|
- lib/flic.rb
|
99
|
+
- lib/flic/callbacks.rb
|
99
100
|
- lib/flic/client.rb
|
100
|
-
- lib/flic/client/
|
101
|
-
- lib/flic/
|
102
|
-
- lib/flic/
|
103
|
-
- lib/flic/
|
101
|
+
- lib/flic/client/connection_channel.rb
|
102
|
+
- lib/flic/client/features.rb
|
103
|
+
- lib/flic/client/features/connection_channel.rb
|
104
|
+
- lib/flic/client/features/force_disconnect.rb
|
105
|
+
- lib/flic/client/features/get_button_uuid.rb
|
106
|
+
- lib/flic/client/features/get_info.rb
|
107
|
+
- lib/flic/client/features/ping.rb
|
108
|
+
- lib/flic/client/features/scan.rb
|
109
|
+
- lib/flic/client/features/scan_wizard.rb
|
110
|
+
- lib/flic/client/scan_wizard.rb
|
111
|
+
- lib/flic/client/scanner.rb
|
112
|
+
- lib/flic/client/server_info.rb
|
104
113
|
- lib/flic/protocol.rb
|
105
114
|
- lib/flic/protocol/commands.rb
|
106
115
|
- lib/flic/protocol/commands/cancel_scan_wizard.rb
|
@@ -115,6 +124,7 @@ files:
|
|
115
124
|
- lib/flic/protocol/commands/ping.rb
|
116
125
|
- lib/flic/protocol/commands/remove_connection_channel.rb
|
117
126
|
- lib/flic/protocol/commands/remove_scanner.rb
|
127
|
+
- lib/flic/protocol/connection.rb
|
118
128
|
- lib/flic/protocol/events.rb
|
119
129
|
- lib/flic/protocol/events/advertisement_packet.rb
|
120
130
|
- lib/flic/protocol/events/bluetooth_controller_state_change.rb
|
@@ -147,11 +157,13 @@ files:
|
|
147
157
|
- lib/flic/protocol/primitives/create_connection_channel_error.rb
|
148
158
|
- lib/flic/protocol/primitives/device_name.rb
|
149
159
|
- lib/flic/protocol/primitives/disconnect_reason.rb
|
160
|
+
- lib/flic/protocol/primitives/disconnect_time.rb
|
150
161
|
- lib/flic/protocol/primitives/enum.rb
|
151
162
|
- lib/flic/protocol/primitives/latency_mode.rb
|
152
163
|
- lib/flic/protocol/primitives/removed_reason.rb
|
153
164
|
- lib/flic/protocol/primitives/scan_wizard_result.rb
|
154
165
|
- lib/flic/protocol/primitives/uuid.rb
|
166
|
+
- lib/flic/simple_client.rb
|
155
167
|
- lib/flic/version.rb
|
156
168
|
homepage: https://github.com/anarchocurious/flic
|
157
169
|
licenses:
|
data/lib/flic/event_bus.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'flic'
|
2
|
-
|
3
|
-
require 'thread'
|
4
|
-
|
5
|
-
module Flic
|
6
|
-
class EventBus
|
7
|
-
class Error < StandardError; end
|
8
|
-
class EventBusShutdown < Error; end
|
9
|
-
|
10
|
-
autoload :Driver, 'flic/event_bus/driver'
|
11
|
-
autoload :Subscription, 'flic/event_bus/subscription'
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@semaphore = Mutex.new
|
15
|
-
@subscriptions = []
|
16
|
-
@is_shutdown = false
|
17
|
-
end
|
18
|
-
|
19
|
-
def subscribe(subscription = Subscription.new)
|
20
|
-
@semaphore.synchronize do
|
21
|
-
raise EventBusShutdown if shutdown?
|
22
|
-
|
23
|
-
@subscriptions << subscription
|
24
|
-
end
|
25
|
-
|
26
|
-
if block_given?
|
27
|
-
begin
|
28
|
-
yield subscription
|
29
|
-
ensure
|
30
|
-
unsubscribe subscription
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def unsubscribe(subscription)
|
36
|
-
@semaphore.synchronize do
|
37
|
-
raise EventBusShutdown if shutdown?
|
38
|
-
|
39
|
-
@subscriptions.delete subscription
|
40
|
-
end
|
41
|
-
|
42
|
-
subscription.destroy
|
43
|
-
end
|
44
|
-
|
45
|
-
def listen
|
46
|
-
subscribe do |subscription|
|
47
|
-
subscription.listen do
|
48
|
-
yield
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def broadcast(*args)
|
54
|
-
@semaphore.synchronize do
|
55
|
-
raise EventBusShutdown if shutdown?
|
56
|
-
|
57
|
-
@subscriptions.each do |subscription|
|
58
|
-
subscription.publish(*args)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def shutdown?
|
64
|
-
@is_shutdown
|
65
|
-
end
|
66
|
-
|
67
|
-
def shutdown
|
68
|
-
@semaphore.synchronize do
|
69
|
-
unless shutdown?
|
70
|
-
@is_shutdown = true
|
71
|
-
|
72
|
-
@subscriptions.each do |subscription|
|
73
|
-
subscription.destroy
|
74
|
-
end
|
75
|
-
|
76
|
-
@subscriptions.clear
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|