SharpTools Presence

It thought I would share my solution using @joshua_lyon’s SharpTools to SmartThings presence issues. I started out with the example on his site, but continued to have some issues. Eventually I found the heart of the matter: when arriving or departing from home my phone was often in the process of handing off between 4G and WiFi while the task was being triggered. This would cause calls to timeout and silently fail. I played with setting timeouts, but continued to have issues.

My solution was to add retry logic to my Tasker task. I try up to 10 times to update my presence, and if after that I still fail, I leave a notification indicating that it gave up. This screenshot shows most of the task:

The only important things not shown here:

  • The first notification should be “Permanent” – this means it can’t be dismissed by the user (we dismiss it programmatically at the end of the task). This notification just tells you when the task is running.
  • For the two SharpTools actions, make sure to check “Continue Task After Error” – we are handling errors, so we don’t want to exit upon encountering one. You can also play with the timeout values in here.
  • The value of 10 in the GOTO is what controls how many iterations to attempt.

I have a Depart task thats pretty much identical, I just look for not present instead of present.

4 Likes

Great idea on the adding in the retries for when you have spotty network connectivity! Thanks for sharing your SharpTools use case!

I like the idea of adding a permanent notification while the task is running and a notification at the end if things fail. Does the notification of failure at the end have action buttons in it? That way you could manually trigger the presence change if it didn’t work automatically.

Edit: I’ve also linked to this post from the tutorial about building a custom presence device using SharpTools:

3 Likes

That’s a good idea, I might add that this weekend. The retry definitely helps with failures – I forgot to mention that I have it set to display the attempt count in the “gave up” notification and I frequently see it get up to about 8/10. You can also play with the timeout values for the SharpTools calls (I am using 2 seconds each). Additionally, I perform a set, then retrieve back the value – I have found this much more reliable then calling a set and assuming it worked if no error is thrown.

I’m trying to follow along, but getting caught up in how you added an Action Label (LoopStart) between task step 2 & 3. Also, can you clarify what step you have the %attempts variable in the gave up step?

EDIT: Got it - had to take the training wheels off in Tasker and disable beginner mode in preferences.

2 Likes

Last question for the day - how do you get the option to show up under the notify action if it failed?

This looks very interesting - I have just been using a wait command in tasker and then sending the Sharptools presence on condition that the variable (that I use to ‘mark’ myself as home/away) was still true.

Hellfire - can you post a link to your actual profile so we can download and import into Tasker? I tried copying it, but it seemed to have a problem with the LoopStart step (and I have already disabled Beginner mode in preferences).

Thanks!!

1 Like

From what I can tell, @hellfire51 is checking to see if the %st_attr_value is set as expected. So when he gets home, part of the process is to use ‘Thing: Get Attribute’ to see if the value of the presence attribute is not set to present (If %st_attr_value !~ present). If the device status still isn’t present at the end of his task, he creates a notification using Alert > Notify in Tasker.

Note that the following variables are set with the Thing: Get Attribute plugin:

  • %st_attr_name
    The attribute name (eg. ‘presence’, ‘switch’, ‘level’, ‘temperature’)
  • %st_attr_value
    The value of the attribute (eg. ‘present’, ‘on’, ‘100’, ‘72’)
  • %st_thing_id
    The internal Thing ID of the Thing
  • %st_thing_name
    The user friendly name/label of the Thing

Here’s an article on using conditional actions:


For others who are trying to follow the full logic, it’s something like:

  1. Show a notification at the start that we are doing work
  2. Initialize the variable that we will use to keep track of how many attempts (loops) we have completed
  3. Add 1 to the loop tracking variable each time we loop
    Note: Also label this as LoopStart so we can jump back to it easily
  4. Call the 'arrived` method of your Virtual Presence Device
  5. Get the ‘presence’ attribute of the Virtual Presence Device
  6. If the virtual presence device isn’t present and we’ve attempted less than 10 attempts, then go back to the label LoopStart (Step 3)
  7. Cancel the notification from Step 1 that said we are doing work (since we are done)
  8. Create a notification 'Arrived Home’
    Note: This either needs to be conditional or step 9 needs to overwrite it conditionally.
  9. If the virtual presence device isn’t present, create a notification ‘Failed to update presence’

