android icon indicating copy to clipboard operation
android copied to clipboard

[Feature Request] Ability to configure app to send empty pings without location to save on battery.

Open sebastiannielsen opened this issue 4 years ago • 7 comments
trafficstars

  • 2.2.2 (22202):
  • 11:
  • Samsung Note 10:

I would want to have the ability for the app to send JSON pings to HTTP pretty frequently (could be like type=ping). These messages could contain the following:

{"_type":"ping","batt":47,"bs":2,"conn":"w","created_at":1615721919,"tid":"d1"}

And then, if my server wants the location of the user, I could respond with:

{"_type":"cmd","action":"reportLocation"}

And then it will request a full fix (high-power GPS), wait until fix is sufficently accurate (by delaying until fix meets the "inaccurate locations" setting), then transmit location ONCE to server. Then it goes back to its "empty JSON ping mode" again, waiting for next location request. (unless I respond to the ONCE location transmission with a new "reportLocation" response - then it would just infinitely report locations until the server no longer reponds with "reportLocation")

In this way, I can control from my server when I need the location, and not needlessly request fix (which sucks battery) when I don't need it.

This monitoring mode, could be called "ServerControlled", and have a index of -2.

like: -2 ServerControlled -1 Quiet 0 Manual 1 Significant 2 Move

When in ServerControlled mode, "Location Interval" in configuration will then describe how often it sends these "empty pings" instead of full location updates.

sebastiannielsen avatar Mar 14 '21 11:03 sebastiannielsen

We already have something called ping in the form of location messages with t: p in them.

Other than that I think what you're suggesting sounds a bit like overkill, particularly if we want parity with iOS. Be aware that reportLocation needs the app to actually be able to see that message; IIRC (but @growse will elaborate and correct me, I hope :-) this is no longer so easy on Android either.

We've rather good battery usage in significant changes mode, where the apps report location upon change.

jpmens avatar Mar 14 '21 12:03 jpmens

yeah, I know about the t: p messages.

Of course, I understand that the app needs to see that message, which is pretty easy for me since I turned off battery optimization, mening it gets pretty good network access, which is the only thing it requires. Since Im using HTTP, it just does the pings and reads the responses simply. Note that doze is not really a big problem, since the phone will in most cases be in active usage while my server requests location. Its just simply, that I want to request location when OTHER apps do certain things on my server.

The problem with "Significant changes" mode, is that a ping is only sent during significant changes. I would want to tell the app "update NOW!" and it will make a best-effort attempt to update at high-power request. (and this requires then the app to send pings rather frequently, like each 10 minutes).

My use case is to pick the device location during certain events on the server. For example, when a package is scanned for delivery, the delivery server then queries the location of the phone to be able to show the package delivery location.

Or if something happens, and the alarm button inside the car is pushed (which sends a simple HTTP messsage to server via mobile data) - then I want my server to be able to request the location, and then send that via a custom API request to monitoring centre.

I know I could kind of solve it, by updating the configuration remotely when there is orders to deliver, to move mode, and then quitting out of move mode automatically when the order roster is exhausted. But would be much more efficient by just requesting the location at the times I need the location, by responding to regular keep-alive pings from the app.

sebastiannielsen avatar Mar 14 '21 12:03 sebastiannielsen

If I've read this right, the main request is that you'd like the ability to explicitly request that the app acquire and report a location, even while the app is in quiet mode. Remote commands are a reasonable thing to ask for, and it's on the roadmap to doing - it's not without its challenges though.

As you state - the challenge here is how do you initiate a command from the server to the client when the transport is HTTP? It's not a stateful connection, so the server has no mechanism by which it can unilaterally send a command to the client - it has to be in response to something, so it seems that the proposal to send periodic pings over HTTP is a mechanism that tries to solve this. It essentially opens a connection to send a content-free request to the server to give the server the opportunity to send back a response (which could be a command, or anything). Have I got that right?

If so, it seems like we'd be trying to coerce HTTP into doing something it's not really a good fit for. The other transport option, MQTT, is much better suited to this sort of thing as the connection is stateful - the server has an open socket it can do whatever it wants with, no initiating request required (beyond setting up the connection).

