Class: Radbeacon::Usb

Inherits:
BluetoothLeDevice show all
Includes:
Utils
Defined in:
lib/radbeacon/usb.rb

Constant Summary collapse

C_DEVICE_NAME =

Define GATT characteristic constants Generic Access Profile

"0x0003"
C_APPEARANCE =
"0x0006"
C_MANUFACTURER_NAME =

Device Information

"0x000a"
C_MODEL_NUMBER =
"0x000d"
C_SERIAL_STRING =
"0x0010"
C_FIRMWARE_STRING =
"0x0013"
GATT_DEV_MODEL =

Configuration

"0x0017"
GATT_DEV_ID =
"0x001a"
GATT_DEV_NAME =
"0x001d"
GATT_UUID =
"0x0020"
GATT_MAJOR =
"0x0023"
GATT_MINOR =
"0x0026"
GATT_POWER =
"0x0029"
GATT_TXPOWER =
"0x002c"
GATT_INTERVAL =
"0x002f"
GATT_RESULT =
"0x0032"
GATT_NEW_PIN =
"0x0035"
GATT_ACTION =
"0x0038"
GATT_PIN =
"0x003b"
GATT_BCTYPE =
"0x003e"
GATT_FWVERSION =
"0x0041"
GATT_CONN_TIMEOUT =
"0x0044"
GATT_BEACON_SWITCH =
"0x0047"
GATT_ACTION_DONOTHING =

Define GATT action/result constants Actions

"00000000"
GATT_ACTION_UPDATE_ADV =
"00000001"
GATT_ACTION_UPDATE_PIN =
"00000002"
GATT_ACTION_FACTORY_RESET =
"00000003"
GATT_ACTION_DFU =
"00000004"
GATT_ACTION_LOCK =
"00000005"
GATT_ACTION_CONNECTABLE_TIME =
"00000006"
GATT_SUCCES =

Results

"00000000"
GATT_INVALID_PIN =
"00000001"
GATT_ERROR =

not used

"00000002"
TRANSMIT_POWER_VALUES =

Transmit power and advertisement frequency values

{-23 => "00", -21 => "01", -18 => "03", -14 => "05",
-11 => "07", -7 => "09", -4 => "0b", 0 => "0d", 3 => "0f"}
DEFAULT_MEASURED_POWER_VALUES =
[-94, -92, -90, -86, -84, -79, -74, -72, -66]
ADVERTISING_RATE_VALUES =
{0 => "0000", 1 => "2006", 2 => "0003", 3 => "f501", 4 => "7001",
5 => "2001", 6 => "ea00", 7 => "c400", 8 => "a800", 9 => "9100", 10 => "8000"}
BEACON_TYPES =
{"ibeacon" => "01", "altbeacon" => "02", "dual" => "03"}
TIMEOUT =

Timeout length for GATT commands

0.5
VALID_UUID =

Valid UUID pattern

/^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$/

Instance Attribute Summary collapse

Attributes inherited from BluetoothLeDevice

#characteristics, #is_connectable, #name, #values

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

#bytes_to_major_minor, #bytes_to_power, #bytes_to_text, #bytes_to_uuid, #major_minor_to_bytes, #pin_to_bytes, #power_to_bytes, #text_to_bytes, #uuid_to_bytes

Methods inherited from BluetoothLeDevice

#can_connect?, #char_values, #characteristics_command, #discover_characteristics, #display, #fetch_characteristics

Constructor Details

#initialize(device) ⇒ Usb

Returns a new instance of Usb.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/radbeacon/usb.rb', line 73

def initialize(device)
  @errors = []
  @mac_address = device.mac_address
  @dev_model = bytes_to_text(device.values[GATT_DEV_MODEL])
  @dev_id =  bytes_to_text(device.values[GATT_DEV_ID])
  @dev_version =  bytes_to_text(device.values[GATT_FWVERSION])
  @dev_name =  bytes_to_text(device.values[GATT_DEV_NAME])
  @uuid =  bytes_to_uuid(device.values[GATT_UUID])
  @major =  bytes_to_major_minor(device.values[GATT_MAJOR])
  @minor = bytes_to_major_minor(device.values[GATT_MINOR])
  @power = bytes_to_power(device.values[GATT_POWER])
  @tx_power = TRANSMIT_POWER_VALUES.key(device.values[GATT_TXPOWER])
  @adv_rate = ADVERTISING_RATE_VALUES.key(device.values[GATT_INTERVAL].delete(' '))
  @beacon_type = BEACON_TYPES.key(device.values[GATT_BCTYPE])
end

Instance Attribute Details

#adv_rateObject

Returns the value of attribute adv_rate.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def adv_rate
  @adv_rate
end

#beacon_typeObject

Returns the value of attribute beacon_type.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def beacon_type
  @beacon_type
end

#dev_idObject

Returns the value of attribute dev_id.



61
62
63
# File 'lib/radbeacon/usb.rb', line 61

def dev_id
  @dev_id
end

#dev_modelObject

Returns the value of attribute dev_model.



61
62
63
# File 'lib/radbeacon/usb.rb', line 61

def dev_model
  @dev_model
