Skip to content

Conversation

@notrege
Copy link
Contributor

@notrege notrege commented Mar 5, 2024

Describe the pull request:

  • Bug fix
  • Functional change
  • New feature
  • Code cleanup
  • Build system change
  • Documentation change
  • Language translation

Pull request long description:

When switching from a non-bluetooth computer to a bluetooh computer an unnecessary bluetooth scan may be forced. This change will avoid the scan if the bluetooth device address is known.

I discovered this issue when sharing a laptop to upload dives. If I upload dives using a bluetooth computer I have to rescan the device address after a dive is uploaded with a different computer. This change uses the existing device address instead of scanning. A scan can be forces by clearing/rechecking the "Choose Bluetooth download mode" checkbox.

Changes made:

There are two changes. First, set the device address using the prefs value when a dive computer is selected. Second, avoid scanning if the device address is already known.

Related issues:

Additional information:

Release note:

Documentation change:

Mentions:

notrege added 2 commits March 5, 2024 09:05
When switching from a non-bluetooth computer to a bluetooh computer an unnecessary bluetooth scan may be forced.   This patch will avoid the scan if the bluetooth device address is known.



Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
Avoid unnecessary bluetooth device address scanning.
Copy link
Member

@mikeller mikeller left a comment

Choose a reason for hiding this comment

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

Congratulations on your first pull request!

A couple of remarks that need attention.