That said, MQTT isn't the right answer in all environments and I'm not 100% against the idea that the user could enable an HTTP-poll, which would work across all modes and simply send an empty request to the server to give it that opportunity to respond with a command (or other user's locations, or whatever). I'd just want to think about what the implementation might look like, desired frequency etc.

growse avatar Mar 14 '21 13:03 growse

@growse Exactly - my point is that there should be a third mode like "-2" which is "ServerControlled" - where "LocationInterval" in settings, decide how often it does send a HTTP/S ping request (regardless of movement or similiar, just purely based on time).

and at that particular HTTP/S request, the server has the opportunity to reply with a response to request position. Or just respond with nothing else than a empty JSON object or similiar if they just don't want to request location.

One problem with MQTT over mobile networks are CGNAT devices at mobile operators, which means I don't see MQTT as a viable option - it HAS to be something where the phone initiates the request to the server, and gets a response.

Thats why I see HTTP/S poll as a viable option, and its better to let the user, using locationinterval, trigger a HTTP/S poll at that interval (regardless of circumstances - it just purely waits LocationInterval seconds, then sends a poll, then waits LocationInterval seconds, then send a poll, etc). HTTP/S also works good with anonymous prepaid cards, where operators may block other ports than 80 and 443 to reduce the possibility of abuse.

This then also gurantees a response, since the CGNAT device at the mobile operator will then always pull open a new connection to the HTTP/S server when a request is done. While with MQTT, there is a risk the operator sees the connection as stale and tears it down at CGNAT level (possible without notifying the parties, causing timeouts).

sebastiannielsen avatar Mar 14 '21 13:03 sebastiannielsen

I hear the argument around MQTT in respect of carriers doing awful things with CGNAT etc.

I'm somewhat tentative about making this another mode (we have too many modes already in my view), and I'd probably rather see this as a preference that the user can toggle on/off when using HTTP regardless of mode. I also wouldn't want to necessarily tie it to an existing preference like location interval, there will be other use cases who might want a very aggressive poll interval, but a fairly relaxed location interval.

I'll have a think about what this might look like and play about with some ideas.

growse avatar Mar 14 '21 13:03 growse

The idea of tying it to "LocationInterval", is that if you want a "relaxed location interval", you just configure it in "ServerControlled" mode with a aggressive "LocationInterval" (which will poll the server often with a empty ping) - and then - on the SERVER SIDE, you would set up some script that counts or stores the time from the last "reportLocation" response, and when you have reached your desired "real" "LocationInterval", you just respond with "reportLocation".

Meaning, it becomes superflous with a separate "poll interval" setting, as the location reporting interval can be handled on the server side perfectly, meaning that "LocationInterval" can take the job as the poll interval when you are in "ServerControlled" mode.

Another advantage, is that if you on your server, trigger a "reportLocation" on a event (like in my example, a delivery scan), its up to you as server owner, if you want to reset the "LocationInterval" time (which means it would wait your full desired time before requesting location again) - which means it prematurely triggered a location request, now it will wait a full Interval before next, or if you cotinue counting on your LocationInterval and treat the event-based "reportLocation" as non-existent, meaning the event-based "reportLocation" becomes sandwiched in-between 2 normal "reportLocation".

Another advantage is that you can dynamically change the "real" LocationInterval for example depending on time of day or similiar, without having to remotely update the configuration in app. You just change the interval at which you send "reportLocation" as response to the ping, dynamically as you see fit.

Or you could do this in Quiet mode somehow, but that could raise privacy concerns for old users that are used to it ignoring reportLocation from server in that mode. So thats why I suggest a new explicit mode, where total control is handed over to the server.

sebastiannielsen avatar Mar 14 '21 13:03 sebastiannielsen

Could webhooks be feasibly used for this "ServerControlled" option? I'm not sure if there are any system limitations that would prevent them from being used, but otherwise they should be much more efficient than polling in terms of network usage and possibly battery life

ahmouse15 avatar Oct 26 '21 03:10 ahmouse15