flic 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/flic.rb +2 -1
  3. data/lib/flic/callbacks.rb +36 -0
  4. data/lib/flic/client.rb +52 -203
  5. data/lib/flic/client/connection_channel.rb +21 -0
  6. data/lib/flic/client/features.rb +15 -0
  7. data/lib/flic/client/features/connection_channel.rb +175 -0
  8. data/lib/flic/client/features/force_disconnect.rb +13 -0
  9. data/lib/flic/client/features/get_button_uuid.rb +43 -0
  10. data/lib/flic/client/features/get_info.rb +52 -0
  11. data/lib/flic/client/features/ping.rb +55 -0
  12. data/lib/flic/client/features/scan.rb +112 -0
  13. data/lib/flic/client/features/scan_wizard.rb +131 -0
  14. data/lib/flic/client/scan_wizard.rb +14 -0
  15. data/lib/flic/client/scanner.rb +12 -0
  16. data/lib/flic/client/server_info.rb +16 -0
  17. data/lib/flic/protocol.rb +1 -0
  18. data/lib/flic/protocol/commands/change_mode_parameters.rb +3 -2
  19. data/lib/flic/protocol/commands/create_connection_channel.rb +3 -2
  20. data/lib/flic/protocol/commands/remove_connection_channel.rb +1 -1
  21. data/lib/flic/{client → protocol}/connection.rb +20 -26
  22. data/lib/flic/protocol/events/button_click_or_hold.rb +1 -1
  23. data/lib/flic/protocol/events/button_single_or_double_click.rb +1 -1
  24. data/lib/flic/protocol/events/button_single_or_double_click_or_hold.rb +1 -1
  25. data/lib/flic/protocol/events/button_up_or_down.rb +1 -1
  26. data/lib/flic/protocol/events/connection_channel_removed.rb +2 -2
  27. data/lib/flic/protocol/events/connection_status_changed.rb +1 -1
  28. data/lib/flic/protocol/events/create_connection_channel_response.rb +1 -1
  29. data/lib/flic/protocol/events/get_info_response.rb +3 -2
  30. data/lib/flic/protocol/primitives.rb +1 -0
  31. data/lib/flic/protocol/primitives/disconnect_time.rb +29 -0
  32. data/lib/flic/simple_client.rb +116 -0
  33. data/lib/flic/version.rb +1 -1
  34. metadata +18 -6
  35. data/lib/flic/event_bus.rb +0 -81
  36. data/lib/flic/event_bus/driver.rb +0 -23
  37. data/lib/flic/event_bus/subscription.rb +0 -66
