If you can share your nodered flows, that would be great!
Sure! So hereās the flows I have which handle saving and restoring the trackers:
[{"id":"581a5f86.3054f","type":"switch","z":"dc93c609.7a6e5","name":"On dev_id","property":"data.dev_id","propertyType":"msg","rules":[{"t":"eq","v":"headset","vt":"str"},{"t":"eq","v":"car","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":710,"y":700,"wires":[["de0e2780.084cb8"],["d5b19a86.01522"]]},{"id":"de0e2780.084cb8","type":"ha-entity","z":"dc93c609.7a6e5","name":"Headset","server":"cc03735a.94933","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Tracker Headset"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:crosshairs-gps"},{"property":"unit_of_measurement","value":""}],"state":"data.location_name","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":880,"y":680,"wires":[[]]},{"id":"fded4805.d50cb","type":"change","z":"dc93c609.7a6e5","name":"Store attributes","rules":[{"t":"set","p":"data","pt":"msg","to":"payload.event.service_data","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"data.tracker_backup","pt":"msg","to":"true","tot":"bool"},{"t":"set","p":"data.gps_accuracy","pt":"msg","to":"$number(data.gps_accuracy)\t","tot":"jsonata"},{"t":"set","p":"data.gps","pt":"msg","to":"[$number(data.gps[0]), $number(data.gps[1])]\t","tot":"jsonata"},{"t":"set","p":"payload.attributes","pt":"msg","to":"data","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":700,"wires":[["581a5f86.3054f"]]},{"id":"d5b19a86.01522","type":"ha-entity","z":"dc93c609.7a6e5","name":"Car","server":"cc03735a.94933","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Tracker Car"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:crosshairs-gps"},{"property":"unit_of_measurement","value":""}],"state":"data.location_name","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":870,"y":740,"wires":[[]]},{"id":"7b8864b0.1652c4","type":"comment","z":"dc93c609.7a6e5","name":"Store device tracker info","info":"Device trackers created via device_tracker.see do not automatically restore. Stash their location info so we can manually restore with it.","x":130,"y":640,"wires":[]},{"id":"602d92b6.a42fa4","type":"ha-get-entities","z":"dc93c609.7a6e5","server":"cc03735a.94933","name":"Get trackers","rules":[{"property":"attributes.tracker_backup","logic":"is","value":"true","valueType":"bool"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":330,"y":800,"wires":[["7609b15f.8a9e28"]]},{"id":"7609b15f.8a9e28","type":"split","z":"dc93c609.7a6e5","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":470,"y":800,"wires":[["490c0eab.946d5"]]},{"id":"fc26191b.157f","type":"api-call-service","z":"dc93c609.7a6e5","name":"Restore tracker","server":"cc03735a.94933","version":1,"debugenabled":false,"service_domain":"device_tracker","service":"see","entityId":"","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":780,"y":800,"wires":[[]]},{"id":"490c0eab.946d5","type":"change","z":"dc93c609.7a6e5","name":"Make data","rules":[{"t":"set","p":"service_data","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"service_data.location_name","pt":"msg","to":"payload.attributes.location_name","tot":"msg"},{"t":"set","p":"service_data.dev_id","pt":"msg","to":"payload.attributes.dev_id","tot":"msg"},{"t":"set","p":"service_data.host_name","pt":"msg","to":"payload.attributes.host_name","tot":"msg"},{"t":"set","p":"service_data.host_name","pt":"msg","to":"payload.attributes.mac","tot":"msg"},{"t":"set","p":"service_data.gps_accuracy","pt":"msg","to":"payload.attributes.gps_accuracy","tot":"msg"},{"t":"set","p":"service_data.gps","pt":"msg","to":"payload.attributes.gps","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.data","pt":"msg","to":"service_data","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":800,"wires":[["fc26191b.157f"]]},{"id":"321799bf.493f66","type":"server-events","z":"dc93c609.7a6e5","name":"Service called","server":"cc03735a.94933","event_type":"call_service","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"x":150,"y":700,"wires":[["cffde61f.b769a8"]]},{"id":"cffde61f.b769a8","type":"switch","z":"dc93c609.7a6e5","name":"device_tracker.see","property":"payload.event.domain","propertyType":"msg","rules":[{"t":"neq","v":"device_tracker","vt":"str"},{"t":"jsonata_exp","v":"payload.event.service = 'see'","vt":"jsonata"}],"checkall":"false","repair":false,"outputs":2,"x":350,"y":700,"wires":[[],[]]},{"id":"57ee725d.2b2644","type":"server-events","z":"dc93c609.7a6e5","name":"HA start up","server":"cc03735a.94933","event_type":"custom_homeassistant_started","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"x":130,"y":800,"wires":[["602d92b6.a42fa4"]]},{"id":"cc03735a.94933","type":"server","z":"","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]
When you use an entity
node to create sensors from Node RED you need to have an entity
node per sensor you want to create, you cannot use a template to define the ID of that sensor and have one node make/update multiple. So in this part of the flow:
Youāll need to update the change node to provide your device IDs and then update the entity
nodes to have the sensor ID you want. The flow that runs on startup to restore doesnāt need any changes, it finds all sensors with the attribute tracker_backup
and then restores a tracker from their attributes.
You will also need one other thing, an automation that on startup of HA fires an event called custom_homeassistant_started
, thatās what the second flow listens for. Hereās that automation:
- id: '1587784727281'
alias: Fire start-up event
description: Create an event on start-up that Node-RED can listen for.
trigger:
- event: start
platform: homeassistant
condition: []
action:
- event: custom_homeassistant_started
event_data: {}
I created this automation prior to 0.109 but technically starting 0.109 homeassistant fires its own native event that Node RED can listen for named homeassistant_started
. However I still have this automation because I believe I tried switching to that and noticed that HA fires that event before it finishes setting up platforms and restoring states whereas this automation runs after all that is done.
So Iād recommend keeping it but its possible something has changed since then so it might be worth testing the native event again to see. I know personally anytime I can remove custom functionality in favor of native functionality I try to do it.
Oh also thereās one gap I havenāt been able to solve. When you actually restart the host machine (not HA) then the trackers are not restored in my experience. This is because when the host is restated then both HA and the Node RED addon hare starting up at the same time. When this happens my experience has been that HA comes up first and fires the custom_homeassistant_started
event before Node RED is up and listening for it thus missing its restore window. Iām not sure if thatās true for everyone or depends on the complexity of your HA vs. Node RED.
Regardless I havenāt managed to solve it yet. I so rarely restart the host I honestly just havenāt worried about it, I can always do a manual restore if truly necessary. If it is a problem for you I think you can solve it by listening for the home_assistant_client
event of type connected
after Node RED startup and triggering restore off of that. Youād only want to listen for that after startup though because that event also triggers after every redeploy of Node RED and restart of HA. The logic seemed a bit complicated so it wasnāt worth the time to me but if it is an issue for you I think something along those lines could work.
well it seems that now Android companion app support BT natively.
so the whole thing can become more simple isnāt it?
Hi I tried to use your config but I see error in config for automation ābackup_tracker_dataā related to value_template: {{ trigger.to_state.state }}.
It is still working for you?
Ty in advance!
Actually, yes.
I finally got it set up using the new bluetooth sensor in the Android app.
first you need to create a device tracker in known_devices.yaml for your car (or you can use the one you already created for this above).
Then you need to see which MAC address you want to use for your car. I found this info by connecting my phone to my car bluetooth and seeing what the mac address showed that it was connected to in the sensor attribute.
Once you know that information you can then set up an automation in HA to set the car location based on when your phone disconnects from your car bluetooth.
here are the pieces as I have them:
In known_devices.yaml:
tacoma_app:
icon:
name: Tacoma Location from App
picture: /local/tacoma.jpg
track: true
In automation.yaml
- alias: Set Tacoma Location
trigger:
- platform: template
value_template: "{{ is_state_attr('sensor.my_mobile_app_bluetooth_connection', 'connected_paired_devices', '[]') }}"
condition:
- condition: template
value_template: "{{ trigger.from_state.attributes.connected_paired_devices == '[84:DD:20:62:FA:FE]' }}" # set this to your car bluetooth so that it only updates the location when you disconnect from your car bluetooth and nothing else
action:
- service: device_tracker.see
data_template:
dev_id: tacoma_app
location_name: not_home
gps:
- "{{ state_attr('device_tracker.my_mobile_app', 'latitude') }}"
- "{{ state_attr('device_tracker.my_mobile_app', 'longitude') }}"
the above trigger will have to be modified if you regularly have multiple bluetooth devices connected when you are using your car - which I havenāt worked out the template for yet. if it becomes a problem I can work on it then but for now this works for me.
And we no longer need Tasker which, TBH, I never really got to work reliablyā¦
update to aboveā¦
I decided to go ahead and update the code to handle the possibility of having more than your car connected to your phone.
here is the updated automation:
- alias: Set Tacoma Location
trigger:
- platform: state
entity_id: sensor.my_mobile_app_bluetooth_connection
condition:
- condition: template
value_template: "{{ '84:DD:20:62:FA:FE' in trigger.from_state.attributes.connected_paired_devices }}"
- condition: template
value_template: "{{ '84:DD:20:62:FA:FE' not in trigger.to_state.attributes.connected_paired_devices }}"
action:
- service: device_tracker.see
data_template:
dev_id: tacoma_app
location_name: not_home
gps:
- "{{ state_attr('device_tracker.my_mobile_app', 'latitude') }}"
- "{{ state_attr('device_tracker.my_mobile_app', 'longitude') }}"
Thatās niceā¦
But wouldnāt this
set the location to not_home
even if you park your car at home?
(Iām new to device_tracker.see
)
yeah, but that part really doesnāt matter as much as the location.
If it is important Iām sure you could also template the location_name to set it to home if the zone is the home zone.
the other thing I just noticed is that the device tracker data doesnāt seem to survive restarts.
I managed this adding the single device to the āincludeā section of my recorder.
I tested the automation for 2 days and I noticed that the position is not updated sometimes. Maybe it depends from my mobileā¦Iām thinking to add a repeat to the position so it will be updated more often.
I changed it to
location_name: ā{{ states(ādevice_tracker.mobiledeviceā) }}ā
I tried that and it didnāt work. It still loses the state after a restart.
I built a flow in node red which saves the position on a website using GET and pulls it back using a http request when home assistant is restarted.
I assume you could do the same using a input_text.
If itās wanted then I can post the flow.
I also added a loop to try and pull new data from the phone before itās saved.
Thanks for the offer but I donāt use Node-red.
I probably could get creative and save it to a variable if I really needed it.
But hopefully I wonāt get into a situation where I need to remember where I parked my truck and in the meantime Iāve restarted HA. Seeing as Iām the only one who ever restarts HA so if Iām home (and presumably so would my truckā¦) and messing with HA I would have more serious problems to worry about than remembering that I parked my truck in the driveway!
Not saving the state was more of a WTH than a real need.
Speaking of whichā¦
Power loss?
Power supply gives up?
But I understand why device trackers donāt save the state, they are not meant to save the state. That would defeat their purpose.
When HA restarts it should update all device trackers, perhaps if you could set a āmanualā attribute on them.
Iām not sure thatās necessarily the case.
If that is the case then no entities in HA (aside from those controlled exclusively from within HA itself) should retain their states thru a restart. Who is to say a light wasnāt turned off while HA was down? There are many other or better examples but I hope you get my point.
We have an optional āoptimistic modeā for other entities. Why couldnāt we have something similar for device trackers? I think having a ālast known good locationā for a device tracker could come in handy - like in the current use case.
Exactly what Iām saying.
Sensors are supposed to sense stuff, not assume.
If it retains itās state after startup then it assumes.
Exactly my point again. HA must update states after a boot up or it will be out of sync with reality.
HA doesnāt know how long it has been off (maybe it can find it out) but giving a last known location can still be on the other side of the planet.
I would rather see āunknownā than a wild guess
Voted! TY for your initiative!
But my point is that we should have the option to tell HA to assume a location based on the last known good location. It should be my choice if thatās how I want my sensor to act.
Because right now Iām forced to jump thru hoops creating variables and automations to fix the issue instead of just simply having an option in the device tracker config that says āoptimistic: trueā or āretain: trueā.
input_* entities have that similar functionality. if there is no initial state set then it gets the same value that it had when HA shut down. So they āassumeā that nothing has changed in the interim. Otherwise, to be consistent, there should be no option for an initial value or that they retain their last known state after a restart. they should always show āunknownā until programmatically updated with the desired value.
Iām sure there are other entities that act that way as well.
Of course, in a perfect world every entity would be able to be instantly polled or prompted for an update instantaneously after a restart. Sometimes (like in this particular case) thatās not possible. And in this particular case that information is lost forever with no easy way to get it back until we go back to the vehicle and connect/disconnect the bluetooth (or whatever method you are using). But if you already knew where you last parked then the whole point of that exercise is completely moot. Itās a catch-22 - you have to remember where you last parked in order to find your vehicle to set the known location in order for you to remember where you last parked.
As long as itās an optionā¦
But I would never use that on device trackers.
What if you walk outside your house and get a good location.
You drive away and just as you leave the house a small power dip makes your HA restart.
Ha assumes your previous position was home and unlocks the doors/alarm.
Not for meā¦
Noā¦
Just save the location in a variable and use device_tracker.see to set the position according to your preference using a uptime sensor and conditions on how it should assume last position.
If I restart HA it waits for two minutes to make sure everything is up and running then it sets the car position to where it was parked.