Get any Google assistant command from any device or home speaker into Tasker.....

507 views
Skip to first unread message

Rich D

unread,
Feb 20, 2021, 12:38:40 PM2/20/21
to Tasker Google Groups Post
A while back I made a project that basically steals the Google assistant command so you could get any command given to the assistant into Tasker. This only works on the device that you spoke the command into.  It can be found here.


This project will now allow you to use any device including the Google home speaker to get the commands into Tasker. It requires using a dedicated android device to continually monitor for a logcat event and then steal the command from your Google assistant activity web page. 

I found that any time you issue a command to the assistant it will send a push to all other devices connected to your assistant. I assume this might be the way it handles when multiple devices hear the same ok google command so they can say "answering on another device.  This puts a entry in the logcat.  So I simply monitor for that then open the assistant activity page and steal the command with autoinput. 

Using autoinput to get the last assistant activity is not the best approach so hopefully someone will be able to figure out how to get the info with a http request. This will make things far more efficient. Any help with that would be greatly appreciated.

Unfortunately this same entry shows up approx every 30 min even when there has been no activity with the assistant. So  I need to test the activity page for every one of these entries to test if it was a activity that triggered it. I have done this with multiple variable splits that gets the fist activity on the web page and tests the time  of the activity from the web page against the current time to see if the command was just issued. 

This is still a work in progress and pretty much a proof of concept. I am currently leaving the web page open and then issue a autoweb command to refresh it. I use a black scene to prevent any screen burn. .  Here is the log cat entry. You will of course need to find the one that is specific to your device

         1613790301.826  2182  2182 W GCM     : broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.google.android.googlequicksearchbox (has extras) }


Edit. I found in testing if I only have 2 devices linked to the assistant then only one of them will receive this logcat event. When I linked my home speaker then both of my other devices showed the logcat entry. In other words it acts like a master slave set up. Google picks the device to be the master wich will answer the command so the slave gets the push. If you issue a command to the slave the master will not receive the push.  However if there is a third device like the home speaker then that will now be the master so both of the other slave devices will now receive the push. This all works even when the devices are not close to each other. So long story short, your home device for monitoring needs to be a slave device. 

