feat(pm3py): validate PWM LED capability using device capabilities, raise on non-PWM LEDs
This commit is contained in:
@@ -12,6 +12,15 @@ def make_mock_transport():
|
||||
transport = AsyncMock()
|
||||
return transport
|
||||
|
||||
def _make_caps_response(is_rdv4=False):
|
||||
"""Build a capabilities response with is_rdv4 flag."""
|
||||
# version(1) + baudrate(4) + bigbuf_size(4) + 4 bytes of flags
|
||||
flags = bytearray(4)
|
||||
flags[0] = 0x80 # compiled_with_lf
|
||||
if is_rdv4:
|
||||
flags[3] = 0x02 # is_rdv4 at byte 12 bit 1
|
||||
return make_ng_response(Cmd.CAPABILITIES, 0, struct.pack("<BII", 7, 115200, 40000) + bytes(flags))
|
||||
|
||||
def test_ping():
|
||||
transport = make_mock_transport()
|
||||
hw = HWCommands(transport)
|
||||
@@ -49,15 +58,17 @@ def test_led_on_by_name():
|
||||
def test_led_pulse():
|
||||
transport = make_mock_transport()
|
||||
hw = HWCommands(transport)
|
||||
# pulse on "red" (C=0x04) — not PWM-capable on Easy, so pre-set as RDV4
|
||||
hw._is_rdv4 = True # skip capabilities fetch; RDV4 has PWM on A,D only... but red=C
|
||||
# Actually red=C is not PWM on either platform. Use "orange" (A) which is PWM on both.
|
||||
transport.send_ng.return_value = make_ng_response(Cmd.LED_CONTROL, 0, b"")
|
||||
result = asyncio.get_event_loop().run_until_complete(
|
||||
hw.led("red", pulse=True, speed=300, count=3))
|
||||
transport.send_ng.assert_called_once()
|
||||
# Verify the payload
|
||||
hw.led("orange", pulse=True, speed=300, count=3))
|
||||
# Verify the payload (last call to send_ng)
|
||||
call_args = transport.send_ng.call_args
|
||||
payload = call_args[0][1] # second positional arg
|
||||
payload = call_args[0][1]
|
||||
led_mask, action, brightness, speed, count = struct.unpack("<BBBHH", payload)
|
||||
assert led_mask == 0x04 # red = C
|
||||
assert led_mask == 0x01 # orange = A
|
||||
assert action == 4 # pulse
|
||||
assert speed == 300
|
||||
assert count == 3
|
||||
@@ -65,10 +76,23 @@ def test_led_pulse():
|
||||
def test_led_brightness():
|
||||
transport = make_mock_transport()
|
||||
hw = HWCommands(transport)
|
||||
# Pre-cache as Easy — PWM capable on A,B only
|
||||
hw._is_rdv4 = False
|
||||
transport.send_ng.return_value = make_ng_response(Cmd.LED_CONTROL, 0, b"")
|
||||
result = asyncio.get_event_loop().run_until_complete(hw.led("all", brightness=50))
|
||||
result = asyncio.get_event_loop().run_until_complete(hw.led("green", brightness=50))
|
||||
payload = transport.send_ng.call_args[0][1]
|
||||
led_mask, action, bright, _, _ = struct.unpack("<BBBHH", payload)
|
||||
assert led_mask == 0x0F # all
|
||||
assert led_mask == 0x02 # green = B
|
||||
assert action == 3 # pwm
|
||||
assert bright == 50
|
||||
|
||||
def test_led_pwm_non_capable_raises():
|
||||
"""PWM on a non-PWM LED should raise PM3Error."""
|
||||
from pm3py.transport import PM3Error
|
||||
import pytest
|
||||
transport = make_mock_transport()
|
||||
hw = HWCommands(transport)
|
||||
hw._is_rdv4 = False # Easy: only A,B support PWM
|
||||
with pytest.raises(PM3Error, match="do not support"):
|
||||
asyncio.get_event_loop().run_until_complete(
|
||||
hw.led("blue", brightness=50)) # blue=D, not PWM on Easy
|
||||
|
||||
Reference in New Issue
Block a user