Android Phone Finder from OpenHAB (Google Assistant and Alexa)

Goal:

  • Use voice command (Google Assistant and/or Alexa) to initiate Android phone finder feature
    • “Hey Google, turn on Jim’s Phone Finder”
    • “Alexa, turn on Bob’s Phone Finder”
  • Programmatically initiate phone finder feature

When you have multiple android phones, asking Google to find my phone results in it prompting about each phone one by one. It can get quite tedious. Sometimes it would just ring the first phone.

This solution lets you ring the specific phone using an openhab item.

Updates:

  • 2024-01-07 fixed the page parsing again, and make it a self-contained script. It is no longer necessary to manually create the required items.
  • 2023-03-22 fixed find_elements to find multiple phones
  • 2023-03-21 Adapted to Google’s obfuscated class names
  • 2022-12-30 Refactor and move cookie storage into metadata
  • 2022-07-23 Google stopped showing the find my phone feature in the search result. Changed the find my phone url to google.com/android/find - the FindMyPhone#ring method is also updated accordingly

Requirements:

  • selenium standalone docker
  • JRuby automation addon on openHAB 4.x

Selenium Docker Setup

Using docker-compose.yml:

version: "3"
services:
  selenium:
    container_name: selenium
    image: selenium/standalone-chrome
    restart: always
    shm_size: 2gb
    ports:
      - "4444:4444"

Pull the image and start the docker:

$ docker-compose pull selenium
$ docker-compose up -d selenium

Configurations

Please see the script’s source code for the instructions. You need to specify the list of phone names in an array.

Items setup

The necessary items will be created by the script for you.

If you have previously created the items manually, please remove them (either the .items file or through UI). They were called:

  • FindMyPhone_Cookies item
  • gPhoneFinders group
  • Find_XXXX_Phone items that correspond to your phone(s)

Don’t forget to tell Google to Sync my devices and Alexa to Discover devices

