def LifeScanPacket(include_link_control: bool, ) -> construct.Struct: # pylint: disable=invalid-name if include_link_control: link_control_construct = _LINK_CONTROL else: link_control_construct = construct.Const(b"\x00") return construct.Struct( "data" / construct.RawCopy( construct.Struct( construct.Const(b"\x02"), # stx "length" / construct.Rebuild( construct.Byte, lambda this: len(this.message) + 6), "link_control" / link_control_construct, "message" / construct.Bytes(lambda this: this.length - 6), construct.Const(b"\x03"), # etx ), ), "checksum" / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt, construct.this.data.data), )
def LifeScanPacket(include_link_control): # pylint: disable=invalid-name # type: (bool) -> construct.Struct if include_link_control: link_control_construct = _LINK_CONTROL else: link_control_construct = construct.Const(b'\x00') return construct.Struct( 'data' / construct.RawCopy( construct.Struct( construct.Const(b'\x02'), # stx 'length' / construct.Rebuild( construct.Byte, lambda this: len(this.message) + 6), 'link_control' / link_control_construct, 'message' / construct.Bytes(lambda this: this.length - 6), construct.Const(b'\x03'), # etx ), ), 'checksum' / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt, construct.this.data.data), )
def LifeScanPacket(command_prefix, include_link_control): if include_link_control: link_control_construct = _LINK_CONTROL else: link_control_construct = construct.Const(b'\x00') command_prefix_construct = construct.Const(command_prefix, construct.Byte) return construct.Struct( 'data' / construct.RawCopy( construct.Struct( construct.Const(b'\x02'), # stx 'length' / construct.Rebuild( construct.Byte, lambda this: len(this.message) + 7), 'link_control' / link_control_construct, 'command_prefix' / command_prefix_construct, 'message' / construct.Bytes(lambda this: this.length - 7), construct.Const(b'\x03'), # etx ), ), 'checksum' / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt, construct.this.data.data), )
)), seed_hash=construct.If(construct.this.header.has_seed_hash, construct.Bytes(5)), randovania_version=construct.Bytes(4), # short git hash generator_params=construct.ExprAdapter( construct.Prefixed(construct.VarInt, construct.GreedyBytes), # parsing decoder=create_rotator(inverse=True), # building encoder=create_rotator(inverse=False), ), ))), permalink_checksum=construct.Checksum( construct.Bytes(2), lambda data: hashlib.blake2b(data, digest_size=2).digest(), construct.this.fields.data, ), end=construct.Terminated, ) @dataclasses.dataclass(frozen=True) class Permalink: parameters: GeneratorParameters seed_hash: Optional[bytes] randovania_version: bytes def __post_init__(self): if len(self.randovania_version) != 4: raise ValueError(
def byte_checksum(data): return functools.reduce(operator.add, data) & 0xFF _PACKET = construct.Struct( 'data' / construct.RawCopy( construct.Struct( construct.Const(b'\x51'), 'command' / construct.Byte, 'message' / construct.Bytes(4), 'direction' / construct.Mapping(construct.Byte, {e: e.value for e in Direction}), ), ), 'checksum' / construct.Checksum(construct.Byte, byte_checksum, construct.this.data.data), ) _EMPTY_MESSAGE = 0 _CONNECT_REQUEST = 0x22 _VALID_CONNECT_RESPONSE = {0x22, 0x24, 0x54} _GET_DATETIME = 0x23 _SET_DATETIME = 0x33 _GET_MODEL = 0x24 _GET_READING_COUNT = 0x2b _GET_READING_DATETIME = 0x25 _GET_READING_VALUE = 0x26
class Direction(enum.Enum): In = 0x20 Out = 0x10 _PACKET = construct.Struct( stx=construct.Const(0x53, construct.Byte), direction=construct.Mapping(construct.Byte, {e: e.value for e in Direction}), length=construct.Rebuild(construct.Byte, lambda this: len(this.message) + 2), message=construct.Bytes(lambda this: this.length - 2), checksum=construct.Checksum(construct.Byte, xor_checksum, construct.this.message), etx=construct.Const(0xAA, construct.Byte), ) _FIRST_MESSAGE = construct.Struct( const_1=construct.Const(0x30, construct.Byte), count=construct.Int16ub, const_2=construct.Const(0xAA, construct.Byte)[19], ) _CHALLENGE_PACKET_FULL = b"\x53\x20\x04\x10\x30\x20\xAA" _RESPONSE_MESSAGE = b"\x10\x40" _DATE_SET_MESSAGE = b"\x10\x10" _DISCONNECT_MESSAGE = b"\x10\x60"
message_id_schema = c.Enum( c.Int16ul, NMEA0183=9, PROFILE6=1308, ) ping_schema = c.Struct( start=c.RawCopy(c.Const(b'BR')), payload_length=c.RawCopy(c.Int16ul), message_id=c.RawCopy(message_id_schema), src_device_id=c.RawCopy(c.Int8ul), dest_device_id=c.RawCopy(c.Int8ul), payload=c.RawCopy(c.Bytes(c.this.payload_length.value)), checksum=c.Checksum( c.Int16ul, lambda b: sum(b) % (1 << 16), lambda cxt: b''.join(cxt[attr].data for attr in [ 'start', 'payload_length', 'message_id', 'src_device_id', 'dest_device_id', 'payload' ])), ) profile6_schema = c.Struct(ping_number=c.Int32ul, start_mm=c.Int32ul, length_mm=c.Int32ul, start_ping_hz=c.Int32ul, end_ping_hz=c.Int32ul, adc_sample_hz=c.Int32ul, timestamp_msec=c.Int32ul, spare2=c.Padding(4), ping_duration_sec=c.Float32l, analog_gain=c.Float32l, max_pwr=c.Float32l,