|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +import os |
| 4 | +import binascii |
| 5 | + |
| 6 | +import infuse_iot.generated.rpc_definitions as defs |
| 7 | +from infuse_iot.commands import InfuseRpcCommand |
| 8 | +from infuse_iot.util.ctypes import UINT32_MAX |
| 9 | + |
| 10 | + |
| 11 | +class data_logger_read(InfuseRpcCommand, defs.data_logger_read): |
| 12 | + RPC_DATA_RECEIVE = True |
| 13 | + |
| 14 | + @classmethod |
| 15 | + def add_parser(cls, parser): |
| 16 | + logger = parser.add_mutually_exclusive_group(required=True) |
| 17 | + logger.add_argument("--onboard", action="store_true", help="Onboard flash logger") |
| 18 | + logger.add_argument("--removable", action="store_true", help="Removable flash logger (SD)") |
| 19 | + parser.add_argument("--start", type=int, default=0, help="First logger block to read (default 0)") |
| 20 | + parser.add_argument("--last", type=int, default=UINT32_MAX, help="Last logger block to read (default all)") |
| 21 | + |
| 22 | + def __init__(self, args): |
| 23 | + self.infuse_id = args.id |
| 24 | + self.start = args.start |
| 25 | + self.last = args.last |
| 26 | + if args.onboard: |
| 27 | + self.logger = defs.rpc_enum_data_logger.FLASH_ONBOARD |
| 28 | + elif args.removable: |
| 29 | + self.logger = defs.rpc_enum_data_logger.FLASH_REMOVABLE |
| 30 | + else: |
| 31 | + raise NotImplementedError |
| 32 | + self.expected_offset = 0 |
| 33 | + self.output = b"" |
| 34 | + |
| 35 | + def request_struct(self): |
| 36 | + return self.request(self.logger, self.start, self.last) |
| 37 | + |
| 38 | + def request_json(self): |
| 39 | + return {"logger": self.logger.name, "start_block": self.start, "last_block": self.last} |
| 40 | + |
| 41 | + def data_recv_cb(self, offset: int, data: bytes) -> None: |
| 42 | + if offset != self.expected_offset: |
| 43 | + missing = offset - self.expected_offset |
| 44 | + print(f"Missed {missing:d} bytes from offset 0x{self.expected_offset:08x}") |
| 45 | + self.output += b"\x00" * missing |
| 46 | + |
| 47 | + self.output += data |
| 48 | + # Next expected offset |
| 49 | + self.expected_offset = offset + len(data) |
| 50 | + |
| 51 | + def handle_response(self, return_code, response): |
| 52 | + if return_code != 0: |
| 53 | + print(f"Failed to read data logger ({os.strerror(-return_code)})") |
| 54 | + return |
| 55 | + |
| 56 | + if response.sent_len != len(self.output): |
| 57 | + print(f"Unexpected received length ({response.sent_len} != {len(self.output)})") |
| 58 | + return |
| 59 | + |
| 60 | + if response.sent_crc != binascii.crc32(self.output): |
| 61 | + print(f"Unexpected received length ({response.sent_crc:08x} != {binascii.crc32(self.output)}:08x)") |
| 62 | + return |
| 63 | + |
| 64 | + output_file = f"{self.infuse_id:016x}_{self.logger.name}.bin" |
| 65 | + with open(output_file, "wb") as f: |
| 66 | + f.write(self.output) |
| 67 | + print(f"Wrote {response.sent_len:d} bytes to {output_file}") |
0 commit comments