Skip to content

Commit

Permalink
Merge V2.0.0 into master (ikalchev#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
ikalchev authored May 4, 2018
1 parent 084bb73 commit aecb41a
Show file tree
Hide file tree
Showing 45 changed files with 1,433 additions and 982 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ sudo: true
branches:
only:
- master
- dev
- /^\d\.\d+$/
- /^\d\.\d+\.\d+(rc\d+|\.dev\d+)?$/
matrix:
include:
- python: 3.4
env: TOXENV=py34
- python: 3.5
env: TOXENV=py35
- python: 3.6
Expand Down
97 changes: 97 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Changelog

All notable changes to this project will be documented in this file (since version `1.1.8`).
If you notice that something is missing, please open an issue or submit a PR.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).


## [Unreleased]



## [2.0.0] - 2018-05-04

### Added
- New helper methods to run the `run` method repeatedly, until the driver is stopped. `Accessory.repeat(time)` or `AsyncAccessory.repeat(time)`. [#74](https://github.com/ikalchev/HAP-python/pull/74)
- New helper method `service.configure_char`. Shortcut to configuring a characteristic. [#84](https://github.com/ikalchev/HAP-python/pull/84)
- Characteristics and Services can now be created from a json dictionary with `from_dict`. [#85](https://github.com/ikalchev/HAP-python/pull/85)
- Added helper method to enable easy override of the `AccessoryInformation` service. [#102](https://github.com/ikalchev/HAP-python/pull/102)
- Added helper method to load a service and chars and add it to an accessory. [#102](https://github.com/ikalchev/HAP-python/pull/102)

### Changed
- Accessory.run method is now called through an event loop. You can either inherit from `Accessory` like before: The `run` method will be wrapped in a thread. Or inherit from `AsyncAccessory` and implement `async def run`. This will lead to the execution in the event loop. [#74](https://github.com/ikalchev/HAP-python/pull/74)
- Scripts are now located in a separate directory: `scripts`. [#81](https://github.com/ikalchev/HAP-python/pull/81)
- `driver.start` starts the event loop with `loop.run_forever()`. [#83](https://github.com/ikalchev/HAP-python/pull/83)
- Debug logs for `char.set_value` and `char.client_update_value`. [#99](https://github.com/ikalchev/HAP-python/pull/99)
- Changed default values associated with the `AccessoryInformation` service. [#102](https://github.com/ikalchev/HAP-python/pull/102)
- `Accessory._set_services` is now deprecated. Instead services should be initialized in the accessories `init` method. [#102](https://github.com/ikalchev/HAP-python/pull/102)

### Fixed
- Overriding properties now checks that value is still a valid value, otherwise value will be set to the default value. [#82](https://github.com/ikalchev/HAP-python/pull/82)
- The `AccessoryInformation` service will always have the `iid=1`. [#102](https://github.com/ikalchev/HAP-python/pull/102)

### Breaking Changes
- With introduction of async methods the min required Python version changes to `3.5`. [#74](https://github.com/ikalchev/HAP-python/pull/74)
- The `Accessory.Category` class was removed and the `Category` constants moved to `pyhap/const.py` with the naming: `CATEGORY_[OLD_NAME]` (e.g. `CATEGORY_OTHER`) [#86](https://github.com/ikalchev/HAP-python/pull/86)
- Updated `Accessories` to work with changes. [#74](https://github.com/ikalchev/HAP-python/pull/74), [#89](https://github.com/ikalchev/HAP-python/pull/89)
- Renamed `Accessory.broker` to `Accessory.Driver`. `acc.set_broker` is now `acc.set_driver`. [#104](https://github.com/ikalchev/HAP-python/pull/104)
- QR Code is now optional. It requires `pip install HAP-python[QRCode]`. [#103](https://github.com/ikalchev/HAP-python/pull/103)
- `Loader.get_serv_loader` and `Loader.get_char_loader` are replaced by `Loader.get_loader`, since it now handles loading chars and services in one class. [#108](https://github.com/ikalchev/HAP-python/pull/108)

### Developers
- `to_HAP` methods don't require the `iid_manager` any more [#84](https://github.com/ikalchev/HAP-python/pull/84), [#85](https://github.com/ikalchev/HAP-python/pull/85)
- `Service._add_chars` is now integrated in `Service.add_characteristic` [85](https://github.com/ikalchev/HAP-python/pull/85)
- `driver.update_advertisment` is now `driver.update_advertisement` [85](https://github.com/ikalchev/HAP-python/pull/85)
- `TypeLoader`, `CharLoader` and `ServiceLoader` are now combined into the `Loader` with the new methods `get_char` and `get_service` to load new chars and services. [85](https://github.com/ikalchev/HAP-python/pull/85)
- Moved some constants to `pyhap/const.py` and removed `HAP_FORMAT`, `HAP_UNITS` and `HAP_PERMISSIONS` in favor for `HAP_FORMAT_[OLD_FORMAT]`, etc. [#86](https://github.com/ikalchev/HAP-python/pull/86)
- Updated tests and added new test dependency `pytest-timeout` [#88](https://github.com/ikalchev/HAP-python/pull/88)
- Rewrote `IIDManager` and split `IIDManager.remove` into `remove_obj` and `remove_iid`. [#100](https://github.com/ikalchev/HAP-python/pull/100)
- `requirements.txt` file has been added for min, `requirements_all.txt` covers all requirements. [#103](https://github.com/ikalchev/HAP-python/pull/103)



## [1.1.9] - 2018-04-06

### Breaking Changes
- `Characteristics` are now initialized with only `display_name`, `type_id` and `properties` as parameter. Removed `value` and `broker`. [73](https://github.com/ikalchev/HAP-python/pull/73)
- Split `Characteristic.set_value` method into `set_value` and `client_update_value`. `set_value` is intended to send value updates to HomeKit, it won't call the `setter_callback` anymore. `client_update_value` is now used by the `driver` to update the `value` of the char accordingly and call `setter_callback`. It will also notify any other clients about the value change. [73](https://github.com/ikalchev/HAP-python/pull/73)

### Developers
- Removed `Characteristic.NotConfiguredError`. [73](https://github.com/ikalchev/HAP-python/pull/73)
- Updated tests. [73](https://github.com/ikalchev/HAP-python/pull/73)
- `Characteristic.to_HAP` doesn't require the `iid_manager` any more. [73](https://github.com/ikalchev/HAP-python/pull/73)
- `Characteristic.notify` doesn't check if broker is set anymore. [73](https://github.com/ikalchev/HAP-python/pull/73)
- Added helper function `Characteristic._get_default_value`. [73](https://github.com/ikalchev/HAP-python/pull/73)
- Added helper function `Characterisitc.to_valid_value`. [73](https://github.com/ikalchev/HAP-python/pull/73)



## [1.1.8] - 2018-03-29

### Added
- New method `Characteristic.override_properties`. [#66](https://github.com/ikalchev/HAP-python/pull/62)
- Added new `Apple-defined` types. Please check the [commit](https://github.com/ikalchev/HAP-python/commit/eaccedb8ba5a5a90b71584a477a19aa099e3cf8f) to see which have changed.

### Changed
- Driver calls `char.set_value` now with `should_notify=True` instead of `False` to notify other clients about the value change as well. [#62](https://github.com/ikalchev/HAP-python/pull/62)

### Fixes
- Accessories with `AID=7` stopped working [#61](https://github.com/ikalchev/HAP-python/pull/61). Don't assign it to new accessories.

### Breaking Changes
- Default value for `ValidValues` parameter is now the `valid value` with the least value. Mostly `0` or `1`. [#57](https://github.com/ikalchev/HAP-python/pull/57)
- Removed the deprecated method `char.get_value`. [#67](https://github.com/ikalchev/HAP-python/pull/67)
- Removed optional characteristics (`Service.opt_characteristics`) from the service characterization. They have been handled similar to `Service.characteristics` internally. They are still part of `pyhap/resources/services.json` however. [#67](https://github.com/ikalchev/HAP-python/pull/67)
- Updated the `Apple-defined` types. Unsupported once have been removed. Please check the [commit](https://github.com/ikalchev/HAP-python/commit/eaccedb8ba5a5a90b71584a477a19aa099e3cf8f) to see which have changed.

### Developers
- Removed `Characteristic._create_hap_template()` and merged it into `Characteristic.to_HAP`. [#66](https://github.com/ikalchev/HAP-python/pull/66)
- Removed `char.has_valid_values` and replaced it with runtime checks. [#66](https://github.com/ikalchev/HAP-python/pull/66)
- Added a `requirements_all.txt` file. [#65](https://github.com/ikalchev/HAP-python/pull/65)



## [1.1.7] - 2018-02-25

No changelog for this version has been added yet.
33 changes: 20 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ $ sudo apt-get install libavahi-compat-libdnssd-dev
```
`avahi-utils` may also fit the bill. Then, you can install with `pip3` (you will need `sudo` or `--user` for the install):
```sh
$ pip3 install HAP-python
$ pip3 install HAP-python[QRCode]
```

This will install HAP-python in your python packages, so that you can import it as `pyhap`. To uninstall, just do:
Expand All @@ -54,10 +54,11 @@ will take care of advertising it on the local network, setting a HAP server and
running the Accessory. Take a look at [main.py](main.py) for a quick start on that.

```python
from pyhap.accessory import Accessory, Category
from pyhap.accessory import Accessory, AsyncAccessory, Category
import pyhap.loader as loader

class TemperatureSensor(Accessory):
### Async accessory - run method is run asynchronously in the event loop
class TemperatureSensor(AsyncAccessory):
"""Implementation of a mock temperature sensor accessory."""

category = Category.SENSOR # This is for the icon in the iOS Home app.
Expand Down Expand Up @@ -98,25 +99,31 @@ class TemperatureSensor(Accessory):
temp_sensor_service = loader.get_serv_loader().get("TemperatureSensor")
self.add_service(temp_sensor_service)

def run(self):
@AsyncAcessory.run_at_interval(3) # Run this method every 3 seconds
async def run(self):
"""We override this method to implement what the accessory will do when it is
started. An accessory is started and stopped from the AccessoryDriver.
It might be convenient to use the Accessory's run_sentinel, which is a
threading.Event object which is set when the accessory should stop running.
In this example, we wait 3 seconds to see if the run_sentinel will be set and if
not, we set the current temperature to a random number.
We set the current temperature to a random number. The decorator runs this method
every 3 seconds.
"""
while not self.run_sentinel.wait(3):
self.temp_char.set_value(random.randint(18, 26))
self.temp_char.set_value(random.randint(18, 26))

def stop(self):
"""We override this method to clean up any resources or perform final actions, as
this is called by the AccessoryDriver when the Accessory is being stopped (it is
called right after run_sentinel is set).
this is called by the AccessoryDriver when the Accessory is being stopped.
"""
print("Stopping accessory.")

### Synchronouse accessory - run method is in a thread
class SyncTemperatureSensor(Accessory):
"""Everything is same as in the TemperatureSensor, apart from the run method which is
not async.
"""

@Accessory.run_at_interval(3)
def run(self):
self.temp_char.set_value(random.randint(18, 26))
```

## Integrating non-compatible devices <a name="HttpAcc"></a>
Expand Down
8 changes: 0 additions & 8 deletions docs/source/api/characteristic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,3 @@ Characteristic Base class for a HAP Accessory ``Service``.

.. autoclass:: pyhap.characteristic.Characteristic
:members:


CharLoader
==========

Useful for loading ``Characteristic`` for a ``Service``.

.. autoclass:: pyhap.loader.CharLoader
10 changes: 10 additions & 0 deletions docs/source/api/loader.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. _api-loader:

======
Loader
======

Useful for creating a ``Service`` or ``Characteristic``.

.. autoclass:: pyhap.loader.Loader
:members:
9 changes: 0 additions & 9 deletions docs/source/api/service.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,3 @@ Service Base class for a HAP ``Accessory``.

.. autoclass:: pyhap.service.Service
:members:


ServiceLoader
=============

Useful for creating a ``Service``.

.. autoclass:: pyhap.loader.ServiceLoader
:members:
11 changes: 7 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@
"""
import logging
import signal
import time
import random

from pyhap.accessories.TemperatureSensor import TemperatureSensor
from pyhap.accessory import Bridge
from pyhap.accessory_driver import AccessoryDriver
import pyhap.loader as loader

logging.basicConfig(level=logging.INFO)


def get_bridge():
"""Call this method to get a Bridge instead of a standalone accessory."""
bridge = Bridge(display_name="Bridge")
temp_sensor = TemperatureSensor("Termometer")
temp_sensor2 = TemperatureSensor("Termometer2")
bridge = Bridge(display_name='Bridge')
temp_sensor = TemperatureSensor('Sensor 2')
temp_sensor2 = TemperatureSensor('Sensor 1')
bridge.add_accessory(temp_sensor)
bridge.add_accessory(temp_sensor2)

Expand All @@ -32,7 +35,7 @@ def get_bridge():

def get_accessory():
"""Call this method to get a standalone Accessory."""
acc = TemperatureSensor("MyTempSensor")
acc = TemperatureSensor('MyTempSensor')
return acc


Expand Down
15 changes: 14 additions & 1 deletion pyhap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,20 @@
CHARACTERISTICS_FILE = os.path.join(_RESOURCE_DIR, "characteristics.json")
SERVICES_FILE = os.path.join(_RESOURCE_DIR, "services.json")

HAP_PYTHON_VERSION = (1, 1, 9)
HAP_PYTHON_VERSION = (2, 0, 0)
"""
HAP-python current version.
"""


SUPPORT_QR_CODE = False
try:
import base36 as _
import pyqrcode as _
SUPPORT_QR_CODE = True
except ImportError:
pass
"""
Flag if QR Code dependencies are installed.
Installation with `pip install HAP-python[QRCode]`.
"""
32 changes: 13 additions & 19 deletions pyhap/accessories/AM2302.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,30 @@
import pigpio
import sensors.DHT22 as DHT22

from pyhap.accessory import Accessory, Category
import pyhap.loader as loader
from pyhap.accessory import Accessory
from pyhap.const import CATEGORY_SENSOR


class AM2302(Accessory):

category = Category.SENSOR
category = CATEGORY_SENSOR

def __init__(self, *args, pin=4, **kwargs):
super(AM2302, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.pin = pin

self.temp_char = self.get_service("TemperatureSensor")\
.get_characteristic("CurrentTemperature")
serv_temp = self.add_preload_service('TemperatureSensor')
serv_humidity = self.add_preload_service('HumiditySensor')

self.humidity_char = self.get_service("HumiditySensor")\
.get_characteristic("CurrentRelativeHumidity")
self.char_temp = serv_temp.get_characteristic('CurrentTemperature')
self.char_humidity = serv_humidity \
.get_characteristic('CurrentRelativeHumidity')

self.sensor = DHT22.sensor(pigpio.pi(), pin)

def _set_services(self):
super(AM2302, self)._set_services()
self.add_service(
loader.get_serv_loader().get("TemperatureSensor"))
self.add_service(
loader.get_serv_loader().get("HumiditySensor"))

def __getstate__(self):
state = super(AM2302, self).__getstate__()
state["sensor"] = None
state = super().__getstate__()
state['sensor'] = None
return state

def __setstate__(self, state):
Expand All @@ -52,5 +46,5 @@ def run(self):
time.sleep(0.2)
t = self.sensor.temperature()
h = self.sensor.humidity()
self.temp_char.set_value(t)
self.humidity_char.set_value(h)
self.char_temp.set_value(t)
self.char_humidity.set_value(h)
23 changes: 9 additions & 14 deletions pyhap/accessories/BMP180.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,25 @@
# Assume you have a bmp module with BMP180 class with read() method.
from sensors.bmp180 import BMP180 as sensor

from pyhap.accessory import Accessory, Category
import pyhap.loader as loader
from pyhap.accessory import Accessory
from pyhap.const import CATEGORY_SENSOR


class BMP180(Accessory):

category = Category.SENSOR
category = CATEGORY_SENSOR

def __init__(self, *args, **kwargs):
super(BMP180, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)

self.temp_char = self.get_service("TemperatureSensor")\
.get_characteristic("CurrentTemperature")
serv_temp = self.add_preload_service('TemperatureSensor')
self.char_temp = serv_temp.get_characteristic('CurrentTemperature')

self.sensor = sensor()

def _set_services(self):
super(BMP180, self)._set_services()
self.add_service(
loader.get_serv_loader().get("TemperatureSensor"))

def __getstate__(self):
state = super(BMP180, self).__getstate__()
state["sensor"] = None
state = super().__getstate__()
state['sensor'] = None
return state

def __setstate__(self, state):
Expand All @@ -36,4 +31,4 @@ def __setstate__(self, state):
def run(self):
while not self.run_sentinel.wait(30):
temp, _pressure = self.sensor.read()
self.temp_char.set_value(temp)
self.char_temp.set_value(temp)
Loading

0 comments on commit aecb41a

Please sign in to comment.