Here’s the XML I’m using for my presence and departed tasks. The only thing missing is the manual presence update @joshua_lyon posted a screenshot of. The rest is exactly like @hellfire51.

http://pastebin.com/HFQtZJMV <-Arrival
http://pastebin.com/HkYGhqvP <-Departure

1 Like

Cheers - much appreciated!

I’ve found an issue in my order of events after setting up two phones - let me know if you’re having issues and i will reupload my new XML’s. Specifically, I was checking for “present” instead of “departed” in my leaving geofence tasks

1 Like

I actually look for a partial match on “present” and in my depart task I look for a partial match on “not”. I figured that was a little less brittle if SmartThings decided to change the String value.

I had originally planned on posting the Task, but inspecting the XML showed some type of ID values for the SharpTools portions – I wasn’t sure if there were any security ramifications to sharing them. I would guess these are some sort of device ID and SharpTools doesn’t leak out any OAUTH tokens. @joshua_lyon can maybe confirm?

Right, these are just the device IDs. Tasker doesn’t store any OAuth information.

That being said, you could just manually remove the device IDs from the XML as they should be unique GUIDs that aren’t reused across the platform. (Eg. Those device IDs shouldn’t match for anyone else).

That’s what I expected. When I get a chance I will post the task. I hadn’t yet added the suggested buttons to the failure notification – probably do that too.

On a related note: I also didn’t mention the whole profile – namely the trigger. I am currently using “WiFi Near” as I have found that to be most reliable. Even Autolocation seems to have occasional problems. This does, however probably make more more susceptible to the “handoff” problem since WiFi being near often causes a switch to WiFi…

2 Likes

WiFi is only problematic because you do have issues with range, so at the very edge of your network you will connect, but your connection would be so bad that actually getting ST to do something could be problematic.

You also have the issue of getting into a problem if you ever reboot your device or put it into airplane mode – for whatever reason – while still being home.

This is why I use AutoLocation and set it to not exit the geofence if the network is lost, because it avoids that particular issue.

Can you explain how you achieve location not going out of your Geofence when network is off/lost?

I would love to have that logic built into tasker.

Thanks!

This is part of the AutoLocation advanced settings, not sure if there’s an equivalent in Tasker itself without the plug-in.

https://drive.google.com/open?id=0B-NCeoCkjO2pVFhYWHN6ckdGODQ

Thanks, mang! Learned something new today (and it’s early)…

Hey @hellfire51! For a Tasker newbie, could you elaborate how you set up the loop task? I’m trying to follow the single image but, for example, I can’t see where to do the loop thing…

Thanks!

EDIT: Done! No help needed!Thanks! I’ll give this solution a try! Very optimistic!

EDIT2: Can’t seem to create the exit part of the tasker task… can someone guide me? Oh! And the ‘Updating Presence’ notification won’t go away?

Ugh!

@hellfire51’s solution is not working for me, even though it is exactly what I need…

For example, the “Updating Presence” notice won’t go away… and the system took about 9 hours to recognize I was home even though I was on wifi coverage and connection all thru the night…

