Welcome to HAP-python’s documentation!¶
This documentation contains everything you need to know about HAP-python.
Getting Help¶
Having Trouble? Post an issue on the GitHub repo, with as much information as possible about your issue.
First Steps¶
HAP-python at a glance¶
HAP-python is an application framework to build out Accessories or Bridges for Apple’s HomeKit protocol.
Need to fill in the rest.
Installation Guide¶
Before We Begin¶
HAP-python requires Python 3.4+. This guide will cover the current version of Raspbian and Ubuntu LTS. It is somewhat safe to assume the process for newer versions of Ubuntu will work.
Installing Pre-Requisites¶
Raspbian Stretch¶
As a prerequisite, you will need Avahi/Bonjour installed (due to zeroconf
package):
sudo apt install libavahi-compat-libdnssd-dev
Ubuntu 16.04 LTS¶
Same with Raspbian, we will need to install Avahi/Bonjour, but a fresh 16.04 install will
require the python3-dev
package as well:
sudo apt install libavahi-compat-libdnssd-dev python3-dev
Installing HAP-python¶
Make a directory for your project, and cd
into it:
~ $ mkdir hk_project
~ $ cd hk_project
~/hk_project $
It is best to use a virtualenv for most Python projects, we can use one here as well.
Make sure that you have the venv
module installed for Python 3:
sudo apt install python3-venv
To create a virtualenv and activate it, simply run these commands inside your project directory:
python3 -m venv venv
source venv/bin/activate
Because we used a Python 3 virtualenv and activated it, we can install HAP-python
with pip
:
pip install HAP-python
Tutorials¶
Need to fill in
Examples¶
Need to fill in
- HAP-python at a glance
- Brief explanation of HAP-python, and the possible use cases.
- Installation Guide
- How to install HAP-python on a Debian based system, such as a Raspberry Pi, or Ubuntu.
- Tutorials
- Get started building your first HomeKit Accessory.
- Examples
- A set of prebuilt accessories to either build your own class around, or to use as a starting point into your own custom Accessory class.
API Reference¶
API Index¶
Accessory¶
Base class for HAP Accessories.
-
class
pyhap.accessory.
Accessory
(driver, display_name, aid=None, iid_manager=None)[source]¶ A representation of a HAP accessory.
Inherit from this class to build your own accessories.
-
add_info_service
()[source]¶ Helper method to add the required AccessoryInformation service.
Called in __init__ to be sure that it is the first service added. May be overridden.
-
add_preload_service
(service, chars=None, unique_id=None)[source]¶ Create a service with the given name and add it to this acc.
-
add_protocol_version_service
()[source]¶ Helper method to add the required HAP Protocol Information service
-
add_service
(*servs)[source]¶ Add the given services to this Accessory.
This also assigns unique IIDS to the services and their Characteristics.
Note
Do not add or remove characteristics from services that have been added to an Accessory, as this will lead to inconsistent IIDs.
Parameters: servs – Variable number of services to add to this Accessory. Type: Service
-
available
¶ Accessory is available.
If available is False, get_characteristics will return SERVICE_COMMUNICATION_FAILURE for the accessory which will show as unavailable.
Expected to be overridden.
-
get_characteristic
(aid, iid)[source]¶ Get the characteristic for the given IID.
The AID is used to verify if the search is in the correct accessory.
-
get_service
(name)[source]¶ Return a Service with the given name.
A single Service is returned even if more than one Service with the same name are present.
Parameters: name (str) – The display_name of the Service to search for. Returns: A Service with the given name or None if no such service exists in this Accessory. Return type: Service
-
publish
(value, sender, sender_client_addr=None, immediate=False)[source]¶ Append AID and IID of the sender and forward it to the driver.
Characteristics call this method to send updates.
Parameters: - data (dict) – Data to publish, usually from a Characteristic.
- sender – The Service or Characteristic from which the call originated.
Type:
-
run
()[source]¶ Called when the Accessory should start doing its thing.
Called when HAP server is running, advertising is set, etc. Can be overridden with a normal or async method.
-
static
run_at_interval
(seconds)[source]¶ Decorator that runs decorated method every x seconds, until stopped.
Can be used with normal and async methods.
@Accessory.run_at_interval(3) def run(self): print("Hello again world!")
Parameters: seconds (float) – The amount of seconds to wait for the event to be set. Determines the interval on which the decorated method will be called.
-
set_info_service
(firmware_revision=None, manufacturer=None, model=None, serial_number=None)[source]¶ Quick assign basic accessory information.
-
setup_message
()[source]¶ Print setup message to console.
For QRCode base36, pyqrcode are required. Installation through pip install HAP-python[QRCode]
-
stop
()[source]¶ Called when the Accessory should stop what is doing and clean up any resources.
Can be overridden with a normal or async method.
-
AccessoryDriver¶
Accessory Driver class to host an Accessory.
-
class
pyhap.accessory_driver.
AccessoryDriver
(*, address=None, port=51234, persist_file='accessory.state', pincode=None, encoder=None, loader=None, loop=None, mac=None, listen_address=None, advertised_address=None, interface_choice=None, async_zeroconf_instance=None, zeroconf_server=None)[source]¶ An AccessoryDriver mediates between incoming requests from the HAPServer and the Accessory.
The driver starts and stops the HAPServer, the mDNS advertisements and responds to events from the HAPServer.
-
accessories_hash
¶ Hash the get_accessories response to track configuration changes.
-
async_send_event
(topic, data, sender_client_addr, immediate)[source]¶ Send an event to a client.
Must be called in the event loop
-
async_start
()[source]¶ Starts the accessory.
- Call the accessory’s run method.
- Start handling accessory events.
- Start the HAP server.
- Publish a mDNS advertisement.
- Print the setup QR code if the accessory is not paired.
All of the above are started in separate threads. Accessory thread is set as daemon.
-
async_subscribe_client_topic
(client, topic, subscribe=True)[source]¶ (Un)Subscribe the given client from the given topic.
This method must be run in the event loop.
Parameters: - client (tuple <str, int>) – A client (address, port) tuple that should be subscribed.
- topic (str) – The topic to which to subscribe.
- subscribe (bool) – Whether to subscribe or unsubscribe the client. Both subscribing an already subscribed client and unsubscribing a client that is not subscribed do nothing.
-
async_update_advertisement
()[source]¶ Updates the mDNS service info for the accessory from the event loop.
-
config_changed
()[source]¶ Notify the driver that the accessory’s configuration has changed.
Persists the accessory, so that the new configuration is available on restart. Also, updates the mDNS advertisement, so that iOS clients know they need to fetch new data.
-
connection_lost
(client)[source]¶ Called when a connection is lost to a client.
This method must be run in the event loop.
Parameters: client (tuple <str, int>) – A client (address, port) tuple that should be unsubscribed.
-
finish_pair
()[source]¶ Finishing pairing or unpairing.
Updates the accessory and updates the mDNS service.
The mDNS announcement must not be updated until AFTER the final pairing response is sent or homekit will see that the accessory is already paired and assume it should stop pairing.
-
get_accessories
()[source]¶ Returns the accessory in HAP format.
Returns: An example HAP representation is: { "accessories": [ "aid": 1, "services": [ "iid": 1, "type": ..., "characteristics": [{ "iid": 2, "type": ..., "description": "CurrentTemperature", ... }] ] ] }
Return type: dict
-
get_characteristics
(char_ids)[source]¶ Returns values for the required characteristics.
Parameters: char_ids (list<str>) – A list of characteristic “paths”, e.g. “1.2” is aid 1, iid 2. Returns: Status success for each required characteristic. For example: { "characteristics: [{ "aid": 1, "iid": 2, "status" 0 }] }
Return type: dict
-
pair
(client_username_bytes: bytes, client_public: bytes, client_permissions: bytes) → bool[source]¶ Called when a client has paired with the accessory.
Persist the new accessory state.
Parameters: - client_username_bytes (bytes) – The client username bytes.
- client_public (bytes) – The client’s public key.
- client_permissions (bytes (int)) – The client’s permissions.
Returns: Whether the pairing is successful.
Return type: bool
-
prepare
(prepare_query, client_addr)[source]¶ Called from
HAPServerHandler
when iOS wants to prepare a write.Parameters: prepare_query – A prepare query. For example: { "ttl": 10000, # in milliseconds "pid": 12345678, }
-
publish
(data, sender_client_addr=None, immediate=False)[source]¶ Publishes an event to the client.
The publishing occurs only if the current client is subscribed to the topic for the aid and iid contained in the data.
Parameters: data (dict) – The data to publish. It must at least contain the keys “aid” and “iid”.
-
set_characteristics
(chars_query, client_addr)[source]¶ Called from
HAPServerHandler
when iOS configures the characteristics.Parameters: chars_query – A configuration query. For example: { "characteristics": [{ "aid": 1, "iid": 2, "value": False, # Value to set "ev": True # (Un)subscribe for events from this characteristics. }] }
-
signal_handler
(_signal, _frame)[source]¶ Stops the AccessoryDriver for a given signal.
An AccessoryDriver can be registered as a signal handler with this method. For example, you can register it for a KeyboardInterrupt as follows: >>> import signal >>> signal.signal(signal.SIGINT, anAccDriver.signal_handler)
Now, when the user hits Ctrl+C, the driver will stop its accessory, the HAP server and everything else that needs stopping and will exit gracefully.
-
start
()[source]¶ Start the event loop and call start_service.
Pyhap will be stopped gracefully on a KeyBoardInterrupt.
-
Bridge¶
Bridge Class to host multiple HAP Accessories.
-
class
pyhap.accessory.
Bridge
(driver, display_name, iid_manager=None)[source]¶ A representation of a HAP bridge.
A Bridge can have multiple Accessories.
-
add_accessory
(acc)[source]¶ Add the given
Accessory
to thisBridge
.Every
Accessory
in aBridge
must have an AID and this AID must be unique among all theAccessories
in the same Bridge. If the givenAccessory
’s AID is None, a unique AID will be assigned to it. Otherwise, it will be verified that the AID is not the standalone aid (STANDALONE_AID
) and that there is no otherAccessory
already in thisBridge
with that AID.Note
A
Bridge
cannot be added to anotherBridge
.Parameters: acc (Accessory) – The Accessory
to be bridged.Raises: ValueError – When the given Accessory
is of categoryCATEGORY_BRIDGE
or if the AID of theAccessory
clashes with anotherAccessory
already in thisBridge
.
-
Characteristic¶
Characteristic Base class for a HAP Accessory Service
.
See also
pyhap.service.Service
-
class
pyhap.characteristic.
Characteristic
(display_name, type_id, properties, allow_invalid_client_values=False, unique_id=None)[source]¶ Represents a HAP characteristic, the smallest unit of the smart home.
A HAP characteristic is some measurement or state, like battery status or the current temperature. Characteristics are contained in services. Each characteristic has a unique type UUID and a set of properties, like format, min and max values, valid values and others.
-
client_update_value
(value, sender_client_addr=None)[source]¶ Called from broker for value change in Home app.
Change self.value to value and call callback.
-
classmethod
from_dict
(name, json_dict, from_loader=False)[source]¶ Initialize a characteristic object from a dict.
Parameters: json_dict (dict) – Dictionary containing at least the keys Format, Permissions and UUID
-
get_value
()[source]¶ This is to allow for calling getter_callback
Returns: Current Characteristic Value
-
notify
(sender_client_addr=None)[source]¶ Notify clients about a value change. Sends the value.
See also
accessory.publish
See also
accessory_driver.publish
-
override_properties
(properties=None, valid_values=None)[source]¶ Override characteristic property values and valid values.
Parameters: - properties (dict) – Dictionary with values to override the existing properties. Only changed values are required.
- valid_values (dict) – Dictionary with values to override the existing valid_values. Valid values will be set to new dictionary.
-
set_value
(value, should_notify=True)[source]¶ Set the given raw value. It is checked if it is a valid value.
If not set_value will be aborted and an error message will be displayed.
Characteristic.setter_callback You may also define a setter_callback on the Characteristic. This will be called with the value being set as the arg.
See also
Characteristic.value
Parameters: - value (Depends on properties["Format"]) – The value to assign as this Characteristic’s value.
- should_notify (bool) – Whether a the change should be sent to subscribed clients. Notify will be performed if the broker is set.
-
Loader¶
Useful for creating a Service
or Characteristic
.
-
class
pyhap.loader.
Loader
(path_char='/home/docs/checkouts/readthedocs.org/user_builds/hap-python/checkouts/latest/pyhap/resources/characteristics.json', path_service='/home/docs/checkouts/readthedocs.org/user_builds/hap-python/checkouts/latest/pyhap/resources/services.json')[source]¶ Looks up type descriptions based on a name.
See also
pyhap/resources/services.json
See also
pyhap/resources/characteristics.json
Service¶
Service Base class for a HAP Accessory
.
-
class
pyhap.service.
Service
(type_id, display_name=None, unique_id=None)[source]¶ A representation of a HAP service.
A Service contains multiple characteristics. For example, a TemperatureSensor service has the characteristic CurrentTemperature.
-
configure_char
(char_name, properties=None, valid_values=None, value=None, setter_callback=None, getter_callback=None)[source]¶ Helper method to return fully configured characteristic.
-
classmethod
from_dict
(name, json_dict, loader)[source]¶ Initialize a service object from a dict.
Parameters: json_dict (dict) – Dictionary containing at least the keys UUID and RequiredCharacteristics
-
get_characteristic
(name)[source]¶ Return a Characteristic object by the given name from this Service.
Parameters: name (str) – The name of the characteristic to search for. :raise ValueError if characteristic is not found.
Returns: A characteristic with the given name. Return type: Characteristic
-
State¶
-
class
pyhap.state.
State
(*, address: Union[str, List[str], None] = None, mac=None, pincode=None, port=None)[source]¶ Class to store all (semi-)static information.
That includes all needed for setup of driver and pairing.
-
add_paired_client
(client_username_bytes: bytes, client_public: bytes, perms: bytes) → None[source]¶ Add a given client to dictionary of paired clients.
Parameters: - client_username_bytes (bytes) – The client’s user id bytes.
- client_public (bytes) – The client’s public key (not the session public key).
-
address
¶ Return the first address for backwards compat.
-
paired
¶ Return if main accessory is currently paired.
-
Util¶
Utilities Module
-
pyhap.util.
event_wait
(event, timeout)[source]¶ Wait for the given event to be set or for the timeout to expire.
Parameters: - event (asyncio.Event) – The event to wait for.
- timeout (float) – The timeout for which to wait, in seconds.
Returns: event.is_set()
Return type: bool
-
pyhap.util.
generate_mac
()[source]¶ Generates a fake mac address used in broadcast.
Returns: MAC address in format XX:XX:XX:XX:XX:XX Return type: str
-
pyhap.util.
generate_pincode
()[source]¶ Generates a random pincode.
Returns: pincode in format xxx-xx-xxx
Return type: bytearray
-
pyhap.util.
generate_setup_id
()[source]¶ Generates a random Setup ID for an
Accessory
orBridge
.Used in QR codes and the setup hash.
Returns: 4 digit alphanumeric code. Return type: str
-
pyhap.util.
get_local_address
() → str[source]¶ Grabs the local IP address using a socket.
Returns: Local IP Address in IPv4 format. Return type: str
-
pyhap.util.
iscoro
(func)[source]¶ Check if the function is a coroutine or if the function is a
functools.partial
, check the wrapped function for the same.
- API Index
- API documentation for HAP-python.