From cace50a03059a8b742b943d25038aef072049170 Mon Sep 17 00:00:00 2001 From: Sonya Vasquez Date: Mon, 9 Sep 2024 10:38:14 -0700 Subject: [PATCH 1/5] add u8 arrays --- examples/get_info.py | 8 ++++---- pyharp/device.py | 1 + pyharp/messages.py | 35 ++++++++++++++++++++++++++++++----- tests/test_messages.py | 4 ++++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/examples/get_info.py b/examples/get_info.py index d7b7a47..32dffe6 100755 --- a/examples/get_info.py +++ b/examples/get_info.py @@ -16,8 +16,8 @@ # Open serial connection and save communication to a file if os.name == 'posix': # check for Linux. #device = Device("/dev/harp_device_00", "ibl.bin") - #device = Device("/dev/ttyACM0") - device = Device("/dev/ttyUSB0") + device = Device("/dev/ttyACM0") + #device = Device("/dev/ttyUSB0") else: # assume Windows. device = Device("COM95", "ibl.bin") device.info() # Display device's info on screen @@ -37,8 +37,8 @@ device_assembly = device.ASSEMBLY_VERSION # Get device's assembly version reg_dump = device.dump_registers() -for i in range(11): - print(reg_dump[i]) +for reg in reg_dump: + print(reg) # Close connection device.disconnect() diff --git a/pyharp/device.py b/pyharp/device.py index 547639f..1f7a0a1 100644 --- a/pyharp/device.py +++ b/pyharp/device.py @@ -256,6 +256,7 @@ def disable_alive_en(self): def send(self, message_bytes: bytearray, dump: bool = True) -> ReplyHarpMessage: """Send a harp message; return the device's reply.""" #print(f"Sending: {repr(message_bytes)}") + self.log.debug(f"sent: {repr(message_bytes)}") self._ser.write(message_bytes) # TODO: handle case where read is None diff --git a/pyharp/messages.py b/pyharp/messages.py index 3d34af4..babeb77 100644 --- a/pyharp/messages.py +++ b/pyharp/messages.py @@ -1,7 +1,7 @@ from __future__ import annotations # for type hints (PEP 563) from enum import Enum # from abc import ABC, abstractmethod -from typing import Union, Tuple, Optional +from typing import Union, Tuple, Optional, List import struct @@ -123,6 +123,10 @@ def ReadU16(address: int) -> ReadU16HarpMessage: def ReadU32(address: int) -> ReadU32HarpMessage: return ReadU32HarpMessage(address) + @staticmethod + def ReadS32(address: int) -> ReadS32HarpMessage: + return ReadS32HarpMessage(address) + @staticmethod def ReadFloat(address: int) -> ReadFloatHarpMessage: return ReadFloatHarpMessage(address) @@ -155,6 +159,9 @@ def WriteU32(address: int, value: int) -> WriteU32HarpMessage: def WriteS32(address: int, value: int) -> WriteS32HarpMessage: return WriteS32HarpMessage(address, value) + def WriteS32Array(address: int, value: list[int]) -> WriteS32HarpMessage: + return WriteS32ArrayHarpMessage(address, value) + @staticmethod def parse(frame: bytearray) -> ReplyHarpMessage: return ReplyHarpMessage(frame) @@ -287,6 +294,9 @@ class ReadU32HarpMessage(ReadHarpMessage): def __init__(self, address: int): super().__init__(PayloadType.U32, address) +class ReadS32HarpMessage(ReadHarpMessage): + def __init__(self, address: int): + super().__init__(PayloadType.S32, address) class ReadFloatHarpMessage(ReadHarpMessage): def __init__(self, address: int): @@ -393,12 +403,27 @@ def payload(self) -> int: return int.from_bytes(self._frame[5:9], byteorder="little", signed=False) -class WriteS32HarpMessage(WriteHarpMessage): +class WriteU8ArrayMessage(WriteHarpMessage): + def __init__(self, address: int, data_format, value: Union[list, tuple]): + self.data_format = data_format + packed_data = struct.pack(self.data_format, *value) + super().__init__(PayloadType.U8, packed_data, address, + offset=(len(packed_data)-1)) + + @property + def payload(self) -> List[int]: + return struct.unpack('{self.data_format}', self._frame[5:4*self.payload_count])[0] + + +class WriteS32ArrayHarpMessage(WriteHarpMessage): def __init__(self, address: int, value: int): + self.payload_count = len(value) super().__init__( - PayloadType.S32, value.to_bytes(4, byteorder="little", signed=True), address, offset=3 - ) + PayloadType.S32, + struct.pack('<{len(value)l', *value), + address, offset=(4*self.payload_count - 1)) + @property def payload(self) -> int: - return int.from_bytes(self._frame[5:9], byteorder="little", signed=True) + return struct.unpack('<{self.payload_count}l', self._frame[5:4*self.payload_count])[0] diff --git a/tests/test_messages.py b/tests/test_messages.py index 1100ae9..24a904e 100644 --- a/tests/test_messages.py +++ b/tests/test_messages.py @@ -79,6 +79,10 @@ def test_create_write_S16() -> None: print(message.frame) +def test_create_writeS32() -> None: + assert False + + def test_read_who_am_i() -> None: message = HarpMessage.ReadU16(CommonRegisters.WHO_AM_I) From b2182ae273196496ca8792d0e2d754954de6fe9d Mon Sep 17 00:00:00 2001 From: Sonya Vasquez Date: Fri, 21 Feb 2025 10:55:06 -0800 Subject: [PATCH 2/5] undo get info example change --- examples/get_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/get_info.py b/examples/get_info.py index 32dffe6..71cd01a 100755 --- a/examples/get_info.py +++ b/examples/get_info.py @@ -16,8 +16,8 @@ # Open serial connection and save communication to a file if os.name == 'posix': # check for Linux. #device = Device("/dev/harp_device_00", "ibl.bin") - device = Device("/dev/ttyACM0") - #device = Device("/dev/ttyUSB0") + #device = Device("/dev/ttyACM0") + device = Device("/dev/ttyUSB0") else: # assume Windows. device = Device("COM95", "ibl.bin") device.info() # Display device's info on screen From f6f5a77159b02387a6860fd819a00a783cab4f27 Mon Sep 17 00:00:00 2001 From: Sonya Vasquez Date: Fri, 21 Feb 2025 10:58:51 -0800 Subject: [PATCH 3/5] undo unused test --- tests/test_messages.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_messages.py b/tests/test_messages.py index 24a904e..1100ae9 100644 --- a/tests/test_messages.py +++ b/tests/test_messages.py @@ -79,10 +79,6 @@ def test_create_write_S16() -> None: print(message.frame) -def test_create_writeS32() -> None: - assert False - - def test_read_who_am_i() -> None: message = HarpMessage.ReadU16(CommonRegisters.WHO_AM_I) From 9e2783503a2cc818c518547beb9c322e3ebf1f19 Mon Sep 17 00:00:00 2001 From: Sonya Vasquez Date: Fri, 6 Jun 2025 14:07:19 -0700 Subject: [PATCH 4/5] name harpserial threads; make both daemon threads --- pyharp/harp_serial.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyharp/harp_serial.py b/pyharp/harp_serial.py index 3b9d4a2..57e647e 100644 --- a/pyharp/harp_serial.py +++ b/pyharp/harp_serial.py @@ -48,10 +48,13 @@ def __init__(self, serial_port: str, **kwargs): self._ser, partial(HarpSerialProtocol, self._read_q), ) + self._reader.daemon = True + self._reader.name = f"{serial_port}_harp_serial_reader_worker" self._reader.start() transport, protocol = self._reader.connect() self._parse_thread = threading.Thread( + name=f"{serial_port}_harp_serial_parse_worker", target=self.parse_harp_msgs_threaded, daemon=True, ) From bb009592a683a31ca61df356f276ef8df14b493e Mon Sep 17 00:00:00 2001 From: Sonya Vasquez Date: Mon, 9 Jun 2025 11:42:57 -0700 Subject: [PATCH 5/5] add debug log message --- pyharp/device.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyharp/device.py b/pyharp/device.py index 13df1a2..32419fd 100644 --- a/pyharp/device.py +++ b/pyharp/device.py @@ -97,6 +97,7 @@ def disconnect(self) -> None: self._ser.close() def read_who_am_i(self) -> int: + self.log.debug("Requesting whoami.") address = CommonRegisters.WHO_AM_I reply: ReplyHarpMessage = self.send( @@ -306,4 +307,4 @@ def get_events(self) -> list[ReplyHarpMessage]: def event_count(self) -> int: """Get the number of events in the event queue.""" - return self._ser.event_q.qsize() \ No newline at end of file + return self._ser.event_q.qsize()