bluetooth_clocks package#
Set and get the time on various Bluetooth clocks.
This project offers a way to easily recognize Bluetooth Low Energy clocks from their advertisements and has a device-independent API to set and get the time on them.
- class bluetooth_clocks.BluetoothClock(device: BLEDevice)[source]#
Bases:
ABC
Abstract class that represents the definition of a Bluetooth clock.
Support for every type of Bluetooth clock is implemented as a separate subclass by giving the class variables a value and/or by overriding methods or implementing abstract methods of this class.
- CHAR_UUID: ClassVar[UUID]#
The UUID of the characteristic used to read/write the time.
- LOCAL_NAME: ClassVar[str | None]#
The local name used to recognize this type of device.
This is
None
if the local name isn’t used to recognize the device.
- LOCAL_NAME_STARTS_WITH: ClassVar[bool | None]#
Whether the local name should start with LOCAL_NAME.
True
if the start of LOCAL_NAME is used to recognize this type of device.False
if the local name should exactly match LOCAL_NAME. This isNone
if the local name isn’t used to recognize the device.
- SERVICE_UUID: ClassVar[UUID]#
The UUID of the service used to read/write the time.
- TIME_GET_FORMAT: ClassVar[str | None]#
The format string to convert bytes read from the device to a time.
This is
None
if the device doesn’t support reading the time.
- WRITE_WITH_RESPONSE: ClassVar[bool]#
True
if the bytes to set the time should use write with response.
- classmethod create_from_advertisement(device: BLEDevice, advertisement_data: AdvertisementData) BluetoothClock [source]#
Create object of a
BluetoothClock
subclass from advertisement data.This is a factory method that you use if you don’t know the exact device type beforehand. This method automatically recognizes the device type and creates an object of the corresponding subclass.
- Parameters:
device (BLEDevice) – The Bluetooth device.
advertisement_data (AdvertisementData) – The advertisement data.
- Raises:
UnsupportedDeviceError – If the device with address address isn’t supported.
- Returns:
An object of the subclass corresponding to the recognized device type.
- Return type:
- abstract get_bytes_from_time(timestamp: float, ampm: bool = False) bytes [source]#
Generate the bytes to set the time on this device.
Override this method in a subclass to implement the device’s time format.
- Parameters:
- Returns:
The bytes needed to set the time of the device to timestamp.
- Return type:
Example
>>> from bluetooth_clocks.devices.thermopro import TP393 >>> from bleak.backends.device import BLEDevice >>> from datetime import datetime >>> clock = TP393(BLEDevice("10:76:36:14:2A:3D", "TP393 (2A3D)", {}, -67)) >>> timestamp = datetime.fromisoformat("2023-01-07 17:32:50").timestamp() >>> clock.get_bytes_from_time(timestamp, ampm=True).hex() 'a517010711203206005a'
- async get_time() float [source]#
Get the time of the Bluetooth clock.
- Raises:
TimeNotReadableError – If the device doesn’t support getting the time.
- Returns:
The time of the Bluetooth clock.
- Return type:
- get_time_from_bytes(time_bytes: bytes) float [source]#
Convert bytes read from a device to a timestamp.
Override this method in a subclass for a device that supports getting the time.
- Parameters:
time_bytes (bytes) – The raw bytes read from the device.
- Raises:
InvalidTimeBytesError – If time_bytes don’t have the right format.
TimeNotReadableError – If the device doesn’t support getting the time.
- Returns:
The time encoded as a Unix timestamp.
- Return type:
Example
>>> from bluetooth_clocks.devices.xiaomi import LYWSD02 >>> from bleak.backends.device import BLEDevice >>> from datetime import datetime >>> clock = LYWSD02(BLEDevice("E7:2E:00:B1:38:96", "", {}, -67)) >>> timestamp = clock.get_time_from_bytes( ... bytes([0xdd, 0xbc, 0xb9, 0x63, 0x00])) >>> print(datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")) 2023-01-07 18:41:33
- classmethod is_readable() bool [source]#
Test whether you can read the time from this device.
- Returns:
True
if this device supports reading the time,False
otherwise.- Return type:
Example
>>> from bluetooth_clocks.devices.xiaomi import LYWSD02 >>> from bluetooth_clocks.devices.qingping import CGC1 >>> LYWSD02.is_readable() True >>> CGC1.is_readable() False
- classmethod recognize(device: BLEDevice, advertisement_data: AdvertisementData) bool [source]#
Recognize this device type from advertisement data.
By default this checks whether the advertisement data has a local name that is equal to or starts with LOCAL_NAME, by calling
recognize_from_local_name()
.Override this method in a subclass if the device type should be recognized in another way from advertisement data.
- Parameters:
device (BLEDevice) – The Bluetooth device.
advertisement_data (AdvertisementData) – The advertisement data.
- Returns:
True
if this subclass ofBluetoothClock
recognizes the device,False
otherwise.- Return type:
- classmethod recognize_from_local_name(local_name: str | None) bool [source]#
Recognize the device from an advertised local name.
This is a helper method that subclasses can use to implement their
recognize()
method.- Parameters:
local_name (str | None = None) – The local name of the device, or
None
if it doesn’t advertise its local name.- Returns:
True
if this subclass ofBluetoothClock
recognizes the device from its local name local_name,False
otherwise.- Return type:
- classmethod recognize_from_service_uuids(service_uuids: list[str] | None) bool [source]#
Recognize this device type from service UUIDs.
This is a helper method that subclasses can use to implement their
recognize()
method.- Parameters:
service_uuids (list[str] | None = None) – Service UUIDs of the device, or
None
if the device doesn’t advertise service UUIDs.- Returns:
True
if this subclass ofBluetoothClock
recognizes the device from the service UUIDs in service_uuids,False
otherwise.- Return type:
- bluetooth_clocks.MICROSECONDS = 1000000#
The number of microseconds in a second.
You can use this constant in subclasses of
BluetoothClock
.
- bluetooth_clocks.SECONDS_IN_HOUR = 3600#
The number of seconds in an hour.
You can use this constant in subclasses of
BluetoothClock
.
- bluetooth_clocks.supported_devices() list[str] [source]#
Get a list of names of supported devices.
Example
>>> from bluetooth_clocks import supported_devices >>> "ThermoPro TP393" in supported_devices() True
Subpackages#
- bluetooth_clocks.devices package
- Submodules
- bluetooth_clocks.devices.current_time_service module
CurrentTimeService
CurrentTimeService.CHAR_UUID
CurrentTimeService.DEVICE_TYPE
CurrentTimeService.SERVICE_UUID
CurrentTimeService.TIME_GET_FORMAT
CurrentTimeService.TIME_SET_FORMAT
CurrentTimeService.WRITE_WITH_RESPONSE
CurrentTimeService.get_bytes_from_time()
CurrentTimeService.get_time_from_bytes()
CurrentTimeService.recognize()
InfiniTime
- bluetooth_clocks.devices.pvvx module
- bluetooth_clocks.devices.qingping module
- bluetooth_clocks.devices.thermopro module
- bluetooth_clocks.devices.xiaomi module
Submodules#
bluetooth_clocks.exceptions module#
Module with exceptions raised by this library.
- exception bluetooth_clocks.exceptions.BluetoothClocksError[source]#
Bases:
Exception
Base class for all exceptions raised by this library.
- exception bluetooth_clocks.exceptions.InvalidTimeBytesError[source]#
Bases:
BluetoothClocksError
Exception raised when bytes read from a device don’t have the right format.
- exception bluetooth_clocks.exceptions.TimeNotReadableError[source]#
Bases:
BluetoothClocksError
Exception raised when reading the time on a device that doesn’t support this.
- exception bluetooth_clocks.exceptions.UnsupportedDeviceError[source]#
Bases:
BluetoothClocksError
Exception raised when a device is not supported.
bluetooth_clocks.scanners module#
Module with functions to scan for Bluetooth clocks.
- async bluetooth_clocks.scanners.discover_clocks(callback: Callable[[BluetoothClock], None], scan_duration: float = 5.0) None [source]#
Discover Bluetooth clocks.
- Parameters:
callback (Callable[[BluetoothClock], None]) – Function to call when a clock has been discovered. This function gets passed the discovered
BluetoothClock
object as its argument.scan_duration (float) – The scan duration for discovering devices. Defaults to 5 seconds.
- async bluetooth_clocks.scanners.find_clock(address: str, scan_duration: float = 5.0) BluetoothClock | None [source]#
Get BluetoothClock object from Bluetooth address.
- Parameters:
- Raises:
UnsupportedDeviceError – If the device with address address isn`t supported.
- Returns:
A
BluetoothClock
object for the device, orNone
if the device isn’t found.- Return type:
BluetoothClock | None