Skip to content
This repository has been archived by the owner on Jan 23, 2022. It is now read-only.

Commit

Permalink
Improve build + python style + improvements + drop python 3.5 support
Browse files Browse the repository at this point in the history
  • Loading branch information
tgermain authored and thomasgermain committed Sep 3, 2019
1 parent c814b23 commit cf47fa5
Show file tree
Hide file tree
Showing 64 changed files with 3,689 additions and 3,600 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,6 @@ venv.bak/

# mypy
.mypy_cache/

#idea
.idea/
17 changes: 11 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ os:
- linux

python:
- '3.5'
- '3.6'
matrix:
include:
- python: '3.7'
dist: xenial
sudo: true
- '3.7'

install:
- pip install -r requirements.txt
- pip install pylint
- pip install mypy
- pip install pycodestyle
- pip install coveralls
script:
- pylint vr900connector
- pycodestyle vr900connector
- mypy --strict vr900connector
- pylint --rcfile=tests/.pylintrc tests
- pycodestyle tests
- mypy --strict tests
- coverage run --source=vr900connector setup.py pytest
after_success:
- coveralls
Expand Down
59 changes: 28 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<b>Please note that the project is still in beta state, it means I may do some (un)intentional breaking changes</b>

## Legal Disclaimer
This software is not affiliated with Vaillant and the developers take no legal responsibility for the functionality or security of your vaillant devices
This software is not affiliated with Vaillant and the developers take no legal responsibility for the functionality or security of your vaillant devices.

## Install
```bash
Expand All @@ -26,23 +26,20 @@ pytest

### Module usage

The connector is separate in two layers:
The project is separated in two layers:

#### 1. ApiConnector
This is the low level connector using the vaillant API and returning raw data directly coming from the API. The connector is handling the login and session.
This is the low level connector using the vaillant API and returning raw data directly coming from the API (basically, `json` formatted responses. The connector is handling the login and session.
The connector able to reuse an already existing session (cookies). Two files are saved (cookies and serial number of your installation) on the file system. Default location is:
```python
tempfile.gettempdir() + "/.vaillant_vr900_files"
```
but it can be overridden. Files are named .vr900-vaillant.cookies and .vr900-vaillant.serial.
`~/.vr900connector` but it can be overridden. Files are named `.cookies` and `.serial`.


Here is an example how to use it:
```python
from vr900connector.api import ApiConnector, Urls
from vr900connector.api import ApiConnector, urls

connector = ApiConnector('user', 'pass')
connector.get(Urls.facilities_list())
connector.get(urls.facilities_list())
```
to get some information about your installation, this returns the raw response, something like this:
```json
Expand Down Expand Up @@ -78,42 +75,42 @@ from vr900connector.api import ApiConnector
connector = ApiConnector('user', 'pass')
connector.get('')
```
with urls from
```python
vr900connector.api.urls
```
with urls from `vr900connector.api.urls`

I recommend using this layer if you only want to retrieve basic data (outdoor temperature, current temperature, etc.)
I would recommend using this layer if you only want to retrieve basic data (outdoor temperature, current temperature, etc.)

#### 2. SystemManager
This layer allows you to interact in a more friendly way with the system.
The underlying connector is hidden and raw responses are mapped to more useful object.
This layer allows you to interact in a more friendly way with the system and compute some data for you.
The underlying `ApiConnector` is hidden and raw responses are mapped to more useful objects.

For now, the only function is:

Here is an example:
```python
from vr900connector.systemmanager import SystemManager
from vr900connector.model import OperationMode

manager = SystemManager('user', 'pass')
system = manager.get_system()

# get the complete system
system = manager.get_system()

# set the hot water target temperature to 55
manager.set_hot_water_setpoint_temperature('dhw_id', 55)

