Class: BLE::Device
Overview
Defined Under Namespace
Classes: NotConnected
Instance Method Summary collapse
-
#[](service, characteristic, raw: false) ⇒ Object
Get value for a service/characteristic.
-
#[]=(service, characteristic, val, raw: false) ⇒ void
Set value for a service/characteristic.
-
#address ⇒ String
The Bluetooth device address of the remote device.
-
#alias ⇒ String
The name alias for the remote device.
-
#alias=(val) ⇒ void
Setting an empty string or nil as alias will convert it back to the remote device name.
-
#blocked=(val) ⇒ void
If set to true any incoming connections from the device will be immediately rejected.
-
#cancel_pairing ⇒ Boolean
This method can be used to cancel a pairing operation initiated by the Pair method.
-
#characteristics(service) ⇒ Array<String>?
List of available characteristics UUID for a service.
-
#connect(profile = :all) ⇒ Boolean
This connect to the specified profile UUID or to any (:all) profiles the remote device supports that can be connected to and have been flagged as auto-connectable on our side.
-
#disconnect(profile = :all) ⇒ Boolean
This method gracefully disconnects :all connected profiles and then terminates low-level ACL connection.
-
#has_service?(service) ⇒ Boolean
Check if service is available on the device.
-
#initialize(adapter, dev, auto_refresh: true) ⇒ Device
constructor
A new instance of Device.
-
#is_blocked? ⇒ Boolean
Is the device blocked?.
-
#is_connected? ⇒ Boolean
Indicates if the remote device is currently connected.
-
#is_paired? ⇒ Boolean
Indicates if the remote device is paired.
-
#is_trusted? ⇒ Boolean
Is the device trusted?.
-
#name ⇒ String
The Bluetooth remote name.
-
#pair ⇒ Boolean
This method will connect to the remote device, initiate pairing and then retrieve all SDP records (or GATT primary services).
-
#refresh ⇒ Boolean
Refresh list of services and characteristics.
-
#refresh! ⇒ self
Refresh list of services and characteristics.
-
#remove ⇒ Boolean
This removes the remote device object.
-
#rssi ⇒ Integer
Received Signal Strength Indicator of the remote device (inquiry or advertising).
-
#services ⇒ Array<String>
List of available services as UUID.
-
#trusted=(val) ⇒ void
Indicates if the remote is seen as trusted.
-
#tx_power ⇒ Integer
Advertised transmitted power level (inquiry or advertising).
Methods included from Notifications
#on_notification, #start_notify!
Constructor Details
#initialize(adapter, dev, auto_refresh: true) ⇒ Device
Returns a new instance of Device.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/ble/device.rb', line 19 def initialize(adapter, dev, auto_refresh: true) @adapter, @dev = adapter, dev @auto_refresh = auto_refresh @services = {} @n_adapter = adapter @p_adapter = "/org/bluez/#{@n_adapter}" @o_adapter = BLUEZ.object(@p_adapter) @o_adapter.introspect @n_dev = 'dev_' + dev.tr(':', '_') @p_dev = "/org/bluez/#{@n_adapter}/#{@n_dev}" @o_dev = BLUEZ.object(@p_dev) @o_dev.introspect self.refresh if @auto_refresh @o_dev[I_PROPERTIES] .on_signal('PropertiesChanged') do |intf, props| case intf when I_DEVICE case props['Connected'] when true self.refresh if @auto_refresh end end end end |
Instance Method Details
#[](service, characteristic, raw: false) ⇒ Object
Get value for a service/characteristic.
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 |
# File 'lib/ble/device.rb', line 390 def [](service, characteristic, raw: false) _require_connection! uuid = _uuid_characteristic(characteristic) chars = _characteristics(service) raise Service::NotFound, service if chars.nil? char = chars[uuid] raise Characteristic::NotFound, characteristic if char.nil? if char.flag?('read') char.read(raw: raw) elsif char.flag?('encrypt-read') || char.flag?('encrypt-authenticated-read') raise NotYetImplemented else raise AccessUnavailable end end |
#[]=(service, characteristic, val, raw: false) ⇒ void
This method returns an undefined value.
Set value for a service/characteristic
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
# File 'lib/ble/device.rb', line 419 def []=(service, characteristic, val, raw: false) _require_connection! uuid = _uuid_characteristic(characteristic) chars = _characteristics(service) raise ServiceNotFound, service if chars.nil? char = chars[uuid] raise CharacteristicNotFound, characteristic if char.nil? if char.flag?('write') || char.flag?('write-without-response') char.write(val, raw: raw) elsif char.flag?('encrypt-write') || char.flag?('encrypt-authenticated-write') raise NotYetImplemented else raise AccessUnavailable end nil end |
#address ⇒ String
The Bluetooth device address of the remote device.
244 245 246 |
# File 'lib/ble/device.rb', line 244 def address @o_dev[I_DEVICE]['Address'] end |
#alias ⇒ String
The name alias for the remote device. The alias can be used to have a different friendly name for the remote device. In case no alias is set, it will return the remote device name.
261 262 263 |
# File 'lib/ble/device.rb', line 261 def alias @o_dev[I_DEVICE]['Alias'] end |
#alias=(val) ⇒ void
This method returns an undefined value.
Setting an empty string or nil as alias will convert it back to the remote device name.
268 269 270 |
# File 'lib/ble/device.rb', line 268 def alias=(val) @o_dev[I_DEVICE]['Alias'] = val.nil? ? "" : val.to_str end |
#blocked=(val) ⇒ void
This method returns an undefined value.
If set to true any incoming connections from the device will be immediately rejected. Any device drivers will also be removed and no new ones will be probed as long as the device is blocked
301 302 303 304 305 306 |
# File 'lib/ble/device.rb', line 301 def blocked=(val) if ! [ true, false ].include?(val) raise ArgumentError, "value must be a boolean" end @o_dev[I_DEVICE]['Blocked'] = val end |
#cancel_pairing ⇒ Boolean
This method can be used to cancel a pairing operation initiated by the Pair method.
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ble/device.rb', line 97 def cancel_pairing @o_dev[I_DEVICE].CancelPairing true rescue DBus::Error => e case e.name when E_DOES_NOT_EXIST then true when E_FAILED then false else raise ScriptError end end |
#characteristics(service) ⇒ Array<String>?
The list is retrieve once when object is connected if auto_refresh is enable, otherwise you need to call #refresh.
List of available characteristics UUID for a service.
235 236 237 238 239 240 |
# File 'lib/ble/device.rb', line 235 def characteristics(service) _require_connection! if chars = _characteristics(service) chars.keys end end |
#connect(profile = :all) ⇒ Boolean
This connect to the specified profile UUID or to any (:all) profiles the remote device supports that can be connected to and have been flagged as auto-connectable on our side. If only subset of profiles is already connected it will try to connect currently disconnected ones. If at least one profile was connected successfully this method will indicate success.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/ble/device.rb', line 116 def connect(profile=:all) case profile when UUID::REGEX @o_dev[I_DEVICE].ConnectProfile(profile) when :all @o_dev[I_DEVICE].Connect() else raise ArgumentError, "profile uuid or :all expected" end true rescue DBus::Error => e case e.name when E_NOT_READY when E_FAILED when E_IN_PROGRESS false when E_ALREADY_CONNECTED true when E_UNKNOWN_OBJECT raise StalledObject else raise ScriptError end end |
#disconnect(profile = :all) ⇒ Boolean
This method gracefully disconnects :all connected profiles and then terminates low-level ACL connection. ACL connection will be terminated even if some profiles were not disconnected properly e.g. due to misbehaving device. This method can be also used to cancel a preceding #connect call before a reply to it has been received. If a profile UUID is specified, only this profile is disconnected, and as their is no connection tracking for a profile, so as long as the profile is registered this will always succeed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/ble/device.rb', line 149 def disconnect(profile=:all) case profile when UUID::REGEX @o_dev[I_DEVICE].DisconnectProfile(profile) when :all @o_dev[I_DEVICE].Disconnect() else raise ArgumentError, "profile uuid or :all expected" end true rescue DBus::Error => e case e.name when E_FAILED when E_IN_PROGRESS false when E_INVALID_ARGUMENTS raise ArgumentError, "unsupported profile (#{profile})" when E_NOT_SUPPORTED raise NotSupported when E_NOT_CONNECTED true when E_UNKNOWN_OBJECT raise StalledObject else raise ScriptError end end |
#has_service?(service) ⇒ Boolean
Check if service is available on the device
221 222 223 |
# File 'lib/ble/device.rb', line 221 def has_service?(service) @service.key?(_uuid_service(service)) end |
#is_blocked? ⇒ Boolean
Is the device blocked?
291 292 293 |
# File 'lib/ble/device.rb', line 291 def is_blocked? @o_dev[I_DEVICE]['Blocked'] end |
#is_connected? ⇒ Boolean
Indicates if the remote device is currently connected.
187 188 189 190 191 192 193 194 195 |
# File 'lib/ble/device.rb', line 187 def is_connected? @o_dev[I_DEVICE]['Connected'] rescue DBus::Error => e case e.name when E_UNKNOWN_OBJECT raise StalledObject else raise ScriptError end end |
#is_paired? ⇒ Boolean
Indicates if the remote device is paired
176 177 178 179 180 181 182 183 184 |
# File 'lib/ble/device.rb', line 176 def is_paired? @o_dev[I_DEVICE]['Paired'] rescue DBus::Error => e case e.name when E_UNKNOWN_OBJECT raise StalledObject else raise ScriptError end end |
#is_trusted? ⇒ Boolean
Is the device trusted?
274 275 276 |
# File 'lib/ble/device.rb', line 274 def is_trusted? @o_dev[I_DEVICE]['Trusted'] end |
#name ⇒ String
The Bluetooth remote name. It is better to always use the #alias when displaying the devices name.
252 253 254 |
# File 'lib/ble/device.rb', line 252 def name # optional @o_dev[I_DEVICE]['Name'] end |
#pair ⇒ Boolean
This method will connect to the remote device, initiate pairing and then retrieve all SDP records (or GATT primary services). If the application has registered its own agent, then that specific agent will be used. Otherwise it will use the default agent. Only for applications like a pairing wizard it would make sense to have its own agent. In almost all other cases the default agent will handle this just fine. In case there is no application agent and also no default agent present, this method will fail.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/ble/device.rb', line 77 def pair @o_dev[I_DEVICE].Pair true rescue DBus::Error => e case e.name when E_INVALID_ARGUMENTS then false when E_FAILED then false when E_ALREADY_EXISTS then true when E_AUTH_CANCELED then raise NotAutorized when E_AUTH_FAILED then raise NotAutorized when E_AUTH_REJECTED then raise NotAutorized when E_AUTH_TIMEOUT then raise NotAutorized when E_AUTH_ATTEMPT_FAILED then raise NotAutorized else raise ScriptError end end |
#refresh ⇒ Boolean
Refresh list of services and characteristics
334 335 336 337 338 339 |
# File 'lib/ble/device.rb', line 334 def refresh refresh! true rescue NotConnected, StalledObject false end |
#refresh! ⇒ self
Refresh list of services and characteristics
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 |
# File 'lib/ble/device.rb', line 344 def refresh! _require_connection! max_wait ||= 1.5 # Use ||= due to the retry @services = Hash[@o_dev[I_DEVICE]['GattServices'].map {|p_srv| o_srv = BLUEZ.object(p_srv) o_srv.introspect srv = o_srv[I_PROPERTIES].GetAll(I_GATT_SERVICE).first char = Hash[srv['Characteristics'].map {|p_char| o_char = BLUEZ.object(p_char) o_char.introspect uuid = o_char[I_GATT_CHARACTERISTIC]['UUID' ].downcase flags = o_char[I_GATT_CHARACTERISTIC]['Flags'] [ uuid, Characteristic.new({ :uuid => uuid, :flags => flags, :obj => o_char }) ] }] uuid = srv['UUID'].downcase [ uuid, { :uuid => uuid, :primary => srv['Primary'], :characteristics => char } ] }] self rescue DBus::Error => e case e.name when E_UNKNOWN_OBJECT raise StalledObject when E_INVALID_ARGS # That's probably because all the bluez information # haven't been collected yet on dbus for GattServices if max_wait > 0 sleep(0.25) ; max_wait -= 0.25 ; retry end raise NotReady else raise ScriptError end end |
#remove ⇒ Boolean
This removes the remote device object. It will remove also the pairing information.
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/ble/device.rb', line 51 def remove @o_adapter[I_ADAPTER].RemoveDevice(@p_dev) true rescue DBus::Error => e case e.name when E_FAILED then false when E_DOES_NOT_EXIST then raise StalledObject when E_UNKNOWN_OBJECT then raise StalledObject else raise ScriptError end end |
#rssi ⇒ Integer
Received Signal Strength Indicator of the remote device (inquiry or advertising).
311 312 313 314 315 316 317 318 |
# File 'lib/ble/device.rb', line 311 def rssi # optional @o_dev[I_DEVICE]['RSSI'] rescue DBus::Error => e case e.name when E_INVALID_ARGS then raise NotSupported else raise ScriptError end end |
#services ⇒ Array<String>
The list is retrieve once when object is connected if auto_refresh is enable, otherwise you need to call #refresh.
This is the list of UUIDs for which we have an entry in the underlying api (bluez-dbus), which can be less that the list of advertised UUIDs.
List of available services as UUID.
214 215 216 217 |
# File 'lib/ble/device.rb', line 214 def services _require_connection! @services.keys end |
#trusted=(val) ⇒ void
This method returns an undefined value.
Indicates if the remote is seen as trusted. This setting can be changed by the application.
282 283 284 285 286 287 |
# File 'lib/ble/device.rb', line 282 def trusted=(val) if ! [ true, false ].include?(val) raise ArgumentError, "value must be a boolean" end @o_dev[I_DEVICE]['Trusted'] = val end |
#tx_power ⇒ Integer
Advertised transmitted power level (inquiry or advertising).
322 323 324 325 326 327 328 329 |
# File 'lib/ble/device.rb', line 322 def tx_power # optional @o_dev[I_DEVICE]['TxPower'] rescue DBus::Error => e case e.name when E_INVALID_ARGS then raise NotSupported else raise ScriptError end end |