Skip to content

Commit

Permalink
Handle filler value for DateCode (#38)
Browse files Browse the repository at this point in the history
It appears that some EMU-2 devices will fill the date code with '\xff'
characters in some scenarios. We've already seen some fields use 0xff to
represent a sort of 'filler' value where there is no date to give. This
scenario is a little bit different because the raw representation is
0xff where before we were seeing 0xff written out in ASCII characters,
but given that the number of characters still matches documentation's
expected value I think we can draw the same conclusion here.

There are a few components to this change:
1. Switch from plain ASCII to codepage 1252 extended ASCII. This is
   actually called out in the RAVEn protocol documentation.
2. Set the _stash attribute earlier in the _reset method to limit
   the fallout of any problems feeding the XML root tag to the parser.
3. Specifically handle an all-0xFF date code as 'None'.
  • Loading branch information
cottsay authored Jan 19, 2025
1 parent 81d3322 commit 15df28a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
2 changes: 1 addition & 1 deletion aioraven/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def convert_date(raw: Optional[str]) -> Optional[date]:


def convert_date_code(raw: Optional[str]) -> Optional[Tuple[date, str]]:
if raw is not None:
if raw is not None and not all(ch == '\xff' for ch in raw):
if len(raw) >= 9:
date = convert_date(raw[:8])
if date is not None:
Expand Down
5 changes: 3 additions & 2 deletions aioraven/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ def __init__(
self._closed = self._loop.create_future()

def _reset(self) -> None:
self._parser = Et.XMLPullParser(events=('end',))
self._parser.feed(b'<?xml version="1.0" encoding="ASCII"?><root>')
self._stash = b''
self._parser = Et.XMLPullParser(events=('end',))
self._parser.feed(
b'<?xml version="1.0" encoding="Windows-1252"?><root>')

def _get_close_waiter(self, stream: Any) -> Future[None]:
return self._closed
Expand Down
38 changes: 38 additions & 0 deletions test/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,44 @@ async def test_get_device_info():
date_code=(date(2022, 1, 1), 'a0000042'))


@pytest.mark.asyncio
async def test_get_device_info_date_code_filler():
"""
Verify behavior of the ``get_device_info`` command with a filler value for
date_code.
"""
responses = {
b'<Command><Name>get_device_info</Name></Command>':
b'<DeviceInfo>'
b' <DeviceMacId>0x0123456789ABCDEF</DeviceMacId>'
b' <InstallCode>0xABCDEF0123456789</InstallCode>'
b' <LinkKey>0xABCDEF0123456789ABCDEF0123456789</LinkKey>'
b' <FWVersion>1.21g</FWVersion>'
b' <HWVersion>5.55 rev 2</HWVersion>'
b' <ImageType>Mocked</ImageType>'
b' <Manufacturer>aioraven</Manufacturer>'
b' <ModelId>Python</ModelId>'
b' <DateCode>\xff\xff\xff\xff\xff\xff\xff\xff'
b'\xff\xff\xff\xff\xff\xff\xff\xff</DateCode>'
b'</DeviceInfo>',
}

async with mock_device(responses) as (host, port):
async with RAVEnNetworkDevice(host, port) as dut:
actual = await dut.get_device_info()

assert actual == DeviceInfo(
device_mac_id=bytes.fromhex('0123456789ABCDEF'),
install_code=bytes.fromhex('ABCDEF0123456789'),
link_key=bytes.fromhex('ABCDEF0123456789ABCDEF0123456789'),
fw_version='1.21g',
hw_version='5.55 rev 2',
image_type='Mocked',
manufacturer='aioraven',
model_id='Python',
date_code=None)


@pytest.mark.asyncio
async def test_get_instantaneous_demand():
"""Verify behavior of the ``get_instantaneous_demand`` command."""
Expand Down

0 comments on commit 15df28a

Please sign in to comment.