From ead656be6d12a80082a1eb7e3fafe2627a2345ed Mon Sep 17 00:00:00 2001 From: Kai Geissdoerfer Date: Mon, 17 Feb 2025 09:27:21 +0100 Subject: [PATCH 01/31] firmware: switch from nrf-connect to vanilla zephyr --- ZephyrFirmware/app/west.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/ZephyrFirmware/app/west.yml b/ZephyrFirmware/app/west.yml index 860ca1f..4708254 100644 --- a/ZephyrFirmware/app/west.yml +++ b/ZephyrFirmware/app/west.yml @@ -1,14 +1,10 @@ manifest: - self: - west-commands: scripts/west-commands.yml - remotes: - - name: ncs - url-base: https://github.com/nrfconnect + - name: zephyrproject-rtos + url-base: https://github.com/zephyrproject-rtos projects: - - name: nrf - remote: ncs - repo-path: sdk-nrf - revision: v2.9.0 + - name: zephyr + remote: zephyrproject-rtos + revision: main import: true From 378c0df91443141825fc7bda254a477001dd4e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 17 Feb 2025 10:08:18 +0100 Subject: [PATCH 02/31] Less verbose prints --- Auth/fcm_receiver.py | 1 - NovaApi/ExecuteAction/LocateTracker/location_request.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/Auth/fcm_receiver.py b/Auth/fcm_receiver.py index 16f4311..4c651cd 100644 --- a/Auth/fcm_receiver.py +++ b/Auth/fcm_receiver.py @@ -64,7 +64,6 @@ def get_android_id(self): # Define a callback function for handling notifications def _on_notification(self, obj, notification, data_message): - print("[FCMReceiver] Notification received!") # Check if the payload is present if 'data' in obj and 'com.google.android.apps.adm.FCM_PAYLOAD' in obj['data']: diff --git a/NovaApi/ExecuteAction/LocateTracker/location_request.py b/NovaApi/ExecuteAction/LocateTracker/location_request.py index 8501103..85e82db 100644 --- a/NovaApi/ExecuteAction/LocateTracker/location_request.py +++ b/NovaApi/ExecuteAction/LocateTracker/location_request.py @@ -44,8 +44,6 @@ def handle_location_response(response): print("[LocationRequest] Location request successful.") result = parse_device_update_protobuf(response) #print_device_update_protobuf(response) - else: - print("[LocationRequest] Received response for a different request. Ignoring.") fcm_token = FcmReceiver().register_for_location_updates(handle_location_response) From 7bb6062db9df6b4f57efb8c40750d934f6a37ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 17 Feb 2025 10:33:37 +0100 Subject: [PATCH 03/31] More info if EIK cannot be decrypted --- .../LocateTracker/decrypt_locations.py | 11 +- ProtoDecoders/DeviceUpdate.proto | 1 + ProtoDecoders/DeviceUpdate_pb2.py | 184 +++++++++--------- ProtoDecoders/DeviceUpdate_pb2.pyi | 6 +- .../GetEidInfoForE2eeDevices/get_owner_key.py | 3 + 5 files changed, 107 insertions(+), 98 deletions(-) diff --git a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py index a0b671b..0358421 100644 --- a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py +++ b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py @@ -24,15 +24,18 @@ def is_mcu_tracker(device_registration: DeviceRegistration) -> bool: def retrieve_identity_key(device_registration: DeviceRegistration) -> bytes: is_mcu = is_mcu_tracker(device_registration) + encrypted_user_secrets = device_registration.encryptedUserSecrets encrypted_identity_key = flip_bits( - device_registration.encryptedUserSecrets.encryptedIdentityKey, + encrypted_user_secrets.encryptedIdentityKey, is_mcu) owner_key = get_owner_key() - identity_key = decrypt_eik(owner_key, encrypted_identity_key) - - return identity_key + try: + identity_key = decrypt_eik(owner_key, encrypted_identity_key) + return identity_key + except Exception as e: + print(f"Failed to decrypt identity key encrypted with owner key version {encrypted_user_secrets.ownerKeyVersion}: {str(e)}") def decrypt_location_response_locations(device_update_protobuf): diff --git a/ProtoDecoders/DeviceUpdate.proto b/ProtoDecoders/DeviceUpdate.proto index 45c8c40..31fe3a3 100644 --- a/ProtoDecoders/DeviceUpdate.proto +++ b/ProtoDecoders/DeviceUpdate.proto @@ -12,6 +12,7 @@ message GetEidInfoForE2eeDevicesResponse { message EncryptedOwnerKeyAndMetadata { bytes encryptedOwnerKey = 1; + int32 ownerKeyVersion = 2; string securityDomain = 3; } diff --git a/ProtoDecoders/DeviceUpdate_pb2.py b/ProtoDecoders/DeviceUpdate_pb2.py index 92d76d6..b2049f6 100644 --- a/ProtoDecoders/DeviceUpdate_pb2.py +++ b/ProtoDecoders/DeviceUpdate_pb2.py @@ -15,105 +15,105 @@ from ProtoDecoders import Common_pb2 as ProtoDecoders_dot_Common__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n ProtoDecoders/DeviceUpdate.proto\x1a\x1aProtoDecoders/Common.proto\"g\n GetEidInfoForE2eeDevicesResponse\x12\x43\n\x1c\x65ncryptedOwnerKeyAndMetadata\x18\x04 \x01(\x0b\x32\x1d.EncryptedOwnerKeyAndMetadata\"Q\n\x1c\x45ncryptedOwnerKeyAndMetadata\x12\x19\n\x11\x65ncryptedOwnerKey\x18\x01 \x01(\x0c\x12\x16\n\x0esecurityDomain\x18\x03 \x01(\t\"6\n\x0b\x44\x65vicesList\x12\'\n\x0e\x64\x65viceMetadata\x18\x02 \x03(\x0b\x32\x0f.DeviceMetadata\"R\n\x12\x44\x65vicesListRequest\x12<\n\x18\x64\x65viceListRequestPayload\x18\x01 \x01(\x0b\x32\x1a.DevicesListRequestPayload\"B\n\x19\x44\x65vicesListRequestPayload\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.DeviceType\x12\n\n\x02id\x18\x03 \x01(\t\"\x96\x01\n\x14\x45xecuteActionRequest\x12\"\n\x05scope\x18\x01 \x01(\x0b\x32\x13.ExecuteActionScope\x12\"\n\x06\x61\x63tion\x18\x02 \x01(\x0b\x32\x12.ExecuteActionType\x12\x36\n\x0frequestMetadata\x18\x03 \x01(\x0b\x32\x1d.ExecuteActionRequestMetadata\"\xaf\x01\n\x1c\x45xecuteActionRequestMetadata\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.DeviceType\x12\x13\n\x0brequestUuid\x18\x02 \x01(\t\x12\x15\n\rfmdClientUuid\x18\x03 \x01(\t\x12\x37\n\x11gcmRegistrationId\x18\x04 \x01(\x0b\x32\x1c.GcmCloudMessagingIdProtobuf\x12\x0f\n\x07unknown\x18\x06 \x01(\x08\")\n\x1bGcmCloudMessagingIdProtobuf\x12\n\n\x02id\x18\x01 \x01(\t\"\xa4\x01\n\x11\x45xecuteActionType\x12\x36\n\rlocateTracker\x18\x1e \x01(\x0b\x32\x1f.ExecuteActionLocateTrackerType\x12+\n\nstartSound\x18\x1f \x01(\x0b\x32\x17.ExecuteActionSoundType\x12*\n\tstopSound\x18 \x01(\x0b\x32\x17.ExecuteActionSoundType\"{\n\x1e\x45xecuteActionLocateTrackerType\x12*\n\x1blastHighTrafficEnablingTime\x18\x02 \x01(\x0b\x32\x05.Time\x12-\n\x0f\x63ontributorType\x18\x03 \x01(\x0e\x32\x14.SpotContributorType\"=\n\x16\x45xecuteActionSoundType\x12#\n\tcomponent\x18\x01 \x01(\x0e\x32\x10.DeviceComponent\"_\n\x12\x45xecuteActionScope\x12\x19\n\x04type\x18\x02 \x01(\x0e\x32\x0b.DeviceType\x12.\n\x06\x64\x65vice\x18\x03 \x01(\x0b\x32\x1e.ExecuteActionDeviceIdentifier\">\n\x1d\x45xecuteActionDeviceIdentifier\x12\x1d\n\tcanonicId\x18\x01 \x01(\x0b\x32\n.CanonicId\"\x96\x01\n\x0c\x44\x65viceUpdate\x12\x32\n\x0b\x66\x63mMetadata\x18\x01 \x01(\x0b\x32\x1d.ExecuteActionRequestMetadata\x12\'\n\x0e\x64\x65viceMetadata\x18\x03 \x01(\x0b\x32\x0f.DeviceMetadata\x12)\n\x0frequestMetadata\x18\x02 \x01(\x0b\x32\x10.RequestMetadata\"\xbd\x01\n\x0e\x44\x65viceMetadata\x12\x36\n\x15identifierInformation\x18\x01 \x01(\x0b\x32\x17.IdentitfierInformation\x12\'\n\x0binformation\x18\x04 \x01(\x0b\x32\x12.DeviceInformation\x12\x1d\n\x15userDefinedDeviceName\x18\x05 \x01(\t\x12+\n\x10imageInformation\x18\x06 \x01(\x0b\x32\x11.ImageInformation\"$\n\x10ImageInformation\x12\x10\n\x08imageUrl\x18\x01 \x01(\t\"\x90\x01\n\x16IdentitfierInformation\x12+\n\x10phoneInformation\x18\x01 \x01(\x0b\x32\x11.PhoneInformation\x12(\n\x04type\x18\x02 \x01(\x0e\x32\x1a.IdentifierInformationType\x12\x1f\n\ncanonicIds\x18\x03 \x01(\x0b\x32\x0b.CanonicIds\"3\n\x10PhoneInformation\x12\x1f\n\ncanonicIds\x18\x02 \x01(\x0b\x32\x0b.CanonicIds\"+\n\nCanonicIds\x12\x1d\n\tcanonicId\x18\x01 \x03(\x0b\x32\n.CanonicId\"\x17\n\tCanonicId\x12\n\n\x02id\x18\x01 \x01(\t\"\xa6\x01\n\x11\x44\x65viceInformation\x12/\n\x12\x64\x65viceRegistration\x18\x01 \x01(\x0b\x32\x13.DeviceRegistration\x12\x31\n\x13locationInformation\x18\x02 \x01(\x0b\x32\x14.LocationInformation\x12-\n\x11\x61\x63\x63\x65ssInformation\x18\x03 \x03(\x0b\x32\x12.AccessInformation\"<\n\x15\x44\x65viceTypeInformation\x12#\n\ndeviceType\x18\x02 \x01(\x0e\x32\x0f.SpotDeviceType\"\xd0\x01\n\x12\x44\x65viceRegistration\x12\x35\n\x15\x64\x65viceTypeInformation\x18\x02 \x01(\x0b\x32\x16.DeviceTypeInformation\x12\x33\n\x14\x65ncryptedUserSecrets\x18\x13 \x01(\x0b\x32\x15.EncryptedUserSecrets\x12\x14\n\x0cmanufacturer\x18\x14 \x01(\t\x12\x17\n\x0f\x66\x61stPairModelId\x18\x15 \x01(\t\x12\x10\n\x08pairDate\x18\x17 \x01(\x05\x12\r\n\x05model\x18\" \x01(\t\"\xb7\x01\n\x14\x45ncryptedUserSecrets\x12\x1c\n\x14\x65ncryptedIdentityKey\x18\x01 \x01(\x0c\x12\x17\n\x0fownerKeyVersion\x18\x03 \x01(\x05\x12\x1b\n\x13\x65ncryptedAccountKey\x18\x04 \x01(\x0c\x12\x1b\n\x0c\x63reationDate\x18\x08 \x01(\x0b\x32\x05.Time\x12.\n&encryptedSha256AccountKeyPublicAddress\x18\x0b \x01(\x0c\"F\n\x13LocationInformation\x12/\n\x07reports\x18\x03 \x01(\x0b\x32\x1e.LocationsAndTimestampsWrapper\"n\n\x1dLocationsAndTimestampsWrapper\x12M\n!recentLocationAndNetworkLocations\x18\x04 \x01(\x0b\x32\".RecentLocationAndNetworkLocations\"\xf3\x01\n!RecentLocationAndNetworkLocations\x12\'\n\x0erecentLocation\x18\x01 \x01(\x0b\x32\x0f.LocationReport\x12&\n\x17recentLocationTimestamp\x18\x02 \x01(\x0b\x32\x05.Time\x12)\n\x10networkLocations\x18\x05 \x03(\x0b\x32\x0f.LocationReport\x12(\n\x19networkLocationTimestamps\x18\x06 \x03(\x0b\x32\x05.Time\x12(\n minLocationsNeededForAggregation\x18\t \x01(\r\"[\n\x11\x41\x63\x63\x65ssInformation\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x11\n\thasAccess\x18\x02 \x01(\x08\x12\x0f\n\x07isOwner\x18\x03 \x01(\x08\x12\x13\n\x0bthisAccount\x18\x04 \x01(\x08\".\n\x0fRequestMetadata\x12\x1b\n\x0cresponseTime\x18\x01 \x01(\x0b\x32\x05.Time\"n\n\x1d\x45ncryptionUnlockRequestExtras\x12\x11\n\toperation\x18\x01 \x01(\x05\x12\'\n\x0esecurityDomain\x18\x02 \x01(\x0b\x32\x0f.SecurityDomain\x12\x11\n\tsessionId\x18\x06 \x01(\t\"/\n\x0eSecurityDomain\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07unknown\x18\x02 \x01(\x05\"A\n\x08Location\x12\x10\n\x08latitude\x18\x01 \x01(\x0f\x12\x11\n\tlongitude\x18\x02 \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\"\xb6\x02\n\x18RegisterBleDeviceRequest\x12\x17\n\x0f\x66\x61stPairModelId\x18\x07 \x01(\t\x12\'\n\x0b\x64\x65scription\x18\n \x01(\x0b\x32\x12.DeviceDescription\x12)\n\x0c\x63\x61pabilities\x18\x0b \x01(\x0b\x32\x13.DeviceCapabilities\x12=\n\x19\x65\x32\x65\x65PublicKeyRegistration\x18\x10 \x01(\x0b\x32\x1a.E2EEPublicKeyRegistration\x12\x18\n\x10manufacturerName\x18\x11 \x01(\t\x12\x0f\n\x07ringKey\x18\x15 \x01(\x0c\x12\x13\n\x0brecoveryKey\x18\x16 \x01(\x0c\x12\x1b\n\x13unwantedTrackingKey\x18\x18 \x01(\x0c\x12\x11\n\tmodelName\x18\x19 \x01(\t\"\xaa\x01\n\x19\x45\x32\x45\x45PublicKeyRegistration\x12\x18\n\x10rotationExponent\x18\x01 \x01(\x05\x12\x33\n\x14\x65ncryptedUserSecrets\x18\x03 \x01(\x0b\x32\x15.EncryptedUserSecrets\x12)\n\x0fpublicKeyIdList\x18\x04 \x01(\x0b\x32\x10.PublicKeyIdList\x12\x13\n\x0bpairingDate\x18\x05 \x01(\x05\"\xb9\x01\n\x0fPublicKeyIdList\x12\x39\n\x0fpublicKeyIdInfo\x18\x01 \x03(\x0b\x32 .PublicKeyIdList.PublicKeyIdInfo\x1ak\n\x0fPublicKeyIdInfo\x12\x18\n\ttimestamp\x18\x01 \x01(\x0b\x32\x05.Time\x12\"\n\x0bpublicKeyId\x18\x02 \x01(\x0b\x32\r.TruncatedEID\x12\x1a\n\x12trackableComponent\x18\x03 \x01(\x05\"$\n\x0cTruncatedEID\x12\x14\n\x0ctruncatedEid\x18\x01 \x01(\x0c\"\xe1\x01\n$UploadPrecomputedPublicKeyIdsRequest\x12L\n\ndeviceEids\x18\x01 \x03(\x0b\x32\x38.UploadPrecomputedPublicKeyIdsRequest.DevicePublicKeyIds\x1ak\n\x12\x44\x65vicePublicKeyIds\x12\x1d\n\tcanonicId\x18\x01 \x01(\x0b\x32\n.CanonicId\x12$\n\nclientList\x18\x02 \x01(\x0b\x32\x10.PublicKeyIdList\x12\x10\n\x08pairDate\x18\x03 \x01(\x05\"c\n\x12\x44\x65viceCapabilities\x12\x15\n\risAdvertising\x18\x01 \x01(\x08\x12\x19\n\x11\x63\x61pableComponents\x18\x05 \x01(\x05\x12\x1b\n\x13trackableComponents\x18\x06 \x01(\x05\"\x93\x01\n\x11\x44\x65viceDescription\x12\x17\n\x0fuserDefinedName\x18\x01 \x01(\t\x12#\n\ndeviceType\x18\x02 \x01(\x0e\x32\x0f.SpotDeviceType\x12@\n\x1b\x64\x65viceComponentsInformation\x18\t \x03(\x0b\x32\x1b.DeviceComponentInformation\".\n\x1a\x44\x65viceComponentInformation\x12\x10\n\x08imageUrl\x18\x01 \x01(\t*\xa5\x01\n\nDeviceType\x12\x17\n\x13UNKNOWN_DEVICE_TYPE\x10\x00\x12\x12\n\x0e\x41NDROID_DEVICE\x10\x01\x12\x0f\n\x0bSPOT_DEVICE\x10\x02\x12\x14\n\x10TEST_DEVICE_TYPE\x10\x03\x12\x0f\n\x0b\x41UTO_DEVICE\x10\x04\x12\x13\n\x0f\x46\x41STPAIR_DEVICE\x10\x05\x12\x1d\n\x19SUPERVISED_ANDROID_DEVICE\x10\x07*\xa6\x01\n\x13SpotContributorType\x12\x19\n\x15\x46MDN_DISABLED_DEFAULT\x10\x00\x12!\n\x1d\x46MDN_CONTRIBUTOR_HIGH_TRAFFIC\x10\x03\x12\"\n\x1e\x46MDN_CONTRIBUTOR_ALL_LOCATIONS\x10\x04\x12\x15\n\x11\x46MDN_HIGH_TRAFFIC\x10\x01\x12\x16\n\x12\x46MDN_ALL_LOCATIONS\x10\x02*\x85\x01\n\x0f\x44\x65viceComponent\x12 \n\x1c\x44\x45VICE_COMPONENT_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x44\x45VICE_COMPONENT_RIGHT\x10\x01\x12\x19\n\x15\x44\x45VICE_COMPONENT_LEFT\x10\x02\x12\x19\n\x15\x44\x45VICE_COMPONENT_CASE\x10\x03*`\n\x19IdentifierInformationType\x12\x16\n\x12IDENTIFIER_UNKNOWN\x10\x00\x12\x16\n\x12IDENTIFIER_ANDROID\x10\x01\x12\x13\n\x0fIDENTIFIER_SPOT\x10\x02*\x82\x05\n\x0eSpotDeviceType\x12\x17\n\x13\x44\x45VICE_TYPE_UNKNOWN\x10\x00\x12\x16\n\x12\x44\x45VICE_TYPE_BEACON\x10\x01\x12\x1a\n\x16\x44\x45VICE_TYPE_HEADPHONES\x10\x02\x12\x14\n\x10\x44\x45VICE_TYPE_KEYS\x10\x03\x12\x15\n\x11\x44\x45VICE_TYPE_WATCH\x10\x04\x12\x16\n\x12\x44\x45VICE_TYPE_WALLET\x10\x05\x12\x13\n\x0f\x44\x45VICE_TYPE_BAG\x10\x07\x12\x16\n\x12\x44\x45VICE_TYPE_LAPTOP\x10\x08\x12\x13\n\x0f\x44\x45VICE_TYPE_CAR\x10\t\x12\x1e\n\x1a\x44\x45VICE_TYPE_REMOTE_CONTROL\x10\n\x12\x15\n\x11\x44\x45VICE_TYPE_BADGE\x10\x0b\x12\x14\n\x10\x44\x45VICE_TYPE_BIKE\x10\x0c\x12\x16\n\x12\x44\x45VICE_TYPE_CAMERA\x10\r\x12\x13\n\x0f\x44\x45VICE_TYPE_CAT\x10\x0e\x12\x17\n\x13\x44\x45VICE_TYPE_CHARGER\x10\x0f\x12\x18\n\x14\x44\x45VICE_TYPE_CLOTHING\x10\x10\x12\x13\n\x0f\x44\x45VICE_TYPE_DOG\x10\x11\x12\x18\n\x14\x44\x45VICE_TYPE_NOTEBOOK\x10\x12\x12\x18\n\x14\x44\x45VICE_TYPE_PASSPORT\x10\x13\x12\x15\n\x11\x44\x45VICE_TYPE_PHONE\x10\x14\x12\x17\n\x13\x44\x45VICE_TYPE_SPEAKER\x10\x15\x12\x16\n\x12\x44\x45VICE_TYPE_TABLET\x10\x16\x12\x13\n\x0f\x44\x45VICE_TYPE_TOY\x10\x17\x12\x18\n\x14\x44\x45VICE_TYPE_UMBRELLA\x10\x18\x12\x16\n\x12\x44\x45VICE_TYPE_STYLUS\x10\x19\x12\x17\n\x13\x44\x45VICE_TYPE_EARBUDS\x10\x1a\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n ProtoDecoders/DeviceUpdate.proto\x1a\x1aProtoDecoders/Common.proto\"g\n GetEidInfoForE2eeDevicesResponse\x12\x43\n\x1c\x65ncryptedOwnerKeyAndMetadata\x18\x04 \x01(\x0b\x32\x1d.EncryptedOwnerKeyAndMetadata\"j\n\x1c\x45ncryptedOwnerKeyAndMetadata\x12\x19\n\x11\x65ncryptedOwnerKey\x18\x01 \x01(\x0c\x12\x17\n\x0fownerKeyVersion\x18\x02 \x01(\x05\x12\x16\n\x0esecurityDomain\x18\x03 \x01(\t\"6\n\x0b\x44\x65vicesList\x12\'\n\x0e\x64\x65viceMetadata\x18\x02 \x03(\x0b\x32\x0f.DeviceMetadata\"R\n\x12\x44\x65vicesListRequest\x12<\n\x18\x64\x65viceListRequestPayload\x18\x01 \x01(\x0b\x32\x1a.DevicesListRequestPayload\"B\n\x19\x44\x65vicesListRequestPayload\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.DeviceType\x12\n\n\x02id\x18\x03 \x01(\t\"\x96\x01\n\x14\x45xecuteActionRequest\x12\"\n\x05scope\x18\x01 \x01(\x0b\x32\x13.ExecuteActionScope\x12\"\n\x06\x61\x63tion\x18\x02 \x01(\x0b\x32\x12.ExecuteActionType\x12\x36\n\x0frequestMetadata\x18\x03 \x01(\x0b\x32\x1d.ExecuteActionRequestMetadata\"\xaf\x01\n\x1c\x45xecuteActionRequestMetadata\x12\x19\n\x04type\x18\x01 \x01(\x0e\x32\x0b.DeviceType\x12\x13\n\x0brequestUuid\x18\x02 \x01(\t\x12\x15\n\rfmdClientUuid\x18\x03 \x01(\t\x12\x37\n\x11gcmRegistrationId\x18\x04 \x01(\x0b\x32\x1c.GcmCloudMessagingIdProtobuf\x12\x0f\n\x07unknown\x18\x06 \x01(\x08\")\n\x1bGcmCloudMessagingIdProtobuf\x12\n\n\x02id\x18\x01 \x01(\t\"\xa4\x01\n\x11\x45xecuteActionType\x12\x36\n\rlocateTracker\x18\x1e \x01(\x0b\x32\x1f.ExecuteActionLocateTrackerType\x12+\n\nstartSound\x18\x1f \x01(\x0b\x32\x17.ExecuteActionSoundType\x12*\n\tstopSound\x18 \x01(\x0b\x32\x17.ExecuteActionSoundType\"{\n\x1e\x45xecuteActionLocateTrackerType\x12*\n\x1blastHighTrafficEnablingTime\x18\x02 \x01(\x0b\x32\x05.Time\x12-\n\x0f\x63ontributorType\x18\x03 \x01(\x0e\x32\x14.SpotContributorType\"=\n\x16\x45xecuteActionSoundType\x12#\n\tcomponent\x18\x01 \x01(\x0e\x32\x10.DeviceComponent\"_\n\x12\x45xecuteActionScope\x12\x19\n\x04type\x18\x02 \x01(\x0e\x32\x0b.DeviceType\x12.\n\x06\x64\x65vice\x18\x03 \x01(\x0b\x32\x1e.ExecuteActionDeviceIdentifier\">\n\x1d\x45xecuteActionDeviceIdentifier\x12\x1d\n\tcanonicId\x18\x01 \x01(\x0b\x32\n.CanonicId\"\x96\x01\n\x0c\x44\x65viceUpdate\x12\x32\n\x0b\x66\x63mMetadata\x18\x01 \x01(\x0b\x32\x1d.ExecuteActionRequestMetadata\x12\'\n\x0e\x64\x65viceMetadata\x18\x03 \x01(\x0b\x32\x0f.DeviceMetadata\x12)\n\x0frequestMetadata\x18\x02 \x01(\x0b\x32\x10.RequestMetadata\"\xbd\x01\n\x0e\x44\x65viceMetadata\x12\x36\n\x15identifierInformation\x18\x01 \x01(\x0b\x32\x17.IdentitfierInformation\x12\'\n\x0binformation\x18\x04 \x01(\x0b\x32\x12.DeviceInformation\x12\x1d\n\x15userDefinedDeviceName\x18\x05 \x01(\t\x12+\n\x10imageInformation\x18\x06 \x01(\x0b\x32\x11.ImageInformation\"$\n\x10ImageInformation\x12\x10\n\x08imageUrl\x18\x01 \x01(\t\"\x90\x01\n\x16IdentitfierInformation\x12+\n\x10phoneInformation\x18\x01 \x01(\x0b\x32\x11.PhoneInformation\x12(\n\x04type\x18\x02 \x01(\x0e\x32\x1a.IdentifierInformationType\x12\x1f\n\ncanonicIds\x18\x03 \x01(\x0b\x32\x0b.CanonicIds\"3\n\x10PhoneInformation\x12\x1f\n\ncanonicIds\x18\x02 \x01(\x0b\x32\x0b.CanonicIds\"+\n\nCanonicIds\x12\x1d\n\tcanonicId\x18\x01 \x03(\x0b\x32\n.CanonicId\"\x17\n\tCanonicId\x12\n\n\x02id\x18\x01 \x01(\t\"\xa6\x01\n\x11\x44\x65viceInformation\x12/\n\x12\x64\x65viceRegistration\x18\x01 \x01(\x0b\x32\x13.DeviceRegistration\x12\x31\n\x13locationInformation\x18\x02 \x01(\x0b\x32\x14.LocationInformation\x12-\n\x11\x61\x63\x63\x65ssInformation\x18\x03 \x03(\x0b\x32\x12.AccessInformation\"<\n\x15\x44\x65viceTypeInformation\x12#\n\ndeviceType\x18\x02 \x01(\x0e\x32\x0f.SpotDeviceType\"\xd0\x01\n\x12\x44\x65viceRegistration\x12\x35\n\x15\x64\x65viceTypeInformation\x18\x02 \x01(\x0b\x32\x16.DeviceTypeInformation\x12\x33\n\x14\x65ncryptedUserSecrets\x18\x13 \x01(\x0b\x32\x15.EncryptedUserSecrets\x12\x14\n\x0cmanufacturer\x18\x14 \x01(\t\x12\x17\n\x0f\x66\x61stPairModelId\x18\x15 \x01(\t\x12\x10\n\x08pairDate\x18\x17 \x01(\x05\x12\r\n\x05model\x18\" \x01(\t\"\xb7\x01\n\x14\x45ncryptedUserSecrets\x12\x1c\n\x14\x65ncryptedIdentityKey\x18\x01 \x01(\x0c\x12\x17\n\x0fownerKeyVersion\x18\x03 \x01(\x05\x12\x1b\n\x13\x65ncryptedAccountKey\x18\x04 \x01(\x0c\x12\x1b\n\x0c\x63reationDate\x18\x08 \x01(\x0b\x32\x05.Time\x12.\n&encryptedSha256AccountKeyPublicAddress\x18\x0b \x01(\x0c\"F\n\x13LocationInformation\x12/\n\x07reports\x18\x03 \x01(\x0b\x32\x1e.LocationsAndTimestampsWrapper\"n\n\x1dLocationsAndTimestampsWrapper\x12M\n!recentLocationAndNetworkLocations\x18\x04 \x01(\x0b\x32\".RecentLocationAndNetworkLocations\"\xf3\x01\n!RecentLocationAndNetworkLocations\x12\'\n\x0erecentLocation\x18\x01 \x01(\x0b\x32\x0f.LocationReport\x12&\n\x17recentLocationTimestamp\x18\x02 \x01(\x0b\x32\x05.Time\x12)\n\x10networkLocations\x18\x05 \x03(\x0b\x32\x0f.LocationReport\x12(\n\x19networkLocationTimestamps\x18\x06 \x03(\x0b\x32\x05.Time\x12(\n minLocationsNeededForAggregation\x18\t \x01(\r\"[\n\x11\x41\x63\x63\x65ssInformation\x12\r\n\x05\x65mail\x18\x01 \x01(\t\x12\x11\n\thasAccess\x18\x02 \x01(\x08\x12\x0f\n\x07isOwner\x18\x03 \x01(\x08\x12\x13\n\x0bthisAccount\x18\x04 \x01(\x08\".\n\x0fRequestMetadata\x12\x1b\n\x0cresponseTime\x18\x01 \x01(\x0b\x32\x05.Time\"n\n\x1d\x45ncryptionUnlockRequestExtras\x12\x11\n\toperation\x18\x01 \x01(\x05\x12\'\n\x0esecurityDomain\x18\x02 \x01(\x0b\x32\x0f.SecurityDomain\x12\x11\n\tsessionId\x18\x06 \x01(\t\"/\n\x0eSecurityDomain\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07unknown\x18\x02 \x01(\x05\"A\n\x08Location\x12\x10\n\x08latitude\x18\x01 \x01(\x0f\x12\x11\n\tlongitude\x18\x02 \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\"\xb6\x02\n\x18RegisterBleDeviceRequest\x12\x17\n\x0f\x66\x61stPairModelId\x18\x07 \x01(\t\x12\'\n\x0b\x64\x65scription\x18\n \x01(\x0b\x32\x12.DeviceDescription\x12)\n\x0c\x63\x61pabilities\x18\x0b \x01(\x0b\x32\x13.DeviceCapabilities\x12=\n\x19\x65\x32\x65\x65PublicKeyRegistration\x18\x10 \x01(\x0b\x32\x1a.E2EEPublicKeyRegistration\x12\x18\n\x10manufacturerName\x18\x11 \x01(\t\x12\x0f\n\x07ringKey\x18\x15 \x01(\x0c\x12\x13\n\x0brecoveryKey\x18\x16 \x01(\x0c\x12\x1b\n\x13unwantedTrackingKey\x18\x18 \x01(\x0c\x12\x11\n\tmodelName\x18\x19 \x01(\t\"\xaa\x01\n\x19\x45\x32\x45\x45PublicKeyRegistration\x12\x18\n\x10rotationExponent\x18\x01 \x01(\x05\x12\x33\n\x14\x65ncryptedUserSecrets\x18\x03 \x01(\x0b\x32\x15.EncryptedUserSecrets\x12)\n\x0fpublicKeyIdList\x18\x04 \x01(\x0b\x32\x10.PublicKeyIdList\x12\x13\n\x0bpairingDate\x18\x05 \x01(\x05\"\xb9\x01\n\x0fPublicKeyIdList\x12\x39\n\x0fpublicKeyIdInfo\x18\x01 \x03(\x0b\x32 .PublicKeyIdList.PublicKeyIdInfo\x1ak\n\x0fPublicKeyIdInfo\x12\x18\n\ttimestamp\x18\x01 \x01(\x0b\x32\x05.Time\x12\"\n\x0bpublicKeyId\x18\x02 \x01(\x0b\x32\r.TruncatedEID\x12\x1a\n\x12trackableComponent\x18\x03 \x01(\x05\"$\n\x0cTruncatedEID\x12\x14\n\x0ctruncatedEid\x18\x01 \x01(\x0c\"\xe1\x01\n$UploadPrecomputedPublicKeyIdsRequest\x12L\n\ndeviceEids\x18\x01 \x03(\x0b\x32\x38.UploadPrecomputedPublicKeyIdsRequest.DevicePublicKeyIds\x1ak\n\x12\x44\x65vicePublicKeyIds\x12\x1d\n\tcanonicId\x18\x01 \x01(\x0b\x32\n.CanonicId\x12$\n\nclientList\x18\x02 \x01(\x0b\x32\x10.PublicKeyIdList\x12\x10\n\x08pairDate\x18\x03 \x01(\x05\"c\n\x12\x44\x65viceCapabilities\x12\x15\n\risAdvertising\x18\x01 \x01(\x08\x12\x19\n\x11\x63\x61pableComponents\x18\x05 \x01(\x05\x12\x1b\n\x13trackableComponents\x18\x06 \x01(\x05\"\x93\x01\n\x11\x44\x65viceDescription\x12\x17\n\x0fuserDefinedName\x18\x01 \x01(\t\x12#\n\ndeviceType\x18\x02 \x01(\x0e\x32\x0f.SpotDeviceType\x12@\n\x1b\x64\x65viceComponentsInformation\x18\t \x03(\x0b\x32\x1b.DeviceComponentInformation\".\n\x1a\x44\x65viceComponentInformation\x12\x10\n\x08imageUrl\x18\x01 \x01(\t*\xa5\x01\n\nDeviceType\x12\x17\n\x13UNKNOWN_DEVICE_TYPE\x10\x00\x12\x12\n\x0e\x41NDROID_DEVICE\x10\x01\x12\x0f\n\x0bSPOT_DEVICE\x10\x02\x12\x14\n\x10TEST_DEVICE_TYPE\x10\x03\x12\x0f\n\x0b\x41UTO_DEVICE\x10\x04\x12\x13\n\x0f\x46\x41STPAIR_DEVICE\x10\x05\x12\x1d\n\x19SUPERVISED_ANDROID_DEVICE\x10\x07*\xa6\x01\n\x13SpotContributorType\x12\x19\n\x15\x46MDN_DISABLED_DEFAULT\x10\x00\x12!\n\x1d\x46MDN_CONTRIBUTOR_HIGH_TRAFFIC\x10\x03\x12\"\n\x1e\x46MDN_CONTRIBUTOR_ALL_LOCATIONS\x10\x04\x12\x15\n\x11\x46MDN_HIGH_TRAFFIC\x10\x01\x12\x16\n\x12\x46MDN_ALL_LOCATIONS\x10\x02*\x85\x01\n\x0f\x44\x65viceComponent\x12 \n\x1c\x44\x45VICE_COMPONENT_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x44\x45VICE_COMPONENT_RIGHT\x10\x01\x12\x19\n\x15\x44\x45VICE_COMPONENT_LEFT\x10\x02\x12\x19\n\x15\x44\x45VICE_COMPONENT_CASE\x10\x03*`\n\x19IdentifierInformationType\x12\x16\n\x12IDENTIFIER_UNKNOWN\x10\x00\x12\x16\n\x12IDENTIFIER_ANDROID\x10\x01\x12\x13\n\x0fIDENTIFIER_SPOT\x10\x02*\x82\x05\n\x0eSpotDeviceType\x12\x17\n\x13\x44\x45VICE_TYPE_UNKNOWN\x10\x00\x12\x16\n\x12\x44\x45VICE_TYPE_BEACON\x10\x01\x12\x1a\n\x16\x44\x45VICE_TYPE_HEADPHONES\x10\x02\x12\x14\n\x10\x44\x45VICE_TYPE_KEYS\x10\x03\x12\x15\n\x11\x44\x45VICE_TYPE_WATCH\x10\x04\x12\x16\n\x12\x44\x45VICE_TYPE_WALLET\x10\x05\x12\x13\n\x0f\x44\x45VICE_TYPE_BAG\x10\x07\x12\x16\n\x12\x44\x45VICE_TYPE_LAPTOP\x10\x08\x12\x13\n\x0f\x44\x45VICE_TYPE_CAR\x10\t\x12\x1e\n\x1a\x44\x45VICE_TYPE_REMOTE_CONTROL\x10\n\x12\x15\n\x11\x44\x45VICE_TYPE_BADGE\x10\x0b\x12\x14\n\x10\x44\x45VICE_TYPE_BIKE\x10\x0c\x12\x16\n\x12\x44\x45VICE_TYPE_CAMERA\x10\r\x12\x13\n\x0f\x44\x45VICE_TYPE_CAT\x10\x0e\x12\x17\n\x13\x44\x45VICE_TYPE_CHARGER\x10\x0f\x12\x18\n\x14\x44\x45VICE_TYPE_CLOTHING\x10\x10\x12\x13\n\x0f\x44\x45VICE_TYPE_DOG\x10\x11\x12\x18\n\x14\x44\x45VICE_TYPE_NOTEBOOK\x10\x12\x12\x18\n\x14\x44\x45VICE_TYPE_PASSPORT\x10\x13\x12\x15\n\x11\x44\x45VICE_TYPE_PHONE\x10\x14\x12\x17\n\x13\x44\x45VICE_TYPE_SPEAKER\x10\x15\x12\x16\n\x12\x44\x45VICE_TYPE_TABLET\x10\x16\x12\x13\n\x0f\x44\x45VICE_TYPE_TOY\x10\x17\x12\x18\n\x14\x44\x45VICE_TYPE_UMBRELLA\x10\x18\x12\x16\n\x12\x44\x45VICE_TYPE_STYLUS\x10\x19\x12\x17\n\x13\x44\x45VICE_TYPE_EARBUDS\x10\x1a\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ProtoDecoders.DeviceUpdate_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - _globals['_DEVICETYPE']._serialized_start=4670 - _globals['_DEVICETYPE']._serialized_end=4835 - _globals['_SPOTCONTRIBUTORTYPE']._serialized_start=4838 - _globals['_SPOTCONTRIBUTORTYPE']._serialized_end=5004 - _globals['_DEVICECOMPONENT']._serialized_start=5007 - _globals['_DEVICECOMPONENT']._serialized_end=5140 - _globals['_IDENTIFIERINFORMATIONTYPE']._serialized_start=5142 - _globals['_IDENTIFIERINFORMATIONTYPE']._serialized_end=5238 - _globals['_SPOTDEVICETYPE']._serialized_start=5241 - _globals['_SPOTDEVICETYPE']._serialized_end=5883 + _globals['_DEVICETYPE']._serialized_start=4695 + _globals['_DEVICETYPE']._serialized_end=4860 + _globals['_SPOTCONTRIBUTORTYPE']._serialized_start=4863 + _globals['_SPOTCONTRIBUTORTYPE']._serialized_end=5029 + _globals['_DEVICECOMPONENT']._serialized_start=5032 + _globals['_DEVICECOMPONENT']._serialized_end=5165 + _globals['_IDENTIFIERINFORMATIONTYPE']._serialized_start=5167 + _globals['_IDENTIFIERINFORMATIONTYPE']._serialized_end=5263 + _globals['_SPOTDEVICETYPE']._serialized_start=5266 + _globals['_SPOTDEVICETYPE']._serialized_end=5908 _globals['_GETEIDINFOFORE2EEDEVICESRESPONSE']._serialized_start=64 _globals['_GETEIDINFOFORE2EEDEVICESRESPONSE']._serialized_end=167 _globals['_ENCRYPTEDOWNERKEYANDMETADATA']._serialized_start=169 - _globals['_ENCRYPTEDOWNERKEYANDMETADATA']._serialized_end=250 - _globals['_DEVICESLIST']._serialized_start=252 - _globals['_DEVICESLIST']._serialized_end=306 - _globals['_DEVICESLISTREQUEST']._serialized_start=308 - _globals['_DEVICESLISTREQUEST']._serialized_end=390 - _globals['_DEVICESLISTREQUESTPAYLOAD']._serialized_start=392 - _globals['_DEVICESLISTREQUESTPAYLOAD']._serialized_end=458 - _globals['_EXECUTEACTIONREQUEST']._serialized_start=461 - _globals['_EXECUTEACTIONREQUEST']._serialized_end=611 - _globals['_EXECUTEACTIONREQUESTMETADATA']._serialized_start=614 - _globals['_EXECUTEACTIONREQUESTMETADATA']._serialized_end=789 - _globals['_GCMCLOUDMESSAGINGIDPROTOBUF']._serialized_start=791 - _globals['_GCMCLOUDMESSAGINGIDPROTOBUF']._serialized_end=832 - _globals['_EXECUTEACTIONTYPE']._serialized_start=835 - _globals['_EXECUTEACTIONTYPE']._serialized_end=999 - _globals['_EXECUTEACTIONLOCATETRACKERTYPE']._serialized_start=1001 - _globals['_EXECUTEACTIONLOCATETRACKERTYPE']._serialized_end=1124 - _globals['_EXECUTEACTIONSOUNDTYPE']._serialized_start=1126 - _globals['_EXECUTEACTIONSOUNDTYPE']._serialized_end=1187 - _globals['_EXECUTEACTIONSCOPE']._serialized_start=1189 - _globals['_EXECUTEACTIONSCOPE']._serialized_end=1284 - _globals['_EXECUTEACTIONDEVICEIDENTIFIER']._serialized_start=1286 - _globals['_EXECUTEACTIONDEVICEIDENTIFIER']._serialized_end=1348 - _globals['_DEVICEUPDATE']._serialized_start=1351 - _globals['_DEVICEUPDATE']._serialized_end=1501 - _globals['_DEVICEMETADATA']._serialized_start=1504 - _globals['_DEVICEMETADATA']._serialized_end=1693 - _globals['_IMAGEINFORMATION']._serialized_start=1695 - _globals['_IMAGEINFORMATION']._serialized_end=1731 - _globals['_IDENTITFIERINFORMATION']._serialized_start=1734 - _globals['_IDENTITFIERINFORMATION']._serialized_end=1878 - _globals['_PHONEINFORMATION']._serialized_start=1880 - _globals['_PHONEINFORMATION']._serialized_end=1931 - _globals['_CANONICIDS']._serialized_start=1933 - _globals['_CANONICIDS']._serialized_end=1976 - _globals['_CANONICID']._serialized_start=1978 - _globals['_CANONICID']._serialized_end=2001 - _globals['_DEVICEINFORMATION']._serialized_start=2004 - _globals['_DEVICEINFORMATION']._serialized_end=2170 - _globals['_DEVICETYPEINFORMATION']._serialized_start=2172 - _globals['_DEVICETYPEINFORMATION']._serialized_end=2232 - _globals['_DEVICEREGISTRATION']._serialized_start=2235 - _globals['_DEVICEREGISTRATION']._serialized_end=2443 - _globals['_ENCRYPTEDUSERSECRETS']._serialized_start=2446 - _globals['_ENCRYPTEDUSERSECRETS']._serialized_end=2629 - _globals['_LOCATIONINFORMATION']._serialized_start=2631 - _globals['_LOCATIONINFORMATION']._serialized_end=2701 - _globals['_LOCATIONSANDTIMESTAMPSWRAPPER']._serialized_start=2703 - _globals['_LOCATIONSANDTIMESTAMPSWRAPPER']._serialized_end=2813 - _globals['_RECENTLOCATIONANDNETWORKLOCATIONS']._serialized_start=2816 - _globals['_RECENTLOCATIONANDNETWORKLOCATIONS']._serialized_end=3059 - _globals['_ACCESSINFORMATION']._serialized_start=3061 - _globals['_ACCESSINFORMATION']._serialized_end=3152 - _globals['_REQUESTMETADATA']._serialized_start=3154 - _globals['_REQUESTMETADATA']._serialized_end=3200 - _globals['_ENCRYPTIONUNLOCKREQUESTEXTRAS']._serialized_start=3202 - _globals['_ENCRYPTIONUNLOCKREQUESTEXTRAS']._serialized_end=3312 - _globals['_SECURITYDOMAIN']._serialized_start=3314 - _globals['_SECURITYDOMAIN']._serialized_end=3361 - _globals['_LOCATION']._serialized_start=3363 - _globals['_LOCATION']._serialized_end=3428 - _globals['_REGISTERBLEDEVICEREQUEST']._serialized_start=3431 - _globals['_REGISTERBLEDEVICEREQUEST']._serialized_end=3741 - _globals['_E2EEPUBLICKEYREGISTRATION']._serialized_start=3744 - _globals['_E2EEPUBLICKEYREGISTRATION']._serialized_end=3914 - _globals['_PUBLICKEYIDLIST']._serialized_start=3917 - _globals['_PUBLICKEYIDLIST']._serialized_end=4102 - _globals['_PUBLICKEYIDLIST_PUBLICKEYIDINFO']._serialized_start=3995 - _globals['_PUBLICKEYIDLIST_PUBLICKEYIDINFO']._serialized_end=4102 - _globals['_TRUNCATEDEID']._serialized_start=4104 - _globals['_TRUNCATEDEID']._serialized_end=4140 - _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST']._serialized_start=4143 - _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST']._serialized_end=4368 - _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST_DEVICEPUBLICKEYIDS']._serialized_start=4261 - _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST_DEVICEPUBLICKEYIDS']._serialized_end=4368 - _globals['_DEVICECAPABILITIES']._serialized_start=4370 - _globals['_DEVICECAPABILITIES']._serialized_end=4469 - _globals['_DEVICEDESCRIPTION']._serialized_start=4472 - _globals['_DEVICEDESCRIPTION']._serialized_end=4619 - _globals['_DEVICECOMPONENTINFORMATION']._serialized_start=4621 - _globals['_DEVICECOMPONENTINFORMATION']._serialized_end=4667 + _globals['_ENCRYPTEDOWNERKEYANDMETADATA']._serialized_end=275 + _globals['_DEVICESLIST']._serialized_start=277 + _globals['_DEVICESLIST']._serialized_end=331 + _globals['_DEVICESLISTREQUEST']._serialized_start=333 + _globals['_DEVICESLISTREQUEST']._serialized_end=415 + _globals['_DEVICESLISTREQUESTPAYLOAD']._serialized_start=417 + _globals['_DEVICESLISTREQUESTPAYLOAD']._serialized_end=483 + _globals['_EXECUTEACTIONREQUEST']._serialized_start=486 + _globals['_EXECUTEACTIONREQUEST']._serialized_end=636 + _globals['_EXECUTEACTIONREQUESTMETADATA']._serialized_start=639 + _globals['_EXECUTEACTIONREQUESTMETADATA']._serialized_end=814 + _globals['_GCMCLOUDMESSAGINGIDPROTOBUF']._serialized_start=816 + _globals['_GCMCLOUDMESSAGINGIDPROTOBUF']._serialized_end=857 + _globals['_EXECUTEACTIONTYPE']._serialized_start=860 + _globals['_EXECUTEACTIONTYPE']._serialized_end=1024 + _globals['_EXECUTEACTIONLOCATETRACKERTYPE']._serialized_start=1026 + _globals['_EXECUTEACTIONLOCATETRACKERTYPE']._serialized_end=1149 + _globals['_EXECUTEACTIONSOUNDTYPE']._serialized_start=1151 + _globals['_EXECUTEACTIONSOUNDTYPE']._serialized_end=1212 + _globals['_EXECUTEACTIONSCOPE']._serialized_start=1214 + _globals['_EXECUTEACTIONSCOPE']._serialized_end=1309 + _globals['_EXECUTEACTIONDEVICEIDENTIFIER']._serialized_start=1311 + _globals['_EXECUTEACTIONDEVICEIDENTIFIER']._serialized_end=1373 + _globals['_DEVICEUPDATE']._serialized_start=1376 + _globals['_DEVICEUPDATE']._serialized_end=1526 + _globals['_DEVICEMETADATA']._serialized_start=1529 + _globals['_DEVICEMETADATA']._serialized_end=1718 + _globals['_IMAGEINFORMATION']._serialized_start=1720 + _globals['_IMAGEINFORMATION']._serialized_end=1756 + _globals['_IDENTITFIERINFORMATION']._serialized_start=1759 + _globals['_IDENTITFIERINFORMATION']._serialized_end=1903 + _globals['_PHONEINFORMATION']._serialized_start=1905 + _globals['_PHONEINFORMATION']._serialized_end=1956 + _globals['_CANONICIDS']._serialized_start=1958 + _globals['_CANONICIDS']._serialized_end=2001 + _globals['_CANONICID']._serialized_start=2003 + _globals['_CANONICID']._serialized_end=2026 + _globals['_DEVICEINFORMATION']._serialized_start=2029 + _globals['_DEVICEINFORMATION']._serialized_end=2195 + _globals['_DEVICETYPEINFORMATION']._serialized_start=2197 + _globals['_DEVICETYPEINFORMATION']._serialized_end=2257 + _globals['_DEVICEREGISTRATION']._serialized_start=2260 + _globals['_DEVICEREGISTRATION']._serialized_end=2468 + _globals['_ENCRYPTEDUSERSECRETS']._serialized_start=2471 + _globals['_ENCRYPTEDUSERSECRETS']._serialized_end=2654 + _globals['_LOCATIONINFORMATION']._serialized_start=2656 + _globals['_LOCATIONINFORMATION']._serialized_end=2726 + _globals['_LOCATIONSANDTIMESTAMPSWRAPPER']._serialized_start=2728 + _globals['_LOCATIONSANDTIMESTAMPSWRAPPER']._serialized_end=2838 + _globals['_RECENTLOCATIONANDNETWORKLOCATIONS']._serialized_start=2841 + _globals['_RECENTLOCATIONANDNETWORKLOCATIONS']._serialized_end=3084 + _globals['_ACCESSINFORMATION']._serialized_start=3086 + _globals['_ACCESSINFORMATION']._serialized_end=3177 + _globals['_REQUESTMETADATA']._serialized_start=3179 + _globals['_REQUESTMETADATA']._serialized_end=3225 + _globals['_ENCRYPTIONUNLOCKREQUESTEXTRAS']._serialized_start=3227 + _globals['_ENCRYPTIONUNLOCKREQUESTEXTRAS']._serialized_end=3337 + _globals['_SECURITYDOMAIN']._serialized_start=3339 + _globals['_SECURITYDOMAIN']._serialized_end=3386 + _globals['_LOCATION']._serialized_start=3388 + _globals['_LOCATION']._serialized_end=3453 + _globals['_REGISTERBLEDEVICEREQUEST']._serialized_start=3456 + _globals['_REGISTERBLEDEVICEREQUEST']._serialized_end=3766 + _globals['_E2EEPUBLICKEYREGISTRATION']._serialized_start=3769 + _globals['_E2EEPUBLICKEYREGISTRATION']._serialized_end=3939 + _globals['_PUBLICKEYIDLIST']._serialized_start=3942 + _globals['_PUBLICKEYIDLIST']._serialized_end=4127 + _globals['_PUBLICKEYIDLIST_PUBLICKEYIDINFO']._serialized_start=4020 + _globals['_PUBLICKEYIDLIST_PUBLICKEYIDINFO']._serialized_end=4127 + _globals['_TRUNCATEDEID']._serialized_start=4129 + _globals['_TRUNCATEDEID']._serialized_end=4165 + _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST']._serialized_start=4168 + _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST']._serialized_end=4393 + _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST_DEVICEPUBLICKEYIDS']._serialized_start=4286 + _globals['_UPLOADPRECOMPUTEDPUBLICKEYIDSREQUEST_DEVICEPUBLICKEYIDS']._serialized_end=4393 + _globals['_DEVICECAPABILITIES']._serialized_start=4395 + _globals['_DEVICECAPABILITIES']._serialized_end=4494 + _globals['_DEVICEDESCRIPTION']._serialized_start=4497 + _globals['_DEVICEDESCRIPTION']._serialized_end=4644 + _globals['_DEVICECOMPONENTINFORMATION']._serialized_start=4646 + _globals['_DEVICECOMPONENTINFORMATION']._serialized_end=4692 # @@protoc_insertion_point(module_scope) diff --git a/ProtoDecoders/DeviceUpdate_pb2.pyi b/ProtoDecoders/DeviceUpdate_pb2.pyi index 8c52eff..d38e6e1 100644 --- a/ProtoDecoders/DeviceUpdate_pb2.pyi +++ b/ProtoDecoders/DeviceUpdate_pb2.pyi @@ -119,12 +119,14 @@ class GetEidInfoForE2eeDevicesResponse(_message.Message): def __init__(self, encryptedOwnerKeyAndMetadata: _Optional[_Union[EncryptedOwnerKeyAndMetadata, _Mapping]] = ...) -> None: ... class EncryptedOwnerKeyAndMetadata(_message.Message): - __slots__ = ("encryptedOwnerKey", "securityDomain") + __slots__ = ("encryptedOwnerKey", "ownerKeyVersion", "securityDomain") ENCRYPTEDOWNERKEY_FIELD_NUMBER: _ClassVar[int] + OWNERKEYVERSION_FIELD_NUMBER: _ClassVar[int] SECURITYDOMAIN_FIELD_NUMBER: _ClassVar[int] encryptedOwnerKey: bytes + ownerKeyVersion: int securityDomain: str - def __init__(self, encryptedOwnerKey: _Optional[bytes] = ..., securityDomain: _Optional[str] = ...) -> None: ... + def __init__(self, encryptedOwnerKey: _Optional[bytes] = ..., ownerKeyVersion: _Optional[int] = ..., securityDomain: _Optional[str] = ...) -> None: ... class DevicesList(_message.Message): __slots__ = ("deviceMetadata",) diff --git a/SpotApi/GetEidInfoForE2eeDevices/get_owner_key.py b/SpotApi/GetEidInfoForE2eeDevices/get_owner_key.py index b6a9b77..2a1fa08 100644 --- a/SpotApi/GetEidInfoForE2eeDevices/get_owner_key.py +++ b/SpotApi/GetEidInfoForE2eeDevices/get_owner_key.py @@ -15,6 +15,9 @@ def _retrieve_owner_key() -> str: encrypted_owner_key = eid_info.encryptedOwnerKeyAndMetadata.encryptedOwnerKey owner_key = decrypt_owner_key(shared_key, encrypted_owner_key) + owner_key_version = eid_info.encryptedOwnerKeyAndMetadata.ownerKeyVersion + + print(f"Retrieved owner key with version: {owner_key_version}") return owner_key.hex() From dce063b8600b8b077de0fbd3056745f9e0a2e560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 17 Feb 2025 10:44:52 +0100 Subject: [PATCH 04/31] More info if Chrome cannot be found --- Auth/auth_flow.py | 2 ++ KeyBackup/shared_key_flow.py | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Auth/auth_flow.py b/Auth/auth_flow.py index 7d63204..f7d96c8 100644 --- a/Auth/auth_flow.py +++ b/Auth/auth_flow.py @@ -13,6 +13,8 @@ def request_oauth_account_token_flow(): chrome_options.add_argument("--disable-extensions") chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("--no-sandbox") + + # For Windows users only: set binary location to "C:\ProgramData\chocolatey\bin\chrome.exe" or similar # chrome_options.binary_location = r"INSERT_PATH_TO_CHROME_BINARY_HERE" print("""[AuthFlow] This script will now open Google Chrome on your device to login to your Google account. diff --git a/KeyBackup/shared_key_flow.py b/KeyBackup/shared_key_flow.py index 2c6406d..936274b 100644 --- a/KeyBackup/shared_key_flow.py +++ b/KeyBackup/shared_key_flow.py @@ -13,9 +13,18 @@ # Initialize undetected Chrome WebDriver def create_driver(): - options = uc.ChromeOptions() - options.add_argument("--start-maximized") - return uc.Chrome(options=options) + chrome_options = uc.ChromeOptions() + chrome_options.add_argument("--start-maximized") + + # For Windows users only: set binary location to "C:\ProgramData\chocolatey\bin\chrome.exe" or similar + # chrome_options.binary_location = r"INSERT_PATH_TO_CHROME_BINARY_HERE" + + try: + driver = uc.Chrome(options=chrome_options) + print("[SharedKeyFlow] ChromeDriver installed and browser started.") + return driver + except Exception as e: + raise Exception("[SharedKeyFlow] Failed to install ChromeDriver. A current version of Chrome was not detected on your system.\n\nIf you know that Chrome is installed, first try to update Chrome to the latest version. If the script is still not working afterward, open the file 'KeyBackup/shared_key_flow.py' and set the path to your Chrome executable in line 20.") def request_shared_key_flow(): From 41aafef500bf092932b40ddba75db4bed27f26a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:17:55 +0100 Subject: [PATCH 05/31] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0c1bc27..9467e26 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Currently, it is possible to query Find My Device trackers and Android devices, ### Known Issues - There seem to be issues with the package "undetected-chromedriver" not detecting Chrome on Windows and ARM Linux. macOS is working fine. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. +- "Your encryption data is locked on your device" is shown if you have never paired an Find My Device tracker with your phone. Solution: Temporalily pair a tracker with your phone. ### Firmware for custom ESP32-based trackers If you want to use an ESP32 as a custom Find My Device tracker, you can find the firmware in the folder ESP32Firmware. To register a new tracker, run main.py and press 'r' if you are asked to. Afterward, follow the instructions on-screen. From 78eb4ffc43aa8e55aaf604e8b6d29a0f254e04f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:18:33 +0100 Subject: [PATCH 06/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9467e26..75544da 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Currently, it is possible to query Find My Device trackers and Android devices, ### Known Issues - There seem to be issues with the package "undetected-chromedriver" not detecting Chrome on Windows and ARM Linux. macOS is working fine. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. -- "Your encryption data is locked on your device" is shown if you have never paired an Find My Device tracker with your phone. Solution: Temporalily pair a tracker with your phone. +- "Your encryption data is locked on your device" is shown if you have never paired an Find My Device tracker with an Android device. Solution: Temporarily pair a tracker with your phone. ### Firmware for custom ESP32-based trackers If you want to use an ESP32 as a custom Find My Device tracker, you can find the firmware in the folder ESP32Firmware. To register a new tracker, run main.py and press 'r' if you are asked to. Afterward, follow the instructions on-screen. From 0228cfaa8940044b88c314e366ab594dc3457bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:36:29 +0100 Subject: [PATCH 07/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 75544da..228e33c 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Currently, it is possible to query Find My Device trackers and Android devices, ### Known Issues - There seem to be issues with the package "undetected-chromedriver" not detecting Chrome on Windows and ARM Linux. macOS is working fine. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. -- "Your encryption data is locked on your device" is shown if you have never paired an Find My Device tracker with an Android device. Solution: Temporarily pair a tracker with your phone. +- "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: Temporarily pair a tracker with your phone. ### Firmware for custom ESP32-based trackers If you want to use an ESP32 as a custom Find My Device tracker, you can find the firmware in the folder ESP32Firmware. To register a new tracker, run main.py and press 'r' if you are asked to. Afterward, follow the instructions on-screen. From f815763d8026db7af8dd236abf7bb4edb1d180ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:37:03 +0100 Subject: [PATCH 08/31] Update README.md --- ESP32Firmware/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESP32Firmware/README.md b/ESP32Firmware/README.md index 29cad80..18c5074 100644 --- a/ESP32Firmware/README.md +++ b/ESP32Firmware/README.md @@ -24,7 +24,7 @@ The firmware works differently to regular Find My Device trackers. It is made to ## Known Issues - You need to run main.c every 3-7 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. -- Might not work with 'fresh' Google accounts, make sure that you used the Find My Device app on an Android device before registering a new tracker +- Might not work with 'fresh' Google accounts: "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: Temporarily pair a real tracker with your phone. - You cannot view locations for the ESP32 in the Google Find My Device app. You will need to use the Python script to do so. - No privacy features such as rotating MAC addresses are implemented - The firmware was built to receive as many network reports as possible. Therefore, it might consume more power than necessary. To fix this, you can tweak the parameters (TX Power and advertising interval) in [`main.c`](main/main.c) From ceb80729928df4814905f94dbc3b44c92267cda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 17 Feb 2025 13:31:36 +0100 Subject: [PATCH 09/31] Add hint --- Auth/fcm_receiver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Auth/fcm_receiver.py b/Auth/fcm_receiver.py index 4c651cd..c49f9ef 100644 --- a/Auth/fcm_receiver.py +++ b/Auth/fcm_receiver.py @@ -108,7 +108,7 @@ async def _register_for_fcm_and_listen(self): await self._register_for_fcm() await self.pc.start() self._listening = True - print("[FCMReceiver] Listening for notifications.") + print("[FCMReceiver] Listening for notifications. This can take a few seconds...") if __name__ == "__main__": From 1adc0323d230afa5648ba190245f23047ad0e58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 17 Feb 2025 13:08:00 +0100 Subject: [PATCH 10/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 228e33c..43db1e0 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Currently, it is possible to query Find My Device trackers and Android devices, ### Known Issues - There seem to be issues with the package "undetected-chromedriver" not detecting Chrome on Windows and ARM Linux. macOS is working fine. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. -- "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: Temporarily pair a tracker with your phone. +- "Your encryption data is locked on your device" is shown if you have never set up Find My Device on an Android device. Solution: Login with your Google Account on an Android device, go to Settings > Google > All Services > Find My Device > Find your offline devices > enable "With network in all areas" or "With network in high-traffic areas only". If "Find your offline devices" is not shown in Settings, you will need to download the Find My Device app from Google's Play Store, and pair a real Find My Device tracker with your device to force-enable the Find My Device network. ### Firmware for custom ESP32-based trackers If you want to use an ESP32 as a custom Find My Device tracker, you can find the firmware in the folder ESP32Firmware. To register a new tracker, run main.py and press 'r' if you are asked to. Afterward, follow the instructions on-screen. From fcc1e93008002c5e015722807a24e1b5981c5c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 17 Feb 2025 13:11:32 +0100 Subject: [PATCH 11/31] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 43db1e0..2c81de6 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Currently, it is possible to query Find My Device trackers and Android devices, - You can try out this code by running [main.py](main.py): `python main.py` ### Known Issues -- There seem to be issues with the package "undetected-chromedriver" not detecting Chrome on Windows and ARM Linux. macOS is working fine. -- No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. +- There seem to be issues with the package "undetected-chromedriver" not detecting Chrome on Windows and ARM Linux. Solution: Add the path of Chrome manually in the files shared_key_flow.py and auth_flow.py. Further steps are commented in those files. - "Your encryption data is locked on your device" is shown if you have never set up Find My Device on an Android device. Solution: Login with your Google Account on an Android device, go to Settings > Google > All Services > Find My Device > Find your offline devices > enable "With network in all areas" or "With network in high-traffic areas only". If "Find your offline devices" is not shown in Settings, you will need to download the Find My Device app from Google's Play Store, and pair a real Find My Device tracker with your device to force-enable the Find My Device network. +- No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. ### Firmware for custom ESP32-based trackers If you want to use an ESP32 as a custom Find My Device tracker, you can find the firmware in the folder ESP32Firmware. To register a new tracker, run main.py and press 'r' if you are asked to. Afterward, follow the instructions on-screen. From 03b732098a4110301cfc69e898d82cc9287003a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 17 Feb 2025 13:12:13 +0100 Subject: [PATCH 12/31] Update README.md --- ESP32Firmware/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESP32Firmware/README.md b/ESP32Firmware/README.md index 18c5074..c37db74 100644 --- a/ESP32Firmware/README.md +++ b/ESP32Firmware/README.md @@ -24,7 +24,7 @@ The firmware works differently to regular Find My Device trackers. It is made to ## Known Issues - You need to run main.c every 3-7 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. -- Might not work with 'fresh' Google accounts: "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: Temporarily pair a real tracker with your phone. +- Might not work with 'fresh' Google accounts: "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: See [README of the parent folder](../README.md). - You cannot view locations for the ESP32 in the Google Find My Device app. You will need to use the Python script to do so. - No privacy features such as rotating MAC addresses are implemented - The firmware was built to receive as many network reports as possible. Therefore, it might consume more power than necessary. To fix this, you can tweak the parameters (TX Power and advertising interval) in [`main.c`](main/main.c) From 848eb1b78f22e026974440caa03df0070972e3a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 17 Feb 2025 13:35:44 +0100 Subject: [PATCH 13/31] Improve prints --- .../ExecuteAction/LocateTracker/location_request.py | 10 +++++----- NovaApi/ListDevices/nbe_list_devices.py | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/NovaApi/ExecuteAction/LocateTracker/location_request.py b/NovaApi/ExecuteAction/LocateTracker/location_request.py index 85e82db..9dec8a5 100644 --- a/NovaApi/ExecuteAction/LocateTracker/location_request.py +++ b/NovaApi/ExecuteAction/LocateTracker/location_request.py @@ -29,9 +29,9 @@ def create_location_request(canonic_device_id, fcm_registration_id, request_uuid return hex_payload -def get_location_data_for_device(canonic_device_id): +def get_location_data_for_device(canonic_device_id, name): - print("[LocationRequest] Requesting location data for device with canonic ID:", canonic_device_id) + print(f"[LocationRequest] Requesting location data for {name}...") result = None request_uuid = generate_random_uuid() @@ -41,7 +41,7 @@ def handle_location_response(response): device_update = parse_device_update_protobuf(response) if device_update.fcmMetadata.requestUuid == request_uuid: - print("[LocationRequest] Location request successful.") + print("[LocationRequest] Location request successful. Decrypting locations...") result = parse_device_update_protobuf(response) #print_device_update_protobuf(response) @@ -51,9 +51,9 @@ def handle_location_response(response): nova_request(NOVA_ACTION_API_SCOPE, hex_payload) while result is None: - asyncio.get_event_loop().run_until_complete(asyncio.sleep(1)) + asyncio.get_event_loop().run_until_complete(asyncio.sleep(0.1)) decrypt_location_response_locations(result) if __name__ == '__main__': - get_location_data_for_device(get_example_data("sample_canonic_device_id")) \ No newline at end of file + get_location_data_for_device(get_example_data("sample_canonic_device_id"), "Test") \ No newline at end of file diff --git a/NovaApi/ListDevices/nbe_list_devices.py b/NovaApi/ListDevices/nbe_list_devices.py index 060e48b..7590f31 100644 --- a/NovaApi/ListDevices/nbe_list_devices.py +++ b/NovaApi/ListDevices/nbe_list_devices.py @@ -66,9 +66,10 @@ def list_devices(): register_esp32() else: selected_idx = int(selected_value) - 1 + selected_device_name = canonic_ids[selected_idx][0] selected_canonic_id = canonic_ids[selected_idx][1] - get_location_data_for_device(selected_canonic_id) + get_location_data_for_device(selected_canonic_id, selected_device_name) if __name__ == '__main__': From 304012b5c6769c998b8f37b71df402ffee5ce4ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 17 Feb 2025 15:44:23 +0100 Subject: [PATCH 14/31] Better Chrome detection --- Auth/auth_flow.py | 17 +------- KeyBackup/shared_key_flow.py | 19 +-------- chrome_driver.py | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 33 deletions(-) create mode 100644 chrome_driver.py diff --git a/Auth/auth_flow.py b/Auth/auth_flow.py index f7d96c8..0f80292 100644 --- a/Auth/auth_flow.py +++ b/Auth/auth_flow.py @@ -3,19 +3,10 @@ # Copyright © 2024 Leon Böttger. All rights reserved. # -import time -import undetected_chromedriver as uc from selenium.webdriver.support.ui import WebDriverWait +from chrome_driver import create_driver def request_oauth_account_token_flow(): - # Set up Chrome options - chrome_options = uc.ChromeOptions() - chrome_options.add_argument("--disable-extensions") - chrome_options.add_argument("--disable-gpu") - chrome_options.add_argument("--no-sandbox") - - # For Windows users only: set binary location to "C:\ProgramData\chocolatey\bin\chrome.exe" or similar - # chrome_options.binary_location = r"INSERT_PATH_TO_CHROME_BINARY_HERE" print("""[AuthFlow] This script will now open Google Chrome on your device to login to your Google account. > Please make sure that Chrome is installed on your system. @@ -28,11 +19,7 @@ def request_oauth_account_token_flow(): # Automatically install and set up the Chrome driver print("[AuthFlow] Installing ChromeDriver...") - try: - driver = uc.Chrome(options=chrome_options) - print("[AuthFlow] ChromeDriver installed and browser started.") - except Exception as e: - raise Exception("[AuthFlow] Failed to install ChromeDriver. A current version of Chrome was not detected on your system.\n\nIf you know that Chrome is installed, first try to update Chrome to the latest version. If the script is still not working afterward, open the file 'Auth/auth_flow.py' and set the path to your Chrome executable in line 16.") + driver = create_driver() try: # Open the browser and navigate to the URL diff --git a/KeyBackup/shared_key_flow.py b/KeyBackup/shared_key_flow.py index 936274b..419f284 100644 --- a/KeyBackup/shared_key_flow.py +++ b/KeyBackup/shared_key_flow.py @@ -5,27 +5,10 @@ from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as ec -import undetected_chromedriver as uc from KeyBackup.response_parser import get_fmdn_shared_key from KeyBackup.shared_key_request import get_security_domain_request_url - - -# Initialize undetected Chrome WebDriver -def create_driver(): - chrome_options = uc.ChromeOptions() - chrome_options.add_argument("--start-maximized") - - # For Windows users only: set binary location to "C:\ProgramData\chocolatey\bin\chrome.exe" or similar - # chrome_options.binary_location = r"INSERT_PATH_TO_CHROME_BINARY_HERE" - - try: - driver = uc.Chrome(options=chrome_options) - print("[SharedKeyFlow] ChromeDriver installed and browser started.") - return driver - except Exception as e: - raise Exception("[SharedKeyFlow] Failed to install ChromeDriver. A current version of Chrome was not detected on your system.\n\nIf you know that Chrome is installed, first try to update Chrome to the latest version. If the script is still not working afterward, open the file 'KeyBackup/shared_key_flow.py' and set the path to your Chrome executable in line 20.") - +from chrome_driver import create_driver def request_shared_key_flow(): driver = create_driver() diff --git a/chrome_driver.py b/chrome_driver.py new file mode 100644 index 0000000..78826ac --- /dev/null +++ b/chrome_driver.py @@ -0,0 +1,79 @@ +# +# GoogleFindMyTools - A set of tools to interact with the Google Find My API +# Copyright © 2024 Leon Böttger. All rights reserved. +# + +import undetected_chromedriver as uc +import os +import shutil +import platform + +def find_chrome(): + """Find Chrome executable using known paths and system commands.""" + possiblePaths = [ + r"C:\Program Files\Google\Chrome\Application\chrome.exe", + r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", + r"C:\ProgramData\chocolatey\bin\chrome.exe", + r"C:\Users\%USERNAME%\AppData\Local\Google\Chrome\Application\chrome.exe", + "/usr/bin/google-chrome", + "/usr/local/bin/google-chrome", + "/opt/google/chrome/chrome", + "/snap/bin/chromium", + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + ] + + # Check predefined paths + for path in possiblePaths: + if os.path.exists(path): + return path + + # Use system command to find Chrome + try: + if platform.system() == "Windows": + chrome_path = shutil.which("chrome") + else: + chrome_path = shutil.which("google-chrome") or shutil.which("chromium") + if chrome_path: + return chrome_path + except Exception as e: + print(f"[ChromeDriver] Error while searching system paths: {e}") + + return None + + +def create_driver(): + """Create a Chrome WebDriver with undetected_chromedriver.""" + chrome_options = uc.ChromeOptions() + chrome_options.add_argument("--start-maximized") + chrome_options.add_argument("--disable-extensions") + chrome_options.add_argument("--disable-gpu") + chrome_options.add_argument("--no-sandbox") + + try: + driver = uc.Chrome(options=chrome_options) + print("[ChromeDriver] Installed and browser started.") + return driver + except Exception: + print("[ChromeDriver] Default ChromeDriver creation failed. Trying alternative paths...") + + chrome_path = find_chrome() + if chrome_path: + chrome_options.binary_location = chrome_path + try: + driver = uc.Chrome(options=chrome_options) + print(f"[ChromeDriver] ChromeDriver started using {chrome_path}") + return driver + except Exception as e: + print(f"[ChromeDriver] ChromeDriver failed using path {chrome_path}: {e}") + else: + print("[ChromeDriver] No Chrome executable found in known paths.") + + raise Exception( + "[ChromeDriver] Failed to install ChromeDriver. A current version of Chrome was not detected on your system.\n" + "If you know that Chrome is installed, update Chrome to the latest version. If the script is still not working, " + "set the path to your Chrome executable manually inside the script." + ) + + +if __name__ == '__main__': + create_driver() \ No newline at end of file From d8cd52cba62b35ee66293d43f04b698b01311f83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Tue, 18 Feb 2025 10:32:39 +0100 Subject: [PATCH 15/31] Fix --- README.md | 12 ++++++++---- chrome_driver.py | 11 +++++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2c81de6..99ec64e 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,18 @@ This repository includes some useful tools that reimplement parts of Google's Fi Currently, it is possible to query Find My Device trackers and Android devices, read out their E2EE keys, and decrypt encrypted locations sent from the Find My Device network. You can also send register your own ESP32- or Zephyr-based trackers, as described below. ### How to use -- All packages in requirements.txt need to be installed: `pip install -r requirements.txt` -- The latest version of Google Chrome needs to be installed on your system. -- You can try out this code by running [main.py](main.py): `python main.py` +- Clone this repository: `git clone` or download the ZIP file +- Change into the directory: `cd GoogleFindMyTools` +- Optional: Create venv: `python -m venv venv` +- Optional: Activate venv: `venv\Scripts\activate` (Windows) or `source venv/bin/activate` (Linux & macOS) +- Install all required packages: `pip install -r requirements.txt` +- Install the latest version of Google Chrome: https://www.google.com/chrome/ +- Start the program by running [main.py](main.py): `python main.py` or `python3 main.py` ### Known Issues -- There seem to be issues with the package "undetected-chromedriver" not detecting Chrome on Windows and ARM Linux. Solution: Add the path of Chrome manually in the files shared_key_flow.py and auth_flow.py. Further steps are commented in those files. - "Your encryption data is locked on your device" is shown if you have never set up Find My Device on an Android device. Solution: Login with your Google Account on an Android device, go to Settings > Google > All Services > Find My Device > Find your offline devices > enable "With network in all areas" or "With network in high-traffic areas only". If "Find your offline devices" is not shown in Settings, you will need to download the Find My Device app from Google's Play Store, and pair a real Find My Device tracker with your device to force-enable the Find My Device network. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. +- No support for ARM Linux ### Firmware for custom ESP32-based trackers If you want to use an ESP32 as a custom Find My Device tracker, you can find the firmware in the folder ESP32Firmware. To register a new tracker, run main.py and press 'r' if you are asked to. Afterward, follow the instructions on-screen. diff --git a/chrome_driver.py b/chrome_driver.py index 78826ac..903198e 100644 --- a/chrome_driver.py +++ b/chrome_driver.py @@ -41,15 +41,21 @@ def find_chrome(): return None -def create_driver(): - """Create a Chrome WebDriver with undetected_chromedriver.""" +def get_options(): chrome_options = uc.ChromeOptions() chrome_options.add_argument("--start-maximized") chrome_options.add_argument("--disable-extensions") chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("--no-sandbox") + return chrome_options + + +def create_driver(): + """Create a Chrome WebDriver with undetected_chromedriver.""" + try: + chrome_options = get_options() driver = uc.Chrome(options=chrome_options) print("[ChromeDriver] Installed and browser started.") return driver @@ -58,6 +64,7 @@ def create_driver(): chrome_path = find_chrome() if chrome_path: + chrome_options = get_options() chrome_options.binary_location = chrome_path try: driver = uc.Chrome(options=chrome_options) From 41e1731e051e9ed77d7f6fc258c82ea370eb79aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Wed, 19 Feb 2025 15:15:36 +0100 Subject: [PATCH 16/31] Add hint for owner key version mismatch --- .../LocateTracker/decrypt_locations.py | 17 ++++++++++++++++- .../get_eid_info_request.py | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py index 0358421..ce284f0 100644 --- a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py +++ b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py @@ -13,6 +13,7 @@ from ProtoDecoders import Common_pb2 from ProtoDecoders.DeviceUpdate_pb2 import DeviceRegistration from ProtoDecoders.decoder import parse_device_update_protobuf +from SpotApi.GetEidInfoForE2eeDevices.get_eid_info_request import get_eid_info from SpotApi.GetEidInfoForE2eeDevices.get_owner_key import get_owner_key from SpotApi.CreateBleDevice.create_ble_device import mcu_fast_pair_model_id, flip_bits @@ -35,7 +36,21 @@ def retrieve_identity_key(device_registration: DeviceRegistration) -> bytes: identity_key = decrypt_eik(owner_key, encrypted_identity_key) return identity_key except Exception as e: - print(f"Failed to decrypt identity key encrypted with owner key version {encrypted_user_secrets.ownerKeyVersion}: {str(e)}") + + e2eeData = get_eid_info() + current_owner_key_version = e2eeData.encryptedOwnerKeyAndMetadata.ownerKeyVersion + + print("") + print("-" * 40) + print("Attention:") + print("-" * 40) + + if encrypted_user_secrets.ownerKeyVersion < current_owner_key_version: + print(f"Failed to decrypt E2EE data. This tracker was encrypted with owner key version {encrypted_user_secrets.ownerKeyVersion}, but the current owner key version is {current_owner_key_version}.\nThis happens if you reset your end-to-end-encrypted data in the past.\nThe tracker cannot be decrypted anymore, and it is recommended to remove it in the Find My Device app.") + exit(1) + else: + print(f"Failed to decrypt identity key encrypted with owner key version {encrypted_user_secrets.ownerKeyVersion}, current owner key version is {current_owner_key_version}.\nThis may happen if you reset your end-to-end-encrypted data. To resolve this issue, open the folder 'Auth' and delete the file 'secrets.json'.") + exit(1) def decrypt_location_response_locations(device_update_protobuf): diff --git a/SpotApi/GetEidInfoForE2eeDevices/get_eid_info_request.py b/SpotApi/GetEidInfoForE2eeDevices/get_eid_info_request.py index 632449e..6619b12 100644 --- a/SpotApi/GetEidInfoForE2eeDevices/get_eid_info_request.py +++ b/SpotApi/GetEidInfoForE2eeDevices/get_eid_info_request.py @@ -21,4 +21,4 @@ def get_eid_info(): if __name__ == '__main__': - print(get_eid_info().encryptedOwnerKeyAndMetadata.encryptedOwnerKey.hex()) \ No newline at end of file + print(get_eid_info().encryptedOwnerKeyAndMetadata) \ No newline at end of file From 685fa0025a06b23130120942c7257cae8649e4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 24 Feb 2025 15:08:13 +0100 Subject: [PATCH 17/31] Limit announced advertisements to align with server --- ESP32Firmware/README.md | 2 +- .../LocateTracker/decrypt_locations.py | 3 ++- SpotApi/CreateBleDevice/config.py | 9 +++++++++ SpotApi/CreateBleDevice/create_ble_device.py | 19 ++++--------------- SpotApi/CreateBleDevice/util.py | 15 +++++++++++++++ .../upload_precomputed_public_key_ids.py | 7 ++++--- 6 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 SpotApi/CreateBleDevice/config.py create mode 100644 SpotApi/CreateBleDevice/util.py diff --git a/ESP32Firmware/README.md b/ESP32Firmware/README.md index c37db74..8fa86ec 100644 --- a/ESP32Firmware/README.md +++ b/ESP32Firmware/README.md @@ -23,7 +23,7 @@ The firmware works differently to regular Find My Device trackers. It is made to ## Known Issues -- You need to run main.c every 3-7 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. +- You need to run main.c every 7 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. - Might not work with 'fresh' Google accounts: "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: See [README of the parent folder](../README.md). - You cannot view locations for the ESP32 in the Google Find My Device app. You will need to use the Python script to do so. - No privacy features such as rotating MAC addresses are implemented diff --git a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py index ce284f0..cffeee2 100644 --- a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py +++ b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py @@ -13,9 +13,10 @@ from ProtoDecoders import Common_pb2 from ProtoDecoders.DeviceUpdate_pb2 import DeviceRegistration from ProtoDecoders.decoder import parse_device_update_protobuf +from SpotApi.CreateBleDevice.config import mcu_fast_pair_model_id +from SpotApi.CreateBleDevice.util import flip_bits from SpotApi.GetEidInfoForE2eeDevices.get_eid_info_request import get_eid_info from SpotApi.GetEidInfoForE2eeDevices.get_owner_key import get_owner_key -from SpotApi.CreateBleDevice.create_ble_device import mcu_fast_pair_model_id, flip_bits # Indicates if the device is a custom microcontroller diff --git a/SpotApi/CreateBleDevice/config.py b/SpotApi/CreateBleDevice/config.py new file mode 100644 index 0000000..6d03593 --- /dev/null +++ b/SpotApi/CreateBleDevice/config.py @@ -0,0 +1,9 @@ +# +# GoogleFindMyTools - A set of tools to interact with the Google Find My API +# Copyright © 2024 Leon Böttger. All rights reserved. +# + +from SpotApi.CreateBleDevice.util import hours_to_seconds + +mcu_fast_pair_model_id = "003200" +max_truncated_eid_seconds_server = hours_to_seconds(168) \ No newline at end of file diff --git a/SpotApi/CreateBleDevice/create_ble_device.py b/SpotApi/CreateBleDevice/create_ble_device.py index 9f6b9a0..9466319 100644 --- a/SpotApi/CreateBleDevice/create_ble_device.py +++ b/SpotApi/CreateBleDevice/create_ble_device.py @@ -10,22 +10,11 @@ from FMDNCrypto.eid_generator import ROTATION_PERIOD, generate_eid from KeyBackup.cloud_key_decryptor import encrypt_aes_gcm from ProtoDecoders.DeviceUpdate_pb2 import DeviceComponentInformation, SpotDeviceType, RegisterBleDeviceRequest, PublicKeyIdList +from SpotApi.CreateBleDevice.config import mcu_fast_pair_model_id, max_truncated_eid_seconds_server +from SpotApi.CreateBleDevice.util import flip_bits from SpotApi.GetEidInfoForE2eeDevices.get_owner_key import get_owner_key from SpotApi.spot_request import spot_request -mcu_fast_pair_model_id = "003200" - -def hours_to_seconds(hours): - return hours * 3600 - - -def flip_bits(data: bytes, enabled: bool) -> bytes: - """Flips all bits in each byte of the given byte sequence.""" - if enabled: - return bytes(b ^ 0xFF for b in data) - - return data - def register_esp32(): @@ -44,7 +33,7 @@ def register_esp32(): # Device Components Information component_information = DeviceComponentInformation() - component_information.imageUrl = "https://m.media-amazon.com/images/I/61o2ZUzB4XL._AC_UF1000,1000_QL80_.jpg" + component_information.imageUrl = "https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/_images/esp32-DevKitM-1-isometric.png" register_request.description.deviceComponentsInformation.append(component_information) # Capabilities @@ -71,7 +60,7 @@ def register_esp32(): truncated_eid = eid[:10] # announce advertisements - for _ in range(int(hours_to_seconds(3000) / ROTATION_PERIOD)): + for _ in range(int(max_truncated_eid_seconds_server / ROTATION_PERIOD)): pub_key_id = PublicKeyIdList.PublicKeyIdInfo() pub_key_id.publicKeyId.truncatedEid = truncated_eid pub_key_id.timestamp.seconds = time_counter diff --git a/SpotApi/CreateBleDevice/util.py b/SpotApi/CreateBleDevice/util.py new file mode 100644 index 0000000..f406748 --- /dev/null +++ b/SpotApi/CreateBleDevice/util.py @@ -0,0 +1,15 @@ +# +# GoogleFindMyTools - A set of tools to interact with the Google Find My API +# Copyright © 2024 Leon Böttger. All rights reserved. +# + +def flip_bits(data: bytes, enabled: bool) -> bytes: + """Flips all bits in each byte of the given byte sequence.""" + if enabled: + return bytes(b ^ 0xFF for b in data) + + return data + + +def hours_to_seconds(hours): + return hours * 3600 \ No newline at end of file diff --git a/SpotApi/UploadPrecomputedPublicKeyIds/upload_precomputed_public_key_ids.py b/SpotApi/UploadPrecomputedPublicKeyIds/upload_precomputed_public_key_ids.py index 36059cb..6f8afdb 100644 --- a/SpotApi/UploadPrecomputedPublicKeyIds/upload_precomputed_public_key_ids.py +++ b/SpotApi/UploadPrecomputedPublicKeyIds/upload_precomputed_public_key_ids.py @@ -7,7 +7,8 @@ from FMDNCrypto.eid_generator import ROTATION_PERIOD, generate_eid from NovaApi.ExecuteAction.LocateTracker.decrypt_locations import retrieve_identity_key, is_mcu_tracker from ProtoDecoders.DeviceUpdate_pb2 import DevicesList, UploadPrecomputedPublicKeyIdsRequest, PublicKeyIdList -from SpotApi.CreateBleDevice.create_ble_device import hours_to_seconds +from SpotApi.CreateBleDevice.config import max_truncated_eid_seconds_server +from SpotApi.CreateBleDevice.util import hours_to_seconds from SpotApi.spot_request import spot_request @@ -28,7 +29,7 @@ def refresh_custom_trackers(device_list: DevicesList): new_truncated_ids.canonicId.id = device.identifierInformation.canonicIds.canonicId[0].id identity_key = retrieve_identity_key(device.information.deviceRegistration) - next_eids = get_next_eids(identity_key, new_truncated_ids.pairDate, int(time.time() - hours_to_seconds(3))) + next_eids = get_next_eids(identity_key, new_truncated_ids.pairDate, int(time.time() - hours_to_seconds(3)), duration_seconds=max_truncated_eid_seconds_server) for next_eid in next_eids: new_truncated_ids.clientList.publicKeyIdInfo.append(next_eid) @@ -44,7 +45,7 @@ def refresh_custom_trackers(device_list: DevicesList): print(f"[UploadPrecomputedPublicKeyIds] Failed to refresh custom trackers. Please file a bug report. Continuing... {str(e)}") -def get_next_eids(eik: bytes, pair_date: int, start_date: int, duration_seconds: int = hours_to_seconds(8760)) -> list[PublicKeyIdList.PublicKeyIdInfo]: +def get_next_eids(eik: bytes, pair_date: int, start_date: int, duration_seconds: int) -> list[PublicKeyIdList.PublicKeyIdInfo]: duration_seconds = int(duration_seconds) public_key_id_list = [] From 0c76aff7a7a4a0d86764b912384b9639c60ee5e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Fri, 28 Feb 2025 16:22:05 +0100 Subject: [PATCH 18/31] Limit announced advertisements to align with server --- ESP32Firmware/README.md | 2 +- SpotApi/CreateBleDevice/config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ESP32Firmware/README.md b/ESP32Firmware/README.md index 8fa86ec..fe63cba 100644 --- a/ESP32Firmware/README.md +++ b/ESP32Firmware/README.md @@ -23,7 +23,7 @@ The firmware works differently to regular Find My Device trackers. It is made to ## Known Issues -- You need to run main.c every 7 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. +- You need to run main.c every 4 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. - Might not work with 'fresh' Google accounts: "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: See [README of the parent folder](../README.md). - You cannot view locations for the ESP32 in the Google Find My Device app. You will need to use the Python script to do so. - No privacy features such as rotating MAC addresses are implemented diff --git a/SpotApi/CreateBleDevice/config.py b/SpotApi/CreateBleDevice/config.py index 6d03593..399bc86 100644 --- a/SpotApi/CreateBleDevice/config.py +++ b/SpotApi/CreateBleDevice/config.py @@ -6,4 +6,4 @@ from SpotApi.CreateBleDevice.util import hours_to_seconds mcu_fast_pair_model_id = "003200" -max_truncated_eid_seconds_server = hours_to_seconds(168) \ No newline at end of file +max_truncated_eid_seconds_server = hours_to_seconds(4*24) \ No newline at end of file From ad91e2f36cabe0356bd2239453ca52d4849807a5 Mon Sep 17 00:00:00 2001 From: Vasile Sularea Date: Sat, 1 Mar 2025 12:23:23 +0100 Subject: [PATCH 19/31] Adding support for ESP32-C3 using nimble Added to the gitignore the venv and the python cached files --- .gitignore | 5 + ESP32Firmware/main/main.c | 199 +++++++++++++++++++++++++++----------- 2 files changed, 148 insertions(+), 56 deletions(-) diff --git a/.gitignore b/.gitignore index c99ad0f..637dda8 100644 --- a/.gitignore +++ b/.gitignore @@ -180,4 +180,9 @@ xcuserdata /*.gcno **/xcshareddata/WorkspaceSettings.xcsettings +### Venv ### +venv/ + +*** Python cache*** +*.pyc # End of https://www.toptal.com/developers/gitignore/api/macos,xcode,swift,swiftpackagemanager,objective-c diff --git a/ESP32Firmware/main/main.c b/ESP32Firmware/main/main.c index 9f1a8cc..b5baddb 100644 --- a/ESP32Firmware/main/main.c +++ b/ESP32Firmware/main/main.c @@ -2,18 +2,59 @@ #include #include #include -#include "esp_bt.h" -#include "esp_gap_ble_api.h" #include "esp_log.h" #include "nvs_flash.h" // For NVS functions like nvs_flash_init -#include "esp_bt_main.h" // For esp_bluedroid_* functions #include "esp_err.h" // For error handling #define TAG "ESP_FMDN" +#if defined(CONFIG_IDF_TARGET_ESP32C3) +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "services/gap/ble_svc_gap.h" + +#elif defined(CONFIG_IDF_TARGET_ESP32) +#include "esp_bt.h" +#include "esp_bt_main.h" // For esp_bluedroid_* functions +#include "esp_gap_ble_api.h" + +#else +#error "Unsupported target" +#endif + // This is the advertisement key / EID. Change it to your own EID. const char *eid_string = "INSERT_YOUR_ADVERTISEMENT_KEY_HERE"; +// Find My Device Network (FMDN) advertisement +// Octet Value Description +// 0 0x02 Length +// 1 0x01 Flags data type value +// 2 0x06 Flags data +// 3 0x18 or 0x19 Length +// 4 0x16 Service data data type value +// 5 0xAA 16-bit service UUID +// 6 0xFE 16-bit service UUID +// 7 0x40 or 0x41 FMDN frame type with unwanted tracking protection mode indication +// 8..27 Random 20-byte ephemeral identifier +// 28 Hashed flags + +uint8_t adv_raw_data[31] = { + 0x02, // Length + 0x01, // Flags data type value + 0x06, // Flags data + 0x19, // Length + 0x16, // Service data data type value + 0xAA, // 16-bit service UUID + 0xFE, // 16-bit service UUID + 0x41, // FMDN frame type with unwanted tracking protection mode indication + // 20-byte ephemeral identifier (inserted below) + // Hashed flags (implicitly initialized to 0) +}; + + // Function to convert a hex string into a byte array void hex_string_to_bytes(const char *hex, uint8_t *bytes, size_t len) { for (size_t i = 0; i < len; i++) { @@ -21,6 +62,58 @@ void hex_string_to_bytes(const char *hex, uint8_t *bytes, size_t len) { } } +#if defined(CONFIG_IDF_TARGET_ESP32C3) +// BLE advertising callback +static void ble_advertise_cb(struct ble_gap_event *event, void *arg) +{ + switch (event->type) { + case BLE_GAP_EVENT_ADV_COMPLETE: + ESP_LOGI(TAG, "Advertising completed"); + break; + default: + break; + } +} + +// Set up and start advertising +static void ble_start_advertising(uint8_t *adv_raw_data, size_t adv_raw_data_len) +{ + struct ble_gap_adv_params adv_params = { + .conn_mode = BLE_GAP_CONN_MODE_NON, + .disc_mode = BLE_GAP_DISC_MODE_GEN, + .itvl_min = 0x20, + .itvl_max = 0x20 + }; + + + ble_gap_adv_set_data(adv_raw_data, adv_raw_data_len); + + // Start advertising + ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, ble_advertise_cb, NULL); + + ESP_LOGI(TAG, "Started advertising"); +} + +static void ble_host_task(void *param) +{ + ESP_LOGI(TAG, "BLE Host Task Started"); + nimble_port_run(); + nimble_port_freertos_deinit(); +} + +// Sync callback +static void on_sync(void) +{ + // Set device name + ble_svc_gap_device_name_set("ESP32-C3-BLE"); + + // Start advertising + ble_start_advertising(adv_raw_data, sizeof(adv_raw_data)); + //print adv raw data + ESP_LOGI(TAG, "adv_raw_data: %s", adv_raw_data); +} +#endif + void app_main() { // Initialize NVS (required for BLE initialization) esp_err_t ret = nvs_flash_init(); @@ -30,67 +123,61 @@ void app_main() { } ESP_ERROR_CHECK(ret); - // Initialize Bluetooth controller - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); - ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); - - // Initialize Bluedroid stack - ESP_ERROR_CHECK(esp_bluedroid_init()); - ESP_ERROR_CHECK(esp_bluedroid_enable()); - - // Set BLE TX power to 9 dBm - ESP_ERROR_CHECK(esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9)); - ESP_ERROR_CHECK(esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9)); - ESP_LOGI(TAG, "Set BLE TX Power to 9 dBm"); - - // Find My Device Network (FMDN) advertisement - // Octet Value Description - // 0 0x02 Length - // 1 0x01 Flags data type value - // 2 0x06 Flags data - // 3 0x18 or 0x19 Length - // 4 0x16 Service data data type value - // 5 0xAA 16-bit service UUID - // 6 0xFE 16-bit service UUID - // 7 0x40 or 0x41 FMDN frame type with unwanted tracking protection mode indication - // 8..27 Random 20-byte ephemeral identifier - // 28 Hashed flags - - uint8_t adv_raw_data[31] = { - 0x02, // Length - 0x01, // Flags data type value - 0x06, // Flags data - 0x19, // Length - 0x16, // Service data data type value - 0xAA, // 16-bit service UUID - 0xFE, // 16-bit service UUID - 0x41, // FMDN frame type with unwanted tracking protection mode indication - // 20-byte ephemeral identifier (inserted below) - // Hashed flags (implicitly initialized to 0) - }; + // 20-byte ephemeral identifier uint8_t eid_bytes[20]; hex_string_to_bytes(eid_string, eid_bytes, 20); memcpy(&adv_raw_data[8], eid_bytes, 20); - ESP_ERROR_CHECK(esp_ble_gap_config_adv_data_raw(adv_raw_data, sizeof(adv_raw_data))); + #if defined(CONFIG_IDF_TARGET_ESP32C3) + ESP_LOGI(TAG, "Initializing BLE"); + + // Initialize NimBLE - ESP-IDF v5.3 style + ESP_ERROR_CHECK(nimble_port_init()); + + // Initialize the NimBLE host configuration + ble_hs_cfg.sync_cb = on_sync; + + // Initialize GAP service + ble_svc_gap_init(); + + // Create host task + nimble_port_freertos_init(ble_host_task); - // Configure advertisement parameters - esp_ble_adv_params_t adv_params = { + #elif defined(CONFIG_IDF_TARGET_ESP32) + // Initialize Bluetooth controller + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); + ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); - // change those if you want to save power - .adv_int_min = 0x20, - .adv_int_max = 0x20, + // Initialize Bluedroid stack + ESP_ERROR_CHECK(esp_bluedroid_init()); + ESP_ERROR_CHECK(esp_bluedroid_enable()); - .adv_type = ADV_TYPE_NONCONN_IND, - .own_addr_type = BLE_ADDR_TYPE_PUBLIC, - .channel_map = ADV_CHNL_ALL, - .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, - }; + // Set BLE TX power to 9 dBm + ESP_ERROR_CHECK(esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9)); + ESP_ERROR_CHECK(esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9)); + ESP_LOGI(TAG, "Set BLE TX Power to 9 dBm"); - // Start advertising - ESP_ERROR_CHECK(esp_ble_gap_start_advertising(&adv_params)); - ESP_LOGI(TAG, "BLE advertising started."); + + ESP_ERROR_CHECK(esp_ble_gap_config_adv_data_raw(adv_raw_data, sizeof(adv_raw_data))); + + // Configure advertisement parameters + esp_ble_adv_params_t adv_params = { + + // change those if you want to save power + .adv_int_min = 0x20, + .adv_int_max = 0x20, + + .adv_type = ADV_TYPE_NONCONN_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + }; + + // Start advertising + ESP_ERROR_CHECK(esp_ble_gap_start_advertising(&adv_params)); + ESP_LOGI(TAG, "BLE advertising started."); + #endif } \ No newline at end of file From 9b7d3c2e12a806e29b52762873b4578f6443f14b Mon Sep 17 00:00:00 2001 From: Vasile Sularea Date: Sat, 1 Mar 2025 12:38:35 +0100 Subject: [PATCH 20/31] Adding a google maps link to location print for ease of use of seeing where your devices are --- .../LocateTracker/decrypt_locations.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py index cffeee2..c0e7033 100644 --- a/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py +++ b/NovaApi/ExecuteAction/LocateTracker/decrypt_locations.py @@ -19,6 +19,19 @@ from SpotApi.GetEidInfoForE2eeDevices.get_owner_key import get_owner_key +def create_google_maps_link(latitude, longitude): + try: + latitude = float(latitude) + longitude = float(longitude) + if not (-90 <= latitude <= 90 and -180 <= longitude <= 180): + raise ValueError("Invalid latitude or longitude values.") + except ValueError as e: + return f"Error: {e}" #more descriptive error message for the user + base_url = "https://www.google.com/maps/search/?api=1" + query_params = f"query={latitude},{longitude}" + + return f"{base_url}&{query_params}" + # Indicates if the device is a custom microcontroller def is_mcu_tracker(device_registration: DeviceRegistration) -> bool: return device_registration.fastPairModelId == mcu_fast_pair_model_id @@ -134,7 +147,8 @@ def decrypt_location_response_locations(device_update_protobuf): print(f"Latitude: {latitude}") print(f"Longitude: {longitude}") print(f"Altitude: {altitude}") - + print(f"Google Maps Link: {create_google_maps_link(latitude, longitude)}") + print(f"Time: {datetime.datetime.fromtimestamp(loc.time).strftime('%Y-%m-%d %H:%M:%S')}") print(f"Status: {loc.status}") print(f"Is Own Report: {loc.is_own_report}") From 1f901500e68c4df47c9fd07d6dc0b390403e3ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:53:03 +0100 Subject: [PATCH 21/31] Update README.md --- ESP32Firmware/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ESP32Firmware/README.md b/ESP32Firmware/README.md index fe63cba..2c4407b 100644 --- a/ESP32Firmware/README.md +++ b/ESP32Firmware/README.md @@ -1,9 +1,11 @@ # Find My Device ESP32 Firmware -This code enables you to use an ESP32-device as a custom Google Find My Device tracker. Note that the firmware is very experimental. +This code enables you to use an ESP32-device as a custom Google Find My Device tracker. Note that the firmware is very experimental. The firmware works differently to regular Find My Device trackers. It is made to be as simple as possible. It has no Fast Pair support, MAC rotation, advertisement rotation, etc. +Currently known working devices include the ESP32 and ESP32-C3. If you use a different board and it works/doesn't work, feel free to message me, I'll update this README then. + ## How to use From 947571415e7e0c67dcea0d3af61d783d0ff8f32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:55:41 +0100 Subject: [PATCH 22/31] Update README.md --- ESP32Firmware/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESP32Firmware/README.md b/ESP32Firmware/README.md index 2c4407b..c43ac94 100644 --- a/ESP32Firmware/README.md +++ b/ESP32Firmware/README.md @@ -4,7 +4,7 @@ This code enables you to use an ESP32-device as a custom Google Find My Device t The firmware works differently to regular Find My Device trackers. It is made to be as simple as possible. It has no Fast Pair support, MAC rotation, advertisement rotation, etc. -Currently known working devices include the ESP32 and ESP32-C3. If you use a different board and it works/doesn't work, feel free to message me, I'll update this README then. +Currently known working devices include the ESP32 (Dev Module V1), the ESP32-CAM, and ESP32-C3. If you use a different board and it works/doesn't work, feel free to message me, I'll update this README then. ## How to use From 87d51ad67a465e99a318e9e274d163ee47332301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 24 Mar 2025 10:12:52 +0100 Subject: [PATCH 23/31] Extend lskf_hasher.py --- KeyBackup/lskf_hasher.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/KeyBackup/lskf_hasher.py b/KeyBackup/lskf_hasher.py index 9f73179..d8b17e1 100644 --- a/KeyBackup/lskf_hasher.py +++ b/KeyBackup/lskf_hasher.py @@ -2,9 +2,12 @@ # GoogleFindMyTools - A set of tools to interact with the Google Find My API # Copyright © 2024 Leon Böttger. All rights reserved. # +import hashlib from binascii import unhexlify - +from concurrent.futures import ProcessPoolExecutor +import time import pyscrypt + from example_data_provider import get_example_data @@ -33,9 +36,26 @@ def get_lskf_hash(pin: str, salt: bytes) -> bytes: return hashed +def hash_pin(pin): + sample_pin_salt = unhexlify(get_example_data("sample_pin_salt")) + + hash_object = hashlib.sha256(get_lskf_hash(pin, sample_pin_salt)) + hash_hex = hash_object.hexdigest() + + print(f"PIN: {pin}, Hash: {hash_hex}") + return pin, hash_hex + + if __name__ == '__main__': + start_time = time.time() + pins = [f"{i:04d}" for i in range(10000)] - sample_pin = get_example_data("sample_pin") - sample_pin_salt = unhexlify(get_example_data("sample_pin_salt")) + with ProcessPoolExecutor() as executor: + results = list(executor.map(hash_pin, pins)) + + for pin, hashed in results: + print(f"PIN: {pin}, Hash: {hashed}") - print(get_lskf_hash(sample_pin, sample_pin_salt).hex()) \ No newline at end of file + end_time = time.time() + elapsed_time = end_time - start_time + print(f"Time taken: {elapsed_time:.2f} seconds") \ No newline at end of file From 997b19ebd8f593781eaf4311107db4c2f91d1b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Thu, 6 Mar 2025 08:56:06 +0100 Subject: [PATCH 24/31] Update README.md --- ESP32Firmware/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESP32Firmware/README.md b/ESP32Firmware/README.md index c43ac94..afecc05 100644 --- a/ESP32Firmware/README.md +++ b/ESP32Firmware/README.md @@ -25,7 +25,7 @@ Currently known working devices include the ESP32 (Dev Module V1), the ESP32-CAM ## Known Issues -- You need to run main.c every 4 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. +- You need to run [`main.py`](../main.py) every 4 days to keep receiving location reports from the server. This is because the advertisements have to be "announced" to Google. - Might not work with 'fresh' Google accounts: "Your encryption data is locked on your device" is shown if you have never paired a Find My Device tracker with an Android device. Solution: See [README of the parent folder](../README.md). - You cannot view locations for the ESP32 in the Google Find My Device app. You will need to use the Python script to do so. - No privacy features such as rotating MAC addresses are implemented From 4a600f6dcee2aa53831fce8a9ff548e53523ce51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Thu, 6 Mar 2025 08:57:09 +0100 Subject: [PATCH 25/31] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 99ec64e..70246c8 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Currently, it is possible to query Find My Device trackers and Android devices, - "Your encryption data is locked on your device" is shown if you have never set up Find My Device on an Android device. Solution: Login with your Google Account on an Android device, go to Settings > Google > All Services > Find My Device > Find your offline devices > enable "With network in all areas" or "With network in high-traffic areas only". If "Find your offline devices" is not shown in Settings, you will need to download the Find My Device app from Google's Play Store, and pair a real Find My Device tracker with your device to force-enable the Find My Device network. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. - No support for ARM Linux +- Please also consider the issues listed in the [README in the ESP32Firmware folder](ESP32Firmware/README.md) if you want to register custom trackers. ### Firmware for custom ESP32-based trackers If you want to use an ESP32 as a custom Find My Device tracker, you can find the firmware in the folder ESP32Firmware. To register a new tracker, run main.py and press 'r' if you are asked to. Afterward, follow the instructions on-screen. From bfe39365a2f78dd8a2f6a7e0693fe2dbc2df26c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Thu, 6 Mar 2025 16:24:47 +0100 Subject: [PATCH 26/31] Add sdkconfig for ESP32-C3, fix function return type --- ESP32Firmware/main/main.c | 3 ++- ESP32Firmware/sdkconfig.defaults.esp32c3 | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 ESP32Firmware/sdkconfig.defaults.esp32c3 diff --git a/ESP32Firmware/main/main.c b/ESP32Firmware/main/main.c index b5baddb..5f887c5 100644 --- a/ESP32Firmware/main/main.c +++ b/ESP32Firmware/main/main.c @@ -64,7 +64,7 @@ void hex_string_to_bytes(const char *hex, uint8_t *bytes, size_t len) { #if defined(CONFIG_IDF_TARGET_ESP32C3) // BLE advertising callback -static void ble_advertise_cb(struct ble_gap_event *event, void *arg) +static int ble_advertise_cb(struct ble_gap_event *event, void *arg) { switch (event->type) { case BLE_GAP_EVENT_ADV_COMPLETE: @@ -73,6 +73,7 @@ static void ble_advertise_cb(struct ble_gap_event *event, void *arg) default: break; } + return 0; } // Set up and start advertising diff --git a/ESP32Firmware/sdkconfig.defaults.esp32c3 b/ESP32Firmware/sdkconfig.defaults.esp32c3 new file mode 100644 index 0000000..a22d810 --- /dev/null +++ b/ESP32Firmware/sdkconfig.defaults.esp32c3 @@ -0,0 +1,2 @@ +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y From 52d7b6015426af4dbec260b63e35e283a1c54187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sun, 23 Mar 2025 22:46:23 +0200 Subject: [PATCH 27/31] Add documentation about secrets.json --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 70246c8..ec96084 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,12 @@ Currently, it is possible to query Find My Device trackers and Android devices, - Install the latest version of Google Chrome: https://www.google.com/chrome/ - Start the program by running [main.py](main.py): `python main.py` or `python3 main.py` +### Authentication + +On first run, authentication sequence is started in a new Chrome browser profile. + +The authentication results are stored in `Auth/secrets.json`. + ### Known Issues - "Your encryption data is locked on your device" is shown if you have never set up Find My Device on an Android device. Solution: Login with your Google Account on an Android device, go to Settings > Google > All Services > Find My Device > Find your offline devices > enable "With network in all areas" or "With network in high-traffic areas only". If "Find your offline devices" is not shown in Settings, you will need to download the Find My Device app from Google's Play Store, and pair a real Find My Device tracker with your device to force-enable the Find My Device network. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. From 0bcafc20036da6a5d1bd3c527029e9103ac0ef1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Mon, 24 Mar 2025 10:05:09 +0100 Subject: [PATCH 28/31] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ec96084..3352eff 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ Currently, it is possible to query Find My Device trackers and Android devices, ### Authentication -On first run, authentication sequence is started in a new Chrome browser profile. +On the first run, an authentication sequence is executed, which requires a computer with access to Google Chrome. -The authentication results are stored in `Auth/secrets.json`. +The authentication results are stored in `Auth/secrets.json`. If you intend to run this tool on a headless machine, you can just copy this file to avoid having to use Chrome. ### Known Issues - "Your encryption data is locked on your device" is shown if you have never set up Find My Device on an Android device. Solution: Login with your Google Account on an Android device, go to Settings > Google > All Services > Find My Device > Find your offline devices > enable "With network in all areas" or "With network in high-traffic areas only". If "Find your offline devices" is not shown in Settings, you will need to download the Find My Device app from Google's Play Store, and pair a real Find My Device tracker with your device to force-enable the Find My Device network. From 2441026f81683fb19a5965e07c45091f3da2727b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Tue, 25 Mar 2025 10:15:08 +0100 Subject: [PATCH 29/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3352eff..488eab1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The authentication results are stored in `Auth/secrets.json`. If you intend to r ### Known Issues - "Your encryption data is locked on your device" is shown if you have never set up Find My Device on an Android device. Solution: Login with your Google Account on an Android device, go to Settings > Google > All Services > Find My Device > Find your offline devices > enable "With network in all areas" or "With network in high-traffic areas only". If "Find your offline devices" is not shown in Settings, you will need to download the Find My Device app from Google's Play Store, and pair a real Find My Device tracker with your device to force-enable the Find My Device network. - No support for trackers using the P-256 curve and 32-Byte advertisements. Regular trackers don't seem to use this curve at all - I can only confirm that it is used with Sony's WH1000XM5 headphones. -- No support for ARM Linux +- No support for the authentication process on ARM Linux - Please also consider the issues listed in the [README in the ESP32Firmware folder](ESP32Firmware/README.md) if you want to register custom trackers. ### Firmware for custom ESP32-based trackers From 8a2aae502f539e97d1aff3c372d82979aa9960f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Fri, 16 May 2025 15:01:45 +0200 Subject: [PATCH 30/31] Update README.md --- ZephyrFirmware/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ZephyrFirmware/README.md b/ZephyrFirmware/README.md index 9acfc95..e03a1b3 100644 --- a/ZephyrFirmware/README.md +++ b/ZephyrFirmware/README.md @@ -7,6 +7,8 @@ It should support any board/chip with a BLE radio that is supported in Zephyr, f - Silicon EFR32BG22 - ST BlueNRG-LP - ESP32 + - Quectel BC68-GV + - TTGO T-BEAM ## Installation From b07a94879c2418e33d30fc6da20881643c5a2f9f Mon Sep 17 00:00:00 2001 From: Kai Geissdoerfer Date: Fri, 20 Jun 2025 13:06:21 +0200 Subject: [PATCH 31/31] zephyr app: improve readme --- ZephyrFirmware/README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ZephyrFirmware/README.md b/ZephyrFirmware/README.md index e03a1b3..04ad690 100644 --- a/ZephyrFirmware/README.md +++ b/ZephyrFirmware/README.md @@ -1,4 +1,4 @@ -# Find My Device ESP32 Firmware +# Find My Device Zephyr Firmware This code enables you to use a Zephyr-supported BLE device as a custom Google Find My Device tracker. It should support any board/chip with a BLE radio that is supported in Zephyr, for example: @@ -13,6 +13,13 @@ It should support any board/chip with a BLE radio that is supported in Zephyr, f ## Installation +Clone the repository and change to the ZephyrFirmware directory: + +``` +git clone git@github.com:leonboe1/GoogleFindMyTools.git +cd ZephyrFirmware +``` + Follow the [official instructions](https://docs.zephyrproject.org/latest/develop/getting_started/index.html#install-dependencies) to install Zephyr's dependencies. Create a virtual environment in this directory and install `west`: @@ -53,6 +60,14 @@ To build with UART logging: west build -p -b nrf52840dk/nrf52840 app -- -DEXTRA_CONF_FILE=logging.conf ``` +## Flashing + +Use west to flash the resulting binary + +``` +west flash +``` + ## Known Issues See [the README](../ESP32Firmware/README.md) for ESP32-based trackers (also applies here).