Skip to main content

Holman Python SDK

Holman CO3015 and BTX1 are Bluetooth tap timers made by Holman.

The Holman Python SDK for Linux allows you to integrate your Holman(s) into any type of Linux application or script that can execute Python code.

BX2 MK1 (CO3112) is also recognized by its exact advertised name BX2. start(runtime=1, zone=2) selects its second outlet; zone 1 remains the default. For example: holmanctl --connect AA:BB:CC:DD:EE:FF --run 1 --zone 2. holmanctl --connect AA:BB:CC:DD:EE:FF --stop retains the all-off command. The newer BX2 model has not been tested.

Prerequisites

The Holman SDK requires Python 3.11+ and a recent installation of BlueZ. It is tested to work fine with BlueZ 5.44, slightly older versions should however work, too.

Installation

These instructions assume a Debian-based Linux.

On Linux the BlueZ library is necessary to access your built-in Bluetooth controller or Bluetooth USB dongle. Some Linux distributions provide a more up-to-date BlueZ package, some other distributions only install older versions that don't implement all Bluetooth features needed for this SDK. In those cases you want to either update BlueZ or build it from sources.

Updating/installing BlueZ via apt-get

  1. bluetoothd --version Obtains the version of the pre-installed BlueZ. bluetoothd daemon must run at startup to expose the Bluetooth API via D-Bus.
  2. sudo apt-get install --no-install-recommends bluetooth Installs BlueZ
  3. If the installed version is too old, proceed with next step: Installing BlueZ from sources

Installing BlueZ from sources

The bluetoothd daemon provides BlueZ's D-Bus interfaces that is accessed by the Holman SDK to communicate with Holman Bluetooth tap timers. The following commands download BlueZ 5.44 sources, built them and replace any pre-installed bluetoothd daemon. It's not suggested to remove any pre-installed BlueZ package as its deinstallation might remove necessary Bluetooth drivers as well.

  1. sudo systemctl stop bluetooth
  2. sudo apt-get update
  3. sudo apt-get install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev libdbus-glib-1-dev unzip
  4. cd
  5. mkdir bluez
  6. cd bluez
  7. wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.44.tar.xz
  8. tar xf bluez-5.44.tar.xz
  9. cd bluez-5.44
  10. ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-library
  11. make
  12. sudo make install
  13. sudo ln -svf /usr/libexec/bluetooth/bluetoothd /usr/sbin/
  14. sudo install -v -dm755 /etc/bluetooth
  15. sudo install -v -m644 src/main.conf /etc/bluetooth/main.conf
  16. sudo systemctl daemon-reload
  17. sudo systemctl start bluetooth
  18. bluetoothd --version # should now print 5.44

Please note that some distributions might use a different directory for system deamons, apply step 13 only as needed.

Enabling your Bluetooth adapter

  1. echo "power on" | sudo bluetoothctl Enables your built-in Bluetooth adapter or external Bluetooth USB dongle

Using BlueZ commandline tools

BlueZ also provides an interactive commandline tool to interact with Bluetooth devices. You know that your BlueZ installation is working fine if it discovers any Bluetooth devices nearby.

sudo bluetoothctl Starts an interactive mode to talk to BlueZ

  • power on Enables the Bluetooth adapter
  • scan on Start Bluetooth device scanning and lists all found devices with MAC addresses
  • connect AA:BB:CC:DD:EE:FF Connects to a Holman tap timer with specified MAC address
  • exit Quits the interactive mode

Installing Holman Python SDK

To install Holman module and the Python3 D-Bus dependency globally, run:

sudo pip3 install holman
sudo apt-get install python3-dbus

Running the Holman control script

To test if your setup is working, run the following command. Note that it must be run as root because on Linux, Bluetooth discovery is a restricted operation.

sudo holmanctl --discover
sudo holmanctl --connect AA:BB:CC:DD:EE:FF # Replace the MAC address with your Holman's MAC address
sudo holmanctl --help # To list all available commands

To start or stop the tap from a script or cron job, add --run or --stop to --connect. holmanctl connects, writes the command, disconnects and exits: with status 0 if the tap timer accepted the command, or 1 if connecting or writing failed.

sudo holmanctl --connect AA:BB:CC:DD:EE:FF --run 10 # Run the tap for 10 minutes (1-255)
sudo holmanctl --connect AA:BB:CC:DD:EE:FF --stop   # Stop the tap

SDK Usage

Discovering nearby Holman tap timers

