Skip to content

Commit fe46ffd

Browse files
authored
Fix for Skyfi making less frequent requests (#30)
* more and better debug-logging * add a sleep of 0.3 after each request * add string representation of ApplianceValues * update tests with complete coverage for SkyFi
1 parent 65f828f commit fe46ffd

File tree

5 files changed

+103
-25
lines changed

5 files changed

+103
-25
lines changed

pydaikin/daikin_skyfi.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Pydaikin appliance, represent a Daikin device."""
22

3+
from asyncio import sleep
34
import logging
45
from urllib.parse import unquote
56

@@ -49,6 +50,8 @@ class DaikinSkyFi(Appliance):
4950
},
5051
}
5152

53+
MAX_CONCURRENT_REQUESTS = 1
54+
5255
def __init__(
5356
self,
5457
device_id: str,
@@ -96,7 +99,7 @@ def support_swing_mode(self):
9699
@staticmethod
97100
def parse_response(response_body):
98101
"""Parse response from Daikin and map it to general Daikin format."""
99-
_LOGGER.debug("Parsing %s", response_body)
102+
_LOGGER.debug("Parsing response %s", response_body)
100103
response = dict([e.split('=') for e in response_body.split('&')])
101104
if response.get('fanflags') == '3':
102105
response['fanspeed'] = str(int(response['fanspeed']) + 4)
@@ -114,7 +117,9 @@ async def _get_resource(self, path: str, params: dict | None = None):
114117
params = {}
115118
# ensure password is the first parameter
116119
params = {**{"pass": self._password}, **params}
117-
return await super()._get_resource(path, params)
120+
ret = await super()._get_resource(path, params)
121+
await sleep(0.3)
122+
return ret
118123

119124
def represent(self, key):
120125
"""Return translated value from key."""
@@ -162,7 +167,7 @@ async def set(self, settings):
162167
def zones(self):
163168
"""Return list of zones."""
164169
if 'nz' not in self.values:
165-
return False
170+
return False # pragma: no cover
166171
return [
167172
v
168173
for i, v in enumerate(

pydaikin/response.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
"Function to parse responses coming in, used by multiple classes"
2+
import logging
23
import re
34
from urllib.parse import unquote
45

6+
_LOGGER = logging.getLogger(__name__)
7+
58

69
def parse_response(response_body):
710
"""Parse response from Daikin."""
11+
_LOGGER.debug("Parsing response: %s", response_body)
812
response = dict(
913
(match.group(1), match.group(2))
1014
for match in re.finditer(r'(\w+)=([^=]*)(?:,|$)', response_body)

pydaikin/values.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ def __iter__(self):
3737
def __len__(self):
3838
return len(self._data)
3939

40+
def __str__(self):
41+
return f"{self._data}"
42+
4043
# --- Custom methods to use smart updates ---
4144
def get(
4245
self, key: str, default=None, *, invalidate: bool = True

tests/test_init.py

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from pydaikin.daikin_airbase import DaikinAirBase
88
from pydaikin.daikin_brp069 import DaikinBRP069
99
from pydaikin.daikin_brp072c import DaikinBRP072C
10-
from pydaikin.daikin_skyfi import DaikinSkyFi
1110

1211

1312
@pytest_asyncio.fixture
@@ -184,27 +183,6 @@ async def test_daikinBRP072C(aresponses, client_session):
184183
aresponses.assert_no_unused_routes()
185184

186185

187-
@pytest.mark.asyncio
188-
async def test_daikinSkiFi(aresponses, client_session):
189-
aresponses.add(
190-
path_pattern="/zones.cgi",
191-
method_pattern="GET",
192-
response="nz=8&zone1=Zone%201&zone2=Zone%202&zone3=Zone%203&zone4=Zone%204&zone5=Zone%205&zone6=Zone%206&zone7=Zone%207&zone8=Zone%208",
193-
)
194-
aresponses.add(
195-
path_pattern="/ac.cgi",
196-
method_pattern="GET",
197-
response="opmode=0&units=.&settemp=24.0&fanspeed=3&fanflags=1&acmode=16&tonact=0&toffact=0&prog=0&time=23:36&day=6&roomtemp=23&outsidetemp=0&louvre=1&zone=0&flt=0&test=0&errdata=146&sensors=1",
198-
)
199-
200-
device = DaikinSkyFi('ip', session=client_session, password="xxxpasswordxxx")
201-
202-
await device.init()
203-
204-
aresponses.assert_all_requests_matched()
205-
aresponses.assert_no_unused_routes()
206-
207-
208186
@pytest.mark.asyncio
209187
async def test_daikinAirBase(aresponses, client_session):
210188
aresponses.add(

tests/test_skyfi.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""Verify that init() calls the expected set of endpoints for each Daikin device."""
2+
3+
import pytest
4+
5+
from pydaikin.daikin_skyfi import DaikinSkyFi
6+
7+
from .test_init import client_session
8+
9+
assert client_session
10+
11+
12+
@pytest.mark.asyncio
13+
async def test_daikinSkiFi(aresponses, client_session):
14+
aresponses.add(
15+
path_pattern="/zones.cgi",
16+
method_pattern="GET",
17+
response="nz=8&zone1=Zone%201&zone2=Zone%202&zone3=Zone%203&zone4=Zone%204&zone5=Zone%205&zone6=Zone%206&zone7=Zone%207&zone8=Zone%208",
18+
)
19+
aresponses.add(
20+
path_pattern="/ac.cgi",
21+
method_pattern="GET",
22+
response="opmode=0&units=.&settemp=24.0&fanspeed=3&fanflags=3&acmode=16&tonact=0&toffact=0&prog=0&time=23:36&day=6&roomtemp=23&outsidetemp=0&louvre=1&zone=0&flt=0&test=0&errdata=146&sensors=1",
23+
)
24+
25+
device = DaikinSkyFi('ip', session=client_session, password="xxxpasswordxxx")
26+
27+
await device.init()
28+
29+
aresponses.assert_all_requests_matched()
30+
aresponses.assert_no_unused_routes()
31+
32+
assert device["mode"] == '16'
33+
assert device.support_away_mode is False
34+
assert device.support_fan_rate is True
35+
assert device.support_swing_mode is False
36+
assert device.represent("zone1") == ("zone1", "Zone 1")
37+
assert device.represent("zone") == ('zone', '00000000')
38+
assert device.inside_temperature == 23.0
39+
assert device.target_temperature == 24.0
40+
assert device.outside_temperature == 0
41+
42+
assert device.represent("mode") == ('mode', 'off')
43+
44+
aresponses.add(
45+
path_pattern="/ac.cgi",
46+
method_pattern="GET",
47+
response="opmode=0&units=.&settemp=20.0&fanspeed=3&fanflags=1&acmode=16&tonact=0&toffact=0&prog=0&time=23:36&day=6&roomtemp=23&outsidetemp=0&louvre=1&zone=0&flt=0&test=0&errdata=146&sensors=1",
48+
)
49+
aresponses.add(
50+
path_pattern="/set.cgi",
51+
method_pattern="GET",
52+
response="opmode=1&units=.&settemp=20.0&fanspeed=3&fanflags=1&acmode=8&tonact=0&toffact=0&prog=0&time=23:36&day=6&roomtemp=23&outsidetemp=0&louvre=1&zone=0&flt=0&test=0&errdata=146&sensors=1",
53+
)
54+
55+
await device.set({"mode": "cool"})
56+
aresponses.assert_all_requests_matched()
57+
assert device.represent("mode") == ('mode', 'cool')
58+
assert device.target_temperature == 20.0
59+
60+
aresponses.add(
61+
path_pattern="/ac.cgi",
62+
method_pattern="GET",
63+
response="opmode=1&units=.&settemp=20.0&fanspeed=3&fanflags=1&acmode=8&tonact=0&toffact=0&prog=0&time=23:36&day=6&roomtemp=23&outsidetemp=0&louvre=1&zone=0&flt=0&test=0&errdata=146&sensors=1",
64+
)
65+
aresponses.add(
66+
path_pattern="/set.cgi",
67+
method_pattern="GET",
68+
response="opmode=0&units=.&settemp=20.0&fanspeed=3&fanflags=1&acmode=8&tonact=0&toffact=0&prog=0&time=23:36&day=6&roomtemp=23&outsidetemp=0&louvre=1&zone=0&flt=0&test=0&errdata=146&sensors=1",
69+
)
70+
await device.set({"mode": "off"})
71+
assert device.zones == [
72+
('Zone 1', '0'),
73+
('Zone 2', '0'),
74+
('Zone 3', '0'),
75+
('Zone 4', '0'),
76+
('Zone 5', '0'),
77+
('Zone 6', '0'),
78+
('Zone 7', '0'),
79+
('Zone 8', '0'),
80+
]
81+
82+
await device.set_zone(0, "zone_onoff_", 1)
83+
aresponses.add(
84+
path_pattern="/setzone.cgi",
85+
method_pattern="GET",
86+
response="opmode=0&units=.&settemp=20.0&fanspeed=3&fanflags=1&acmode=8&tonact=0&toffact=0&prog=0&time=23:36&day=6&roomtemp=23&outsidetemp=0&louvre=1&zone=128&flt=0&test=0&errdata=146&sensors=1",
87+
)
88+
await device.set_zone(0, "zone_onoff", 1)

0 commit comments

Comments
 (0)