Skip to content

Commit

Permalink
[hotfix] remove write analog (#782)
Browse files Browse the repository at this point in the history
  • Loading branch information
njooma authored Nov 5, 2024
1 parent fd55651 commit 1f8974a
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 85 deletions.
13 changes: 0 additions & 13 deletions src/viam/components/board/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,19 +225,6 @@ async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeou
md = kwargs.get("metadata", self.Metadata())
return await get_geometries(self.client, self.name, extra, timeout, md)

async def write_analog(
self,
pin: str,
value: int,
*,
extra: Optional[Dict[str, Any]] = None,
timeout: Optional[float] = None,
**kwargs,
):
md = kwargs.get("metadata", self.Metadata()).proto
request = WriteAnalogRequest(name=self.name, pin=pin, value=value, extra=dict_to_struct(extra))
await self.client.WriteAnalog(request, timeout=timeout, metadata=md)

async def stream_ticks(
self,
interrupts: List[Board.DigitalInterrupt],
Expand Down
12 changes: 3 additions & 9 deletions tests/mocks/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,23 +242,17 @@ async def read(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optiona
async def write(self, value: int, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs):
self.extra = extra
self.timeout = timeout
self.value = value
self.value.value = value


class MockDigitalInterrupt(Board.DigitalInterrupt):
def __init__(self, name: str):
self.high = False
self.last_tick = 0
self.num_ticks = 0
self.val = 182
super().__init__(name)

async def value(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> int:
return self.num_ticks

async def tick(self, high: bool, nanos: int): # Call this to get the mock interrupt to change
self.high = high
self.last_tick = nanos
self.num_ticks += 1
return self.val


class MockGPIOPin(Board.GPIOPin):
Expand Down
151 changes: 88 additions & 63 deletions tests/test_board.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from grpclib import GRPCError
from grpclib.testing import ChannelFor

from viam.components.board import BoardClient, BoardStatus, create_status
from viam.components.board import Board, BoardClient, BoardStatus, create_status
from viam.components.board.service import BoardRPCService
from viam.components.generic.service import GenericRPCService
from viam.errors import ResourceNotFoundError
Expand Down Expand Up @@ -41,17 +41,27 @@


@pytest.fixture(scope="function")
def board() -> MockBoard:
def analog() -> MockAnalog:
return MockAnalog("analog1", 3, 0.0, 1.0, 0.1)


@pytest.fixture(scope="function")
def interrupt() -> MockDigitalInterrupt:
return MockDigitalInterrupt("interrupt1")


@pytest.fixture(scope="function")
def gpio_pin() -> MockGPIOPin:
return MockGPIOPin("pin1")


@pytest.fixture(scope="function")
def board(analog: Board.Analog, interrupt: Board.DigitalInterrupt, gpio_pin: Board.GPIOPin) -> MockBoard:
return MockBoard(
name="board",
analogs={
"reader1": MockAnalog("reader1", 3, 0.0, 1.0, 0.1),
"writer1": MockAnalog("writer1", 5, 0.0, 1.0, 0.1),
},
digital_interrupts={
"interrupt1": MockDigitalInterrupt("interrupt1"),
},
gpio_pins={"pin1": MockGPIOPin("pin1")},
analogs={analog.name: analog},
digital_interrupts={interrupt.name: interrupt},
gpio_pins={gpio_pin.name: gpio_pin},
)


Expand All @@ -68,12 +78,26 @@ def generic_service(board: MockBoard) -> GenericRPCService:


class TestBoard:
class TestAnalog:
async def test_read(self, analog: MockAnalog):
value = await analog.read()
assert value == analog.value

async def test_write(self, analog: MockAnalog):
await analog.write(8)
assert analog.value.value == 8

class TestDigitalInterrupt:
async def test_value(self, interrupt: MockDigitalInterrupt):
value = await interrupt.value()
assert value == interrupt.val

async def test_analog_by_name(self, board: MockBoard):
with pytest.raises(ResourceNotFoundError):
await board.analog_by_name("does not exist")

reader = await board.analog_by_name("reader1")
assert reader.name == "reader1"
reader = await board.analog_by_name("analog1")
assert reader.name == "analog1"

async def test_digital_interrupt_by_name(self, board: MockBoard):
with pytest.raises(ResourceNotFoundError):
Expand All @@ -91,7 +115,7 @@ async def test_gpio_pin_by_name(self, board: MockBoard):

async def test_analog_names(self, board: MockBoard):
names = await board.analog_names()
assert names == ["reader1", "writer1"]
assert names == ["analog1"]

async def test_digital_interrupt_names(self, board: MockBoard):
names = await board.digital_interrupt_names()
Expand All @@ -104,15 +128,12 @@ async def test_do(self, board: MockBoard):

async def test_status(self, board: MockBoard):
status = await create_status(board)
read1 = await board.analogs["reader1"].read()
# Analog writers typically don't have read statuses, but the mock board
# doesn't make that distinction.
read2 = await board.analogs["writer1"].read()
analog = await board.analogs["analog1"].read()
val = await board.digital_interrupts["interrupt1"].value()
assert status.name == MockBoard.get_resource_name(board.name)
assert status.status == message_to_struct(
BoardStatus(
analogs={"reader1": int(read1.value), "writer1": int(read2.value)},
analogs={"analog1": int(analog.value)},
digital_interrupts={"interrupt1": val},
)
)
Expand All @@ -129,15 +150,6 @@ async def test_get_geometries(self, board: MockBoard):
geometries = await board.get_geometries()
assert geometries == GEOMETRIES

async def test_write_analog(self, board: MockBoard):
value = 10
pin = "writer1"
writer = await board.analog_by_name(name=pin)
await writer.write(value=value, timeout=1.11)
assert writer.timeout == loose_approx(1.11)
assert writer.value == value
assert writer.name == pin

async def test_stream_ticks(self, board: MockBoard):
int1 = board.digital_interrupts["interrupt1"]
async for tick in await board.stream_ticks([int1]):
Expand All @@ -156,18 +168,18 @@ async def test_read_analog(self, board: MockBoard, service: BoardRPCService):
await client.ReadAnalogReader(request)

extra = {"foo": "bar", "baz": [1, 2, 3]}
request = ReadAnalogReaderRequest(board_name=board.name, analog_reader_name="reader1", extra=dict_to_struct(extra))
request = ReadAnalogReaderRequest(board_name=board.name, analog_reader_name="analog1", extra=dict_to_struct(extra))
response: ReadAnalogReaderResponse = await client.ReadAnalogReader(request, timeout=4.4)
assert response.value == 3
assert response.min_range == 0.0
assert response.max_range == 1.0
assert response.step_size == pytest.approx(0.1)

reader = cast(MockAnalog, board.analogs["reader1"])
reader = cast(MockAnalog, board.analogs["analog1"])
assert reader.extra == extra
assert reader.timeout == loose_approx(4.4)

async def test_get_digital_interrupt_value(self, board: MockBoard, service: BoardRPCService):
async def test_get_digital_interrupt_value(self, board: MockBoard, service: BoardRPCService, interrupt: MockDigitalInterrupt):
async with ChannelFor([service]) as channel:
client = BoardServiceStub(channel)

Expand All @@ -177,7 +189,7 @@ async def test_get_digital_interrupt_value(self, board: MockBoard, service: Boar

request = GetDigitalInterruptValueRequest(board_name=board.name, digital_interrupt_name="interrupt1")
response: GetDigitalInterruptValueResponse = await client.GetDigitalInterruptValue(request)
assert response.value == 0
assert response.value == interrupt.val

async def test_set_gpio(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
Expand Down Expand Up @@ -293,14 +305,14 @@ async def test_set_power_mode(self, board: MockBoard, service: BoardRPCService):
async def test_write_analog(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
client = BoardServiceStub(channel)
pin = "writer1"
pin = "analog1"
value = 10
request = WriteAnalogRequest(name=board.name, pin=pin, value=value)
response: WriteAnalogResponse = await client.WriteAnalog(request, timeout=6.66)
assert response == WriteAnalogResponse()
mock_analog = cast(MockAnalog, board.analogs["writer1"])
mock_analog = cast(MockAnalog, board.analogs["analog1"])
assert mock_analog.timeout == loose_approx(6.66)
assert mock_analog.value == value
assert mock_analog.value.value == value
assert mock_analog.name == pin

#
Expand Down Expand Up @@ -330,8 +342,8 @@ async def test_analog_by_name(self, board: MockBoard, service: BoardRPCService):
with pytest.raises(GRPCError, match=r".*Status.NOT_FOUND.*"):
await reader.read()

reader = await client.analog_by_name("reader1")
assert reader.name == "reader1"
reader = await client.analog_by_name("analog1")
assert reader.name == "analog1"

async def test_digital_interrupt_by_name(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
Expand Down Expand Up @@ -361,11 +373,11 @@ async def test_analog_names(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
client = BoardClient(name=board.name, channel=channel)

reader = await client.analog_by_name("reader1")
assert reader.name == "reader1"
reader = await client.analog_by_name("analog1")
assert reader.name == "analog1"

names = await client.analog_names()
assert names == ["reader1"]
assert names == ["analog1"]

async def test_digital_interrupt_names(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
Expand Down Expand Up @@ -396,13 +408,50 @@ async def test_set_power_mode(self, board: MockBoard, service: BoardRPCService):
pm_duration.FromTimedelta(pm_timedelta)
assert board.power_mode_duration == pm_duration.ToTimedelta()

async def test_stream_ticks(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
client = BoardClient(name=board.name, channel=channel)
di = await client.digital_interrupt_by_name("interrupt1")

tick_stream = await client.stream_ticks(interrupts=[di])
async for tick in tick_stream:
assert tick.pin_name == "interrupt1"
assert tick.high is True
assert tick.time == 1000
break

async def test_extra(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
client = BoardClient(board.name, channel)
geometries = await client.get_geometries()
assert geometries == GEOMETRIES


class TestAnalogClient:
async def test_read(self, analog: MockAnalog, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
board_client = BoardClient(name=board.name, channel=channel)
analog_client = await board_client.analog_by_name("analog1")
value = await analog_client.read()
assert value == analog.value

async def test_write(self, analog: MockAnalog, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
board_client = BoardClient(name=board.name, channel=channel)
analog_client = await board_client.analog_by_name("analog1")
await analog_client.write(45)
assert analog.value.value == 45


class TestDigitalInterrupt:
async def test_value(self, interrupt: MockDigitalInterrupt, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
board_client = BoardClient(name=board.name, channel=channel)
interrupt_client = await board_client.digital_interrupt_by_name("interrupt1")
value = await interrupt_client.value()
assert value == interrupt.val


class TestGPIOPinClient:
async def test_set(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
Expand Down Expand Up @@ -470,27 +519,3 @@ async def test_get_pwm_freq(self, board: MockBoard, service: BoardRPCService):
mock_pin = cast(MockGPIOPin, board.gpios["pin1"])
assert mock_pin.extra == extra
assert mock_pin.timeout is None

async def test_write_analog(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
client = BoardClient(name=board.name, channel=channel)
writer = await client.analog_by_name("writer1")
value = 42
extra = {"foo": "bar", "baz": [1, 2, 3]}
await writer.write(value, extra=extra)
mock_analog = cast(MockAnalog, board.analogs["writer1"])
assert mock_analog.name == "writer1"
assert mock_analog.value == 42
assert mock_analog.extra == extra

async def test_stream_ticks(self, board: MockBoard, service: BoardRPCService):
async with ChannelFor([service]) as channel:
client = BoardClient(name=board.name, channel=channel)
di = await client.digital_interrupt_by_name("interrupt1")

tick_stream = await client.stream_ticks(interrupts=[di])
async for tick in tick_stream:
assert tick.pin_name == "interrupt1"
assert tick.high is True
assert tick.time == 1000
break

0 comments on commit 1f8974a

Please sign in to comment.