Open munir-zin opened 8 months ago
You do have to disconnect before going into AP mode and disable AP mode before connecting. Not sure if that helps. If not, please provide detailed instructions for how to reproduce the problem. Thanks, —DaveOn Mar 21, 2024, at 4:29 AM, munir-zin @.***> wrote: Hi, I am facing issues setting both modes (AP and STA) of picow. When I try to setup AP mode 1st and then try a connection to router in STA mode, I get following error.
H idrensber, Thank you for your response. I actually want to put the device in both modes simultaneously. I am trying to achieve following:
Can you please let me know if I can achieve this using these CYW43-driver API?
I have achieved this using pico_sdk link. Now I want to achieve this using Zephyr environment.
H idrensber, Thank you for your response. I actually want to put the device in both modes simultaneously. I am trying to achieve following:
- Start device in STA mode and try to connect to the provided network.
- If connection is fail, start AP mode and also keep trying to reconnect.
- User can connect through this AP and a webpage should be displayed to the user with SSID and Password settings.
- User can update these fields and device can connect to these new credentials.
Can you please let me know if I can achieve this using these CYW43-driver API?
I have achieved this using pico_sdk link. Now I want to achieve this using Zephyr environment.
The driver that our Zephyr binding depends on as a submodule (https://github.com/georgerobotics/cyw43-driver.git) does not support simultaneously being in STA and AP mode. This is the same driver that's provided with the Pico SDK. If it did support simultaneous AP and STA, I would have passed that ability along in the Zephyr binding. I thought that the reason for this is because the WiFi module itself does not support it.
If you believe that this is an artificial limitation, you can experiment with removing the check that results in those error messages.
Hi, The wifi module supports both modes simultaneously, as I have done work on it using pico_sdk. There are certain conditions to synchronise them, e.g., if the device is in a connecting state, you can not perform scanning at that particular moment, and vice versa. I will check your code by removing the conditions you suggested and updating you on the results.
I am also facing another issue related to AP mode. When I try to connect a client device to AP mode of PicoW, It does not get IP address and no event for "AP_STA_Connected" is triggered.
When I was writing the code that prevented simultaneous AP and STA modes, I do remember thinking that sometimes I had both working simultaneously, so you could be right (I'd need to check the module spec to be sure).
I believe that you are correct that no IP address is set up when it goes into AP mode. I suspect that most people would want the AP network to have a DHCP server, but some may want static addresses. That is really part of the example app, not the driver, though.
If you want to enhance the sample application so that it can set up the IP network on the AP-mode network, I'd be happy to accept those changes. If you can get the simultaneous AP and STA mode working reliably, I'd be happy to take that too.
Thanks for the update. I will try both of these for my application, and once tested, I will share them with you.
I have updated the code to make both modes work, and I did it. Following code sections are commented (in file: zephyr_cyw43_drv.c
:
function name: zephyr_cyw43_mgmt_connect
// if ((cyw43_state.itf_state >> CYW43_ITF_STA) & 1) {
// int link_status=cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA);
// if (link_status == CYW43_LINK_JOIN || link_status == CYW43_LINK_NONET) {
// LOG_ERR("Already connected.\n");
// rv = -EAGAIN;
// return rv;
// }
// }
// if ((cyw43_state.itf_state >> CYW43_ITF_AP) & 1) {
// LOG_ERR("Please disable access point mode before initiating a client connection.\n");
// rv = -EBUSY;
// return rv;
// }
Function name:zephyr_cyw43_mgmt_ap_enable
// if ((cyw43_state.itf_state >> CYW43_ITF_STA) & 1) {
// int link_status=cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA);
// if (link_status == CYW43_LINK_JOIN || link_status == CYW43_LINK_NONET) {
// LOG_ERR("Currently connected as a client. Please disconnect before enabling AP.\n");
// rv = -EBUSY;
// return rv;
// }
// }
I also added two event raise to detect AP mode enabled or disabled.
case ZEPHYR_CYW43_REQ_ENABLE_AP:
err = zephyr_cyw43_enable_ap(zephyr_cyw43_device);
if (err) { LOG_ERR("Enable AP returned error %d\n", err); }
wifi_mgmt_raise_ap_enable_result_event(zephyr_cyw43_device->iface, err);
break;
case ZEPHYR_CYW43_REQ_DISABLE_AP:
err = zephyr_cyw43_disable_ap(zephyr_cyw43_device);
if (err) { LOG_ERR("Disable AP returned error %d\n", err); }
wifi_mgmt_raise_ap_disable_result_event(zephyr_cyw43_device->iface, err);
break;
Now I am having issue of assigning IP address to client device when connecting to AP mode. I used below code from zephyr/subsys/net/lib/dhcpv4/dhcpv4_server.c
, but it has no impact. I would appreciate if you can suggest me some tutorial or guide for this mechanism.
struct in_addr baseAddr = {{{192, 168, 4, 1}}};
net_dhcpv4_server_start(iface, &baseAddr);
As you discovered, there is a DHCP server in the core codebase, but it seems to be really poorly documented (Google search didn't turn up anything at all, really).
It will start by putting "CONFIG_NET_DHCPV4_SERVER=y" in the prj.conf file, but beyond that, I'm not really sure. I think the best "documentation" may be to just look at the code, so do a search like this:
fgrep CONFIG_NET_DHCPV4_SERVER -r zephyrproject/zephyr
You'll also need to find a way to start and stop the server at runtime, since you'll only want it running when the AP is enabled. One of my colleagues recently implemented something using the server, so I'll see if I can find more info from him about how to integrate it into the application.
I am getting error for dhcp server <err> net_dhcpv4_server: Address pool does not belong to the interface subnet.
I am settingup like this
struct net_if *iface = net_if_get_default();
uint8_t gateway_addr[] = {192, 168, 4, 1};
uint8_t netmask_addr[] = {255, 255, 255, 0};
iface->config.ip.ipv4->gw.s_addr = htonl(*(uint32_t *)gateway_addr);
iface->config.ip.ipv4->netmask.s_addr = htonl(*(uint32_t *)netmask_addr);
struct in_addr baseAddr = {{{192, 168, 4, 1}}};
net_dhcpv4_server_start(iface, &baseAddr);
I am getting "Network Interface is not configured".
I have configured the network interface by setting up following configurations in prj.conf
.
CONFIG_NETWORKING=y
CONFIG_NET_CONFIG_INIT_TIMEOUT=60
CONFIG_NET_CONFIG_AUTO_INIT=y
CONFIG_NET_CONFIG_NEED_IPV4=y
The error logs are:
*** Booting Zephyr OS build v3.6.0 ***
[00:00:02.584,000] <inf> net_config: Initializing network
[00:00:02.584,000] <inf> net_config: Waiting interface 1 (0x3ffb2508) to be up...
[00:00:02.585,000] <err> esp32_wifi: Failed to send packet
[00:00:02.586,000] <err> esp32_wifi: Failed to send packet
[00:00:02.586,000] <err> esp32_wifi: Failed to send packet
[00:00:02.586,000] <inf> net_config: Interface 1 (0x3ffb2508) coming up
[00:00:02.587,000] <err> esp32_wifi: Failed to send packet
[00:00:02.587,000] <inf> net_config: Running dhcpv4 client...
[00:00:03.587,000] <err> esp32_wifi: Failed to send packet
[00:00:04.588,000] <err> esp32_wifi: Failed to send packet
[00:00:11.588,000] <err> esp32_wifi: Failed to send packet
[00:00:16.588,000] <err> esp32_wifi: Failed to send packet
[00:00:24.589,000] <err> esp32_wifi: Failed to send packet
[00:00:41.589,000] <err> esp32_wifi: Failed to send packet
[00:00:50.588,000] <err> net_config: Timeout while waiting network setup
[00:00:50.588,000] <err> net_config: Network initialization failed (-116)
When I try to connect client device, then error logs are:
[00:02:49.293,000] <wrn> net_if: iface 0x3ffb2508 is down
[00:02:49.293,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:02:51.209,000] <wrn> net_if: iface 0x3ffb2508 is down
[00:02:51.209,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:02:53.224,000] <wrn> net_if: iface 0x3ffb2508 is down
[00:02:53.224,000] <err> net_dhcpv4_server: Failed to send ICMP probe
[00:02:58.027,000] <wrn> net_if: iface 0x3ffb2508 is down
[00:02:58.027,000] <err> net_dhcpv4_server: Failed to send ICMP probe
Hi,
I'm actually having problems with AP mode too. I'd honestly not tested it much before (I only really checked to see if it advertised an SSID and that another client could connect to it). I'm going to look into this further, as I'm doing something right now where the AP mode would be important. I'll cross-check what I do with an ESP32 module just to make sure that this isn't a generic problem with Zephyr and Zephyr configuration vs. a problem with the wifi module and driver.
This is the code I am trying to achieve the functionality of.
I am using PicoW and ESP32 devices to setup WiFIManager. I am starting device in AP and STA both modes simultaneously. When I try to connect a client device, I am getting these issue:
NET_EVENT_WIFI_AP_ENABLE_RESULT
is triggered.NET_EVENT_WIFI_AP_STA_CONNECTED
.bool IS_AP_ENABLED = false;
void enableApMode(void)
{
LOG_DBG("Enabling AP Mode.");
struct net_if * netifInterface = net_if_get_default();
struct in_addr gateway_addr = {192, 168, 4, 1};
struct in_addr netmask_addr = {255, 255, 255, 0};
struct in_addr baseAddr = gateway_addr;
LOG_DBG("Gateway: %" PRIu32 ", Netmask: %" PRIu32 "", gateway_addr.s_addr, netmask_addr.s_addr);
net_if_ipv4_set_netmask(netifInterface, &netmask_addr);
net_if_ipv4_set_gw(netifInterface, &gateway_addr);
// netifInterface->config.ip.ipv4->gw.s_addr = htonl(*(uint32_t *)gateway_addr);
// netifInterface->config.ip.ipv4->netmask.s_addr = htonl(*(uint32_t *)netmask_addr);
struct wifi_connect_req_params wifiConfig = {
.ssid = (const uint8_t *)AP_SSID,
.ssid_length = strlen(AP_SSID),
.psk = (const uint8_t *)AP_PSK,
.psk_length = strlen(AP_PSK),
.band = WIFI_FREQ_BAND_2_4_GHZ,
.channel = WIFI_CHANNEL_ANY,
};
if (strlen(AP_PSK) > 0)
{
wifiConfig.security = WIFI_SECURITY_TYPE_PSK;
}
else
{
wifiConfig.security = WIFI_SECURITY_TYPE_NONE;
}
if (net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, netifInterface, &wifiConfig, sizeof(struct wifi_connect_req_params)))
{
LOG_ERR("AP Mode Request Failed\n");
}
netifInterface = net_if_get_default();
if (!netifInterface)
{
printk("Error: No network interface found!\n");
return;
}
printk("DHCPv4 server started...\n");
net_dhcpv4_server_start(netifInterface, &baseAddr);
}
void connectWiFi(void)
{
struct net_if * netifInterface = net_if_get_default();
struct wifi_connect_req_params wifiConfig =
{
.ssid = (const uint8_t *)SSID,
.ssid_length = strlen(SSID),
.psk = (const uint8_t *)PSK,
.psk_length = strlen(PSK),
.band = WIFI_FREQ_BAND_2_4_GHZ,
.channel = WIFI_CHANNEL_ANY,
};
if (strlen(PSK) > 0)
{
wifiConfig.security = WIFI_SECURITY_TYPE_PSK;
}
else
{
wifiConfig.security = WIFI_SECURITY_TYPE_NONE;
}
wifiConfig.band = WIFI_FREQ_BAND_2_4_GHZ;
wifiConfig.mfp = WIFI_MFP_OPTIONAL;
LOG_DBG("Connecting to SSID: %s\n", wifiConfig.ssid);
if (net_mgmt(NET_REQUEST_WIFI_CONNECT, netifInterface, &wifiConfig, sizeof(struct wifi_connect_req_params)))
{
LOG_ERR("WiFi Connection Request Failed\n");
}
}
void handleWiFiEvents(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface)
{
switch (mgmt_event)
{
case NET_EVENT_WIFI_CONNECT_RESULT:
const struct wifi_status *status = (const struct wifi_status *)cb->info;
LOG_DBG("NET_EVENT_WIFI_CONNECT_RESULT");
if (status->status)
{
LOG_ERR("WiFi connection failed (%d).", status->status);
if (!IS_AP_ENABLED)
enableApMode();
else
connectWiFi();
}
break;
case NET_EVENT_WIFI_DISCONNECT_RESULT:
LOG_DBG("NET_EVENT_WIFI_DISCONNECT_RESULT");
if (!IS_AP_ENABLED)
enableApMode();
else
connectWiFi();
break;
case NET_EVENT_WIFI_AP_ENABLE_RESULT:
LOG_DBG("NET_EVENT_WIFI_AP_ENABLE_RESULT");
IS_AP_ENABLED = true;
connectWiFi();
break;
case NET_EVENT_WIFI_AP_DISABLE_RESULT:
LOG_DBG("NET_EVENT_WIFI_AP_DISABLE_RESULT");
IS_AP_ENABLED = false;
break;
case NET_EVENT_WIFI_AP_STA_CONNECTED:
LOG_DBG("NET_EVENT_WIFI_AP_STA_CONNECTED");
break;
case NET_EVENT_WIFI_AP_STA_DISCONNECTED:
LOG_DBG("NET_EVENT_WIFI_AP_STA_DISCONNECTED");
break;
case NET_EVENT_IPV4_ADDR_ADD:
LOG_DBG("NET_EVENT_IPV4_ADDR_ADD");
break;
default:
break;
}
}
void main()
{
LOG_DBG("Setting up WiFi on %s\n", CONFIG_BOARD);
net_mgmt_init_event_callback(&cbWiFi, handleWiFiEvents, WIFI_EVENT_MASK);
net_mgmt_init_event_callback(&cbIPV4, handleWiFiEvents, IPV4_EVENT_MASK);
net_mgmt_add_event_callback(&cbWiFi);
net_mgmt_add_event_callback(&cbIPV4);
// enableApMode();
connectWiFi();
LOG_DBG("WiFi Ready...\n\n");
}
Thanks for sharing your code. I'm actually having trouble getting AP mode to work correctly on the Pico W (nevermind the simultaneous STA mode). Good to see that you have an ESP32 to cross-check with as well. Wifi+Zephyr is obviously a lot more mature on the ESP32 (which I mistakenly called "STM32" in my previous message).
Please do share your results after testing it.
Hi, I'm still looking at this. I pushed some changes that allow the repository to be built for esp32 for comparison. I'm currently working on trying to get a feature in that will optionally allow one to start the DHCP server from the driver in AP mode. I'm also going to be adding the ability to make the DHCP client startup from the driver optional (I think that for both AP mode and STA mode, driver startup of the DHCP client/server should be optional, because some people may want to start those from the application instead).
One thing I noticed while doing this that may help what you're doing: The driver starts the interface up in "dormant" mode. You need to take it out of dormant mode to use it with:
net_if_dormant_off(iface);
I was doing that for STA mode upon connect, but I was not doing it upon enablement of AP mode.
Hi, I just pushed some changes that may help. In addition to the item I mentioned above, I also noticed that the call to cyw43_send_ethernet() has an "interface type" parameter that needs to be set to CYW43_ITF_AP if you're in AP mode or else packet sends don't actually work. I also added an option to have the driver start up a DHCP server when AP mode is initiated.
Hi, I have integrated the DHCP server and trying to connect client. The server is assigning the correct IP address but the gateway or router information is missing. When a device is connected to hotspot/router, it get IP address, gateway and subnet. In this case IP address and subnet are assigned, but gateway is 0.0.0.0. What could be the possible reason?
Hi, I have integrated the DHCP server and trying to connect client. The server is assigning the correct IP address but the gateway or router information is missing. When a device is connected to hotspot/router, it get IP address, gateway and subnet. In this case IP address and subnet are assigned, but gateway is 0.0.0.0. What could be the possible reason?
The reason is that setting the gateway just hasn't been implemented yet. There was a PR (https://github.com/beechwoods-software/zephyr-cyw43-driver/pull/3) submitted regarding this, but the thing I didn't like about it was:
If you'd like to take that PR and make those changes, I'll accept it. Otherwise, I'll eventually do the same.
Hi,
I am trying to write own dhcp server based on lwip apis. I tried to set CYW43_LWIP
variable to 1, so I wan getting a lot of lwip files not found, I also could not lwip files in this repository. Please guide.
Hi, I am trying to write own dhcp server based on lwip apis. I tried to set
CYW43_LWIP
variable to 1, so I wan getting a lot of lwip files not found, I also could not lwip files in this repository. Please guide.
I think you would need to raise that issue with the cyw43-driver project (https://github.com/georgerobotics/cyw43-driver). The purpose of this project is to integrate cyw43-driver with Zephyr for the IP stack, DHCP server, etc. /instead of/ LWIP.
The problem why one can't have AP+STA mode is because of zephyr's limitation. it creates only single netif
instance for same network device. In AP+STA mode, One may desire to set IP for AP mode statically while for STA it should be assigned via DHCP. Because of single netif
instance we can'yt have two set of IPs. There are some macros like NET_DEVICE_DT_INST_DEFINE_INSTANCE
which docs says that it can be used to make multiple netif
instances bound to same network device. I tried it and it did not allow me create multiple instances.
Hi, I am facing issues setting both modes (AP and STA) of picow. When I try to setup AP mode 1st and then try a connection to router in STA mode, I get following error.
Similarly, when I try to connect first and then enable AP mode, I get this error.
NOTE: I am trying to disconnect as well before enabling AP mode.
If I just enable AP mode, it works fine. But When I try to connect a client device with it, the client device does not get any IP address and no event for
NET_EVENT_WIFI_AP_STA_CONNECTED
is received.