diff --git a/findmy/keys.py b/findmy/keys.py index e0febc1..1ebc81d 100644 --- a/findmy/keys.py +++ b/findmy/keys.py @@ -12,7 +12,7 @@ from typing import Generator, Generic, TypeVar, overload from cryptography.hazmat.primitives.asymmetric import ec from typing_extensions import override -from .util import crypto +from .util import crypto, parsers class KeyType(Enum): @@ -70,6 +70,12 @@ class HasPublicKey(HasHashedPublicKey, ABC): def adv_key_b64(self) -> str: """Return the advertised (public) key as a base64-encoded string.""" return base64.b64encode(self.adv_key_bytes).decode("ascii") + + @property + def mac_address(self) -> str: + """Get the mac address from the public key.""" + first_hex = self.adv_key_bytes[0] | 0b11000000 + return parsers.format_hex_byte(first_hex) + ":" + ":".join([parsers.format_hex_byte(x) for x in self.adv_key_bytes[1:6]]) @property @override diff --git a/findmy/reports/reports.py b/findmy/reports/reports.py index 3f17be3..0403839 100644 --- a/findmy/reports/reports.py +++ b/findmy/reports/reports.py @@ -121,6 +121,14 @@ class LocationReport(HasHashedPublicKey): """The `datetime` when this report was recorded by a device.""" timestamp_int = int.from_bytes(self._payload[0:4], "big") + (60 * 60 * 24 * 11323) return datetime.fromtimestamp(timestamp_int, tz=timezone.utc).astimezone() + + @property + def confidence(self) -> int: + """Confidence of the location of this report. Int between 1 and 3""" + # If the payload length is 88, the confidence is the 5th byte, otherwise it's the 6th byte + if (len(self._payload) == 88): + return self.payload[4] + return self.payload[5] @property def latitude(self) -> float: @@ -145,10 +153,10 @@ class LocationReport(HasHashedPublicKey): return struct.unpack(">i", lon_bytes)[0] / 10000000 @property - def confidence(self) -> int: - """Confidence of the location of this report.""" + def horizontal_accuracy(self) -> int: + """Horizontal accuracy of the location of this report.""" if not self.is_decrypted: - msg = "Confidence is unavailable while the report is encrypted." + msg = "Horizontal accuracy is unavailable while the report is encrypted." raise RuntimeError(msg) assert self._decrypted_data is not None diff --git a/findmy/util/parsers.py b/findmy/util/parsers.py index 2f06769..563db93 100644 --- a/findmy/util/parsers.py +++ b/findmy/util/parsers.py @@ -15,3 +15,6 @@ def decode_plist(data: bytes) -> Any: # noqa: ANN401 data = plist_header + data return plistlib.loads(data) + +def format_hex_byte(byte): + return f'{byte:02x}'.upper() \ No newline at end of file