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

Reconnect wifiandheadunit #50

Closed
wants to merge 8 commits into from

Conversation

Ioniq3
Copy link
Contributor

@Ioniq3 Ioniq3 commented Feb 11, 2024

With these modifications, the device receives:

If the initial connection between the head unit and the dongle/phone fails due to a timeout or similar issue, the code now retries the entire process after 30 seconds if the channel is not established. This should be sufficient for the majority of head units.

If the Wi-Fi connection between the dongle and the phone is interrupted and not recovered, for example, if you leave the car for a shorter period than the time needed for the car to power off the dongle, the process will attempt to reconnect every 30 seconds to restore communication when you return to the car.

After some tests, it was found that it works better without the "Connect to USB after phone connection is available" e511b7c commit, so please conduct your own tests accordingly.

It's no longer necessary to use an external program as in the previous pull request.

.tv_sec = 30
};

if (setsockopt(server_sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) {
Copy link
Owner

Choose a reason for hiding this comment

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

Curious: If we're using select before accept, how does setting this help or make a difference?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

accept is a unlimited time blocking function as it read information while select can manage a timeout because select only detect that the is information but not read it

@@ -77,6 +77,9 @@ void UsbManager::disableGadget() {
disableGadget(accessoryGadgetName);

Logger::instance()->info("USB Manager: Disabled all USB gadgets\n");

enableGadget(defaultGadgetName);
Copy link
Owner

Choose a reason for hiding this comment

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

Why is this required? We generally want to keep usb disabled until we have the phone connection ready to work around headunit timeouts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it depends of the head unit makes the timeout, in my case, in hyundai, i need to have the usb connect (and disabled and enable) or it will never try again if you enabled after "large" time disabled. In this particular headunit works better without the "Connect to USB after phone connection is available" e511b7c commit ; but maybe it this not general behavior buy I don't have other cars to test.

In my own personalization I managed/test this commit controlled by a enviroment variable with this code:

    if (const char* env_p = std::getenv("HEADUNIT_FIRST")) {
        UsbManager::instance().enableDefaultAndWaitForAccessroy();
    }

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe its easier if file is present in /boot partition, as this can be edited from the pc prior to install the sdcard...

touch /boot/HEADUNIT_FIRST 

Copy link
Contributor Author

@Ioniq3 Ioniq3 Feb 13, 2024

Choose a reason for hiding this comment

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

Yes, it's another way.
So thanks you for your ideas on personalization, I get some of them and add to /etc/init.d/S93aawgd the following lines in my branch personalization:

		xx=$(ls /var/lib/bluetooth/ | awk -F':' '{print $4$5$6 }' | tr [[:upper:]] [[:lower:]] | tr -d '\n')
                export ADAPTER_ALIAS=AndroidAuto_$xx
                export AAWG_WIFI_SSID=AndroidAuto_$xx
                export AAWG_WIFI_PASSWORD=1234567890
		export HEADUNIT_FIRST=1

before start-stop-daemon -S -b -q -m -p "$PIDFILE" -x "/usr/bin/$DAEMON"

Copy link
Owner

Choose a reason for hiding this comment

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

We can have an env file in /boot or somewhere else and source it if that works. We should ideally have a nicer ini config file, but for now env variables might be easier to get started with.

break;
}
}

if ((m_tcp_fd = accept(server_sock, &client_address, &client_addresslen)) < 0) {
Copy link
Owner

Choose a reason for hiding this comment

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

Don't we need to set send and recieve timeouts to the client connection socket so that it closes when the phone goes away after connection?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this break happens when there is data to read before timeout occurs, going out the while to the accept function

@@ -138,13 +161,17 @@ void AAWProxy::handleClient(int server_sock) {
usb_tcp.join();
tcp_usb.join();

should_exit = true;
Copy link
Owner

Choose a reason for hiding this comment

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

Does this help in any way? We've already joined both the threads by now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I was no sure about this variable to control the threads in this moment is necessary to inform or no, you better knows the behavior

@nisargjhaveri
Copy link
Owner

Thanks @Ioniq3 for the PR! I'll try out this soon.

For the first time connection issue, do we really need to restart the TCP server as well? We can maybe just disconnect and retry the bluetooth connection sequence. This way we can still catch connections coming in the few seconds the TCP server will be down for a few seconds with this change.

@Ioniq3
Copy link
Contributor Author

Ioniq3 commented Feb 11, 2024

Thanks @Ioniq3 for the PR! I'll try out this soon.

For the first time connection issue, do we really need to restart the TCP server as well? We can maybe just disconnect and retry the bluetooth connection sequence. This way we can still catch connections coming in the few seconds the TCP server will be down for a few seconds with this change.

Sure, but as I said in my headunit works better without the "Connect to USB after phone connection is available" commit, apart from this you are right that can coincide in time the restart and the connection, if you see another way please go ahead, I don't have experience with c++ development.

@nisargjhaveri
Copy link
Owner

Seems like we're trying to multiple things in this PR.

Thanks for pointing out that in some cases the old flow to connect where we wait for the usb to connect first works better. To support both the flows let's add a configuration option and select which flow to take for initial connection.

Once we have that in, we can work on reconnect if the initial connection fails. I believe both the flows would have slightly different approach to reconnect in the initial connection flow.

Another is, reconnecting when the TCP fails after the Android Auto is connected and started. Fixing this won't have major differences in both the flows and can be done now. We can maybe restrict this PR only to this, and work on the first two parts separately.

Let me know what you think. Really appreciate everyone's effort on this. :)

@Ioniq3
Copy link
Contributor Author

Ioniq3 commented Feb 17, 2024

Thanks Nisarg.

It's a good idea, I have just divided in three branches:

  • select_mode_operation
  • reconnect-firstconnection
  • reconnect-wifiandheadunit // with only the TCP reconnection

@nisargjhaveri
Copy link
Owner

I tried this out, doesn't seem to work very well for me. The connection seems to be closed/killed soon after the usb is connected.

Also, when you said that your headunit works better without "Connect to USB after phone connection is available", is that with these changes? Or even on main, without the reconnection changes it works better without that commit? What happens if it waits for phone connection?

@Ioniq3
Copy link
Contributor Author

Ioniq3 commented Feb 21, 2024

No, i remove all about the first connection (now in the reconnect-firstconnection branch) to divided in three branches as you suggess, only remains the reconnection after tcp stop receiving from phone in this branch

@nisargjhaveri
Copy link
Owner

No, i remove all about the first connection (now in the reconnect-firstconnection branch) to divided in three branches as you suggess, only remains the reconnection after tcp stop receiving from phone in this branch

Yes, I understand that. Thanks a lot for separating the PRs.

The question is, if we don't merge this PR. Does #56 add any value? What is the issue you face with your headunit in current main?

@Ioniq3
Copy link
Contributor Author

Ioniq3 commented Feb 22, 2024

I don't know if it is a special case or not. When I open the car with the key the usb automatically power on, starting the raspberry pi, but the headunit is turn off until i sit and turn on the contact. In the actual behavior if you make some other things like sit down my daughter and some other thing the phone connect to the rpi meanwhile and how the headunit is turn off when i turn on it doesn't work and i have to reboot the rpi (or the usb gadget and aawgd) to make it works. But in the behavior of the usb connection before I don't have that problem and the connection only start when i turn on the headunit independently of the time the rpi was uptime.

@nisargjhaveri
Copy link
Owner

As I mentioned, the current version doesn't seem to work well. It causes the TCP connection to fail just after it connects, if at all for me. Any ideas why this would happen?

Also, #72 makes further chances to initial connection. If it works, there should be lesser need to retry initial connection.

For disconnection after connection is established, this or similar change wouldn't help much either. Even if we successfully detect tcp disconnection, the usb thread would still keep waiting forever. We need to find a way to interrupt that as well.

@Ioniq3
Copy link
Contributor Author

Ioniq3 commented Mar 3, 2024

Yes, I solved the two problems by a hard way restarting usb_gadget and aawgd signaling a external program when I get a problem on usb or tcp disconnection, but this is not the best and ortodoxal way, it is only a black box workaround. I prefer than people with more knowledge, of course than me, continue make investigations to get the issues and the best way to restart tcp and usb by means of the exact situation to improve.

If you want to close the PR I don't have any problem on it.

@nisargjhaveri
Copy link
Owner

See #90, which might help along with couple of other recent changes. Closing this PR for now.

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