Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bluetooth scanning #686

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Add bluetooth scanning #686

wants to merge 1 commit into from

Conversation

Munchax10
Copy link

@Munchax10 Munchax10 commented Jun 21, 2024

Feel free to review and make changes!

termux-api-package pull request: termux/termux-api-package#187

Feel free to make changes!
Copy link
Contributor

@tstein tstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is not quite the right API to expose. IIUC what you've got is:

  • start - begin collecting discovered devices in the background
  • info - return a time-ordered but untimestamped list of every device-sighting since start (ed: corrected this after the initial comment)
  • stop - stop collecting devices and return that list one last time

Two things feel wrong about this to me:

  1. This sorta kinda resembles how bluetooth discovery UIs work, but you're building a programmatic interface. You don't need to keep history inside this API because it's going to be consumed by code, not by human eyes that might look away for a second and miss something.
  2. You don't have any last-seen tracking, which means that if I wait to scan for more than a handful of seconds, I have no way to distinguish between devices I just saw and devices I saw once, right after start, and never again.

I spent a day chewing on this and imo this should be:

  • start - as above
  • dump or poll - return devices seen since the last dump or poll (info isn't a good verb whether you change the semantics or not)
  • stop - just stop scanning, no devices returned

What do you think?

private static BluetoothAdapter adapter;
private static boolean scanning = false;

private static final BroadcastReceiver receiver = new BroadcastReceiver() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please give this a better name, even though it's the only BroadcastReceiver in sight. device_found_receiver?


public class BluetoothScanAPI {

private static final ArrayList<BluetoothDevice> devices = new ArrayList<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's strictly necessary to track and return last-seen timestamps. It also looks like the scan API will trigger multiple times for the same devices as it's repeatedly discovered, and a longer scan with the code would result in multiple copies of the same device in this array and the returned output.

This seems like it should be HashMap<BluetoothDevice, long>.

public void onReceive(Context context, Intent intent) {
if (Objects.equals(intent.getAction(), BluetoothDevice.ACTION_FOUND)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we'd expect an ACTION_FOUND with device == null? Add a comment if so, log an error saying "that shouldn't happen it but" did if not.


}

private static void printList(JsonWriter out, boolean clear) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This method doesn't actually print. writeDiscoveredDevices, something like that?

(If you accept my suggested API change, you should remove boolean clear and clear unconditionally after calling this in the dump/poll handler.)

}

private static boolean start(Context context) {
if (scanning) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mega nit: { return false; }, and same in stop(), please. :)

Comment on lines +50 to +53
out.name("error").value(false);
} else {
out.name("error").value(true);
out.name("reason").value("Already running!");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having two keys, how about error only being present if it has an error message and returning an empty object on success? There's approximate precedent for that in the NFC API.

@tstein tstein self-requested a review June 23, 2024 17:48
@Munchax10
Copy link
Author

I think this is not quite the right API to expose. IIUC what you've got is:

  • start - begin collecting discovered devices in the background
  • info - return a time-ordered but untimestamped list of every device-sighting since start (ed: corrected this after the initial comment)
  • stop - stop collecting devices and return that list one last time

Two things feel wrong about this to me:

  1. This sorta kinda resembles how bluetooth discovery UIs work, but you're building a programmatic interface. You don't need to keep history inside this API because it's going to be consumed by code, not by human eyes that might look away for a second and miss something.
  2. You don't have any last-seen tracking, which means that if I wait to scan for more than a handful of seconds, I have no way to distinguish between devices I just saw and devices I saw once, right after start, and never again.

I spent a day chewing on this and imo this should be:

  • start - as above
  • dump or poll - return devices seen since the last dump or poll (info isn't a good verb whether you change the semantics or not)
  • stop - just stop scanning, no devices returned

What do you think?

This was my initial thought process, but i realized that force quitting the process would not stop discovery. I do not have time atm, but i would be happy if someone made it automatically discover and keep the process running (so that info would be removed, so would the list).

@tstein
Copy link
Contributor

tstein commented Jul 4, 2024

I don't follow. My suggestion was purely about the ergonomics and usefulness of the API; the fact that discovery would continue if you force-stopped the main termux process (I think that's what you meant) seems the same either way.

@Munchax10
Copy link
Author

If the api was written in java, this would not be the case. Currently its getting through 2 languages, so its pretty hard to manage. If the api used jni, you could share types and objects (but it would be harder for a normal user to implement). If we want to include more features, we would probably need an api rework.

@tstein
Copy link
Contributor

tstein commented Jul 4, 2024

Right, but that's not an option. I'm saying that I think you can and should make those changes within the constraints of a normal termux-api API, to produce a more useful and more comfortable shell interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants