Skip to content

Commit

Permalink
Merge pull request #261 from ikalchev/v2.9.0
Browse files Browse the repository at this point in the history
V2.9.0
  • Loading branch information
ikalchev authored May 29, 2020
2 parents 9875080 + 42850a9 commit fb97881
Show file tree
Hide file tree
Showing 16 changed files with 331 additions and 139 deletions.
8 changes: 6 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ matrix:
include:
- python: "3.5"
env: TOXENV=lint
# - python: "3.5"
# env: TOXENV=pylint
- python: "3.5"
env: TOXENV=pylint
- python: "3.5"
env: TOXENV=py35
- python: "3.6"
env: TOXENV=py36
- python: "3.7"
env: TOXENV=py37
- python: "3.8"
env: TOXENV=py38
- python: "3.6"
env: TOXENV=docs
before-install:
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ Sections
### Developers
-->

## [2.9.0] - 2020-05-29

### Fixed
- Fix random disconnect after upgrade to encrypted. [#253](https://github.com/ikalchev/HAP-python/pull/253)
- Convert the characteristic UUID to string only once. [#256](https://github.com/ikalchev/HAP-python/pull/256)
- Fix pairing failure - split read/write encryption upgrade. [#258](https://github.com/ikalchev/HAP-python/pull/258)
- Allow negotiated framerate to be used - add "-framerate" parameterto avfoundation. [#260](https://github.com/ikalchev/HAP-python/pull/260)

### Added
- Add support for unavailable accessories. [#252](https://github.com/ikalchev/HAP-python/pull/252)

### Developers
- Cleanup and fixes for python 3.7 and 3.8. Enable pylint in Travis. [#255](https://github.com/ikalchev/HAP-python/pull/255)

## [2.8.4] - 2020-05-12

### Fixed
Expand Down
18 changes: 13 additions & 5 deletions pyhap/accessory.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ def __init__(self, driver, display_name, aid=None):
self.aid = aid
self.display_name = display_name
self.driver = driver
self.reachable = True
self.services = []
self.iid_manager = IIDManager()

Expand All @@ -72,7 +71,18 @@ def _set_services(self):
.. deprecated:: 2.0
Initialize the service inside the accessory `init` method instead.
"""
pass

@property
def available(self):
"""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.
"""
return True

def add_info_service(self):
"""Helper method to add the required `AccessoryInformation` service.
Expand Down Expand Up @@ -270,7 +280,7 @@ def run(self):
def _repeat(func):
async def _wrapper(self, *args):
while True:
self.driver.async_add_job(func, self, *args)
await self.driver.async_add_job(func, self, *args)
if await util.event_wait(
self.driver.aio_stop_event, seconds):
break
Expand All @@ -283,14 +293,12 @@ async def run(self):
Called when HAP server is running, advertising is set, etc.
Can be overridden with a normal or async method.
"""
pass

async def stop(self):
"""Called when the Accessory should stop what is doing and clean up any resources.
Can be overridden with a normal or async method.
"""
pass

# Driver

Expand Down
52 changes: 41 additions & 11 deletions pyhap/accessory_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ 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, interface_choice=None):
listen_address=None, advertised_address=None, interface_choice=None,
zeroconf_instance=None):
"""
Initialize a new AccessoryDriver object.
Expand Down Expand Up @@ -175,6 +176,10 @@ def __init__(self, *, address=None, port=51234,
:param interface_choice: The zeroconf interfaces to listen on.
:type InterfacesType: [InterfaceChoice.Default, InterfaceChoice.All]
:param zeroconf_instance: A Zeroconf instance. When running multiple accessories or
bridges a single zeroconf instance can be shared to avoid the overhead
of processing the same data multiple times.
"""
if sys.platform == 'win32':
self.loop = loop or asyncio.ProactorEventLoop()
Expand All @@ -190,7 +195,9 @@ def __init__(self, *, address=None, port=51234,

self.accessory = None
self.http_server_thread = None
if interface_choice is not None:
if zeroconf_instance is not None:
self.advertiser = zeroconf_instance
elif interface_choice is not None:
self.advertiser = Zeroconf(interfaces=interface_choice)
else:
self.advertiser = Zeroconf()
Expand Down Expand Up @@ -455,10 +462,19 @@ def send_events(self):
#
topic, bytedata, sender_client_addr = self.event_queue.get()
subscribed_clients = self.topics.get(topic, [])
logger.debug('Send event: topic(%s), data(%s), sender_client_addr(%s)', topic, bytedata, sender_client_addr)
logger.debug(
'Send event: topic(%s), data(%s), sender_client_addr(%s)',
topic,
bytedata,
sender_client_addr
)
for client_addr in subscribed_clients.copy():
if sender_client_addr and sender_client_addr == client_addr:
logger.debug('Skip sending event to client since its the client that made the characteristic change: %s', client_addr)
logger.debug(
'Skip sending event to client since '
'its the client that made the characteristic change: %s',
client_addr
)
continue
logger.debug('Sending event to client: %s', client_addr)
pushed = self.http_server.push_event(bytedata, client_addr)
Expand Down Expand Up @@ -619,16 +635,30 @@ def get_characteristics(self, char_ids):
:rtype: dict
"""
chars = []
for id in char_ids:
aid, iid = (int(i) for i in id.split('.'))
rep = {HAP_REPR_AID: aid, HAP_REPR_IID: iid}
char = self.accessory.get_characteristic(aid, iid)
for aid_iid in char_ids:
aid, iid = (int(i) for i in aid_iid.split("."))
rep = {
HAP_REPR_AID: aid,
HAP_REPR_IID: iid,
HAP_REPR_STATUS: SERVICE_COMMUNICATION_FAILURE,
}

try:
rep[HAP_REPR_VALUE] = char.get_value()
rep[HAP_REPR_STATUS] = CHAR_STAT_OK
if aid == STANDALONE_AID:
char = self.accessory.iid_manager.get_obj(iid)
available = True
else:
acc = self.accessory.accessories.get(aid)
available = acc.available
char = acc.iid_manager.get_obj(iid)

if available:
rep[HAP_REPR_VALUE] = char.get_value()
rep[HAP_REPR_STATUS] = CHAR_STAT_OK
except CharacteristicError:
logger.error("Error getting value for characteristic %s.", id)
rep[HAP_REPR_STATUS] = SERVICE_COMMUNICATION_FAILURE
except Exception: # pylint: disable=broad-except
logger.exception("Unexpected error getting value for characteristic %s.", id)

chars.append(rep)
logger.debug("Get chars response: %s", chars)
Expand Down
2 changes: 1 addition & 1 deletion pyhap/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@

FFMPEG_CMD = (
# pylint: disable=bad-continuation
'ffmpeg -re -f avfoundation -i 0:0 -threads 0 '
'ffmpeg -re -f avfoundation -framerate {fps} -i 0:0 -threads 0 '
'-vcodec libx264 -an -pix_fmt yuv420p -r {fps} -f rawvideo -tune zerolatency '
'-vf scale={width}:{height} -b:v {v_max_bitrate}k -bufsize {v_max_bitrate}k '
'-payload_type 99 -ssrc {v_ssrc} -f rtp '
Expand Down
5 changes: 3 additions & 2 deletions pyhap/characteristic.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class Characteristic:
"""

__slots__ = ('broker', 'display_name', 'properties', 'type_id',
'value', 'getter_callback', 'setter_callback', 'service')
'value', 'getter_callback', 'setter_callback', 'service', '_uuid_str')

def __init__(self, display_name, type_id, properties):
"""Initialise with the given properties.
Expand All @@ -104,6 +104,7 @@ def __init__(self, display_name, type_id, properties):
self.getter_callback = None
self.setter_callback = None
self.service = None
self._uuid_str = str(type_id).upper()

def __repr__(self):
"""Return the representation of the characteristic."""
Expand Down Expand Up @@ -233,7 +234,7 @@ def to_HAP(self):
"""
hap_rep = {
HAP_REPR_IID: self.broker.iid_manager.get_iid(self),
HAP_REPR_TYPE: str(self.type_id).upper(),
HAP_REPR_TYPE: self._uuid_str,
HAP_REPR_DESC: self.display_name,
HAP_REPR_PERM: self.properties[PROP_PERMISSIONS],
HAP_REPR_FORMAT: self.properties[PROP_FORMAT],
Expand Down
4 changes: 2 additions & 2 deletions 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 = 4
MINOR_VERSION = 9
PATCH_VERSION = 0
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 5)
Expand Down
Loading

0 comments on commit fb97881

Please sign in to comment.