Skip to main content

safera-sense-ble

Async Python library for talking to Safera Sense cooking sensors over Bluetooth Low Energy — as found in Røros Hetta cooker hoods (Safera Sense Integral) and Safera stove guards.

CI PyPI

Credits

Most of the protocol reverse engineering comes from two projects that did the heavy lifting:

This library is an independent, from-scratch implementation of that protocol, extended with findings made during its development (verified on an IFU10CR-PRO, firmware 13/75):

  • the proprietary characteristics require BLE bonding — the device answers ATT "Insufficient authentication" until paired; this library pairs on demand and retries;
  • grease filter saturation lives at byte 59 of the extended sensor report and resets via the SET_HOOD_FILTER_CHANGED command (confirmed with a before/after diff around the vendor app's filter reset);
  • the "particle index" field tracks the vendor app's PM2.5 reading (µg/m³, 0.2 µg/m³ raw resolution).

Unofficial project — not affiliated with Safera Oy or Røros Metall AS.

Features

  • Live sensor stream: subscribe to notifications (~1 Hz) parsed into a typed SensorReport — ambient/surface/pan temperature, humidity, ambient light, eCO2, tVOC, air quality index, PM2.5, stove power draw, cooking activity, alarm level, grease filter saturation, device state and error bitfields.
  • Control: hood fan speeds 1–4 (level 4 = boost), auto mode; light levels 1–3; identify; grease-filter reset.
  • Smart Cooking event log: read or subscribe to the timeline of cooking events (cooking/frying/boiling/heating started, stove alarms, button presses); clear it too.
  • Device info: model, serial, hardware/firmware revisions, Wi-Fi status (SSID, RSSI, device name).
  • Sensible precision: values are quantized to each sensor's meaningful resolution (0.1 °C temperatures, whole-percent humidity, whole lux, 0.1 µg/m³ PM2.5) so consumers don't see measurement jitter as state changes.
  • Built on bleak and bleak-retry-connector; plays well with Home Assistant's Bluetooth stack but has no Home Assistant dependency.

Installation

pip install safera-sense-ble

Usage

Find the device

Safera devices advertise the proprietary service UUID and, depending on branding, a name like Røroshetta, iSense… or Sense_…:

import asyncio
from bleak import BleakScanner
from safera_sense_ble import SAFERA_SERVICE_UUID

async def find():
    devices = await BleakScanner.discover(return_adv=True)
    for device, adv in devices.values():
        if SAFERA_SERVICE_UUID in adv.service_uuids:
            print(device.address, adv.local_name)

asyncio.run(find())

Stream sensor data

import asyncio
from bleak import BleakScanner
from safera_sense_ble import SaferaSenseClient, SensorReport

async def monitor(address: str):
    ble_device = await BleakScanner.find_device_by_address(address)
    client = SaferaSenseClient(ble_device)
    await client.connect()

    info = await client.fetch_device_info()
    print(f"Connected to {info.model} (fw {info.firmware_rev})")

    def on_report(report: SensorReport) -> None:
        print(
            f"{report.ambient_temperature:.1f} °C  "
            f"{report.humidity} %RH  "
            f"eCO2 {report.co2_ppm} ppm  "
            f"PM2.5 {report.particle_index} µg/m³  "
            f"filter {report.grease_filter} %"
        )

    # The device requires bonding for this; the client pairs on demand.
    await client.subscribe_sensor_reports(on_report)
    await asyncio.sleep(30)
    await client.disconnect()

asyncio.run(monitor("D4:6A:C8:XX:XX:XX"))

Control the hood

from safera_sense_ble import FanSpeed, LightLevel

await client.set_fan_speed(FanSpeed.LEVEL_2)   # speeds 1-4
await client.set_fan_speed(FanSpeed.BOOST)     # top step (level 4)
await client.set_fan_auto()                    # air-quality controlled
await client.set_fan_speed(FanSpeed.OFF)

await client.set_light_level(LightLevel.LEVEL_3)  # light levels 1-3
await client.set_light_level(LightLevel.OFF)
await client.toggle_light_auto()               # toggle presence-based auto

await client.identify()                        # make the device identify itself
await client.reset_grease_filter()             # after cleaning the filter

One-shot reads

report = await client.fetch_sensor_report()    # single parsed snapshot
wifi = await client.fetch_wifi_status()        # SSID, RSSI, device name, IP

Smart Cooking event log

from safera_sense_ble import CookingEvent

events = await client.fetch_event_log()        # current timeline (newest first)
for e in events:
    print(e.name, e.timestamp)                 # e.g. "frying_start", device clock

def on_events(events: list[CookingEvent]) -> None:
    if events:
        print("latest:", events[0].name)

await client.subscribe_event_log(on_events)    # notified on new events
await client.clear_event_log()                 # the app's "Clear Timeline"

Event timestamps are in device-clock seconds; correlate them with the live SensorReport.device_clock if you need wall-clock times.

See examples/monitor.py for a runnable script.

API notes

  • All methods are coroutines; the client is designed for a single long-lived connection (the device accepts one central at a time — close the vendor app while connected).
  • SensorReport.from_bytes accepts both the documented 54-byte record and the extended (~69-byte) record sent by hood-integrated devices; hood-only fields (fan_speed_raw, light_raw, grease_filter, …) are None when absent.
  • SaferaSenseClient.dump_characteristics() hex-dumps every readable characteristic — useful for decoding the remaining unknown fields (byte 58 of the sensor report, the event log, READ_SETTINGS, …); contributions welcome here and upstream.

License

MIT — see LICENSE.

Metadata

Release files for safera-sense-ble 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for safera-sense-ble 0.3.0
File Size Uploaded
safera_sense_ble-0.3.0.tar.gz 15.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for safera-sense-ble 0.3.0
File Interpreter ABI Platform
safera_sense_ble-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.7 kB

Release files / safera_sense_ble-0.3.0.tar.gz

Download URL safera_sense_ble-0.3.0.tar.gz
Size 15.6 kB
Tags Source
SHA-256 checksum
How to use checksums
afdf8cbc1a62b93a866426cd34449be1b0ea0e3503d8bd22d00f9ae09f2ec42c
BLAKE2b-256 checksum
How to use checksums
27fe4edd6dec3a2a67853eeba9456ec6ff2fce866d65b0f242cf675a51005968
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / safera_sense_ble-0.3.0-py3-none-any.whl

Download URL safera_sense_ble-0.3.0-py3-none-any.whl
Size 15.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
25667141b611bb91296234c088b55a705aaf9c9110794131db57569fe7c4b975
BLAKE2b-256 checksum
How to use checksums
ccd35fd26d832f5b94c60769f1efb67c3215190390a8fe6099d3d33cccedc3a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page