Skip to content

Commit 80f2bf1

Browse files
committed
initial testing code addition
1 parent 8e45bce commit 80f2bf1

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed

tests/test_usb.py

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
pw_circle = importlib.import_module("plugwise_usb.nodes.circle")
3737
pw_sed = importlib.import_module("plugwise_usb.nodes.sed")
3838
pw_scan = importlib.import_module("plugwise_usb.nodes.scan")
39+
pw_sense = importlib.import_module("plugwise_usb.nodes.sense")
3940
pw_switch = importlib.import_module("plugwise_usb.nodes.switch")
4041
pw_energy_counter = importlib.import_module("plugwise_usb.nodes.helpers.counter")
4142
pw_energy_calibration = importlib.import_module("plugwise_usb.nodes.helpers")
@@ -2312,6 +2313,255 @@ async def load_callback(event: pw_api.NodeEvent, mac: str) -> None: # type: ign
23122313
)
23132314
assert not state[pw_api.NodeFeature.AVAILABLE].state
23142315

2316+
@pytest.mark.asyncio
2317+
async def test_sense_node(self, monkeypatch: pytest.MonkeyPatch) -> None: # noqa: PLR0915
2318+
"""Testing properties of sense."""
2319+
2320+
def fake_cache(dummy: object, setting: str) -> str | None: # noqa: PLR0911 PLR0912
2321+
"""Fake cache retrieval."""
2322+
if setting == pw_node.CACHE_FIRMWARE:
2323+
return "2011-11-3-13-7-33"
2324+
if setting == pw_node.CACHE_HARDWARE:
2325+
return "070030"
2326+
if setting == pw_node.CACHE_RELAY:
2327+
return "True"
2328+
if setting == pw_node.CACHE_NODE_INFO_TIMESTAMP:
2329+
return "2024-12-7-1-0-0"
2330+
if setting == pw_sed.CACHE_SED_AWAKE_DURATION:
2331+
return "20"
2332+
if setting == pw_sed.CACHE_SED_CLOCK_INTERVAL:
2333+
return "12600"
2334+
if setting == pw_sed.CACHE_SED_MAINTENANCE_INTERVAL:
2335+
return "60"
2336+
if setting == pw_sed.CACHE_SED_SLEEP_DURATION:
2337+
return "60"
2338+
if setting == pw_sense.CACHE_SENSE_HYSTERESIS_HUMIDITY_UPPER_BOUND:
2339+
return "60"
2340+
if setting == pw_sense.CACHE_SENSE_HYSTERESIS_HUMIDITY_LOWER_BOUND:
2341+
return "60"
2342+
if setting == pw_sense.CACHE_SENSE_HYSTERESIS_TEMPERATURE_UPPER_BOUND:
2343+
return "25.0"
2344+
if setting == pw_sense.CACHE_SENSE_HYSTERESIS_TEMPERATURE_LOWER_BOUND:
2345+
return "25.0"
2346+
return None
2347+
2348+
def fake_cache_bool(dummy: object, setting: str) -> bool | None:
2349+
"""Fake cache_bool retrieval."""
2350+
if setting in (
2351+
pw_sed.CACHE_SED_CLOCK_SYNC,
2352+
pw_sense.CACHE_SENSE_HYSTERESIS_TEMPERATURE_DIRECTION,
2353+
pw_sense.CACHE_SENSE_HYSTERESIS_HUMIDITY_DIRECTION,
2354+
):
2355+
return True
2356+
if setting in (
2357+
pw_sed.CACHE_SED_DIRTY,
2358+
pw_sense.CACHE_SENSE_HYSTERESIS_HUMIDITY_ENABLED,
2359+
pw_sense.CACHE_SENSE_HYSTERESIS_TEMPERATURE_ENABLED,
2360+
pw_sense.CACHE_SENSE_HYSTERESIS_CONFIG_DIRTY,
2361+
):
2362+
return False
2363+
return None
2364+
2365+
monkeypatch.setattr(pw_node.PlugwiseBaseNode, "_get_cache", fake_cache)
2366+
monkeypatch.setattr(
2367+
pw_node.PlugwiseBaseNode, "_get_cache_as_bool", fake_cache_bool
2368+
)
2369+
mock_stick_controller = MockStickController()
2370+
sense_config_accepted = pw_responses.NodeAckResponse()
2371+
sense_config_accepted.deserialize(
2372+
construct_message(b"0100555555555555555500B5", b"0000")
2373+
)
2374+
sense_config_failed = pw_responses.NodeAckResponse()
2375+
sense_config_failed.deserialize(
2376+
construct_message(b"0100555555555555555500B6", b"0000")
2377+
)
2378+
2379+
async def load_callback(event: pw_api.NodeEvent, mac: str) -> None: # type: ignore[name-defined]
2380+
"""Load callback for event."""
2381+
2382+
test_sense = pw_sense.PlugwiseSense(
2383+
"1298347650AFBECD",
2384+
pw_api.NodeType.SENSE,
2385+
mock_stick_controller,
2386+
load_callback,
2387+
)
2388+
assert not test_sense.cache_enabled
2389+
node_info = pw_api.NodeInfoMessage(
2390+
current_logaddress_pointer=None,
2391+
firmware=dt(2011, 11, 3, 13, 7, 33, tzinfo=UTC),
2392+
hardware="070030",
2393+
node_type=None,
2394+
relay_state=None,
2395+
)
2396+
await test_sense.update_node_details(node_info)
2397+
await test_sense.load()
2398+
2399+
# test hysteresis cache load
2400+
assert not test_sense.hysteresis_config_dirty
2401+
assert not test_sense.humidity_enabled
2402+
assert test_sense.humidity_upper_bound == 60
2403+
assert test_sense.humidity_lower_bound == 60
2404+
assert test_sense.humidity_direction
2405+
assert not test_sense.temperature_enabled
2406+
assert test_sense.temperature_upper_bound == 25
2407+
assert test_sense.temperature_lower_bound == 25
2408+
assert test_sense.temperature_direction
2409+
2410+
# test humidity upper bound
2411+
with pytest.raises(ValueError):
2412+
await test_sense.set_hysteresis_humidity_upper_bound(0)
2413+
with pytest.raises(ValueError):
2414+
await test_sense.set_hysteresis_humidity_upper_bound(100)
2415+
assert not await test_sense.set_hysteresis_humidity_upper_bound(60)
2416+
assert not test_sense.hysteresis_config_dirty
2417+
with pytest.raises(ValueError):
2418+
await test_sense.set_hysteresis_humidity_upper_bound(55)
2419+
assert not test_sense.hysteresis_config_dirty
2420+
assert await test_sense.set_hysteresis_humidity_upper_bound(65)
2421+
assert test_sense.hysteresis_config_dirty
2422+
assert test_sense.humidity_upper_bound == 65
2423+
assert not await test_sense.set_hysteresis_humidity_enabled(False)
2424+
assert await test_sense.set_hysteresis_humidity_enabled(True)
2425+
assert not await test_sense.set_hysteresis_humidity_direction(True)
2426+
assert await test_sense.set_hysteresis_humidity_direction(False)
2427+
2428+
# Restore to original settings after failed config
2429+
awake_response1 = pw_responses.NodeAwakeResponse()
2430+
awake_response1.deserialize(
2431+
construct_message(b"004F555555555555555500", b"FFFE")
2432+
)
2433+
mock_stick_controller.send_response = sense_config_failed
2434+
await test_sense._awake_response(awake_response1) # pylint: disable=protected-access
2435+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2436+
await test_sense._awake_response(awake_response1) # pylint: disable=protected-access
2437+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2438+
assert test_sense.hysteresis_config_dirty
2439+
2440+
# Successful config
2441+
awake_response2 = pw_responses.NodeAwakeResponse()
2442+
awake_response2.deserialize(
2443+
construct_message(b"004F555555555555555500", b"FFFE")
2444+
)
2445+
awake_response2.timestamp = awake_response1.timestamp + td(
2446+
seconds=pw_sed.AWAKE_RETRY
2447+
)
2448+
mock_stick_controller.send_response = sense_config_accepted
2449+
await test_sense._awake_response(awake_response2) # pylint: disable=protected-access
2450+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2451+
await test_sense._awake_response(awake_response2) # pylint: disable=protected-access
2452+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2453+
assert not test_sense.hysteresis_config_dirty
2454+
assert test_sense.humidity_upper_bound == 65
2455+
2456+
# test humidity lower bound
2457+
with pytest.raises(ValueError):
2458+
await test_sense.set_hysteresis_humidity_lower_bound(0)
2459+
with pytest.raises(ValueError):
2460+
await test_sense.set_hysteresis_humidity_lower_bound(100)
2461+
assert not await test_sense.set_hysteresis_humidity_lower_bound(60)
2462+
assert not test_sense.hysteresis_config_dirty
2463+
with pytest.raises(ValueError):
2464+
await test_sense.set_hysteresis_humidity_lower_bound(70)
2465+
assert not test_sense.hysteresis_config_dirty
2466+
assert await test_sense.set_hysteresis_humidity_lower_bound(55)
2467+
assert test_sense.hysteresis_config_dirty
2468+
assert test_sense.humidity_lower_bound == 55
2469+
2470+
# Successful config
2471+
awake_response3 = pw_responses.NodeAwakeResponse()
2472+
awake_response3.deserialize(
2473+
construct_message(b"004F555555555555555500", b"FFFE")
2474+
)
2475+
awake_response3.timestamp = awake_response2.timestamp + td(
2476+
seconds=pw_sed.AWAKE_RETRY
2477+
)
2478+
mock_stick_controller.send_response = sense_config_accepted
2479+
await test_sense._awake_response(awake_response3) # pylint: disable=protected-access
2480+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2481+
await test_sense._awake_response(awake_response3) # pylint: disable=protected-access
2482+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2483+
assert not test_sense.hysteresis_config_dirty
2484+
assert test_sense.humidity_lower_bound == 55
2485+
2486+
# test temperature upper bound
2487+
with pytest.raises(ValueError):
2488+
await test_sense.set_hysteresis_temperature_upper_bound(0)
2489+
with pytest.raises(ValueError):
2490+
await test_sense.set_hysteresis_temperature_upper_bound(61)
2491+
assert not await test_sense.set_hysteresis_temperature_upper_bound(25)
2492+
assert not test_sense.hysteresis_config_dirty
2493+
with pytest.raises(ValueError):
2494+
await test_sense.set_hysteresis_temperature_upper_bound(24)
2495+
assert not test_sense.hysteresis_config_dirty
2496+
assert await test_sense.set_hysteresis_temperature_upper_bound(26)
2497+
assert test_sense.hysteresis_config_dirty
2498+
assert test_sense.temperature_upper_bound == 26
2499+
assert not await test_sense.set_hysteresis_temperature_enabled(False)
2500+
assert await test_sense.set_hysteresis_temperature_enabled(True)
2501+
assert not await test_sense.set_hysteresis_temperature_direction(True)
2502+
assert await test_sense.set_hysteresis_temperature_direction(False)
2503+
2504+
# Restore to original settings after failed config
2505+
awake_response4 = pw_responses.NodeAwakeResponse()
2506+
awake_response4.deserialize(
2507+
construct_message(b"004F555555555555555500", b"FFFE")
2508+
)
2509+
awake_response4.timestamp = awake_response3.timestamp + td(
2510+
seconds=pw_sed.AWAKE_RETRY
2511+
)
2512+
mock_stick_controller.send_response = sense_config_failed
2513+
await test_sense._awake_response(awake_response4) # pylint: disable=protected-access
2514+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2515+
await test_sense._awake_response(awake_response4) # pylint: disable=protected-access
2516+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2517+
assert test_sense.hysteresis_config_dirty
2518+
2519+
# Successful config
2520+
awake_response5 = pw_responses.NodeAwakeResponse()
2521+
awake_response5.deserialize(
2522+
construct_message(b"004F555555555555555500", b"FFFE")
2523+
)
2524+
awake_response5.timestamp = awake_response4.timestamp + td(
2525+
seconds=pw_sed.AWAKE_RETRY
2526+
)
2527+
mock_stick_controller.send_response = sense_config_accepted
2528+
await test_sense._awake_response(awake_response5) # pylint: disable=protected-access
2529+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2530+
await test_sense._awake_response(awake_response5) # pylint: disable=protected-access
2531+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2532+
assert not test_sense.hysteresis_config_dirty
2533+
assert test_sense.temperature_upper_bound == 26
2534+
2535+
# test temperature lower bound
2536+
with pytest.raises(ValueError):
2537+
await test_sense.set_hysteresis_temperature_lower_bound(0)
2538+
with pytest.raises(ValueError):
2539+
await test_sense.set_hysteresis_temperature_lower_bound(61)
2540+
assert not await test_sense.set_hysteresis_temperature_lower_bound(25)
2541+
assert not test_sense.hysteresis_config_dirty
2542+
with pytest.raises(ValueError):
2543+
await test_sense.set_hysteresis_temperature_lower_bound(27)
2544+
assert not test_sense.hysteresis_config_dirty
2545+
assert await test_sense.set_hysteresis_temperature_lower_bound(24)
2546+
assert test_sense.hysteresis_config_dirty
2547+
assert test_sense.temperature_lower_bound == 24
2548+
2549+
# Successful config
2550+
awake_response6 = pw_responses.NodeAwakeResponse()
2551+
awake_response6.deserialize(
2552+
construct_message(b"004F555555555555555500", b"FFFE")
2553+
)
2554+
awake_response6.timestamp = awake_response5.timestamp + td(
2555+
seconds=pw_sed.AWAKE_RETRY
2556+
)
2557+
mock_stick_controller.send_response = sense_config_accepted
2558+
await test_sense._awake_response(awake_response6) # pylint: disable=protected-access
2559+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2560+
await test_sense._awake_response(awake_response6) # pylint: disable=protected-access
2561+
await asyncio.sleep(0.001) # Ensure time for task to be executed
2562+
assert not test_sense.hysteresis_config_dirty
2563+
assert test_sense.temperature_lower_bound == 24
2564+
23152565
@pytest.mark.asyncio
23162566
async def test_switch_node(self, monkeypatch: pytest.MonkeyPatch) -> None:
23172567
"""Testing properties of switch."""

0 commit comments

Comments
 (0)