Skip to content

Instantly share code, notes, and snippets.

@uucidl
Last active August 27, 2023 22:21
Show Gist options
  • Save uucidl/b9c60b6d36d8080d085a8e3310621d64 to your computer and use it in GitHub Desktop.
Save uucidl/b9c60b6d36d8080d085a8e3310621d64 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

@p1ng0o
Copy link

p1ng0o commented Jan 10, 2021

Here what is working for me:

    async def ack_alarm(self):
        await self.__write(self.settings_handle, b'\x04\xff\x00\x00\x00\x00')

    async def write_target(self, channel, high = None, low = None):
        if low:
            low = low*10
        else:
            low = 0xf448

        if high:
            high = high*10
        else:
            high = 0xbcc

        m = bytes([1, channel, low & 0xFF, low >> 8, high & 0xFF, high >> 8])
        await self.__write(self.settings_handle, m)

There is a magic trick regarding these numbers.

write_target can ether clean the target temp, set only a temp target (meat), setup a min/max space (pit watcher).

@lukepighetti
Copy link

Would love to know if anyone has the history dump working.

@kernel610
Copy link

I have set the measurement unit using @UnitsFahrenheitMessage which sets the monitoring device appropriately; however the temp reported back is still in Celsius. Is this expected?

@atessmer
Copy link

Device: IBT-4XS

Device alarm can be silenced by sending @SilenceAlarmMessage: (:byte[]) { 0x04, 0xff, 0x00, 0x00, 0x00, 0x00 } to the @SettingsData characteristic.

Similarly, when an alarm is silenced by pressing the button on the device, it sends the same @SilenceAlarmMessage to the client via the @SettingsResult characteristic

@Pelicans-git
Copy link

Would it be possible to see a hex dump of a trace from start to receiving first temperature? That will be incredibly helpful.

@arjfca
Copy link

arjfca commented Nov 4, 2021

Hello

IBBQ & ESP32

The goal is to be able to access my Bluetooth thermometer using WIFI instead of Bluetooth BLE.

I'm loss... So many interogation. Never worked with these new protocols.

  • I did apply for a MQTT server (HiveMQ Websocket Client)

What should I look for once the code has been uploaded to a ESP32?

Once loaded, how do I confirm

  • the code is working and the thermometer is linked to my ESP32?
  • How do I access information from my phone or tablet?

For the credential.h
Do I use my actual home WIFI SSID and password or create a new one

Do I modify the code line
#include "C:\Users\Utilisateur\Documents\Arduino\libraries\InkBird_BLE2MQTT-master\src\credentials.example.h"
for
#include "C:\Users\Utilisateur\Documents\Arduino\libraries\InkBird_BLE2MQTT-master\src\credentials.h"


I had some compiling error with the original code for a ESP32. I resolved them by replacing
//#include "BLEDevice.h"
with
#include <NimBLEDevice.h> //Seem to use less memory to run the BLE

Any help will be appreciated

Martin

@Kerrdog01
Copy link

Has anyone worked this out in python? I have been trying for days and have looked up so many other examples but can't get it working. Any help would be amazing please

@Kerrdog01
Copy link

After spending just about the whole day looking for a solution I have found a working solution written by a genius!
https://github.com/8none1/pybq/blob/master/bbq.py
Just don't use the MQTT part if you don't need it. It worked the first time for me. I need to learn what they did but hopefully, it helps others!

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