Skip to content

Commit

Permalink
Merge pull request #240 from ikalchev/v2.8.2
Browse files Browse the repository at this point in the history
V2.8.2
  • Loading branch information
ikalchev authored Apr 10, 2020
2 parents fdc2c55 + 6b6a6e4 commit feba438
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 20 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Sections
### Developers
-->

## [2.8.2] - 2020-04-10

### Added
- Add an option to select the zeroconf broadcast interface. [#239](https://github.com/ikalchev/HAP-python/pull/239)
- Allow service callbacks to handle multiple AIDs. [#237](https://github.com/ikalchev/HAP-python/pull/237)

## [2.8.1] - 2020-04-06

### Fixed
Expand Down
42 changes: 26 additions & 16 deletions pyhap/accessory_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class AccessoryDriver:
def __init__(self, *, address=None, port=51234,
persist_file='accessory.state', pincode=None,
encoder=None, loader=None, loop=None, mac=None,
listen_address=None, advertised_address=None):
listen_address=None, advertised_address=None, interface_choice=None):
"""
Initialize a new AccessoryDriver object.
Expand Down Expand Up @@ -172,6 +172,9 @@ def __init__(self, *, address=None, port=51234,
This can be used to announce an external address from behind a NAT.
If not given, the value of the address parameter will be used.
:type advertised_address: str
:param interface_choice: The zeroconf interfaces to listen on.
:type InterfacesType: [InterfaceChoice.Default, InterfaceChoice.All]
"""
if sys.platform == 'win32':
self.loop = loop or asyncio.ProactorEventLoop()
Expand All @@ -187,7 +190,10 @@ def __init__(self, *, address=None, port=51234,

self.accessory = None
self.http_server_thread = None
self.advertiser = Zeroconf()
if interface_choice is not None:
self.advertiser = Zeroconf(interfaces=interface_choice)
else:
self.advertiser = Zeroconf()
self.persist_file = os.path.expanduser(persist_file)
self.encoder = encoder or AccessoryEncoder()
self.topics = {} # topic: set of (address, port) of subscribed clients
Expand Down Expand Up @@ -642,10 +648,12 @@ def set_characteristics(self, chars_query, client_addr):

if HAP_PERMISSION_NOTIFY in cq:
char_topic = get_topic(aid, iid)
logger.debug('Subscribed client %s to topic %s',
client_addr, char_topic)
logger.debug(
"Subscribed client %s to topic %s", client_addr, char_topic
)
self.subscribe_client_topic(
client_addr, char_topic, cq[HAP_PERMISSION_NOTIFY])
client_addr, char_topic, cq[HAP_PERMISSION_NOTIFY]
)

if HAP_REPR_VALUE in cq:
# TODO: status needs to be based on success of set_value
Expand All @@ -658,18 +666,20 @@ def set_characteristics(self, chars_query, client_addr):
service = char.service

if service and service.setter_callback:
service_callbacks.setdefault(
service.display_name,
[service.setter_callback, {}]
service_name = service.display_name
service_callbacks.setdefault(aid, {})
service_callbacks[aid].setdefault(
service_name, [service.setter_callback, {}]
)
service_callbacks[service.display_name][
SERVICE_CALLBACK_DATA
][char.display_name] = cq[HAP_REPR_VALUE]

for service_name in service_callbacks:
service_callbacks[service_name][SERVICE_CALLBACK](
service_callbacks[service_name][SERVICE_CALLBACK_DATA]
)
service_callbacks[aid][service_name][SERVICE_CALLBACK_DATA][
char.display_name
] = cq[HAP_REPR_VALUE]

for aid in service_callbacks:
for service_name in service_callbacks[aid]:
service_callbacks[aid][service_name][SERVICE_CALLBACK](
service_callbacks[aid][service_name][SERVICE_CALLBACK_DATA]
)

def signal_handler(self, _signal, _frame):
"""Stops the AccessoryDriver for a given signal.
Expand Down
2 changes: 1 addition & 1 deletion pyhap/const.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""This module contains constants used by other modules."""
MAJOR_VERSION = 2
MINOR_VERSION = 8
PATCH_VERSION = 1
PATCH_VERSION = 2
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 5)
Expand Down
34 changes: 31 additions & 3 deletions tests/test_accessory_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pytest

from pyhap.accessory import STANDALONE_AID, Accessory
from pyhap.accessory import STANDALONE_AID, Accessory, Bridge
from pyhap.accessory_driver import AccessoryDriver
from pyhap.characteristic import (HAP_FORMAT_INT, HAP_PERMISSION_READ,
PROP_FORMAT, PROP_PERMISSIONS,
Expand Down Expand Up @@ -55,7 +55,9 @@ def test_persist_load():


def test_service_callbacks(driver):
acc = Accessory(driver, 'TestAcc')
bridge = Bridge(driver,"mybridge")
acc = Accessory(driver, 'TestAcc', aid=2)
acc2 = Accessory(driver, 'TestAcc2', aid=3)

service = Service(uuid1(), 'Lightbulb')
char_on = Characteristic('On', uuid1(), CHAR_PROPS)
Expand All @@ -68,10 +70,27 @@ def test_service_callbacks(driver):
service.setter_callback = mock_callback

acc.add_service(service)
driver.add_accessory(acc)
bridge.add_accessory(acc)

service2 = Service(uuid1(), 'Lightbulb')
char_on2 = Characteristic('On', uuid1(), CHAR_PROPS)
char_brightness2 = Characteristic('Brightness', uuid1(), CHAR_PROPS)

service2.add_characteristic(char_on2)
service2.add_characteristic(char_brightness2)

mock_callback2 = MagicMock()
service2.setter_callback = mock_callback2

acc2.add_service(service2)
bridge.add_accessory(acc2)

char_on_iid = char_on.to_HAP()[HAP_REPR_IID]
char_brightness_iid = char_brightness.to_HAP()[HAP_REPR_IID]
char_on2_iid = char_on2.to_HAP()[HAP_REPR_IID]
char_brightness2_iid = char_brightness2.to_HAP()[HAP_REPR_IID]

driver.add_accessory(bridge)

driver.set_characteristics({
HAP_REPR_CHARS: [{
Expand All @@ -82,9 +101,18 @@ def test_service_callbacks(driver):
HAP_REPR_AID: acc.aid,
HAP_REPR_IID: char_brightness_iid,
HAP_REPR_VALUE: 88
}, {
HAP_REPR_AID: acc2.aid,
HAP_REPR_IID: char_on2_iid,
HAP_REPR_VALUE: True
}, {
HAP_REPR_AID: acc2.aid,
HAP_REPR_IID: char_brightness2_iid,
HAP_REPR_VALUE: 12
}]
}, "mock_addr")

mock_callback2.assert_called_with({'On': True, 'Brightness': 12})
mock_callback.assert_called_with({'On': True, 'Brightness': 88})


Expand Down

0 comments on commit feba438

Please sign in to comment.