by whmoorejr » Sun Feb 25, 2024 10:48 pm
Geofences...
In owntracks, they call their geofences several things in the documentation. On the phone app, they are called "Regions" . Once your device is in one of them, you will have two states appear: inregions and inrids. inrids is the key for the region. If you push a new geofence (called waypoints on the MQTT side), if it has the same inrids variable, it will overwrite the other one. This is handy.
To keep the "Regions" the same across devices, I found it easier to type up the JSON code first, plop it into an MQTT Publish action and adjust the topic to align with each phone. Now all the phones in my house have the same "Regions" with the same "inrids" and "inregions" names. If I add geofences to the list, I just re-publish them out to the devices so I can centrally manage it all.
It looks like this:
MQTT Connector Actions (Publish Message)
Device: Owntracks Broker
Action Settings:
Topic: owntracks/bill/myphone/cmd (FYI, for everyone's device, it is "myphone". So the name "bill" is the unique value. I don't have to remember who has what type of phone, or change everything when someone upgrades, etc.
Payload:
- Code: Select all
{
"_type": "cmd",
"action": "setWaypoints",
"waypoints": {
"_type": "waypoints",
"waypoints": [
{
"_type": "waypoint",
"tst": 1708703480,
"rid": "my-region-id-001",
"desc": "Home",
"rad": 250,
"lat": 29.61456,
"lon": -94.84806
},
{
"_type": "waypoint",
"tst": 1708703495,
"rid": "my-region-id-010",
"desc": "Cline",
"rad": 250,
"lat": 30.14447,
"lon": -95.51607
}
]
}
}
Note: "tst" doesn't have to be accurate, but you will have some weird recorder files on the backend of owntracks if you do any data mining later... "tst" is Unix time. I used the time that I created the list (roughly). You can find "Unix Time" by
https://www.unixtimestamp.com/So that's the indigo way to upload geofences / waypoints / regions onto your phones...
Now make a indigo geofence.....
STEP 1:Make a Variable Device
https://www.indigodomo.com/pluginstore/269/ for each Geofence you create.
You will need 2 variables for each variable device:
GeoFence_Home_Members
GeoFence_Home_Occupied
STEP 2:Create 2 triggers (These two trigger will work for an unlimited number of geofences)
1st Trigger: I called mine: MQTT Match All Events
Type: MQTT Connector Event
Event: Topic Component Match
Select Broker: Owntracks Broker
Topic Strings for matching
Match: owntracks
Any:
Match: myphone <-- put another "Any" here if you used different things for different folks (iPhone5, Galaxy7, etc.)
Match: event
Queue Message (check)
Message Type: ##allEvents##
Before you move on to the last trigger, you need another shim. This shim will now update whenever any phone publishes an "Event". (Different from a location publish)
I called mine "MQTT-All Events"
MQTT Shims
MQTT Generic JSON Device
MQTT Broker: Owntracks Broker
Message Type: ##allEvents##
Unique ID Location: Payload Field
Payload Key: _type
Unique ID Value: transition <--- So this should only update if the "Event" is a "Transition" event with an Enter or Exit.
Multi-States Key: . <-- Hard to see, another period is there.
Save.
2nd Trigger: I called mine: MQTT Event: Geofence Processing
Type: MQTT Shims Event
Event: Device Updated
Shim Device: MQTT-All Events
(not sure if I needed this part, but)
Condition: If device
MQTT-All Events sk_type is equal to
transitionAction: Execute Script (This should update all geofence whenever anyone enters or exits any geofence)... so it should stay up-to-date without running unnecessarily.
- Code: Select all
### Get regions from each device. Use "Try" because if they aren't in a region, the state won't exist. So return a " " value instead.
try:
Bill = indigo.devices[1183167460].states["inregions"] # State "inregions" of "MQTT-Bill"
except:
Bill = " "
try:
Vikki = indigo.devices[721909935].states["inregions"] # State "inregions" of "MQTT-Vikki"
except:
Vikki = " "
try:
Anna = indigo.devices[204130087].states["inregions"] # State "inregions" of "MQTT-Anna"
except:
Anna = " "
## Check Geofence Home ##
gfHomeMembers = ""
gfHome = "Home"
gfHomeOccupied = False
if gfHome in Bill:
gfHomeMembers = gfHomeMembers + "Bill, "
gfHomeOccupied = True
if gfHome in Vikki:
gfHomeMembers = gfHomeMembers + "Vikki, "
gfHomeOccupied = True
if gfHome in Anna:
gfHomeMembers = gfHomeMembers + "Anna, "
gfHomeOccupied = True
if gfHomeOccupied == True:
indigo.server.log("Geofence: " + gfHome + " is Occupied By: " + gfHomeMembers)
indigo.variable.updateValue(836883327, value=gfHomeMembers) # "GeoFence_ISL_Home_Members"
indigo.variable.updateValue(933218063, value="true") # "GeoFence_ISL_Home_Occupied"
else:
indigo.server.log("Geofence: " + gfHome + " is Empty")
indigo.variable.updateValue(836883327, value="Empty") # "GeoFence_ISL_Home_Members"
indigo.variable.updateValue(933218063, value="false") # "GeoFence_ISL_Home_Occupied"
## Check Geofence FHS ##
gfFHSMembers = ""
gfFHS = "FHS"
gfFHSOccupied = False
if gfFHS in Bill:
gfFHSMembers = gfFHSMembers + "Bill, "
gfFHSOccupied = True
if gfFHS in Vikki:
gfFHSMembers = gfFHSMembers + "Vikki, "
gfFHSOccupied = True
if gfFHS in Anna:
gfFHSMembers = gfFHSMembers + "Anna, "
gfFHSOccupied = True
if gfFHSOccupied == True:
indigo.server.log("Geofence: " + gfFHS + " is Occupied By:" + gfFHSMembers)
indigo.variable.updateValue(1311857680, value=gfClineMembers) # "GeoFence_FHS_Members"
indigo.variable.updateValue(869336078, value="true") # "GeoFence_FHS_Occupied"
else:
indigo.server.log("Geofence: " + gfFHS + " is Empty")
indigo.variable.updateValue(1311857680, value="Empty") # "GeoFence_FHS_Members"
indigo.variable.updateValue(869336078, value="false") # "GeoFence_FHS_Occupied"
That's it. You now have geofences as devices.
Note: With Owntracks, you can be in multiple regions. The above should work with that. Owntracks will work with GPS (phone) or with iBeacons (which I havn't played with yet). So, you could easily be within multiple "Regions" or geofences, etc.
Other note... If you want to Delete a region from a phone remotely, I'll cover this in another post... but in short, make sure the key "inrids" is the same and change the Lat/Lon to something impossible. Like Lat: 100, Lon: 500. That will remove the "Waypoint" from the device.
Geofences...
In owntracks, they call their geofences several things in the documentation. On the phone app, they are called "Regions" . Once your device is in one of them, you will have two states appear: inregions and inrids. inrids is the key for the region. If you push a new geofence (called waypoints on the MQTT side), if it has the same inrids variable, it will overwrite the other one. This is handy.
To keep the "Regions" the same across devices, I found it easier to type up the JSON code first, plop it into an MQTT Publish action and adjust the topic to align with each phone. Now all the phones in my house have the same "Regions" with the same "inrids" and "inregions" names. If I add geofences to the list, I just re-publish them out to the devices so I can centrally manage it all.
It looks like this:
MQTT Connector Actions (Publish Message)
Device: Owntracks Broker
Action Settings:
Topic: owntracks/bill/myphone/cmd (FYI, for everyone's device, it is "myphone". So the name "bill" is the unique value. I don't have to remember who has what type of phone, or change everything when someone upgrades, etc.
Payload:[code]{
"_type": "cmd",
"action": "setWaypoints",
"waypoints": {
"_type": "waypoints",
"waypoints": [
{
"_type": "waypoint",
"tst": 1708703480,
"rid": "my-region-id-001",
"desc": "Home",
"rad": 250,
"lat": 29.61456,
"lon": -94.84806
},
{
"_type": "waypoint",
"tst": 1708703495,
"rid": "my-region-id-010",
"desc": "Cline",
"rad": 250,
"lat": 30.14447,
"lon": -95.51607
}
]
}
}
[/code]
Note: "tst" doesn't have to be accurate, but you will have some weird recorder files on the backend of owntracks if you do any data mining later... "tst" is Unix time. I used the time that I created the list (roughly). You can find "Unix Time" by [url]https://www.unixtimestamp.com/[/url]
So that's the indigo way to upload geofences / waypoints / regions onto your phones...
Now make a indigo geofence.....
[b][u]STEP 1:[/u][/b]
Make a Variable Device [url]https://www.indigodomo.com/pluginstore/269/[/url] for each Geofence you create.
You will need 2 variables for each variable device:
[list]GeoFence_Home_Members
GeoFence_Home_Occupied[/list]
[b][u]STEP 2:[/u][/b]
Create 2 triggers (These two trigger will work for an unlimited number of geofences)
1st Trigger: I called mine: MQTT Match All Events
[list]Type: MQTT Connector Event
Event: Topic Component Match
Select Broker: Owntracks Broker
Topic Strings for matching
[list]Match: owntracks
Any:
Match: myphone <-- put another "Any" here if you used different things for different folks (iPhone5, Galaxy7, etc.)
Match: event[/list]
Queue Message (check)
Message Type: ##allEvents##[/list]
Before you move on to the last trigger, you need another shim. This shim will now update whenever any phone publishes an "Event". (Different from a location publish)
I called mine "MQTT-All Events"
[list]MQTT Shims
MQTT Generic JSON Device
MQTT Broker: Owntracks Broker
Message Type: ##allEvents##
Unique ID Location: Payload Field
Payload Key: _type
Unique ID Value: transition <--- So this should only update if the "Event" is a "Transition" event with an Enter or Exit.
Multi-States Key: . <-- Hard to see, another period is there.[/list]
Save.
2nd Trigger: I called mine: MQTT Event: Geofence Processing
Type: MQTT Shims Event
Event: Device Updated
Shim Device: MQTT-All Events
(not sure if I needed this part, but)
Condition: If device [i]MQTT-All Events[/i] [i]sk_type[/i] is equal to [i]transition[/i]
Action: Execute Script (This should update all geofence whenever anyone enters or exits any geofence)... so it should stay up-to-date without running unnecessarily.
[code]### Get regions from each device. Use "Try" because if they aren't in a region, the state won't exist. So return a " " value instead.
try:
Bill = indigo.devices[1183167460].states["inregions"] # State "inregions" of "MQTT-Bill"
except:
Bill = " "
try:
Vikki = indigo.devices[721909935].states["inregions"] # State "inregions" of "MQTT-Vikki"
except:
Vikki = " "
try:
Anna = indigo.devices[204130087].states["inregions"] # State "inregions" of "MQTT-Anna"
except:
Anna = " "
## Check Geofence Home ##
gfHomeMembers = ""
gfHome = "Home"
gfHomeOccupied = False
if gfHome in Bill:
gfHomeMembers = gfHomeMembers + "Bill, "
gfHomeOccupied = True
if gfHome in Vikki:
gfHomeMembers = gfHomeMembers + "Vikki, "
gfHomeOccupied = True
if gfHome in Anna:
gfHomeMembers = gfHomeMembers + "Anna, "
gfHomeOccupied = True
if gfHomeOccupied == True:
indigo.server.log("Geofence: " + gfHome + " is Occupied By: " + gfHomeMembers)
indigo.variable.updateValue(836883327, value=gfHomeMembers) # "GeoFence_ISL_Home_Members"
indigo.variable.updateValue(933218063, value="true") # "GeoFence_ISL_Home_Occupied"
else:
indigo.server.log("Geofence: " + gfHome + " is Empty")
indigo.variable.updateValue(836883327, value="Empty") # "GeoFence_ISL_Home_Members"
indigo.variable.updateValue(933218063, value="false") # "GeoFence_ISL_Home_Occupied"
## Check Geofence FHS ##
gfFHSMembers = ""
gfFHS = "FHS"
gfFHSOccupied = False
if gfFHS in Bill:
gfFHSMembers = gfFHSMembers + "Bill, "
gfFHSOccupied = True
if gfFHS in Vikki:
gfFHSMembers = gfFHSMembers + "Vikki, "
gfFHSOccupied = True
if gfFHS in Anna:
gfFHSMembers = gfFHSMembers + "Anna, "
gfFHSOccupied = True
if gfFHSOccupied == True:
indigo.server.log("Geofence: " + gfFHS + " is Occupied By:" + gfFHSMembers)
indigo.variable.updateValue(1311857680, value=gfClineMembers) # "GeoFence_FHS_Members"
indigo.variable.updateValue(869336078, value="true") # "GeoFence_FHS_Occupied"
else:
indigo.server.log("Geofence: " + gfFHS + " is Empty")
indigo.variable.updateValue(1311857680, value="Empty") # "GeoFence_FHS_Members"
indigo.variable.updateValue(869336078, value="false") # "GeoFence_FHS_Occupied"
[/code]
That's it. You now have geofences as devices.
Note: With Owntracks, you can be in multiple regions. The above should work with that. Owntracks will work with GPS (phone) or with iBeacons (which I havn't played with yet). So, you could easily be within multiple "Regions" or geofences, etc.
Other note... If you want to Delete a region from a phone remotely, I'll cover this in another post... but in short, make sure the key "inrids" is the same and change the Lat/Lon to something impossible. Like Lat: 100, Lon: 500. That will remove the "Waypoint" from the device.