# iBBQ / Inkbird BLE Meat Thermometer
# Copyright 2026 Pigs Can Fly Labs LLC
# SPDX-License-Identifier: Apache-2.0

device:
  name: "iBBQ / Inkbird BLE Meat Thermometer"
  manufacturer: "Inkbird / Tenergy Solis / various OEMs"
  manufacturer_status: "unsupported"
  protocol: "ble"
  notes: >
    BLE BBQ/meat thermometer with 2-6 temperature probes. Sold under
    Inkbird, Tenergy Solis, and generic iBBQ brands. $15-25.

    PROTOCOL: uses custom BLE service 0xFFF0 with paired write/notify
    characteristics. Credential-based authentication is REQUIRED after
    connection — write a fixed 15-byte credential packet to 0xFFF2 before
    any other operation. Without this, the device ignores all subsequent
    commands.

    CREDENTIAL: `[0x21, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
    0xB8, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00]` written to 0xFFF2.
    This is a FIXED value — not per-device. The "authentication" is
    essentially a magic wake-up sequence, not real security.

    TEMPERATURE: uint16 LE per probe, in 0.1°C increments (divide by 10
    for °C). num_probes = data_length / 2. Arrives as notifications on
    0xFFF4 after enabling realtime mode.

    ENABLE REALTIME: write `[0x0B, 0x01, 0x00, 0x00, 0x00, 0x00]` to
    0xFFF5. The device then streams temperature notifications on 0xFFF4
    at a regular interval.

    SETTINGS COMMANDS (all to 0xFFF5):
    - Celsius mode: `[0x02, 0x00, ...]`
    - Fahrenheit mode: `[0x02, 0x01, ...]`
    - Silence alarm: `[0x04, 0xFF, 0x00, 0x00, 0x00, 0x00]`
    - Set target temp: `[0x01, probe#, low0, low1, high0, high1]`
    - Battery request: `[0x08, 0x24, 0x00, 0x00, 0x00, 0x00]`

    CHARACTERISTICS:
    - 0xFFF1 SettingsResult (notify) — responses to settings writes
    - 0xFFF2 AccountAndVerify (write) — credential auth
    - 0xFFF3 HistoryData (notify) — historical temperature data
    - 0xFFF4 RealtimeData (notify) — live temperature stream
    - 0xFFF5 SettingsData (write) — configuration commands

    DISCOVERY: advertised name "iBBQ", service UUID 0xFFF0.

    CONFIDENCE: HIGH for all UUIDs, credential packet, enable realtime,
    temperature encoding, and settings commands — sourced from
    gist.github.com/uucidl (iBBQ protocol) and github.com/gleeds/cloudbbq.

  identification:
    local_name_prefix: "iBBQ"
    service_uuids:
      - "0000fff0-0000-1000-8000-00805f9b34fb"

  discovery:
    methods:
      - type: "ble_scan"
        ble:
          local_name:
            match: "prefix"
            value: "iBBQ"
          service_uuids:
            - "0000fff0-0000-1000-8000-00805f9b34fb"
    identity:
      stable_keys: ["address"]
      display: "local_name"
    static_ip_required: false

  setup:
    required: true
    confidence: "high"
    notes: >
      REQUIRED: after connecting, write the fixed 15-byte credential
      packet to 0xFFF2 before any other operation. Then enable realtime
      on 0xFFF5 to start receiving temperature data on 0xFFF4.
    methods:
      - type: "ble_direct"
        verified: true
        description: >
          Connect, authenticate with fixed credential, enable CCCD on
          0xFFF4, enable realtime on 0xFFF5.
        ble:
          pairing_required: false
        steps:
          - action: "Power on thermometer."
            actor: "user"
            request:
              protocol: "ble_gatt"
          - action: >
              Scan for "iBBQ" name or 0xFFF0 service and connect.
            actor: "client"
          - action: >
              Write credential: [0x21,0x07,0x06,0x05,0x04,0x03,0x02,0x01,
              0xB8,0x22,0x00,0x00,0x00,0x00,0x00] to 0xFFF2.
            actor: "client"
          - action: >
              Enable notifications on 0xFFF4 (CCCD write).
            actor: "client"
          - action: >
              Enable realtime: [0x0B,0x01,0x00,0x00,0x00,0x00] to 0xFFF5.
            actor: "client"
    factory_reset:
      confidence: "low"
      effect: >
        No credential state to clear beyond power-cycling.
      procedures:
        - name: "Power cycle"
          steps:
            - action: "Remove batteries and reinsert."
              actor: "user"
              expect: "Device powers on and advertises."
    rejoin:
      in_place_supported: true
      requires_factory_reset: false
      notes: >
        The fixed credential is a wake-up, not a bond. Any client can
        reconnect by sending the credential again.
    credentials:
      wifi_passphrase_protection: "not_applicable"
      stored_on_device: []
      issued_to_client: []
      notes: >
        The 15-byte credential is a fixed magic sequence, not real auth.