Here is the current project.  





    Profile: Get Logs (990)
    Cooldown: 3 Restore: no
    Event: Logcat Entry [ Output Variables:* Component:GCM Filter:broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.google.android.googlequicksearchbox (has extras) } Grep Filter (Check Help):Off ]
    Enter: Assist Logs (991)
    A1: Destroy Scene [ Name:Screen Black Continue Task After Error:On ] 
    A2: Variable Set [ Name:%times To:%TIMES Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    <Put your assistant web address here.>
    A3: AutoTools Web Screen [ Configuration:Display Mode: Normal
    Source: Your assistant activity web address here
    Toast Duration: 5000
    Height: 400
    Gravity: Center
    Animation: Slide In From Top
    Show Duration: 500
    Hide Duration: 250
    Get HTML: true Timeout (Seconds):30 ] 
    A4: Wait [ MS:0 Seconds:7 Minutes:0 Hours:0 Days:0 ] 
    A5: AutoInput UI Query [ Configuration: Timeout (Seconds):20 ] 
    A6: [X] Write File [ File:Assist web info.txt Text:%aitext()
    
    ****************************************** Append:On Add Newline:On ] 
    <Set Time and set  AM / PM>
    A7: Anchor 
    A8: Variable Convert [ Name:%times Function:Seconds to Long Date Time Store Result In:%current_time Mode:Default ] 
    A9: Variable Split [ Name:%current_time Splitter: Delete Base:Off ] 
    A10: Variable Section [ Name:%current_time5 From:6 Length:2 Adapt To Fit:Off Store Result In:%am_pm ] 
    A11: Variable Section [ Name:%current_time5 From:1 Length:5 Adapt To Fit:Off Store Result In:%trimmed_time ] 
    A12: Variable Search Replace [ Variable:%trimmed_time Search:: Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In Array: Replace Matches:On Replace With:. ] 
    <Set data and split data at beginning of list>
    A13: Variable Set [ Name:%data To:%aitext() Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A14: Variable Split [ Name:%data Splitter:Today,Delete all activity from Delete Base:Off Continue Task After Error:On ] 
    A15: Goto [ Type:Action Label Number:1 Label:Error ] If [ %err Set ]
    <Test if activity at top of list is am or pm>
    A16: Anchor 
    A17: Variable Set [ Name:%am_data To:%data2 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A18: Variable Set [ Name:%pm_data To:%data2 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A19: Variable Split [ Name:%am_data Splitter:AM • Delete Base:Off Continue Task After Error:On ] 
    A20: Variable Split [ Name:%am_data1 Splitter:, Delete Base:Off Continue Task After Error:On ] 
    A21: Variable Split [ Name:%pm_data Splitter:PM • Delete Base:Off Continue Task After Error:On ] 
    A22: Variable Split [ Name:%pm_data1 Splitter:, Delete Base:Off Continue Task After Error:On ] 
    A23: Goto [ Type:Action Label Number:1 Label:Error ] If [ %err Set ]
    A24: If [ %am_data1(#) < %pm_data1(#) ]
    A25: Goto [ Type:Action Label Number:1 Label:End ] If [ %am_pm ~ PM ]
    A26: Variable Set [ Name:%last_entry To:%am_data1 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A27: End If 
    A28: If [ %am_data1(#) > %pm_data1(#) ]
    A29: Goto [ Type:Action Label Number:1 Label:End ] If [ %am_pm ~ AM ]
    A30: Variable Set [ Name:%last_entry To:%pm_data1 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A31: End If 
    A32: Variable Split [ Name:%last_entry Splitter:Said , Delete Base:Off Continue Task After Error:On ] 
    A33: Variable Split [ Name:%last_entry2 Splitter:, Delete Base:Off Continue Task After Error:On ] 
    A34: Goto [ Type:Action Label Number:1 Label:End ] If [ %err Set ]
    <Get Time in first activity on list>
    A35: Anchor 
    A36: Variable Set [ Name:%command_time To:%last_entry2(<) Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A37: Variable Search Replace [ Variable:%command_time Search:: Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In Array: Replace Matches:On Replace With:. ] 
    A38: Variable Set [ Name:%time_diff To:abs(%trimmed_time - %command_time) Recurse Variables:Off Do Maths:On Append:Off Max Rounding Digits:3 ] 
    <Check for more than 4 minutes in between trigger time  and command time>
    A39: Goto [ Type:Action Label Number:1 Label:End ] If [ %time_diff > .04 ]
    A40: Flash [ Text:%last_entry21 Long:On ] 
    A41: Notify [ Title:Get Logs %TIMES%command_time Text:%last_entry21      %TIME  CT-%command_time Icon:null Number:0 Permanent:Off Priority:3 Repeat Alert:Off LED Colour:Red LED Rate:0 Sound File: Vibration Pattern: Category: ] 
    <End>
    A42: Anchor 
    A43: Write File [ File:Assist web info.txt Text:End -   %TIME
    
    Diff   -  %time_diff
    
    Last entry - %last_entry
    
    Logcat - %lc_text
    
    
    ****************************************** Append:On Add Newline:On ] 
    A44: Wait [ MS:0 Seconds:4 Minutes:0 Hours:0 Days:0 ] 
    A45: Show Scene [ Name:Screen Black Display As:Activity, No Bar, No Status, No Nav Horizontal Position:100 Vertical Position:100 Animation:System Show Exit Button:On Show Over Keyguard:On Continue Task Immediately:On ] 
    A46: Stop [ With Error:Off Task: ] 
    <Error>
    A47: Anchor 
    A48: Write File [ File:Assist web info.txt Text:Error   %TIME
    
    Diff   -  %time_diff
    
    Last entry - %last_entry
    
     AI text - %aitext()
    
    ****************************************** Append:On Add Newline:On ] 
    A49: Notify [ Title:Error In Assist HTTP %TIMES Text:%TIME  %data Icon:null Number:0 Permanent:Off Priority:3 Repeat Alert:Off LED Colour:Red LED Rate:0 Sound File: Vibration Pattern: Category: ] 
    A50: Flash [ Text:Error Long:On ] 
    A51: Wait [ MS:0 Seconds:4 Minutes:0 Hours:0 Days:0 ] 
    A52: Show Scene [ Name:Screen Black Display As:Activity, No Bar, No Status, No Nav Horizontal Position:100 Vertical Position:100 Animation:System Show Exit Button:On Show Over Keyguard:On Continue Task Immediately:On ] 
    A53: Stop [ With Error:Off Task: ]



Known issues... 

-  Because it uses autoinput to retrieve the command it takes a few seconds to acquire the command.
- It requires a dedicated android device to monitor for the logcat and steal the command. ( I use a tablet that sits in the kitchen just showing pics )

Rich D

unread,
Feb 21, 2021, 6:27:26 PM2/21/21
to Tasker



Edit.... I have been able to parse the data from the Google assistant activity web page so the project no longer requires auto input and it can now work in the background on any device. It will allow  you to steal any command you issue to the assistant and use it in tasker. It should be similar to using IFTTT.  Just come up with a command that the assistant does not recognize and monitor for it in the 'Http Assistant' Task. To get around the assistant answering "I do not understand" or starting a web search you can just make a dummy routine so Google recognizes your command but does nothing.  This approach will also allow you to do extra things for a assistant recognized command. For example you can tell the assistant to 'Turn on Bluetooth'  so the assistant turns on your Bluetooth and you can now have tasker start your Bluetooth profiles or tasks as well..  You can of course add variables to your commands as well.

This project requires the tasker plug in 'Autotools'

I found that any time you issue a command to the assistant it will send a push to all other devices connected to your assistant. I assume this might be the way it handles when multiple devices hear the same ok google command so they can say "answering on another device.  This puts a entry in the logcat.  So I simply monitor for that then use auto tools 'HTML read' action to parse the data from the Google assistant activity page.  It gets the last command issued as well as a unique time stamp of the last time the page was updated. 



Unfortunately this same  logcat entry shows up approx every 30 min even when there has been no activity with the assistant.  So I just test the time stamp to see if the page has been updated since the last command steal. 



This is still a work in progress and pretty much a proof of concept.  Here is the log cat entry. You will of course need to find the one that is specific to your device

         1613790301.826  2182  2182 W GCM     : broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.google.android.googlequicksearchbox (has extras) }


Edit. I found in testing if I only have 2 devices linked to the assistant then only one of them will receive this logcat event. When I linked my home speaker then both of my other devices showed the logcat entry. In other words it acts like a master slave set up. Google picks the device to be the master wich will answer the command so the slave gets the push. If you issue a command to the slave the master will not receive the push.  However if there is a third device like the home speaker then that will now be the master so both of the other slave devices will now receive the push. This all works even when the devices are not close to each other. So long story short, the device running this project needs to be a slave device. 

Here is the current project.  Edited for version 2.




    Profile: Get Logs (1020)
    Cooldown: 3 Restore: no
    Event: Logcat Entry [ Output Variables:* Component:GCM Filter:broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.google.android.googlequicksearchbox (has extras) } Grep Filter (Check Help):Off ]
    Enter: Http Assistant (1018)
    A1: Variable Set [ Name:%run_time To:%TIMES Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    <Set your Google assistant web address and use the Authenticate option to enter your Google password.>
    A2: AutoTools HTML Read [ Configuration:URL: < Your Google assistant Html here.... >
    CSS Queries: .l8sGWb,.rp10kf,.wlgrwd,[data-timestamp]
    Variable Names: %command,%today,%time,%event
    Joiner: =;=
    Output HTML: true Timeout (Seconds):60 Continue Task After Error:On ] 
    A3: Variable Set [ Name:%run_time To:%TIMES-%run_time Recurse Variables:Off Do Maths:On Append:Off Max Rounding Digits:3 ] 
    A4: Variable Split [ Name:%time Splitter:<div class="H3Q9vf XTnvW"> Delete Base:Off Continue Task After Error:On ] 
    A5: Variable Split [ Name:%time2 Splitter:• Delete Base:Off Continue Task After Error:On ] 
    A6: Variable Split [ Name:%event Splitter:data-timestamp=" Delete Base:Off Continue Task After Error:On ] 
    A7: Variable Split [ Name:%event2 Splitter:" data-date=" Delete Base:Off Continue Task After Error:On ] 
    A8: Flash [ Text:%command
    %time21
    %today
    %event21 Long:On ] 
    A9: Write File [ File:assist_http.txt Text:%command
    
    %time21
    
    %today
    
    %event21
    
    %run_time
    
    
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Append:On Add Newline:On ] 
    A10: If [ %Last_command_time ~ %event21 ]
    A11: Stop [ With Error:Off Task: ] 
    A12: End If 
    A13: Variable Set [ Name:%Last_command_time To:%event21 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A14: Write File [ File:assist_http.txt Text:%command
    
    %time21
    
    %today
    
    %event21
    
    %run_time
    
    
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Append:On Add Newline:On ] 
    A15: Notify [ Title:Get Logs %TIMES Text:%command
    %time21
    %today
    %event21
    %run_time Icon:null Number:0 Permanent:Off Priority:3 Repeat Alert:Off LED Colour:Red LED Rate:0 Sound File: Vibration Pattern: Category: ] 
    





To try this project you will need to...

1- re-do the profile context to get the correct logcat entry for your device.

2- In action A2:  you will need to put your Google assistant activity web address in URL category and use the Authenticate option to get your Google password to be used to parse the data from the web page.

Rich D

unread,
Feb 27, 2021, 7:01:16 PM2/27/21
to Tasker Google Groups Post
OK... A few more fixes for version 3. A few days of testing and it has not missed a command yet. 

Changes..

1- changed CSS query to get both event and time from the same the same class then split data in task.

2- added several more tests to filter out profile activations that do not relate to assistant activity web page update.

    Cooldown: 3 Restore: no
    Event: Logcat Entry [ Output Variables:* Component:GCM Filter:broadcast intent callback: result=CANCELLED forIntent { act=com.google.android.c2dm.intent.RECEIVE pkg=com.google.android.googlequicksearchbox (has extras) } Grep Filter (Check Help):Off ]
    Enter: Http Assistant (1034)
    A1: Variable Set [ Name:%run_time To:%TIMES Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A2: Variable Set [ Name:%ret To:
     Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A3: Variable Set [ Name:%space To:   Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A4: Variable Set [ Name:%spc_char To:  Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    <Get HTML info from assistant activity web page
    Set your Google assistant web address and use the Authenticate option to enter your Google password.>
    A5: AutoTools HTML Read [ Configuration:URL:  < Your Google assistant activities web address here. Use the Authenticate option below >
    CSS Queries: .uUy2re,.rp10kf,[data-timestamp]
    Variable Names: %command,%today,%event
    Joiner: =;=
    Output HTML: true Timeout (Seconds):60 Continue Task After Error:On ] 
    <Get run time of HTML Read action>
    A6: Variable Set [ Name:%run_time To:%TIMES-%run_time Recurse Variables:Off Do Maths:On Append:Off Max Rounding Digits:3 ] 
    A7: Variable Set [ Name:%time To:%command Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    <Get command>
    A8: Anchor 
    A9: Variable Convert [ Name:%command Function:HTML to Text Store Result In: Mode:Default ] 
    A10: Variable Split [ Name:%command Splitter:%ret Delete Base:Off ] 
    A11: Variable Set [ Name:%command To:%command1 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    <Test fo today>
    A12: Anchor 
    A13: If [ %today !~ *Today* ]
    A14: Variable Set [ Name:%error To:Failed today test Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A15: Goto [ Type:Action Label Number:1 Label:End ] 
    A16: Stop [ With Error:Off Task: ] 
    A17: End If 
    <Get command time>
    A18: Anchor 
    A19: Variable Split [ Name:%time Splitter:<div class="H3Q9vf XTnvW"> Delete Base:Off Continue Task After Error:On ] 
    A20: Variable Split [ Name:%time2 Splitter:• Delete Base:Off Continue Task After Error:On ] 
    A21: Variable Search Replace [ Variable:%time21 Search:%ret Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In Array: Replace Matches:On Replace With: ] 
    A22: Variable Search Replace [ Variable:%time21 Search:: Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In Array: Replace Matches:On Replace With:. ] 
    A23: Variable Set [ Name:%command_time To:%time21 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A24: Variable Split [ Name:%command_time Splitter:%spc_char Delete Base:Off ] 
    <set current time>
    A25: Anchor 
    A26: Variable Set [ Name:%times To:%TIMES Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A27: Variable Convert [ Name:%times Function:Seconds to Long Date Time Store Result In:%current_time Mode:Default ] 
    A28: Variable Split [ Name:%current_time Splitter: Delete Base:Off ] 
    <Test if command time and current time have same AM or PM>
    A29: Anchor 
    A30: If [ %current_time5 !~ *%command_time4* ]
    A31: Variable Set [ Name:%error To:Failed AM PM test Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A32: Goto [ Type:Action Label Number:1 Label:End ] 
    A33: Stop [ With Error:Off Task: ] 
    A34: End If 
    <Trim current time for maths>
    A35: Anchor 
    A36: Variable Search Replace [ Variable:%current_time5 Search:%command_time4 Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In Array: Replace Matches:On Replace With: ] 
    A37: Variable Search Replace [ Variable:%current_time5 Search:: Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In Array: Replace Matches:On Replace With:. ] 
    A38: Variable Set [ Name:%diff To:abs(%command_time3-%current_time5) Recurse Variables:Off Do Maths:On Append:Off Max Rounding Digits:3 ] 
    <Test for more than 4 min between events>
    A39: Anchor 
    A40: If [ %diff > .05 ]
    A41: Variable Set [ Name:%error To:Failed more than 4 seconds between events test Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A42: Goto [ Type:Action Label Number:1 Label:End ] 
    A43: Stop [ With Error:Off Task: ] 
    A44: End If 
    A45: Write File [ File:assist_http.txt Text:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    Trigger before event time stamp test
    
    Command  - %command
    
    Command time  - %time21
    Time of trigger  -  %TIME         - %TIMES
    
    Today or yesterday   -   %today
    
    Event time stamp   -   %event21
    
    Run time for http get action  -%run_time
    
    
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Append:On Add Newline:On ] 
    <Get event time stamp>
    A46: Anchor 
    A47: Variable Split [ Name:%event Splitter:data-timestamp=" Delete Base:Off Continue Task After Error:On ] 
    A48: Variable Split [ Name:%event2 Splitter:" data-date=" Delete Base:Off Continue Task After Error:On ] 
    A49: Write File [ File:assist_http.txt Text:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    Trigger for accepted command after time stamp test
    
    Command  - %command
    
    Command time  - %time21
    Time of trigger  -  %current_time5          - %TIMES
    
    Diff                           - %diff
    
    Today or yesterday   -   %today
    
    Event time stamp   -   %event21
    
    Run time for http get action  -%run_time
    
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Append:On Add Newline:On ] 
    <Test for false profile trigger - check if event time stamp matches last time stamp>
    A50: Anchor 
    A51: If [ %Last_command_time ~ %event21 ]
    A52: Variable Set [ Name:%error To:False trigger - event time stamps match Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A53: Stop [ With Error:Off Task: ] 
    A54: End If 
    A55: Variable Set [ Name:%Last_command_time To:%event21 Recurse Variables:Off Do Maths:Off Append:Off Max Rounding Digits:3 ] 
    A56: Notify [ Title:Get Logs %TIMES Text:%command
    Trigger time - %current_time5
    Cmnd time  - %time21
    Diff                 - %diff
    %today
    Time stamp - %event21
    HTTP get Time - %run_time Icon:null Number:0 Permanent:Off Priority:3 Repeat Alert:Off LED Colour:Red LED Rate:0 Sound File: Vibration Pattern: Category: ] 
    A57: Stop [ With Error:Off Task: ] 
    <End>
    A58: Anchor 
    A59: Write File [ File:assist_http.txt Text:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    
    %TIME
    
    %error
    
    
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Append:On Add Newline:On ] 
Reply all
Reply to author
Forward
0 new messages