owntracks / recorder

Store and access data published by OwnTracks apps
Other
875 stars 122 forks source link

Capability request: hard limit location handling to a region #458

Closed nickswalker closed 6 months ago

nickswalker commented 6 months ago

I'm interested in ensuring that no location data outside of a geofence is acknowledge or used by the recorder. The mobile clients in principle could (should) be made to enforce the fence, but this would be a backstop in case a client is misconfigured. It is almost possible to implement using the otr_putrec lua hook, which can filter locations before they are stored. But this hook does not prevent the location from being kept in last and from being forwarded out over any listening websockets.

jpmens commented 6 months ago

That sounds interesting. Can you elaborate on a specific use-case?

Also: how would you expect the (probably more than just one) geofence to be defined? Would a JSON file with circular regions similar to the how we implement waypoint import on the devices be suitable?

nickswalker commented 6 months ago

Sure. I want to use recorder to store and serve data from runners participating in a race. Their live location and track would be publicly viewable during the event. I do not want their devices to send their location data (ideally) when they are outside the boundaries of the race area. Given that clients could still unexpectedly send data I don't want, I don't want to store it or retransmit it (which is almost possible with the existing hook), as it would be fed to a public map. The public map bit is why I would still want to be able to use the convenient last endpoint and the websocket API.

For this use case I think a list of points and radii could work, but might be cumbersome. I'm imagining e.g. a typical marathon course which is essentially a 26 mile line where you'd want to accept data within 100m of the line. Easily scripted, but might take ~1000 points. It would be more compact as say a geojson polygon, and easier to author thanks to tools like geojson.io.

This use case could also be addressed with a little MQTT proxy, or perhaps a fancier broker, which filters location messages based on their content. I thought it was close-enough to possible within the existing configuration space that I'd suggest it as a feature though!

jpmens commented 6 months ago

Thank you for explaining, and that all makes sense to me.

I think the easiest short-term solution would be to have a small bit of code which subscribes to an MQTT broker and replublishes to another (from which OwnTracks' Recorder consumes) if and when a location is within the mentioned polygon.

Other than that, I agree with your evaluation that that this would best be done within the current hoook. Is this something you would like to attempt doing?

nickswalker commented 6 months ago

Yes, long term I can contribute this feature.

To leave some breadcrumbs for when I look at this next:

What kind of changes to the hook's API or behavior do you think are appropriate? I interpreted the name and docs for putrec as implying that no record of a publish would be kept if my script returns non-zero, so I think it's a good default to use the hook to also decide whether to write the last record as well. I am less certain about how people expect the websocket to behave, but I also interpreted the websocket as reflective of only 'recorded' data (if you want live-but-unrecorded data, you could use the broker's websocket). Would reinterpreting the hook this way break too many use cases?

If we generalized putrec into a filter hook, it would make sense to expose finer control over what behavior is changed. The hook could return a bitfield controlling store record, store last, websocket publish, .... This would preserve existing uses. Is this complexity warranted?

jpmens commented 6 months ago

I agree that data published on the websocket should correspond to stored data, so we should avoid leakage through it if otr_putrec() says "don't store".

The hook could return a bitfield controlling store record, store last, websocket publish, .... This would preserve existing uses.

I think that's overkill at this point. If the decision within putrec is to not store, the location should be discarded.

Let's keep it simple.