@@ -0,0 +1,13 @@
1
+ require 'flic/client/features'
2
+
3
+ module Flic
4
+ class Client
5
+ module Features
6
+ module ForceDisconnect
7
+ def force_disconnect(button_bluetooth_address)
8
+ send_command Protocol::Commands::ForceDisconnect.new(bluetooth_address: button_bluetooth_address)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,43 @@
1
+ require 'flic/client/features'
2
+
3
+ require 'thread'
4
+
5
+ module Flic
6
+ class Client
7
+ module Features
8
+ module GetButtonUuid
9
+ def initialize(*)
10
+ @button_bluetooth_address_callbacks_semaphore = Mutex.new
11
+ @button_bluetooth_address_callbacks = Hash.new { [] }
12
+
13
+ super
14
+ end
15
+
16
+ def get_button_uuid(button_bluetooth_address, callback = Proc.new)
17
+ command = Protocol::Commands::GetButtonUuid.new(bluetooth_address: button_bluetooth_address)
18
+
19
+ @button_bluetooth_address_callbacks_semaphore.synchronize do
20
+ @button_bluetooth_address_callbacks[command.bluetooth_address] << callback
21
+ end
22
+
23
+ send_command command
24
+ end
25
+
26
+ private
27
+
28
+ def handle_event(event)
29
+ case event
30
+ when Protocol::Events::GetButtonUuidResponse
31
+ callback = @button_bluetooth_address_callbacks_semaphore.synchronize do
32
+ @button_bluetooth_address_callbacks[event.bluetooth_address].shift
33
+ end
34
+
35
+ callback.call event.uuid if callback
36
+ else
37
+ super
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,52 @@
1
+ require 'flic/client/features'
2
+
3
+ require 'thread'
4
+
5
+ module Flic
6
+ class Client
7
+ module Features
8
+ module GetInfo
9
+ def initialize(*)
10
+ @get_info_callbacks_semaphore = Mutex.new
11
+ @get_info_callbacks = []
12
+
13
+ super
14
+ end
15
+
16
+ def get_info(callback = Proc.new)
17
+ @get_info_callbacks_semaphore.synchronize do
18
+ @get_info_callbacks << callback
19
+ end
20
+
21
+ send_command Protocol::Commands::GetInfo.new
22
+ end
23
+
24
+ private
25
+
26
+ def handle_event(event)
27
+ case event
28
+ when Protocol::Events::GetInfoResponse
29
+ server_info = ServerInfo.new(
30
+ event.bluetooth_controller_state,
31
+ event.bluetooth_address,
32
+ event.bluetooth_address_type,
33
+ event.maximum_pending_connections,
34
+ event.maximum_concurrently_connected_buttons,
35
+ event.current_pending_connections,
36
+ event.currently_no_space_for_new_connection,
37
+ event.verified_buttons_bluetooth_addresses
38
+ )
39
+
40
+ callback = @get_info_callbacks_semaphore.synchronize do
41
+ @get_info_callbacks.shift
42
+ end
43
+
44
+ callback.call server_info if callback
45
+ else
46
+ super
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,55 @@
1
+ require 'flic/client/features'
2
+
3
+ require 'thread'
4
+
5
+ module Flic
6
+ class Client
7
+ module Features
8
+ module Ping
9
+ def initialize(*)
10
+ @ping_id_callback_semaphore = Mutex.new
11
+ @ping_id_callback = {}
12
+
13
+ super
14
+ end
15
+
16
+ def ping(callback = Proc.new)
17
+ ping_id = alloc_ping_id_with_callback(callback)
18
+
19
+ send_command Protocol::Commands::Ping.new(ping_id: ping_id)
20
+ end
21
+
22
+ private
23
+
24
+ def alloc_ping_id_with_callback(callback)
25
+ @ping_id_callback_semaphore.synchronize do
26
+ ping_id = nil
27
+
28
+ loop do
29
+ ping_id = rand(2**32)
30
+
31
+ break unless @ping_id_callback.has_key?(ping_id)
32
+ end
33
+
34
+ @ping_id_callback[ping_id] = callback
35
+
36
+ ping_id
37
+ end
38
+ end
39
+
40
+ def handle_event(event)
41
+ case event
42
+ when Protocol::Events::PingResponse
43
+ callback = @ping_id_callback_semaphore.synchronize do
44
+ @ping_id_callback.delete event.ping_id
45
+ end
46
+
47
+ callback.call if callback
48
+ else
49
+ super
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,112 @@
1
+ require 'flic/client/features'
2
+
3
+ require 'thread'
4
+
5
+ module Flic
6
+ class Client
7
+ module Features
8
+ module Scan
9
+ def initialize(*)
10
+ @scan_id_scanner_semaphore = Mutex.new
11
+ @scan_id_scanner = {}
12
+
13
+ super
14
+ end
15
+
16
+ def scanners
17
+ @scan_id_scanner_semaphore.synchronize { @scan_id_scanner.values }
18
+ end
19
+
20
+ def add_scanner(scanner)
21
+ scan_id = _add_scanner(scanner)
22
+
23
+ send_command Protocol::Commands::CreateScanner.new(scan_id: scan_id) if scan_id
24
+ end
25
+
26
+ def remove_scanner(scanner)
27
+ scan_id = _remove_scanner(scanner)
28
+
29
+ send_command Protocol::Commands::RemoveScanner.new(scan_id: scan_id) if scan_id
30
+ end
31
+
32
+ def shutdown(*)
33
+ scanners.each do |scanner|
34
+ _remove_scanner(scanner)
35
+ end
36
+
37
+ super
38
+ end
39
+
40
+ private
41
+
42
+ def handle_event(event)
43
+ case event
44
+ when Protocol::Events::AdvertisementPacket
45
+ scanner = find_scanner_for_scan_id(scanner)
46
+
47
+ if scanner
48
+ scanner.advertisement_received(
49
+ event.bluetooth_address,
50
+ event.name,
51
+ event.rssi,
52
+ event.is_private,
53
+ event.is_already_verified
54
+ )
55
+ end
56
+ else
57
+ super
58
+ end
59
+ end
60
+
61
+ def _add_scanner(scanner)
62
+ scan_id = nil
63
+
64
+ @scan_id_scanner_semaphore.synchronize do
65
+ unless @scan_id_scanner.values.include?(scanner)
66
+ loop do
67
+ scan_id = rand(2**32)
68
+
69
+ break unless @scan_id_scanner.has_key?(scan_id)
70
+ end
71
+
72
+ @scan_id_scanner[scan_id] = scanner
73
+ end
74
+ end
75
+
76
+ scanner.added self if scan_id # we have to do this here because the server does not callback
77
+
78
+ scan_id
79
+ end
80
+
81
+ def _remove_scanner(scanner)
82
+ scan_id = nil
83
+
84
+ @scan_id_scanner_semaphore.synchronize do
85
+ @scan_id_scanner.each do |_scan_id, _scanner|
86
+ if scanner == _scanner
87
+ scan_id = _scan_id
88
+ break
89
+ end
90
+ end
91
+
92
+ @scan_id_scanner.delete scan_id if scan_id
93
+ end
94
+
95
+ scanner.removed self if scan_id # we have to do this here because the server does not callback
96
+
97
+ scan_id
98
+ end
99
+
100
+ def find_scanner_for_scan_id(needle)
101
+ @scan_id_scanner_semaphore.synchronize do
102
+ @scan_id_scanner.each do |scan_id, scanner|
103
+ return scanner if scan_id == needle
104
+ end
105
+ end
106
+
107
+ nil
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,131 @@
1
+ require 'flic/client/features'
2
+
3
+ require 'thread'
4
+
5
+ module Flic
6
+ class Client
7
+ module Features
8
+ module ScanWizard
9
+ def initialize(*)
10
+ @scan_wizard_id_scan_wizard_semaphore = Mutex.new
11
+ @scan_wizard_id_scan_wizard = {}
12
+
13
+ super
14
+ end
15
+
16
+ def scan_wizards
17
+ @scan_wizard_id_scan_wizard_semaphore.synchronize { @scan_wizard_id_scan_wizard.values }
18
+ end
19
+
20
+ def add_scan_wizard(scan_wizard)
21
+ scan_wizard_id = _add_scan_wizard(scan_wizard)
22
+
23
+ if scan_wizard_id
24
+ scan_wizard.added self
25
+ send_command Protocol::Commands::CreateScanWizard.new(scan_wizard_id: scan_wizard_id)
26
+ end
27
+ end
28
+
29
+ def remove_scan_wizard(scan_wizard)
30
+ scan_wizard_id = find_scan_wizard_id_for_scan_wizard(scan_wizard)
31
+
32
+ send_command Protocol::Commands::CancelScanWizard.new(scan_wizard_id: scan_wizard_id) if scan_wizard_id
33
+ end
34
+
35
+ def shutdown(*)
36
+ scan_wizards.each do |scan_wizard|
37
+ _remove_scan_wizard(scan_wizard)
38
+ scan_wizard.removed self, nil, nil, nil
39
+ end
40
+
41
+ super
42
+ end
43
+
44
+ private
45
+
46
+ def handle_event(event)
47
+ case event
48
+ when Protocol::Events::ScanWizardFoundPrivateButton
49
+ scan_wizard = find_scan_wizard_for_scan_wizard_id(event.scan_wizard_id)
50
+
51
+ scan_wizard.found_private_button if scan_wizard
52
+ when Protocol::Events::ScanWizardFoundPublicButton
53
+ scan_wizard = find_scan_wizard_for_scan_wizard_id(event.scan_wizard_id)
54
+
55
+ scan_wizard.button_bluetooth_address = event.bluetooth_address
56
+ scan_wizard.button_name = event.name
57
+ scan_wizard.found_public_button event.bluetooth_address, event.name
58
+ when Protocol::Events::ScanWizardCompleted
59
+ scan_wizard = find_scan_wizard_for_scan_wizard_id(event.scan_wizard_id)
60
+
61
+ if scan_wizard
62
+ _remove_scan_wizard(scan_wizard)
63
+
64
+ scan_wizard.result = event.scan_wizard_result
65
+ scan_wizard.removed self, event.scan_wizard_result, scan_wizard.button_bluetooth_address, scan_wizard.button_name
66
+ end
67
+ else
68
+ super
69
+ end
70
+ end
71
+
72
+ def _add_scan_wizard(scan_wizard)
73
+ scan_wizard_id = nil
74
+
75
+ @scan_wizard_id_scan_wizard_semaphore.synchronize do
76
+ unless @scan_wizard_id_scan_wizard.values.include?(scan_wizard)
77
+ loop do
78
+ scan_wizard_id = rand(2**32)
79
+
80
+ break unless @scan_wizard_id_scan_wizard.has_key?(scan_wizard_id)
81
+ end
82
+
83
+ @scan_wizard_id_scan_wizard[scan_wizard_id] = scan_wizard
84
+ end
85
+ end
86
+
87
+ scan_wizard_id
88
+ end
89
+
90
+ def _remove_scan_wizard(scan_wizard)
91
+ scan_wizard_id = nil
92
+
93
+ @scan_wizard_id_scan_wizard_semaphore.synchronize do
94
+ if @scan_wizard_id_scan_wizard.values.include?(scan_wizard)
95
+ @scan_wizard_id_scan_wizard.each do |_scan_wizard_id, _scan_wizard|
96
+ if scan_wizard == _scan_wizard
97
+ scan_wizard_id = _scan_wizard_id
98
+ break
99
+ end
100
+ end
101
+
102
+ @scan_wizard_id_scan_wizard.delete scan_wizard_id if scan_wizard_id
103
+ end
104
+ end
105
+
106
+ scan_wizard_id
107
+ end
108
+
109
+ def find_scan_wizard_for_scan_wizard_id(needle)
110
+ @scan_wizard_id_scan_wizard_semaphore.synchronize do
111
+ @scan_wizard_id_scan_wizard.each do |scan_wizard_id, scan_wizard|
112
+ return scan_wizard if scan_wizard_id == needle
113
+ end
114
+ end
115
+
116
+ nil
117
+ end
118
+
119
+ def find_scan_wizard_id_for_scan_wizard(needle)
120
+ @scan_wizard_id_scan_wizard_semaphore.synchronize do
121
+ @scan_wizard_id_scan_wizard.each do |scan_wizard_id, scan_wizard|
122
+ return scan_wizard_id if scan_wizard == needle
123
+ end
124
+ end
125
+
126
+ nil
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,14 @@
1
+ require 'flic/client'
2
+
3
+ module Flic
4
+ class Client
5
+ class ScanWizard
6
+ extend Callbacks
7
+
8
+ attr_accessor :button_bluetooth_address, :button_name, :result
9
+
10
+ define_callbacks :added, :removed,
11
+ :found_private_button, :found_public_button, :button_connected
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ require 'flic/client'
2
+
3
+ module Flic
4
+ class Client
5
+ class Scanner
6
+ extend Callbacks
7
+
8
+ define_callbacks :added, :removed,
9
+ :advertisement_received
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require 'flic/client'
2
+
3
+ module Flic
4
+ class Client
5
+ ServerInfo = Struct.new(
6
+ 'ServerInfo',
7
+ :bluetooth_controller_state, :bluetooth_address,
8
+ :bluetooth_address_type,
9
+ :maximum_pending_connections,
10
+ :maximum_concurrently_connected_buttons,
11
+ :current_pending_connections,
12
+ :currently_no_space_for_new_connection,
13
+ :verified_buttons_bluetooth_addresses
14
+ )
15
+ end
16
+ end