The SDK entry point is the TapTimerManager class. Check the following example to dicover any Holman tap timer nearby.

Please note that communication with your Bluetooth adapter happens over BlueZ's D-Bus API, hence an event loop needs to be run in order to receive all Bluetooth related events. You can start and stop the event loop via run() and stop() calls to your TapTimerManager instance.

import holman


class TapTimerManagerPrintListener(holman.TapTimerManagerListener):
    def tap_timer_discovered(self, tap_timer):
        print("Discovered Holman tap_timer", tap_timer.mac_address)


manager = holman.TapTimerManager(adapter_name="hci0")
manager.listener = TapTimerManagerPrintListener()
manager.start_discovery()
manager.run()

Connecting to a Holman tap timer and receiving user input events

Once TapTimerManager has discovered a Holman tap timer you can use the TapTimer object(s) that you retrieved from TapTimerManager.tap_timers() to connect to it. Alternatively you can create a new instance of TapTimer using the name of your Bluetooth adapter (typically hci0) and Holman's MAC address.

Make sure to assign a TapTimerListener object to the listener attribute of your TapTimer instance. It will notify you about all Holman tap timer related events such connection, disconnection and user input events.

The following example connects to a Holman tap timer manually:

import holman

manager = holman.TapTimerManager(adapter_name="hci0")

tap_timer = holman.TapTimer(mac_address="AA:BB:CC:DD:EE:FF", manager=manager)
# Use an instance of your own holman.TapTimerListener subclass
tap_timer.listener = holman.TapTimerListener()
tap_timer.connect()

manager.run()

As with Holman tap timer discovery, remember to start the Bluetooth event loop with TapTimerManager.run().

Start the tap running

Once a Holman tap timer is connected you can start the tap with TapTimer.start(runtime=1). Pass this a runtime (in minutes) for how long to run the tap.

Stop it with TapTimer.stop(). Both write to the tap timer asynchronously; your listener's timer_written() is called once the command has been accepted, or timer_write_failed(error) if it couldn't be written.

Development

The project uses uv for environment and dependency management.

uv sync                 # create .venv with the SDK and dev tools
uv run pytest           # run the tests (no Bluetooth hardware needed)
uv run ruff check .     # lint
uv run ruff format .    # format
uv run pyrefly check    # type check
uv build                # build sdist and wheel into dist/

The tests replace the gatt library with an in-memory fake (tests/conftest.py), so they don't need python3-dbus or bluetoothd. Testing against a real tap timer still requires the system setup above; to use the apt-installed python3-dbus and python3-gi from the uv environment, create it on the system interpreter they were built for, then run holmanctl from it:

sudo apt-get install python3-dbus python3-gi
uv venv --system-site-packages --python /usr/bin/python3
uv sync
sudo .venv/bin/holmanctl --discover

Support

Please open an issue.

Contributing

Contributions are welcome via pull requests. Please open an issue first in case you want to discus your possible improvements to this SDK.

License

The Holman Python SDK is available under the MIT License.

Metadata

Release files for holman 0.2.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 holman 0.2.0
File Size Uploaded Provenance Actions
holman-0.2.0.tar.gz 14.2 kB With provenance Details for holman-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for holman 0.2.0
File Interpreter ABI Platform Actions
holman-0.2.0-py3-none-any.whl Python 3 none any Details for holman-0.2.0-py3-none-any.whl

Total release size: 24.2 kB

Release files / holman-0.2.0.tar.gz

Download URL holman-0.2.0.tar.gz
Size 14.2 kB
Tags Source
SHA-256 checksum
How to use checksums
0903a6c8277ada71c5e2b7f35f643bd5c79e4a9f769144708e1e15e9239e54c3
BLAKE2b-256 checksum
How to use checksums
b1f61595b5a8f7ec0f0c1bc0303e68f6ce1a8020bc33e007773ebbfebdfef9fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

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 Nov 8, 2026.

Transparency log

Release files / holman-0.2.0-py3-none-any.whl

Download URL holman-0.2.0-py3-none-any.whl
Size 10.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b3aa3f4926832728df154318b267529d0ab65f50221ade9b9fbbfef7d6f85a93
BLAKE2b-256 checksum
How to use checksums
480e62d3b688b4360827dd09658cbe0325c30caf1c03e8d3d7c8544552bd04b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

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 Nov 8, 2026.

Transparency log

Security for holman 0.2.0

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for holman-0.2.0.tar.gz

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 Nov 8, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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