Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smangelsdorf/c17720ce1baddf11d5e61a7a0bb6834f to your computer and use it in GitHub Desktop.
Save smangelsdorf/c17720ce1baddf11d5e61a7a0bb6834f to your computer and use it in GitHub Desktop.
ibbq-thermometer-protocol

Example devices

  • Inkbird IBT-2X
  • Inkbird IBT-4XS
  • EasyBBQ FCCID: FCC ID 2AI4MPRO3 (SHENZHEN HYPERSYNES CO.,LTD Smart Wireless Thermometer PRO3)

Properties

  • @ConnectTimeout: 60 seconds
  • @BatteryPollingInterval: 5 minutes

The iBBQ is a Bluetooth LE Gatt Device

@DeviceName: iBBQ

Standard Descriptor:

  • @ClientCharacteristicConfigurationDescriptor: @uuid16{0x2902}

Its main service at @uuid16{0xfff0} contains the following characteristics:

  • @SettingsResult: @uuid16{0xfff1} @notify returns results from control messages
  • @AccountAndVerify: @uuid16{0xfff2} @write deals with the pairing process
  • @HistoryData: @uuid16{0xfff3} @notify is not yet properly documented
  • @RealtimeData: @uuid16{0xfff4} @notify returns the results from probes
  • @SettingsData: @uuid16{0xfff5} @write is where control messages are sent

Some messages

Here are some hardcoded messages:

  • @CredentialsMessage: (:byte[]) { 0x21, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0xb8, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00}
  • @RealtimeDataEnableMessage: (:byte[]) { 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00}
  • @UnitsFahrenheitMessage: (:byte[]) { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00}
  • @UnitsCelsiusMessage: (:byte[]) { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}
  • @RequestBatteryLevelMessage: (:byte[]) { 0x08, 0x24, 0x00, 0x00, 0x00, 0x00 }

A message exists to set target temperatures (low and high, the closest of which will be displayed on the screen)

  • @SetTargetTempMessage: (:byte[]) { 0x01, probe-nr, low[0:7bits], low[8:15bits], high[0:7bits], high[8:15bits] }
    • probe-nr is the probe to select, from 0 onwwards
    • low is a int16 signed integer for the lower temperature, in 10^-1 Celsius
    • high is a int16 signed integer for the higher temperature, in 10^-1 Celsius
initiate-login :: 
  write @CredentialsMessage to characteristic @AccountAndVerify
enable-realtime-data ::
  enable notifications on @ClientCharacteristicConfigurationDescriptor
  write @RealtimeDataEnableMessage to characteristic @SettingsData
set-unit :: Fahrenheit or Celsius
  when Fahrenheit write @UnitsFahrenheitMessage to characteristic @SettingsData
  when Celsius    write @UnitsCelsiusMessage to characteristic @SettingsData
request-battery-level ::
  write @RequestBatteryLevelMessage to characteristic @SettingsData
set-target-temp ::
  write @SetTargetTempMessage to characteristic @SettingsData

When settings are written to @SettingsData, results are received on @SettingsResult

When request-battery-level has been sent, @SettingsResult will receive data which can be parsed as:

struct BatteryLevels {
  header: uint8 = data[0], // header == 0x24
  currentVoltage: uint16 = data[1] | data[2] << 8, // up to maxVoltage
  maxVoltage: uint16 = data[3] | data[4] << 8, // if 0 maxVoltage is 6550
}

When enable-realtime-data has been sent, @RealtimeData will receive data which can be parsed as:

  num_probes = sizeof(data)/sizeof(uint16)
  probes: uint16[num_probes]
  with 0 < i < num_probes:  
    probes[i] : uint16 = data[2*i] | data[2*i + 1] << 8

There's an history data end-point, but the format is unknown.

Alarm
  • Device: IBT-4XS
  • @SilenceAlarmMessage: (:byte[]) { 0x04, 0xff, 0x00, 0x00, 0x00, 0x00 }

Device alarm can be silenced by sending @SilenceAlarmMessage to the @SettingsData characteristic.

When an alarm is silenced by the user pressing the device's button, @SilenceAlarmMessage is received on @SettingsResult

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment