Skip to content

Commit

Permalink
#13 A_CYC_EXTR_FAN_BALANCE_BASE and A_CYC_SUPP_FAN_BALANCE_BASE added…
Browse files Browse the repository at this point in the history
… to settable ints.

2.7 compatible enum method replaced with python 3 Enum class (PROFILE). No code changes in clients required.

version 2.5.0
Reformat with black and isort. Some code cleanup.
  • Loading branch information
yozik04 committed Apr 1, 2020
1 parent 6c15105 commit d3cc972
Show file tree
Hide file tree
Showing 13 changed files with 723 additions and 540 deletions.
51 changes: 22 additions & 29 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import sys

from os import path as p

try:
Expand All @@ -9,42 +7,37 @@


def read(filename, parent=None):
parent = (parent or __file__)
parent = parent or __file__

try:
with open(p.join(p.dirname(parent), filename)) as f:
return f.read()
except IOError:
return ''
return ""


setup(
name='vallox_websocket_api',
packages=['vallox_websocket_api'],
version='2.4.0',
name="vallox_websocket_api",
packages=["vallox_websocket_api"],
version="2.5.0",
python_requires=">=3.5.1, <4",
description='Vallox WebSocket API',
author='Jevgeni Kiski',
author_email='yozik04@gmail.com',
long_description=read('README.md'),
description="Vallox WebSocket API",
author="Jevgeni Kiski",
author_email="yozik04@gmail.com",
long_description=read("README.md"),
long_description_content_type="text/markdown",
url='https://github.com/yozik04/vallox_websocket_api',
license='LGPL 3',
keywords='vallox api',
url="https://github.com/yozik04/vallox_websocket_api",
license="LGPL 3",
keywords="vallox api",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
],
install_requires=[
'websockets >= 7.0, < 9.0',
'construct >= 2.9.0, < 3.0.0',
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
],
setup_requires=['wheel'],
tests_require=[
'mock',
'asynctest',
]
install_requires=["websockets >= 7.0, < 9.0", "construct >= 2.9.0, < 3.0.0",],
setup_requires=["wheel"],
tests_require=["mock", "asynctest",],
)
17 changes: 9 additions & 8 deletions tests/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
import websockets
from vallox_websocket_api.client import Client


def with_client(func):
@asynctest.patch('websockets.connect')
async def wrapper(cls, connect):
client = Client('127.0.0.1')
instance = connect.return_value
@asynctest.patch("websockets.connect")
async def wrapper(cls, connect):
client = Client("127.0.0.1")
instance = connect.return_value

protocol_mock = asynctest.create_autospec(websockets.WebSocketCommonProtocol)
instance.__aenter__.side_effect = protocol_mock
await func(cls, client, protocol_mock.return_value)
protocol_mock = asynctest.create_autospec(websockets.WebSocketCommonProtocol)
instance.__aenter__.side_effect = protocol_mock
await func(cls, client, protocol_mock.return_value)

return wrapper
return wrapper
187 changes: 85 additions & 102 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,145 +1,128 @@
import binascii
import asynctest

from tests.decorators import with_client
import asynctest
from asynctest import CoroutineMock

from tests.decorators import with_client
from vallox_websocket_api.exceptions import ValloxWebsocketException
from websockets.exceptions import InvalidMessage

from vallox_websocket_api.exceptions import ValloxWebsocketException

class TestClient(asynctest.TestCase):
@with_client
async def testFetchMetric(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0024000000000000000000000000000001000800030000000000000061df98b100030003203fb9500331000000000000000000560000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002b000f732a6ca969a171d1730800010000022700000028000000000000000001a6029e000100000028ffffffffffffffffffffffffffffffffffffffffffffffff000000000000000057c503e8ffffffffffff000000190000000000010000000000000000000300001b98012000a50000000000000000001e00010000000100000000000000000007001b000f001700010012000200070044000000010000000000000007003200320001000000000000001e0000c0a80501ffffff0000000000000000000000000000000000000000000000000000000000c0a8050c86076097f78844b7ac4db61e502fe4f2004c004c000100c00101001c001e000a00320000003703840000708f00320032000a0000000000010000000a721f0000000000010000000f728300000000000000000064715700000000000000000000000000000000000000010037001e000000000000000068bf71bb000083910000002600b4000000010001000000010001001e000f00080001001200000003000000000000000000000017000003e90000000000000001000100010000000a003200010000000000000000000000000000000000000000001000000000000000000000000000540048000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
@with_client
async def testFetchMetric(self, client, ws):
ws.recv.return_value = binascii.unhexlify(
"0024000000000000000000000000000001000800030000000000000061df98b100030003203fb9500331000000000000000000560000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002b000f732a6ca969a171d1730800010000022700000028000000000000000001a6029e000100000028ffffffffffffffffffffffffffffffffffffffffffffffff000000000000000057c503e8ffffffffffff000000190000000000010000000000000000000300001b98012000a50000000000000000001e00010000000100000000000000000007001b000f001700010012000200070044000000010000000000000007003200320001000000000000001e0000c0a80501ffffff0000000000000000000000000000000000000000000000000000000000c0a8050c86076097f78844b7ac4db61e502fe4f2004c004c000100c00101001c001e000a00320000003703840000708f00320032000a0000000000010000000a721f0000000000010000000f728300000000000000000064715700000000000000000000000000000000000000010037001e000000000000000068bf71bb000083910000002600b4000000010001000000010001001e000f00080001001200000003000000000000000000000017000003e90000000000000001000100010000000a003200010000000000000000000000000000000000000000001000000000000000000000000000540048000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
)

result = await client.fetch_metric('A_CYC_ENABLED')
result = await client.fetch_metric("A_CYC_ENABLED")

self.assertEqual(1, result)
self.assertEqual(1, result)

ws.send.assert_called_once_with(binascii.unhexlify('0300f6000000f900'))
ws.send.assert_called_once_with(binascii.unhexlify("0300f6000000f900"))

@with_client
async def testSetTempValue(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetTempValue(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

await client.set_values({
'A_CYC_BOOST_AIR_TEMP_TARGET': '19'
})
await client.set_values({"A_CYC_BOOST_AIR_TEMP_TARGET": "19"})

ws.send.assert_called_once_with(binascii.unhexlify('0400f90022501f723ec3'))
ws.send.assert_called_once_with(binascii.unhexlify("0400f90022501f723ec3"))

@with_client
async def testSetTempValueFraction(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetTempValueFraction(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

await client.set_values({
'A_CYC_BOOST_AIR_TEMP_TARGET': '19.1'
})
await client.set_values({"A_CYC_BOOST_AIR_TEMP_TARGET": "19.1"})

ws.send.assert_called_once_with(binascii.unhexlify('0400f9002250297248c3'))
ws.send.assert_called_once_with(binascii.unhexlify("0400f9002250297248c3"))

@with_client
async def testSetTempValueFractionRounding1(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetTempValueFractionRounding1(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

await client.set_values({
'A_CYC_BOOST_AIR_TEMP_TARGET': '19.145'
})
await client.set_values({"A_CYC_BOOST_AIR_TEMP_TARGET": "19.145"})

ws.send.assert_called_once_with(binascii.unhexlify('0400f9002250297248c3'))
ws.send.assert_called_once_with(binascii.unhexlify("0400f9002250297248c3"))

@with_client
async def testSetTempValueFractionRounding2(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetTempValueFractionRounding2(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

await client.set_values({
'A_CYC_BOOST_AIR_TEMP_TARGET': '18.991'
})
await client.set_values({"A_CYC_BOOST_AIR_TEMP_TARGET": "18.991"})

ws.send.assert_called_once_with(binascii.unhexlify('0400f90022501f723ec3'))
ws.send.assert_called_once_with(binascii.unhexlify("0400f90022501f723ec3"))

@with_client
async def testSetValue(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetValue(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

await client.set_values({
'A_CYC_STATE': 0,
'A_CYC_BOOST_TIMER': 0,
'A_CYC_FIREPLACE_TIMER': 0,
'A_CYC_EXTRA_TIMER': 0
})
await client.set_values(
{
"A_CYC_STATE": 0,
"A_CYC_BOOST_TIMER": 0,
"A_CYC_FIREPLACE_TIMER": 0,
"A_CYC_EXTRA_TIMER": 0,
}
)

ws.send.assert_called_once_with(binascii.unhexlify('0a00f900011200000412000005120000061200001349'))
ws.send.assert_called_once_with(
binascii.unhexlify("0a00f900011200000412000005120000061200001349")
)

@with_client
async def testSetAssertion(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetAssertion(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

with self.assertRaises(AssertionError) as context:
await client.set_values({
'A_CYC_BOOST_TIMER': '11.2'
})
with self.assertRaises(AssertionError):
await client.set_values({"A_CYC_BOOST_TIMER": "11.2"})

with self.assertRaises(ValueError) as context:
await client.set_values({
'A_CYC_BOOST_AIR_TEMP_TARGET': '11.a'
})
with self.assertRaises(ValueError):
await client.set_values({"A_CYC_BOOST_AIR_TEMP_TARGET": "11.a"})

with self.assertRaises(AssertionError) as context:
await client.set_values({
'A_CYC_BOOST_SPEED_SETTING': '11.2'
})
with self.assertRaises(AssertionError):
await client.set_values({"A_CYC_BOOST_SPEED_SETTING": "11.2"})

with self.assertRaises(AssertionError) as context:
await client.set_values({
'A_CYC_FIREPLACE_SUPP_FAN': '11.2'
})
with self.assertRaises(AssertionError):
await client.set_values({"A_CYC_FIREPLACE_SUPP_FAN": "11.2"})

@with_client
async def testSetMissing(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetMissing(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

with self.assertRaises(AttributeError) as context:
await client.set_values({
'A_CYC_BOOSTER': 10
})
with self.assertRaises(AttributeError):
await client.set_values({"A_CYC_BOOSTER": 10})

@with_client
async def testSetUnsettable(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetUnsettable(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

with self.assertRaises(AttributeError) as context:
await client.set_values({
'A_CYC_RH_VALUE': 22
})
with self.assertRaises(AttributeError):
await client.set_values({"A_CYC_RH_VALUE": 22})

@with_client
async def testSetNewSettableAddressByName(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetNewSettableAddressByName(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

client.set_settable_address('A_CYC_RH_VALUE', int)
client.set_settable_address("A_CYC_RH_VALUE", int)

await client.set_values({
'A_CYC_RH_VALUE': 22
})
await client.set_values({"A_CYC_RH_VALUE": 22})

@with_client
async def testSetNewSettableAddressByAddress(self, client, ws):
ws.recv.return_value = binascii.unhexlify('0200f500f700')
@with_client
async def testSetNewSettableAddressByAddress(self, client, ws):
ws.recv.return_value = binascii.unhexlify("0200f500f700")

client.set_settable_address(4363, int)
client.set_settable_address(4363, int)

await client.set_values({
'A_CYC_RH_VALUE': 22
})
await client.set_values({"A_CYC_RH_VALUE": 22})

@with_client
async def testSetNewSettableAddressByAddressException(self, client, ws):
ws.recv.side_effect = CoroutineMock(side_effect=InvalidMessage())
@with_client
async def testSetNewSettableAddressByAddressException(self, client, ws):
ws.recv.side_effect = CoroutineMock(side_effect=InvalidMessage())

client.set_settable_address(4363, int)
client.set_settable_address(4363, int)

await self.assertAsyncRaisesRegex(ValloxWebsocketException, "Websocket handshake failed", client.set_values({
'A_CYC_RH_VALUE': 22
}))
await self.assertAsyncRaisesRegex(
ValloxWebsocketException,
"Websocket handshake failed",
client.set_values({"A_CYC_RH_VALUE": 22}),
)
24 changes: 13 additions & 11 deletions tests/test_fetch_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@

import asynctest
import websockets

from vallox_websocket_api import Vallox


def with_vallox(func):
@asynctest.patch('websockets.connect')
@asynctest.patch("websockets.connect")
async def wrapper(cls, connect):
client = Vallox('127.0.0.1')
client = Vallox("127.0.0.1")
client.set_values = asynctest.CoroutineMock()
instance = connect.return_value

Expand All @@ -33,8 +32,8 @@ async def testFetchRawLogs(self, client, ws):
:return:
"""

resp1 = b'\x03\x00\xf3\x00\x06\x00\xfc\x00'
with open(path.join(path.dirname(__file__), 'log_data.bin'), 'rb') as f:
resp1 = b"\x03\x00\xf3\x00\x06\x00\xfc\x00"
with open(path.join(path.dirname(__file__), "log_data.bin"), "rb") as f:
resp2 = f.read()
ws.recv.side_effect = [resp1, resp2]

Expand All @@ -46,9 +45,12 @@ async def testFetchRawLogs(self, client, ws):
self.assertEqual(1308, len(data[0]))
self.assertEqual(8192, len(data[1]))

self.assertEqual(data[0][0], {
'id': 0,
'name': 'extract_air_temp',
'date': datetime.datetime(2019, 7, 21, 10, 18),
'value': 24.1
})
self.assertEqual(
data[0][0],
{
"id": 0,
"name": "extract_air_temp",
"date": datetime.datetime(2019, 7, 21, 10, 18),
"value": 24.1,
},
)
Loading

0 comments on commit d3cc972

Please sign in to comment.