I’m posting both the description and XML here to see if you guys can figure it out?

  <TaskerData sr="" dvi="1" tv="4.8m">
	<Profile sr="prof4" ve="2">
		<cdate>1454092428859</cdate>
		<edate>1454149261088</edate>
		<id>4</id>
		<mid0>5</mid0>
		<nme>ST Presence Daniel</nme>
		<State sr="con0" ve="2">
			<code>170</code>
			<Str sr="arg0" ve="3">sojuelix</Str>
			<Str sr="arg1" ve="3"/>
			<Str sr="arg2" ve="3"/>
			<Int sr="arg3" val="0"/>
			<Int sr="arg4" val="0"/>
			<Int sr="arg5" val="0"/>
		</State>
	</Profile>
	<Task sr="task5">
		<cdate>1454092432690</cdate>
		<edate>1454149244558</edate>
		<id>5</id>
		<Action sr="act0" ve="7">
			<code>523</code>
			<Str sr="arg0" ve="3">Updating Presence</Str>
			<Str sr="arg1" ve="3"/>
			<Img sr="arg2" ve="2"/>
			<Int sr="arg3" val="0"/>
			<Int sr="arg4" val="1"/>
			<Int sr="arg5" val="3"/>
		</Action>
		<Action sr="act1" ve="7">
			<code>547</code>
			<Str sr="arg0" ve="3">%attempts</Str>
			<Str sr="arg1" ve="3">0</Str>
			<Int sr="arg2" val="0"/>
			<Int sr="arg3" val="0"/>
		</Action>
		<Action sr="act2" ve="7">
			<code>888</code>
			<label>LoopStart</label>
			<Str sr="arg0" ve="3">%attempts</Str>
			<Int sr="arg1" val="1"/>
			<Int sr="arg2" val="0"/>
		</Action>
		<Action sr="act3" ve="7">
			<code>3100</code>
			<Bundle sr="arg0">
				<Vals sr="val">
					<android.intent.extra.shortcut.ICON_RESOURCE>com.boshdirect.stwidgets:drawable/ic_thing</android.intent.extra.shortcut.ICON_RESOURCE>
					<android.intent.extra.shortcut.ICON_RESOURCE-type>java.lang.String</android.intent.extra.shortcut.ICON_RESOURCE-type>
					<android.intent.extra.shortcut.INTENT>Intent { act=android.intent.action.MAIN flg=0x40000000 cmp=com.boshdirect.stwidgets/.ToggleThingActivity (has extras) }</android.intent.extra.shortcut.INTENT>
					<android.intent.extra.shortcut.INTENT-type>java.lang.String</android.intent.extra.shortcut.INTENT-type>
					<android.intent.extra.shortcut.NAME>Daniel</android.intent.extra.shortcut.NAME>
					<android.intent.extra.shortcut.NAME-type>java.lang.String</android.intent.extra.shortcut.NAME-type>
					<arg_types>&lt;StringArray sr=""/&gt;</arg_types>
					<arg_types-type>[Ljava.lang.String;</arg_types-type>
					<arguments>&lt;StringArray sr=""/&gt;</arguments>
					<arguments-type>[Ljava.lang.String;</arguments-type>
					<com.twofortyfouram.locale.intent.extra.BLURB>Thing: Daniel
Command: arrived</com.twofortyfouram.locale.intent.extra.BLURB>
					<com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type>
					<command>arrived</command>
					<command-type>java.lang.String</command-type>
					<isParameterOverridden>false</isParameterOverridden>
					<isParameterOverridden-type>java.lang.Boolean</isParameterOverridden-type>
					<isTaskerVariableMode>false</isTaskerVariableMode>
					<isTaskerVariableMode-type>java.lang.Boolean</isTaskerVariableMode-type>
					<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>arguments</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>
					<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>java.lang.String</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>
					<net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled>
					<net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type>
					<thingID>667fa0a9-0813-4d3f-b81e-97bf63456a0e</thingID>
					<thingID-type>java.lang.String</thingID-type>
				</Vals>
			</Bundle>
			<Str sr="arg1" ve="3">com.boshdirect.stwidgets</Str>
			<Str sr="arg2" ve="3">A Thing</Str>
			<Int sr="arg3" val="0"/>
		</Action>
		<Action sr="act4" ve="7">
			<code>19557</code>
			<Bundle sr="arg0">
				<Vals sr="val">
					<attributes>&lt;StringArray sr=""&gt;&lt;_array_attributes0&gt;presence&lt;/_array_attributes0&gt;&lt;/StringArray&gt;</attributes>
					<attributes-type>[Ljava.lang.String;</attributes-type>
					<com.twofortyfouram.locale.intent.extra.BLURB>Thing: Daniel
Attribute: presence

The following variables are set when triggered:
%st_attr_name
%st_attr_value
%st_thing_id
%st_thing_name</com.twofortyfouram.locale.intent.extra.BLURB>
					<com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type>
					<fire_action>1</fire_action>
					<fire_action-type>java.lang.Integer</fire_action-type>
					<isTaskerVariableMode>false</isTaskerVariableMode>
					<isTaskerVariableMode-type>java.lang.Boolean</isTaskerVariableMode-type>
					<net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled>
					<net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type>
					<thingID>667fa0a9-0813-4d3f-b81e-97bf63456a0e</thingID>
					<thingID-type>java.lang.String</thingID-type>
				</Vals>
			</Bundle>
			<Str sr="arg1" ve="3">com.boshdirect.stwidgets</Str>
			<Str sr="arg2" ve="3">Thing: Get Attribute</Str>
			<Int sr="arg3" val="15"/>
		</Action>
		<Action sr="act5" ve="7">
			<code>135</code>
			<Int sr="arg0" val="1"/>
			<Int sr="arg1" val="1"/>
			<Str sr="arg2" ve="3">LoopStart</Str>
			<ConditionList sr="if">
				<bool0>And</bool0>
				<Condition sr="c0" ve="3">
					<lhs>%st_attr_name</lhs>
					<op>3</op>
					<rhs>present</rhs>
				</Condition>
				<Condition sr="c1" ve="3">
					<lhs>%attempts</lhs>
					<op>2</op>
					<rhs>10</rhs>
				</Condition>
			</ConditionList>
		</Action>
		<Action sr="act6" ve="7">
			<code>779</code>
			<Str sr="arg0" ve="3">Updating Presence</Str>
			<Int sr="arg1" val="0"/>
		</Action>
		<Action sr="act7" ve="7">
			<code>523</code>
			<Str sr="arg0" ve="3">Arrived Home</Str>
			<Str sr="arg1" ve="3"/>
			<Img sr="arg2" ve="2"/>
			<Int sr="arg3" val="0"/>
			<Int sr="arg4" val="0"/>
			<Int sr="arg5" val="3"/>
		</Action>
		<Action sr="act8" ve="7">
			<code>523</code>
			<Str sr="arg0" ve="3">Failed To Update Presence</Str>
			<Str sr="arg1" ve="3"/>
			<Img sr="arg2" ve="2"/>
			<Int sr="arg3" val="0"/>
			<Int sr="arg4" val="0"/>
			<Int sr="arg5" val="3"/>
			<ConditionList sr="if">
				<Condition sr="c0" ve="3">
					<lhs>%st_attr_value</lhs>
					<op>3</op>
					<rhs>present</rhs>
				</Condition>
			</ConditionList>
		</Action>
	</Task>
</TaskerData>
Profile: ST Presence Daniel (4)

State: Wifi Near [ SSID:sojuelix MAC:* Capabilities:* Min. Activate Signal Level:0 Channel:0 Toggle Wifi:Off ]
Enter: Anon (5)
A1: Notify [ Title:Updating Presence Text: Icon:null Number:0 Permanent:On Priority:3 ]
A2: Variable Set [ Name:%attempts To:0 Do Maths:Off Append:Off ]

A3: Variable Add [ Name:%attempts Value:1 Wrap Around:0 ]
A4: A Thing [ Configuration:Thing: Daniel
Command: arrived Package:com.boshdirect.stwidgets Name:A Thing Timeout (Seconds):0 ]
A5: Thing: Get Attribute [ Configuration:Thing: Daniel
Attribute: presence

The following variables are set when triggered:
%st_attr_name
%st_attr_value
%st_thing_id
%st_thing_name Package:com.boshdirect.stwidgets Name:Thing: Get Attribute Timeout (Seconds):15 ]
A6: Goto [ Type:Action Label Number:1 Label:LoopStart ] If [ %st_attr_name !~ present & %attempts ~ 10 ]
A7: Notify Cancel [ Title:Updating Presence Warn Not Exist:Off ]
A8: Notify [ Title:Arrived Home Text: Icon:null Number:0 Permanent:Off Priority:3 ]
A9: Notify [ Title:Failed To Update Presence Text: Icon:null Number:0 Permanent:Off Priority:3 ] If [ %st_attr_value !~ present ]

Also! What would I have to do to have the leaving home sequence too?

Thanks!

I had to tweak mine, but here is the description for both arriving and leaving. Been working great for both me and my wife’s android, and takes no more than a handful of attempts to set the virtual presence. Compare this to what you have and see if it helps track down your issue.

Arriving:

Enter Geofence (6)
A1: Notify [ Title:Updating Presence Text: Icon:null Number:0 Permanent:On Priority:3 ]
A2: Variable Set [ Name:%attempts To:0 Do Maths:Off Append:Off ]

A3: Variable Add [ Name:%attempts Value:1 Wrap Around:0 ]
A4: A Thing [ Configuration:Thing: Karson Presence
Command: arrived Package:com.boshdirect.stwidgets Name:A Thing Timeout (Seconds):2 Continue Task After Error:On ]
A5: Thing: Get Attribute [ Configuration:Thing: Karson Presence
Attribute: presence

The following variables are set when triggered:
%st_attr_name
%st_attr_value
%st_thing_id
%st_thing_name Package:com.boshdirect.stwidgets Name:Thing: Get Attribute Timeout (Seconds):2 Continue Task After Error:On ]
A6: Goto [ Type:Action Label Number:1 Label:LoopStart ] If [ %st_attr_value !~ present & %attempts < 10 ]
A7: Notify Cancel [ Title:Updating Presence Warn Not Exist:Off ]
A8: Notify [ Title:Arrived Home Text:Took %attempts/10 attempts to update presence Icon:hd_aaa_ext_import Number:0 Permanent:Off Priority:3 Actions:(1) ]
A9: Notify [ Title:Failed To Update Presence Text: Icon:null Number:0 Permanent:Off Priority:3 Actions:(1) ] If [ %st_attr_value !~ present ]

Departing

Exit Geofence (8)
A1: Notify [ Title:Updating Presence Text: Icon:hd_aaa_ext_export Number:0 Permanent:On Priority:3 ]
A2: Variable Set [ Name:%attempts To:0 Do Maths:Off Append:Off ]

A3: Variable Add [ Name:%attempts Value:1 Wrap Around:0 ]
A4: A Thing [ Configuration:Thing: Karson Presence
Command: departed Package:com.boshdirect.stwidgets Name:A Thing Timeout (Seconds):4 Continue Task After Error:On ]
A5: Thing: Get Attribute [ Configuration:Thing: Karson Presence
Attribute: presence

The following variables are set when triggered:
%st_attr_name
%st_attr_value
%st_thing_id
%st_thing_name Package:com.boshdirect.stwidgets Name:Thing: Get Attribute Timeout (Seconds):4 Continue Task After Error:On ]
A6: Goto [ Type:Action Label Number:1 Label:LoopStart ] If [ %st_attr_value ~ present & %attempts < 15 ]
A7: Notify Cancel [ Title:Updating Presence Warn Not Exist:Off ]
A8: Notify [ Title:Left Home Text:%attempts/15 attempts before presence updated Icon:null Number:0 Permanent:Off Priority:3 ]
A9: Notify [ Title:Failed To Update Presence To Departed Text: Icon:null Number:0 Permanent:Off Priority:3 Actions:(1) ] If [ %st_attr_value ~ present ]

1 Like