sb-ble 0.5.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bbab52be19f92ec7202ac18981e9b65ead354a2c
4
+ data.tar.gz: b695176d8a305d5ac043fa350a5e2d995d8bc699
5
+ SHA512:
6
+ metadata.gz: df55d481209aaa635386dfa2deb9f2204824bc23ac44b8adcb55e8b4331c44971f35b90bb88ed5601b215795b630ca3256796c3a69fecb5c210acba58ccdd90f
7
+ data.tar.gz: 5bb64da90ebf9a2e0ccb14f62c8f6b580f9c01dcb7ff039f28829dc1e64f1145936ee4276035138de31fcafb916ca8a143438f407a4656083f023ddddbd3410b
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.semver ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 5
4
+ :patch: 0
5
+ :special: ''
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "ruby-dbus", "~> 0"
4
+ gem 'semver2', '~> 3'
5
+
6
+ group :development do
7
+ gem "rspec", "~> 3"
8
+ gem "yard", "~> 0"
9
+ gem "rdoc", "~> 3"
10
+ gem "bundler", "~> 1"
11
+ gem "juwelier", "~> 2"
12
+ gem "simplecov", ">= 0"
13
+ gem "pry", "~> 0"
14
+ gem "pry-byebug", "~> 3"
15
+ gem "pry-doc", "~> 0"
16
+ gem "pry-remote", "~> 0"
17
+ gem "pry-rescue", "~> 1"
18
+ gem "pry-stack_explorer", "~> 0"
19
+ gem 'redcarpet'
20
+ gem 'github-markup'
21
+ end
@@ -0,0 +1,130 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ addressable (2.4.0)
5
+ binding_of_caller (0.7.2)
6
+ debug_inspector (>= 0.0.1)
7
+ builder (3.2.3)
8
+ byebug (9.0.6)
9
+ coderay (1.1.1)
10
+ debug_inspector (0.0.3)
11
+ descendants_tracker (0.0.4)
12
+ thread_safe (~> 0.3, >= 0.3.1)
13
+ diff-lcs (1.3)
14
+ docile (1.1.5)
15
+ faraday (0.9.2)
16
+ multipart-post (>= 1.2, < 3)
17
+ git (1.3.0)
18
+ github-markup (1.6.0)
19
+ github_api (0.17.0)
20
+ addressable (~> 2.4.0)
21
+ descendants_tracker (~> 0.0.4)
22
+ faraday (~> 0.8, < 0.10)
23
+ hashie (>= 3.4)
24
+ mime-types (>= 1.16, < 3.0)
25
+ oauth2 (~> 1.0)
26
+ hashie (3.5.5)
27
+ highline (1.7.8)
28
+ interception (0.5)
29
+ json (1.8.6)
30
+ juwelier (2.4.5)
31
+ builder
32
+ bundler (>= 1.13)
33
+ git (>= 1.2.5)
34
+ github_api
35
+ highline (>= 1.6.15)
36
+ kamelcase (~> 0)
37
+ nokogiri (>= 1.5.10)
38
+ psych (~> 2.2)
39
+ rake
40
+ rdoc
41
+ semver2
42
+ jwt (1.5.6)
43
+ kamelcase (0.0.0)
44
+ semver2 (~> 3)
45
+ method_source (0.8.2)
46
+ mime-types (2.99.3)
47
+ mini_portile2 (2.1.0)
48
+ multi_json (1.12.1)
49
+ multi_xml (0.6.0)
50
+ multipart-post (2.0.0)
51
+ nokogiri (1.7.2)
52
+ mini_portile2 (~> 2.1.0)
53
+ oauth2 (1.3.1)
54
+ faraday (>= 0.8, < 0.12)
55
+ jwt (~> 1.0)
56
+ multi_json (~> 1.3)
57
+ multi_xml (~> 0.5)
58
+ rack (>= 1.2, < 3)
59
+ pry (0.10.4)
60
+ coderay (~> 1.1.0)
61
+ method_source (~> 0.8.1)
62
+ slop (~> 3.4)
63
+ pry-byebug (3.4.2)
64
+ byebug (~> 9.0)
65
+ pry (~> 0.10)
66
+ pry-doc (0.10.0)
67
+ pry (~> 0.9)
68
+ yard (~> 0.9)
69
+ pry-remote (0.1.8)
70
+ pry (~> 0.9)
71
+ slop (~> 3.0)
72
+ pry-rescue (1.4.5)
73
+ interception (>= 0.5)
74
+ pry
75
+ pry-stack_explorer (0.4.9.2)
76
+ binding_of_caller (>= 0.7)
77
+ pry (>= 0.9.11)
78
+ psych (2.2.4)
79
+ rack (2.0.3)
80
+ rake (12.0.0)
81
+ rdoc (3.12.2)
82
+ json (~> 1.4)
83
+ redcarpet (3.4.0)
84
+ rspec (3.6.0)
85
+ rspec-core (~> 3.6.0)
86
+ rspec-expectations (~> 3.6.0)
87
+ rspec-mocks (~> 3.6.0)
88
+ rspec-core (3.6.0)
89
+ rspec-support (~> 3.6.0)
90
+ rspec-expectations (3.6.0)
91
+ diff-lcs (>= 1.2.0, < 2.0)
92
+ rspec-support (~> 3.6.0)
93
+ rspec-mocks (3.6.0)
94
+ diff-lcs (>= 1.2.0, < 2.0)
95
+ rspec-support (~> 3.6.0)
96
+ rspec-support (3.6.0)
97
+ ruby-dbus (0.13.0)
98
+ semver2 (3.4.2)
99
+ simplecov (0.14.1)
100
+ docile (~> 1.1.0)
101
+ json (>= 1.8, < 3)
102
+ simplecov-html (~> 0.10.0)
103
+ simplecov-html (0.10.1)
104
+ slop (3.6.0)
105
+ thread_safe (0.3.6)
106
+ yard (0.9.9)
107
+
108
+ PLATFORMS
109
+ ruby
110
+
111
+ DEPENDENCIES
112
+ bundler (~> 1)
113
+ github-markup
114
+ juwelier (~> 2)
115
+ pry (~> 0)
116
+ pry-byebug (~> 3)
117
+ pry-doc (~> 0)
118
+ pry-remote (~> 0)
119
+ pry-rescue (~> 1)
120
+ pry-stack_explorer (~> 0)
121
+ rdoc (~> 3)
122
+ redcarpet
123
+ rspec (~> 3)
124
+ ruby-dbus (~> 0)
125
+ semver2 (~> 3)
126
+ simplecov
127
+ yard (~> 0)
128
+
129
+ BUNDLED WITH
130
+ 1.14.6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Fred Mitchell & Sensorberg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,62 @@
1
+ * sb-ble
2
+ :PROPERTIES:
3
+ :CUSTOM_ID: ruby-ble
4
+ :END:
5
+
6
+ Bluetooth Low Energy for Ruby -- Sensorberg Version
7
+ [[https://badge.fury.io/rb/ble][[[https://badge.fury.io/rb/ble.svg]]]]
8
+
9
+ ** Prelimaries
10
+ This is a fork of a fork. More features are being added here,
11
+ such as support for advertising.
12
+
13
+ ** Requirements
14
+ :PROPERTIES:
15
+ :CUSTOM_ID: requirements
16
+ :END:
17
+
18
+ - ruby >= 2.3
19
+ - Dbus
20
+ - bluez >= 5.36 (available on debian testing)
21
+ - =bluetoothd= started with option =-E= (experimental)
22
+
23
+ ** Examples
24
+ :PROPERTIES:
25
+ :CUSTOM_ID: examples
26
+ :END:
27
+
28
+ #+BEGIN_SRC ruby
29
+ # Selecter adapter
30
+ $a = BLE::Adapter.new('hci0')
31
+ puts "Info: #{$a.iface} #{$a.address} #{$a.name}"
32
+
33
+ # Run discovery
34
+ $a.start_discovery
35
+ sleep(2)
36
+ $a.stop_discovery
37
+
38
+ # Get device and connect to it
39
+ $d = $a['F4:AD:CB:FB:B4:85']
40
+ $d.connect
41
+
42
+ # Get temperature from the environmental sensing service
43
+ $d[:environmental_sensing, :temperature]
44
+
45
+ # Dump device information
46
+ srv = :device_information
47
+ $d.characteristics(srv).each {|uuid|
48
+ info = BLE::Characteristic[uuid]
49
+ name = info.nil? ? uuid : info[:name]
50
+ value = $d[srv, uuid] rescue '/!\\ not-readable /!\\'
51
+ puts "%-30s: %s" % [ name, value ]
52
+ }
53
+ #+END_SRC
54
+
55
+ ** Contributors
56
+ :PROPERTIES:
57
+ :CUSTOM_ID: contributors
58
+ :END:
59
+
60
+ - Fred Mitchell (Sensorberg GmbH) LE Advertisement support
61
+ - Oliver Valls (tramuntanal): Bug fixes / BLE Notification support
62
+ - Stephane D'Alu
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+
14
+ require 'rake'
15
+ require 'semver'
16
+
17
+ def s_version
18
+ SemVer.find.format "%M.%m.%p%s"
19
+ end
20
+
21
+ require 'juwelier'
22
+
23
+ Juwelier::Tasks.new do |gem|
24
+ gem.name = "sb-ble"
25
+ gem.homepage = "http://github.com/flajann2/ruby-ble"
26
+ gem.license = "MIT"
27
+ gem.summary = %Q{Bluetooth Low Energy for Ruby -- Sensorberg Version}
28
+ gem.description = %Q{This supports LE Advertising}
29
+ gem.email = "frederick.mitchell@sensorberg.com"
30
+ gem.authors = ["Fred Mitchell & Sensorberg"]
31
+ gem.version = s_version
32
+ # dependencies defined in Gemfile
33
+ end
34
+
35
+ Juwelier::RubygemsDotOrgTasks.new
36
+ require 'rspec/core'
37
+ require 'rspec/core/rake_task'
38
+ RSpec::Core::RakeTask.new(:spec) do |spec|
39
+ spec.pattern = FileList['spec/**/*_spec.rb']
40
+ end
41
+
42
+ desc "Code coverage detail"
43
+ task :simplecov do
44
+ ENV['COVERAGE'] = "true"
45
+ Rake::Task['spec'].execute
46
+ end
47
+
48
+ task :default => :spec
49
+
50
+ require 'yard'
51
+ YARD::Rake::YardocTask.new
File without changes
@@ -0,0 +1,112 @@
1
+ # coding: utf-8
2
+ require 'dbus'
3
+ require 'logger'
4
+
5
+ # https://github.com/mvidner/ruby-dbus/blob/master/doc/Tutorial.md
6
+ # https://kernel.googlesource.com/pub/scm/bluetooth/bluez/+/refs/heads/master/doc/
7
+
8
+
9
+ #
10
+ module BLE
11
+ private
12
+ # Interfaces
13
+ I_ADAPTER = 'org.bluez.Adapter1'
14
+ I_DEVICE = 'org.bluez.Device1'
15
+ I_AGENT_MANAGER = 'org.bluez.AgentManager1'
16
+ I_AGENT = 'org.bluez.Agent1'
17
+ I_GATT_CHARACTERISTIC = 'org.bluez.GattCharacteristic1'
18
+ I_GATT_SERVICE = 'org.bluez.GattService1'
19
+ I_PROXIMITY_REPORTER = 'org.bluez.ProximityReporter1'
20
+ I_PROPERTIES = 'org.freedesktop.DBus.Properties'
21
+ I_INTROSPECTABLE = 'org.freedesktop.DBus.Introspectable'
22
+
23
+ # Errors
24
+ E_IN_PROGRESS = 'org.bluez.Error.InProgress'
25
+ E_FAILED = 'org.bluez.Error.Failed'
26
+ E_NOT_READY = 'org.bluez.Error.NotReady'
27
+ E_ALREADY_CONNECTED = 'org.bluez.Error.AlreadyConnected'
28
+ E_NOT_CONNECTED = 'org.bluez.Error.NotConnected'
29
+ E_DOES_NOT_EXIST = 'org.bluez.Error.DoesNotExist'
30
+ E_NOT_SUPPORTED = 'org.bluez.Error.NotSupported'
31
+ E_NOT_AUTHORIZED = 'org.bluez.Error.NotAuthorized'
32
+ E_INVALID_ARGUMENTS = 'org.bluez.Error.InvalidArguments'
33
+ E_ALREADY_EXISTS = 'org.bluez.Error.AlreadyExists'
34
+ E_AUTH_CANCELED = 'org.bluez.Error.AuthenticationCanceled'
35
+ E_AUTH_FAILED = 'org.bluez.Error.AuthenticationFailed'
36
+ E_AUTH_REJECTED = 'org.bluez.Error.AuthenticationRejected'
37
+ E_AUTH_TIMEOUT = 'org.bluez.Error.AuthenticationTimeout'
38
+ E_AUTH_ATTEMPT_FAILED = 'org.bluez.Error.ConnectionAttemptFailed'
39
+ E_UNKNOWN_OBJECT = 'org.freedesktop.DBus.Error.UnknownObject'
40
+ E_INVALID_ARGS = 'org.freedesktop.DBus.Error.InvalidArgs'
41
+ E_INVALID_SIGNATURE = 'org.freedesktop.DBus.Error.InvalidSignature'
42
+
43
+ # Bus
44
+ DBUS = DBus.system_bus
45
+ BLUEZ = DBUS.service('org.bluez')
46
+
47
+ public
48
+ # Generic Error class
49
+ class Error < StandardError ; end
50
+ # Notify of unimplemented part
51
+ class NotYetImplemented < Error ; end
52
+ # Notify that the underlying API object is dead
53
+ class StalledObject < Error ; end
54
+ # Notify that execution wass not able to fulill as some requirement
55
+ # was not ready. Usually you can wait a little and restart the action.
56
+ class NotReady < Error ; end
57
+ # Notify that you don't have the necessary authorization to perfrom
58
+ # the operation
59
+ class NotAuthorized < Error ; end
60
+ # Notify that some service/characteristic/... is not found
61
+ # on this device
62
+ class NotFound < Error ; end
63
+ class AccessUnavailable < Error ; end
64
+ class NotSupported < Error ; end
65
+
66
+
67
+ # Base UUID for GATT services defined with 16bit or 32bit UUID
68
+ GATT_BASE_UUID="00000000-0000-1000-8000-00805f9b34fb"
69
+
70
+ #"DisplayOnly", "DisplayYesNo", "KeyboardOnly",
71
+ # "NoInputNoOutput" and "KeyboardDisplay" which
72
+
73
+
74
+ def self.registerAgent(agent, service, path)
75
+ raise NotYetImplemented
76
+ bus = DBus.session_bus
77
+ service = bus.request_service("org.ruby.service")
78
+
79
+ service.export(BLE::Agent.new(agent_path))
80
+
81
+ o_bluez = BLUEZ.object('/org/bluez')
82
+ o_bluez.introspect
83
+ o_bluez[I_AGENT_MANAGER].RegisterAgent(agent_path, "NoInputNoOutput")
84
+ end
85
+
86
+
87
+
88
+
89
+ # Check if Bluetooth underlying API is accessible
90
+ def self.ok?
91
+ BLUEZ.exists?
92
+ end
93
+
94
+ end
95
+
96
+ require_relative 'ble/version'
97
+ require_relative 'ble/uuid'
98
+ require_relative 'ble/adapter'
99
+ require_relative 'ble/char_desc'
100
+ require_relative 'ble/notifications'
101
+ require_relative 'ble/device'
102
+ require_relative 'ble/service'
103
+ require_relative 'ble/char_registry'
104
+ require_relative 'ble/characteristic'
105
+ require_relative 'ble/agent'
106
+
107
+ require_relative 'ble/db_sig_service'
108
+ require_relative 'ble/db_sig_characteristic'
109
+ require_relative 'ble/db_eddystone'
110
+ require_relative 'ble/db_nordic'
111
+
112
+
@@ -0,0 +1,162 @@
1
+ module BLE
2
+ # Adapter class
3
+ # Adapter.list
4
+ # a = Adapter.new('hci0')
5
+ # a.start_discover ; sleep(10) ; a.stop_discovery
6
+ # a.devices
7
+ #
8
+ class Adapter
9
+ # Return a list of available unix device name for the
10
+ # adapter installed on the system.
11
+ # @return [Array<String>] list of unix device name
12
+ def self.list
13
+ o_bluez = BLUEZ.object('/org/bluez')
14
+ o_bluez.introspect
15
+ o_bluez.subnodes.reject {|adapter| ['test'].include?(adapter) }
16
+ end
17
+
18
+ # Create a new Adapter
19
+ #
20
+ # @param iface [String] name of the Unix device
21
+ def initialize(iface)
22
+ @iface = iface.dup.freeze
23
+ @o_adapter = BLUEZ.object("/org/bluez/#{@iface}")
24
+ @o_adapter.introspect
25
+
26
+ # @o_adapter[I_PROPERTIES]
27
+ # .on_signal('PropertiesChanged') do |intf, props|
28
+ # end
29
+ # end
30
+ end
31
+
32
+ # The Bluetooth interface name
33
+ # @return [String] name of the Unix device
34
+ def iface
35
+ @iface
36
+ end
37
+
38
+ # The Bluetooth device address.
39
+ # @return [String] MAC address of the adapter
40
+ def address
41
+ @o_adapter[I_ADAPTER]['Address']
42
+ end
43
+
44
+ # The Bluetooth system name (pretty hostname).
45
+ # @return [String]
46
+ def name
47
+ @o_adapter[I_ADAPTER]['Name']
48
+ end
49
+
50
+ # The Bluetooth friendly name.
51
+ # In case no alias is set, it will return the system provided name.
52
+ # @return [String]
53
+ def alias
54
+ @o_adapter[I_ADAPTER]['Alias']
55
+ end
56
+
57
+ # Set the alias name.
58
+ #
59
+ # When resetting the alias with an empty string, the
60
+ # property will default back to system name
61
+ #
62
+ # @param val [String] new alias name.
63
+ # @return [void]
64
+ def alias=(val)
65
+ @o_adapter[I_ADAPTER]['Alias'] = val.nil? ? '' : val.to_str
66
+ nil
67
+ end
68
+
69
+ # Return the device corresponding to the given address.
70
+ # @note The device object returned has a dependency on the adapter.
71
+ #
72
+ # @param address MAC address of the device
73
+ # @return [Device] a device
74
+ def [](address)
75
+ Device.new(@iface, address)
76
+ end
77
+
78
+ # This method sets the device discovery filter for the caller.
79
+ # When this method is called with +nil+ or an empty list of UUIDs,
80
+ # filter is removed.
81
+ #
82
+ # @todo Need to sync with the adapter-api.txt
83
+ #
84
+ # @param uuids a list of uuid to filter on
85
+ # @param rssi RSSI threshold
86
+ # @param pathloss pathloss threshold
87
+ # @param transport [:auto, :bredr, :le]
88
+ # type of scan to run (default: :le)
89
+ # @return [self]
90
+ def filter(uuids, rssi: nil, pathloss: nil, transport: :le)
91
+ unless [:auto, :bredr, :le].include?(transport)
92
+ raise ArgumentError,
93
+ "transport must be one of :auto, :bredr, :le"
94
+ end
95
+ filter = { }
96
+
97
+ unless uuids.nil? || uuids.empty?
98
+ filter['UUIDs' ] = DBus.variant('as', uuids)
99
+ end
100
+ unless rssi.nil?
101
+ filter['RSSI' ] = DBus.variant('n', rssi)
102
+ end
103
+ unless pathloss.nil?
104
+ filter['Pathloss' ] = DBus.variant('q', pathloss)
105
+ end
106
+ unless transport.nil?
107
+ filter['Transport'] = DBus.variant('s', transport.to_s)
108
+ end
109
+
110
+ @o_adapter[I_ADAPTER].SetDiscoveryFilter(filter)
111
+
112
+ self
113
+ end
114
+
115
+ # Starts the device discovery session.
116
+ # This includes an inquiry procedure and remote device name resolving.
117
+ # Use {#stop_discovery} to release the sessions acquired.
118
+ # This process will start creating device in the underlying api
119
+ # as new devices are discovered.
120
+ #
121
+ # @return [Boolean]
122
+ def start_discovery
123
+ @o_adapter[I_ADAPTER].StartDiscovery
124
+ true
125
+ rescue DBus::Error => e
126
+ case e.name
127
+ when E_IN_PROGRESS then true
128
+ when E_FAILED then false
129
+ else raise ScriptError
130
+ end
131
+ end
132
+
133
+ # This method will cancel any previous {#start_discovery}
134
+ # transaction.
135
+ # @note The discovery procedure is shared
136
+ # between all discovery sessions thus calling {#stop_discovery}
137
+ # will only release a single session.
138
+ #
139
+ # @return [Boolean]
140
+ def stop_discovery
141
+ @o_adapter[I_ADAPTER].StopDiscovery
142
+ true
143
+ rescue DBus::Error => e
144
+ case e.name
145
+ when E_FAILED then false
146
+ when E_NOT_READY then false
147
+ when E_NOT_AUTHORIZED then raise NotAuthorized
148
+ else raise ScriptError
149
+ end
150
+
151
+ end
152
+
153
+ # List of devices MAC address that have been discovered.
154
+ #
155
+ # @return [Array<String>] List of devices MAC address.
156
+ def devices
157
+ @o_adapter.introspect # Force refresh
158
+ @o_adapter.subnodes.map {|dev| # Format: dev_aa_bb_cc_dd_ee_ff
159
+ dev[4..-1].tr('_', ':') }
160
+ end
161
+ end
162
+ end