void DownloadFromDCWidget::DC##num##Clicked() \
{ \
ui.vendor->setCurrentIndex(ui.vendor->findText(qPrefDiveComputer::vendor##num())); \
ui.device->setCurrentText(qPrefDiveComputer::device##num()); \
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be doing the same as what we are already doing in https://github.com/subsurface/subsurface/pull/4120/files#diff-a0bde534c60cabf020b85f0079e0a8d567f5465514e8a59629b3a50a228d17f9R160 - but with slightly different connotations, like not overriding the selection for serial devices (which probably makes sense), and not doing it for MacOS where it does not seem to be working.

The core of the problem seems to be that https://github.com/subsurface/subsurface/pull/4120/files#diff-a0bde534c60cabf020b85f0079e0a8d567f5465514e8a59629b3a50a228d17f9L156 is triggering enableBluetoothMode(), which is springing a bluetooth selection dialogue - so I think it will be better if we just move this line down below ui.device->setCurrentIndex().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks very much for the help and for looking at this. I'm not sure why it should be different for serial vs Bluetooth devices, but I must be missing something. In my test case, I have an Oceanic atom using /dev/tty.usbserial-20030001 and a G2 using a Bluetooth address. With the changes above, I seem to be able to switch back and forth between the two without a Bluetooth scan or losing the serial mount point. I'm doing on this on a sadly old Macbook running Catalina (10.15.7). Won't your suggestion of moving this line down below ui.device-setCurrentIndex() be skipped on MacOs?

Copy link
Member

Choose a reason for hiding this comment

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

The thinking behind not using persisted serial port data in #3840 is that on today's computers practically all serial devices are connected through USB, and on most operating systems have dynamic identifiers (based on the order they were detected in). So in most cases the serial port identifier may or may not have changed. Not sure how this is for MacOS, but the device identifier that you supplied looks a lot like it is dependent on the USB bus ID, which will change if a different port is used.
Re not using remembered bluetooth ids on MacOS, this is based on #2158 (comment), so you'll have to work out with @dirkhh if this is still relevant.

Copy link
Member

Choose a reason for hiding this comment

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

@dirkhh: Do you have any insights about #2158 (comment) still being valid, or should this exclusion be dropped?

Copy link
Collaborator

Choose a reason for hiding this comment

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

From comments that others have made, and from a quick experiment, it seems like Apple may have fixed that.

Copy link
Member

@mikeller mikeller Mar 13, 2024

Choose a reason for hiding this comment

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

Sounds good @dirkhh, thanks for checking.
@notrege we still have the problem that this line essentially doubles up what https://github.com/subsurface/subsurface/pull/4120/files#diff-a0bde534c60cabf020b85f0079e0a8d567f5465514e8a59629b3a50a228d17f9R160 already does, and that it overwrites the serial port if it has already been selected, even if the 'remembered' serial port is not currently available.
So I'd probably remove this line, and instead drop the !isMacOs (and the comment about it) in the code below, and then move ui.bluetoothMode->setChecked(isBluetoothDevice) to below ui.device->setCurrentIndex(deviceIndex(qPrefDiveComputer::device##num())).

if (state == Qt::Checked) {
if (ui.device->currentText().isEmpty()) {
selectRemoteBluetoothDevice();
} else {
Copy link
Member

Choose a reason for hiding this comment

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

You've moved the else clause from the outer if to the (new) inner if - which is not the way this should be working.

Also note that coding style in Subsurface calls for tab as tabs (and not spaces), and for if / else with single statements to be without curly braces.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry about that. I'm afraid that happened when retyping the code in git.

FWIW, the coding style does not state that single statements go without curly braces - the only relevant point I saw was:

o both sides of an if / else clause either use or do not use curly braces:

Copy link
Member

Choose a reason for hiding this comment

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

All good.
In essence, the purpose of having a defined coding style in a project and adhering to it is to avoid unneeded 'noise' from people reworking the style of sections of code when they are reworking or extending it. As such the 'coding style' is much more 'the style used for a majority of the code in a project' than it is a document that tries to codify this style. And in subsurface the predominant style is to not have curly braces for single if / else statements.

Replaces spaces with tabs and corrected misplaced braces (embarassing...).

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
else
if (state == Qt::Checked) {
if (ui.device->currentText().isEmpty())
selectRemoteBluetoothDevice();
Copy link
Member

Choose a reason for hiding this comment

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

One more case of spaces - it often pays to enable 'show whitespace' in your editor before submitting code changes.

another space that should have been a tab.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
selectRemoteBluetoothDevice();
else
if (state == Qt::Checked) {
if (ui.device->currentText().isEmpty())
Copy link
Member

Choose a reason for hiding this comment

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

I think this will work in an undesirable way if a serial port is selected for the device, and the user then checks the bluetooth box - in this case the serial port device selection will be retained. I think a better way to do this will be to use isBluetoothAddress() here to check if the device is a bluetooth device.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks - that's better than just checking for a device id.

notrege added 2 commits March 7, 2024 16:25
Per Michael's suggestion, use isBluetoothAddress as check before skipping Bluetooth scan. 

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
@notrege
Copy link
Contributor Author

notrege commented Mar 13, 2024 via email

@notrege
Copy link
Contributor Author

notrege commented Mar 13, 2024 via email

Preserve bluetooth address if we have it (don't rescan) and for MacOS save the mount point if we have it.     As best as I can tell, the mount points for USB devices do not change on MacOs regardless of the USB port being used.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
Copy link
Member

@mikeller mikeller left a comment

Choose a reason for hiding this comment

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

This is starting to look good now!

is /dev/tty.usbserial-20030001 and it doesn't change regardless of the \
USB port being used. If it isn't saved, it must be reentered. */ \
if (isBluetoothDevice || isMacOs) \
ui.device->setCurrentText(qPrefDiveComputer::device##num()); \
Copy link
Member

Choose a reason for hiding this comment

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

I think it will be better to set the device by index, like how it is done in https://github.com/subsurface/subsurface/pull/4120/files#diff-a0bde534c60cabf020b85f0079e0a8d567f5465514e8a59629b3a50a228d17f9L159 - this way, if the remembered device does not currently exist (i.e. the dive computer is not present / detected) the device will be cleared.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The change I made in enableBluetoothMode() depends on the value of ui.device->currentText(). Consequently, it must be set before enableBluetoothMode is called (via ui.bluetoothMode->setChecked(). If bluetoothMode is not checked, enableBluetoothMode sets the device index to -1. Consequently, either the device index must be set both before and after enableBluetoothMode(), or we need a different flag, such as setting CurrentText, for enableBluetoothMode to skip bluetooth scanning.

Copy link
Member

Choose a reason for hiding this comment

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

The change I made in enableBluetoothMode() depends on the value of ui.device->currentText(). Consequently, it must be set before enableBluetoothMode is called (via ui.bluetoothMode->setChecked().

Fully agreed on this part - my point is just that it is probably a better way to set this indirectly, through ui.device->setCurrentIndex(deviceIndex(qPrefDiveComputer::device##num())) (might also need a QCoreApplication::processEvents() to get ui.device->currentText() to update).

If bluetoothMode is not checked, enableBluetoothMode sets the device index to -1.

Good point, I had not considered the case of remembering the non-bluetooth devices on MacOS.
I suspect that the right thing there is to add another refinement to enableBluetoothMode(), to only set the index to -1 on disabling bluetooth if the selected device is a bluetooth device - equivalent to what you are doing when enabling bluetooth.

ui.bluetoothMode->setChecked(isBluetoothDevice); \
if (ui.device->currentIndex() == -1 || (isBluetoothDevice && !isMacOs)) \
/* macOS seems to have a problem connecting to remembered bluetooth devices if it hasn't already had a connection in the current session */ \
if (ui.device->currentIndex() == -1 || isBluetoothDevice) \
Copy link
Member

Choose a reason for hiding this comment

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

/* macOS seems to have a problem connecting to remembered bluetooth devices if it hasn't already had a connection in the current session */ \
if (ui.device->currentIndex() == -1 || isBluetoothDevice) \
ui.device->setCurrentIndex(deviceIndex(qPrefDiveComputer::device##num())); \
if (isMacOs) { \
Copy link
Member

Choose a reason for hiding this comment

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

Not really required for this, but since you're already testing this with MacOS: Do you want to test if this extra code is still needed for MacOS, or if we can get a simplification by removing this - as stated, this is working fine without the extra code on other platforms.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed this and don't see any adverse effects. Given that I don't have a Windows or Linux platform to test on, it would be very helpful if someone could make sure I didn't break anything on Linux or Windows.

Copy link
Member

@mikeller mikeller Apr 15, 2024

Choose a reason for hiding this comment

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

Happy to test this, but since this code is not run (and potentially even optimised away at build time) on non-MacOS I am fairly confident that removing it won't break anything there.

notrege added 3 commits April 15, 2024 16:19
Removed the MacOs specific code and added comment explaining why ui.device.Text must be set before the ui.bluetoothMode change handler runs.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
Removed blank lines - forgot that blank lines without a continuation \ would break the macro.    Embarrassing to say the least.   I need to figure out how to upload tested code into git.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
Based on Michael's suggestion, added code to refine enableBluetoothMode. 

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
if (!isBluetoothAddress(ui.device->currentText()))
selectRemoteBluetoothDevice();
} else
if (isBluetoothAddress(ui.device->currentText()) || QSysInfo::kernelType() != "darwin")
Copy link
Member

Choose a reason for hiding this comment

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

I did some testing on linux with this, and this is now removing the remembered filesystem path for Garmin devices - so I think it will be better if we remove the || QSysInfo::kernelType() != "darwin" - the fact that we are loading the device from a list of the detected devices with ui.device->setCurrentIndex(deviceIndex(qPrefDiveComputer::device##num())) will make sure that we are not setting a non-existent device.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for testing this - removed Mac specific behavior and any non-Bluetooth mount points will be preserved.

If Bluetooth isn't enabled, don't clear non Bluetooth address.    There was an earlier concern that USB mount point shouldn't be preserved because they may change.   This behavior is different on a Mac where the USB serial mount points tend to be persistent.   Michael tested this on Linux and suggested on saving the mount points for Linux and Windows.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
@notrege
Copy link
Contributor Author

notrege commented Apr 16, 2024 via email

@mikeller
Copy link
Member

Thanks for sticking with this @notrege - the result looks very clean and is a reduction in complexity, which is always welcome.
Tested in linux.

@mikeller mikeller merged commit 77281f8 into subsurface:master Apr 16, 2024
mikeller added a commit to mikeller/subsurface that referenced this pull request Apr 18, 2024
Since the removal of this special case for MacOS was confirmed to be
working in the case of building with bluetooth support in subsurface#4120, we should
probably remove it from the code used when building without bluetooth
support as well.

Signed-off-by: Michael Keller <mikeller@042.ch>
mikeller added a commit that referenced this pull request Apr 21, 2024
Since the removal of this special case for MacOS was confirmed to be
working in the case of building with bluetooth support in #4120, we should
probably remove it from the code used when building without bluetooth
support as well.

Signed-off-by: Michael Keller <mikeller@042.ch>
kmazurki pushed a commit to kmazurki/subsurface that referenced this pull request May 14, 2024
Since the removal of this special case for MacOS was confirmed to be
working in the case of building with bluetooth support in subsurface#4120, we should
probably remove it from the code used when building without bluetooth
support as well.

Signed-off-by: Michael Keller <mikeller@042.ch>
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.

3 participants