services:
  - uuid: "0000fff0-0000-1000-8000-00805f9b34fb"
    name: "iBBQ Service"
    characteristics:
      - uuid: "0000fff2-0000-1000-8000-00805f9b34fb"
        name: "AccountAndVerify"
        properties: ["write"]
        notes: >
          CREDENTIAL AUTH (REQUIRED FIRST): write fixed 15-byte packet
          `[0x21, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
          0xB8, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00]` before any other
          operation.

      - uuid: "0000fff5-0000-1000-8000-00805f9b34fb"
        name: "SettingsData"
        properties: ["write"]
        notes: >
          Configuration write channel. All 6-byte packets.
        commands:
          enable_realtime:
            description: "Start live temperature stream on 0xFFF4."
            value: [0x0B, 0x01, 0x00, 0x00, 0x00, 0x00]
          set_celsius:
            description: "Set temperature unit to Celsius."
            value: [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]
          set_fahrenheit:
            description: "Set temperature unit to Fahrenheit."
            value: [0x02, 0x01, 0x00, 0x00, 0x00, 0x00]
          silence_alarm:
            description: "Silence the audible alarm."
            value: [0x04, 0xFF, 0x00, 0x00, 0x00, 0x00]
          request_battery:
            description: "Request battery status."
            value: [0x08, 0x24, 0x00, 0x00, 0x00, 0x00]
          set_target_temp:
            description: >
              Set target temperature alarm for a probe.
              [0x01, probe_num, low_lo, low_hi, high_lo, high_hi]
              Temperatures as signed int16 in 0.1°C increments.
            template: [0x01, "{probe}", "{low_lo}", "{low_hi}", "{high_lo}", "{high_hi}"]
            parameters:
              probe: { type: "uint8", min: 1, max: 6 }
              low_lo: { type: "uint8" }
              low_hi: { type: "uint8" }
              high_lo: { type: "uint8" }
              high_hi: { type: "uint8" }

      - uuid: "0000fff4-0000-1000-8000-00805f9b34fb"
        name: "RealtimeData"
        properties: ["notify"]
        notes: >
          Live temperature stream. Each notification is an array of uint16
          LE values (one per probe), each in 0.1°C. num_probes = data_length/2.
          Enable notifications (CCCD) before enabling realtime.

      - uuid: "0000fff1-0000-1000-8000-00805f9b34fb"
        name: "SettingsResult"
        properties: ["notify"]
        notes: "Responses to settings writes on 0xFFF5."

      - uuid: "0000fff3-0000-1000-8000-00805f9b34fb"
        name: "HistoryData"
        properties: ["notify"]
        notes: "Historical temperature data (if supported by model)."

entities:
  - platform: "sensor"
    name: "Temperature"
    state_characteristic: "0000fff4-0000-1000-8000-00805f9b34fb"
  - platform: "sensor"
    name: "Battery"
    state_characteristic: "0000fff1-0000-1000-8000-00805f9b34fb"
  - platform: "switch"
    name: "Alarm"
    state_characteristic: "0000fff5-0000-1000-8000-00805f9b34fb"