Obtain your google credential cookies

  • Open your browser, and go to www.google.com
  • Make sure you’re logged in to the account that can perform the “find my phone” function.
  • Enable “Developer tool” of your browser
  • Refresh the google page (www.google.com)
  • Go to `Network" tab and find the first item. This should be the request to www.google.com
  • Find the request header and copy the cookies. It should look like “SIDCC=xxxxx; __Secure-3PSIDCC=xxxxx; blahblah=xxxxx”
  • Send the cookie as a string command to FindMyPhone_Cookies item. This can be done in Karaf console, i.e. send FindMyPhone_Cookies "xxxxxxxx"

The Script

Note:

4 Likes

Google stopped showing the find my phone feature in the search result. Changed the find my phone url to google.com/android/find

Nice work. Unfortunately I was not able to install selenium standalone docker on openHABian and I dont like JRuby. So I re-implemented the code using Node and used ChromeDriver directly.
How to use?

  • Install Node.js,
  • clone https://github.com/Plustig/Android-Phone-Finder/
  • install app using ‘npm install’ in project’s root directory
  • Install ChromeDriver using ‘sudo apt-get install chromium-chromedriver’
  • copy path of chromedriver binary in constructor method of app.js

Support for multiple phones is missing. I invoked the node app like this

/*
This rule scrapes the google's 'find my phone' page to let the phone ring
*/

var Exec = Java.type("org.openhab.core.model.script.actions.Exec");


rules.JSRule({
    name: "Ring My Phone",
    description: "This rule scrapes the google 'find my phone' page to let the phone ring",
    triggers: [triggers.ChannelEventTrigger("deconz:switch:homeserver:tdfr_shortcut_findphone:buttonevent", "1002")],
    execute: data => {
        console.log("Let your phone ring...");
        Exec.executeCommandLine( 'node', '/home/openhabian/selenium-test-app/app.js', 'ring');
    }
});
  
rules.JSRule({
  name: "Refresh google cookies",
  description: "This rule reloads the google cookies needed for authentification.",
  triggers: [triggers.GenericCronTrigger("0 0 */3 ? * *")],
  execute: data => {
      console.log("Refresh google cookies...");
      Exec.executeCommandLine( 'node', '/home/openhabian/selenium-test-app/app.js', 'refresh');
  }
});

Hi guys,

I’m trying to use your solution as well (the JS one in a dockerized environment). I’ve successfully deployed the selenium container and are able to debug the JS code. All seems fine, except the fact, that I’m not able to sign in to my google account. I’ve a feeling that the cookie string is not good I’m sending. My default cookie value looks like this:

‘1P_JAR=VALUE_COMES_HERE;OTZ=;SIDCC=VALUE_COMES_HERE;__Secure-1PSIDCC=VALUE_COMES_HERE;__Secure-3PSIDCC=VALUE_COMES_HERE;’

Is this correct? Or am I doing something wrong? Is there any way to debug, what selenium is doing?

Thanks!

UPDATE: I managed to set the correct cookies using the method from the original repo, so the issue was caused by the incorrect or insufficient cookies.

Blockquote
Open a private tab in your browser, login to https://google.com and export the cookies with EditThisCookie

Update:

  • Previously the cookies didn’t get refreshed/saved correctly so the original cookies were used and they’ll eventually expire
  • Cookies are now set using an openhab command instead of saving it in the script.
  • Store updated cookies in metadata.

Ughhhh!!! Google has now obfuscated their phone finder page.
I wish there’s an official API

I finally spent some time looking into this and adjusted the script to match Google’s new obfuscated class ids. It’s working again now!

1 Like

I’ve updated the script again, adapting to google’s changes. This time I hope it is more generic that it will continue to work longer.

Moving the code to github gist for easier editing.

See the original post at the top for the updated information and script.

What’s new: The script now creates the necessary items, making it easier to install.

1 Like

The script once again breaks because Google changed their device finder page again, presumably due to the new android tracker products being supported.

Between this and the constant need to update the cookies, this time I gave up and switched to using openhab’s Notification actions. I used a special Finder tag / severity with a fixed reference id (a new feature in OH 4.2), and on the phone(s), set the notification sound for the Finder severity to ring despite DND. Lastly I picked a ringtone for that severity that lasts a bit longer, and call it a day.

I hope that one day Google will publish their device finder API, especially now with the “tracker tags” entering the scene.

The script became super simple now :slight_smile:

# frozen_string_literal: true

=begin # rubocop:disable Style/BlockComments

A openHAB script to find your Android phone using openHAB's cloud notification

Author: @jimtng
Last updated: 2024-07-12

Fill out the PHONES constant below with the list of phones to find.

This script will create the necessary items and rules at run-time. The following items will be created:

- FindMyPhone_Group: a group item to hold all the phone finder items
- FindMyPhone_Phone_<name>: a switch item for each phone to find.
  The phone items will have `ga` and `alexa` metadata set to "Switch" so
  they can be discovered by Google Home and Alexa.

These items will be removed when this script is unloaded.

Once discovered, you can say "Hey Google, turn on Jimmy's Phone Finder" to ring the phone.

For more information, see:
https://community.openhab.org/t/android-phone-finder-from-openhab-google-assistant-and-alexa/134723

=end

#########################################################################################################
# Begin  configuration
#########################################################################################################

#
# List of phones to find
#
# The first element is the item's label which will be used for voice command, e.g.
# label: "Jimmy's Phone Finder", alexa command: "Alexa, turn on Jimmy's Phone Finder"
#
# The first word from the label will be used to create the item name,
# e.g. for "Jimmy's Phone Finder", an item called "FindMyPhone_Phone_Jimmy" will be created.
#
# A group called FindMyPhone_Group will be created with all the phone finder items
#
# The hash values are the openHAB cloud user id (email) of the phone owner.
#
PHONES = {
  "Jimmy's Phone Finder" => "jimmy@gmail.com",
  "Johnno's Phone Finder" => "johnno@gmail.com"
}.freeze

#########################################################################################################
# End configuration
#########################################################################################################

items.build do
  group_item FindMyPhone_Group do
    PHONES.each do |name, user_id|
      item_name = name[/^[a-zA-Z]+/]
      switch_item "FindMyPhone_Phone_#{item_name}", name, ga: "Switch", alexa: "Switch",
                                                          metadata: { user_id:, expire: "3s" }
    end
  end
end

rule "Find My Phone: Ring the phone" do
  received_command FindMyPhone_Group.members, command: ON
  run do |event|
    user_id = event.item.metadata["user_id"].value
    Notification.send("Phone Finder", email: user_id, tag: "Finder", id: "phone-finder", icon: "zoom")
  end
end