WildernessLabs / Meadow_Issues

Public repo for bugs and issues with Meadow
15 stars 0 forks source link

Ethernet sample not working as expected #789

Open NevynUK opened 1 month ago

NevynUK commented 1 month ago

Sample application is the Ethernet_Basics application.

Expected Behaviour

The application should wait for a connection and then then get a web page. The connection may already be present in which case the code should proceed to get the web page anyway.

What Happening

Start the board with the network cable connected.

The following is from the start up sequence for the application.

[core] Creating 'F7CoreComputeV2' instance took 899ms
[core] Device Initialize starting...
[core] Device is configured to use Ethernet for the network interface
[esp] Starting Esp32Coprocessor event handler thread.
[esp] Waiting for event.
[esp] Event received.
[esp] Processing event.
[esp] Simple event, interface 6, event code: 36, status code 0x00000000
[esp] Event data collected, raising event.
[esp] Waiting for event.
[esp] Event received.
[esp] Processing event.
[esp] Simple event, interface 1, event code: 38, status code 0x00000000
[esp] Event data collected, raising event.
[esp] Waiting for event.
[application] Interface: eth0: eth0 Ethernet Up
[core] PlatformOS Initialize starting...
[core] SD Card is configured to 'off'
[core] File system Initialize starting...
[core] Creating instance of MeadowApp...
[core] Creating 'MeadowApp' instance took 68ms
[core] Checking for Hardware property
[core] No Hardware property found in App.
[core] All cloud features are disabled.
[core] Initializing App
[core] Running App
[application] Run...

Key points are:

[esp] Simple event, interface 6, event code: 36, status code 0x00000000

Interface 6 (Ethernet ) is sending event 36 (Connected) to Core.

Note that the application has not started yet.

[esp] Simple event, interface 1, event code: 38, status code 0x00000000

Interface 1 (WiFi) is sending event 38 (NTP Update) to Core.

Next up we get a message from the application:

[application] Interface: eth0: eth0 Ethernet Up

This does not appear to be coming from the application code.

The code then seems to pause waiting for an event as the network information is not displayed which it should do.

Next up, disconnect and then reconnect the network cable to the device. The following output is generated:

[esp] Event received.
[esp] Processing event.
[esp] Simple event, interface 6, event code: 37, status code 0x00000000
[esp] Event data collected, raising event.
[esp] Waiting for event.
[application] Network cable disconnected
[esp] Event received.
[esp] Processing event.
[esp] Simple event, interface 6, event code: 36, status code 0x00000000
[esp] Event data collected, raising event.
[esp] Waiting for event.
[application] Interface: eth0: eth0 Ethernet Up
[application] Network cable connected
[esp] Event received.
[esp] Processing event.
[esp] Simple event, interface 1, event code: 38, status code 0x00000000
[esp] Event data collected, raising event.
[esp] Waiting for event.

Running through the events:

[esp] Simple event, interface 6, event code: 37, status code 0x00000000

Interface 6 (Ethernet) raising event 37 (Disconnected) which is picked up by the application.

Plugging the network cable back in to the device we get the Connected and NTP changed events as described previously.

Further Investigation

This could be an issue in Core where the IsConnected property is not being set correctly.

We should probable adjust the sample code and add an else clause to the statement if (ethernet.IsConnected) to output a message that the WiFi cable is not connected.

It may also be desirable to refactor this sample to take into account cables not being connected at the start and plugged / unplugged during the application run.

ctacke commented 1 month ago

This is the same as this one: https://github.com/WildernessLabs/Meadow_Issues/issues/738

IsConnected indicated, on ethernet, if the cable is plugged in. If the ESP knows the state and broadcasts it before the app is up, then Core's perception of the state is unknown. Since it's a boolean, it just picks one - in this case I chose "false" to be that value. Once core is up, it's going to receive events for state change and all is well, but right now Core has no way to query the initial state or to force-trigger the state event (which would effectively run the code as if the cable state changed and set all values and events appropriately.

NevynUK commented 1 month ago

How about using the network information classes and ask the OS if it has an IP address ? These classes eventually call getifaddr (I think that is the name) to get the IP address from the OS.

ctacke commented 1 month ago

IsConnected doesn't indicate an internet connection, it indicates that the physical cable is attached. The underlying OS knows that information (or at least how to get it) because it's capable of sending an event when it changes. We just need one of 2 things for Core:

  1. A way to ad-hoc query the state (a 2-way command-response) or
  2. A way to tell the OS to raise that existing event "right now" with the current state (a one-way command)
NevynUK commented 1 month ago

Isn't IsConnected broader then just Ethernet, what about WiFi and Cell ?

existing event "right now" with the current state

That is what actually happens, it sounds like we have a timing conflict with the connection being raised and the initial property value.

I'm suggesting that we look at using the network interface classes as they should call the getifaddr OS method which should know the state of any network connection. This may mean that we convert the IsConnected property into a method (which as we are heading towards v2 we could do as it is a breaking change) so it is an ideal time to do this.

I would also think that using the network interface classes would give us better cross platform compatibility as fixing the event on F7 just fixes that platform.

Has anyone tested this on a Pi ?

halyssonJr commented 1 month ago

Workaround

Before starting the App, please put it on Task.Run() to wait for the first connection.

            while (ethernet.IsConnected == false || ethernet.IpAddress.ToString() == "255.255.255.255")
            {
                // throw new Exception($"Cannot connect to network: Connection Failed");
                Console.WriteLine($"Connecting to network ...");
                await Task.Delay(5000);
            }