end

#dev_nameObject

Returns the value of attribute dev_name.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def dev_name
  @dev_name
end

#dev_versionObject

Returns the value of attribute dev_version.



61
62
63
# File 'lib/radbeacon/usb.rb', line 61

def dev_version
  @dev_version
end

#errorsObject

Returns the value of attribute errors.



61
62
63
# File 'lib/radbeacon/usb.rb', line 61

def errors
  @errors
end

#mac_addressObject

Returns the value of attribute mac_address.



61
62
63
# File 'lib/radbeacon/usb.rb', line 61

def mac_address
  @mac_address
end

#majorObject

Returns the value of attribute major.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def major
  @major
end

#minorObject

Returns the value of attribute minor.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def minor
  @minor
end

#powerObject

Returns the value of attribute power.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def power
  @power
end

#tx_powerObject

Returns the value of attribute tx_power.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def tx_power
  @tx_power
end

#uuidObject

Returns the value of attribute uuid.



62
63
64
# File 'lib/radbeacon/usb.rb', line 62

def uuid
  @uuid
end

Class Method Details

.create_if_valid(device) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/radbeacon/usb.rb', line 64

def self.create_if_valid(device)
  # Check everything
  required_attrs = [GATT_DEV_MODEL, GATT_DEV_ID, GATT_FWVERSION, GATT_DEV_NAME,
    GATT_UUID, GATT_MAJOR, GATT_MINOR, GATT_POWER, GATT_TXPOWER, GATT_INTERVAL, GATT_BCTYPE]
  if required_attrs.all? { |key| device.values[key] }
    self.new(device)
  end
end

Instance Method Details

#boot_to_dfu(pin) ⇒ Object



130
131
132
133
# File 'lib/radbeacon/usb.rb', line 130

def boot_to_dfu(pin)
  dfu_commands = ["#{GATT_ACTION} #{GATT_ACTION_DFU}", "#{GATT_PIN} #{pin_to_bytes(pin)}"]
  con(dfu_commands)
end

#change_pin(new_pin, old_pin) ⇒ Object



119
120
121
122
123
# File 'lib/radbeacon/usb.rb', line 119

def change_pin(new_pin, old_pin)
  update_pin_commands = ["#{GATT_NEW_PIN} #{pin_to_bytes(new_pin)}", "#{GATT_ACTION} #{GATT_ACTION_UPDATE_PIN}",
    "#{GATT_PIN} #{pin_to_bytes(old_pin)}"]
  con(update_pin_commands)
end

#factory_reset(pin) ⇒ Object



125
126
127
128
# File 'lib/radbeacon/usb.rb', line 125

def factory_reset(pin)
  reset_commands = ["#{GATT_ACTION} #{GATT_ACTION_FACTORY_RESET}", "#{GATT_PIN} #{pin_to_bytes(pin)}"]
  con(reset_commands) && defaults
end

#lock(pin) ⇒ Object



135
136
137
138
# File 'lib/radbeacon/usb.rb', line 135

def lock(pin)
  lock_commands = ["#{GATT_ACTION} #{GATT_ACTION_LOCK}", "#{GATT_PIN} #{pin_to_bytes(pin)}"]
  con(lock_commands)
end

#save(pin) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/radbeacon/usb.rb', line 106

def save(pin)
  if self.valid?
    update_params_commands = ["#{GATT_DEV_NAME} #{text_to_bytes(@dev_name)}",
      "#{GATT_UUID} #{uuid_to_bytes(@uuid)}", "#{GATT_MAJOR} #{major_minor_to_bytes(@major)}",
      "#{GATT_MINOR} #{major_minor_to_bytes(@minor)}", "#{GATT_POWER} #{power_to_bytes(@power)}",
      "#{GATT_TXPOWER} #{TRANSMIT_POWER_VALUES[@tx_power]}", "#{GATT_INTERVAL} #{ADVERTISING_RATE_VALUES[@adv_rate]}",
      "#{GATT_BCTYPE} #{BEACON_TYPES[@beacon_type]}", "#{GATT_ACTION} #{GATT_ACTION_UPDATE_ADV}", "#{GATT_PIN} #{pin_to_bytes(pin)}"]
    con(update_params_commands)
  else
    false
  end
end

#valid?Boolean

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/radbeacon/usb.rb', line 89

def valid?
  @errors = []
  @errors << "Invalid device name" unless @dev_name.length <= 20
  @errors << "Invalid UUID" unless @uuid.match(VALID_UUID)
  @errors << "Invalid major value" unless @major.to_i.between?(0, 65535)
  @errors << "Invalid minor value" unless @minor.to_i.between?(0, 65535)
  @errors << "Invalid measured power value" unless @power.to_i.between?(-127, -1)
  @errors << "Invalid transmit power" unless TRANSMIT_POWER_VALUES.has_key?(@tx_power)
  @errors << "Invalid advertising rate" unless ADVERTISING_RATE_VALUES.has_key?(@adv_rate)
  @errors << "Invalid beacon type" unless BEACON_TYPES.has_key?(@beacon_type)
  if @errors.empty?
    true
  else
    false
  end
end