# set the zone operation mode to 'AUTO'
manager.set_zone_operation_mode('zone_id', OperationMode.AUTO)
```

The main object to manipulate is
```python
vr900connector.model.system
```

Which is grouping all the information about the system.

I recommend using this layer if you want to do more complex things, e.g: if you want to get the target temperature for
a room or a zone, it can become a bit complex since you have to deal with holiday mode, quick mode, quick veto, time program, etc.
This layer is hiding you this complexity
The main object to manipulate is `vr900connector.model.System`, which is grouping all the information about your system.

I would recommend using this layer if you want to do more complex things, e.g: if you want to get the target temperature for
a room or a zone, it can become a bit complex since you have to deal with holiday mode, quick mode, quick veto, time program, etc.
This layer is hiding you this complexity.


## Todo's
- add the possibility to remove quick mode
- Move ApiConnector to async
- Handling ventilation
- Add more documentation
- Handling missing information when VRC700 (and/or boiler) is shutdown
(e.g. TimeProgram are not coming anymore from the API if boiler is down)
- Add some lint/pylint checks during the build (+ refactor some piece of code in a more pythonic way)
(e.g. TimeProgram are not coming anymore from the API if boiler is down)
14 changes: 14 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[mypy]
show_error_context = True
show_column_numbers = True

[mypy-vr900connector.*]
no_implicit_reexport = False

[mypy-vr900connector.model.mapper]
disallow_untyped_defs = False
disallow_incomplete_defs = False

[mypy-tests.*]
disallow_untyped_decorators = False
no_strict_optional = True
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
attrs>=19.0.0,<20.0.0
responses>=0.10.0,<1.0.0
requests>=2.20.0,<3.0.0
jsonpickle>=1.0,<2.0
coveralls>=1.6.0,<2.0
jsonpickle>=1.0,<2.0
11 changes: 3 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,26 @@
long_description = f.read()

setup(name='vr900-connector',
version='0.3.4',
version='0.4.0',
description='Connector to handle vaillant vr900/vr920 data',
long_description_content_type='text/markdown',
long_description=long_description,
url='https://github.com/thomasgermain/vr900-connector.git',
author='Thomas Germain',
author_email='thomas.germain@live.be',
license='MIT',
packages=find_packages(exclude=('tests', 'tests/*', '/tests', '/tests/*')),
packages=find_packages(exclude=
('tests', 'tests/*', '/tests', '/tests/*')),
zip_safe=False,
setup_requires=["pytest-runner"],
install_requires=[
"requests>=2.20.0,<3.0.0",
"jsonpickle>=1.0,<2.0"
],
entry_points={
'console_scripts': [
'vaillant=vaillant.__main__:main',
]
},
classifiers=[
'License :: OSI Approved :: MIT License',
'Development Status :: 4 - Beta',
'Programming Language :: Python',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Home Automation'
Expand Down
6 changes: 6 additions & 0 deletions tests/.pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[MESSAGES CONTROL]
disable=
protected-access,
too-few-public-methods,
too-many-public-methods,
missing-docstring
4 changes: 3 additions & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Vr900connector tests."""
import logging

logging.basicConfig(level=logging.ERROR, format="%(asctime)s:%(levelname)s:%(name)s: %(message)s")
logging.basicConfig(level=logging.ERROR,
format="%(asctime)s:%(levelname)s:%(name)s: %(message)s")
33 changes: 33 additions & 0 deletions tests/files/responses/hvacstate_pending
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"body": {
"errorMessages": [
{
"deviceName": "VC BE 246/5-3",
"type": "STATUS",
"title": "Mode chauffage : Arrêt temporaire après une opération de chauffage",
"statusCode": "S.8",
"description": "...",
"hint": "...",
"timestamp": 1545896904282
}
]
},
"meta": {
"onlineStatus": {
"status": "ONLINE"
},
"firmwareUpdateStatus": {
"status": "UPDATE_NOT_PENDING"
},
"syncState": [
{
"state": "PENDING",
"timestamp": 1546439817247,
"link": {
"rel": "self",
"resourceLink": "/facilities/1234567890123456789012345678/hvacstate/v1/overview"
}
}
]
}
}
File renamed without changes.
File renamed without changes.
18 changes: 18 additions & 0 deletions tests/files/test_syncstate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import unittest

from vr900connector.model import SyncState


class StateTest(unittest.TestCase):

def test_is_sync(self) -> None:
self.assertTrue(SyncState('SYNCED', 123, 'link').is_sync)

def test_is_pending(self) -> None:
self.assertTrue(SyncState('PENDING', 123, 'link').is_pending)

def test_is_outdated(self) -> None:
self.assertTrue(SyncState('OUTDATED', 123, 'link').is_outdated)

def test_is_init(self) -> None:
self.assertTrue(SyncState('INITIALIZING', 123, 'link').is_init)
Loading

0 comments on commit cf47fa5

Please sign in to comment.