ModusToolbox, with the release of the AnyCloud libraries, provides a great platform to seamlessly develop Wi-Fi based projects with the PSoC 6 MCU and 43xxx Wi-Fi + Bluetooth combo devices. AnyCloud is a framework for IoT application development that is not tied to a specific cloud provider or management tool. AnyCloud libraries range from those that help connect to a network to those that help accomplish advanced functionality like Over-the-Air updates and Wi-Fi offload assistants for conserving MCU power. In this blog post, we will be going through Wi-Fi Connection Manager (WCM) which will help reduce the overhead in establishing and maintaining network connections in your IoT application.

 

We already have Wi-Fi Host Driver (WHD) for handling the common connection tasks such as scanning for an AP, associating with an AP, disconnecting from it etc.; So you might think why to have another library that performs similar functions. The answer is simple, it is to make an IoT developer’s life easier! When you are developing, let’s say an MQTT application, before calling your MQTT APIs you need to ensure you have initialized your Wi-Fi device to a known state, initialized lwIP network stack, joined a Wi-Fi network, and added that interface to your lwIP network stack. Additionally, you need to have a full understanding of each library, making it a time-consuming exercise for a beginner to get started. WCM accomplishes these functions in just two APIs and provides support for error handling in case of handshake or DHCP timeouts on top of that!

 

Wait, I know you are not sold on WCM just yet! Let me try to change your mind. I like to think of WCM APIs to be grouped into three categories,

  1. Bare-essentials: These include the init, connect, disconnect, and scan APIs.
  2. Utilities: These include APIs that help you get the MAC and IP address of the device.
  3. Main attractions:
    1. WPS Enrollee: WCM provides support to provision the credentials of the AP using WPS Enrollee in either Push-button (PBC) or PIN mode. There is also a utility API to generate an 8-digit PIN such that the last digit is the checksum of the first 7 digits.
    2. Network link-event notifications: WCM, through a combination of features provided by lwIP and WHD, implements support for notification of link events like disconnection, re-connection, and IP address changes through callbacks.
    3. Scan filters: WCM provides minor add-on to the traditional scan API by incorporating the capability to filter the scan results based on SSID, MAC Address, frequency bands, and RSSI.
    4. Preset configuration of lwIP and Mbed TLS: When you add the WCM library to your application in ModusToolbox, it adds IoT libraries like lwIP, Secure Sockets, Wi-Fi Middleware Core (WMC), WHD, and other supporting libraries. One library of note is the WMC, it provides the glue layer that interfaces network stack (lwIP) with the network interface (WHD) and sample configuration files for lwIP, Mbed TLS, and FreeRTOS that meets the requirements of most IoT applications. If you want to make changes to these configurations, you can make a copy of these files, make your changes, and place them in the root directory of the application.

There are a few things to note when using WCM,

  1. WCM requires the RTOS scheduler to be started before calling the init API.
  2. WCM middleware uses a worker thread to enqueue notification events callback, scan callback, and error-checking handlers. Although the callbacks are registered in the application, they execute under the context of this worker thread.
  3. The WPS functionality is handled in another thread. The WCM worker thread waits until the WPS thread obtains the AP credentials or times out.
  4. The link-events are received by the thread created by WHD which in turn communicates the nature of the event to the WCM worker thread.

 

We have two code examples that will help you get started with evaluating the WCM middleware, which is our next topic of discussion.

 

Using the scan filters from WCM

 

WCM provides the capability to filter the scan result based on a preset type of filter and filter parameter value. You can filter based on SSID, MAC Address, frequency band which the AP is occupying, and the RSSI of the AP. The cy_wcm_start_scan() takes in three parameters, the function pointer to the scan callback which receives the scan results, pointer to a user-defined data, and the scan filter configuration structure. The scan filter configuration structure has a member to specify the type of filter to apply and a member to specify the value of the filter parameter. An interesting use-case for using the SSID scan filter can be to determine the type of AP security to pass to cy_wcm_connect_ap(), thereby avoiding the need to figure it out manually.

 

The scan callback is executed by WCM worker thread every time it is notified by WHD that a scan result is available. One interesting thing to note here is that the scan API is non-blocking and if you call cy_wcm_start_scan(), it doesn’t initiate another scan if the previous scan isn’t completed. You will need to call cy_wcm_start_scan() again after the last scan has completed. The scan callback provides a parameter that lets you know about the status of the scan which you can use to sequence the successive calls to scan API. You can use task notifications if you are using FreeRTOS as shown in the figure below.

 

block_diagram_scan.jpg

 

The mtb-example-anycloud-wifi-scan example also switches between different types of scan filters on every button press. The button press events are indicated to the scan task through task notifications. The parameters used in each scan filter can be specified in a header file.

 

Using the WPS Enrollee to obtain AP credentials

WPS makes it easy to connect your IoT device to the AP without having to provide the SSID and password, by either pressing a push-button (PBC) or keying in the generated PIN in the router. A snippet showcasing how to use the APIs for WPS Enrollee is provided below.

 

    /* Stores the credentials obtained through WPS.*/
    cy_wcm_wps_credential_t credentials[MAX_WIFI_CREDENTIALS_COUNT];
    cy_wcm_wps_config_t wps_config;
    cy_wcm_connect_params_t connect_param;
    cy_wcm_ip_address_t ip_addr;


    /* Initialize the Wi-Fi device as a STA.*/
    cy_wcm_config_t config = {.interface = CY_WCM_INTERFACE_TYPE_STA};


    char pin_string[CY_WCM_WPS_PIN_LENGTH];
    uint16_t credential_count = MAX_WIFI_CREDENTIALS_COUNT;


    /* Configure the mode of WPS as CY_WCM_WPS_PBC_MODE.*/
    wps_config.mode = CY_WCM_WPS_PBC_MODE;


    /* Stores the PIN used for WPS. It is unused when PBC mode is employed.*/
    wps_config.password = pin_string;


    /* Initialize Wi-Fi device, Wi-Fi transport, and lwIP network stack.*/
    result = cy_wcm_init(&config);


    result = cy_wcm_wps_enrollee(&wps_config, &enrollee_details, credentials, 
                                 &credential_count);


    /* Copy credentials  obtained through WPS and connect to AP.*/
    memcpy(connect_param.ap_credentials.SSID, credentials->ssid, sizeof(credentials->ssid));
    memcpy(connect_param.ap_credentials.password, credentials->passphrase, 
           sizeof(credentials->passphrase));
    connect_param.ap_credentials.security = credentials->security;
    result = cy_wcm_connect_ap(&connect_param, &ip_addr);

 

Please note that the cy_wcm_wps_generate_pin () is needed only when WPS PIN mode is used as shown in the snippet below.

 

    /* Configure the mode of WPS as CY_WCM_WPS_PIN_MODE.*/
    wps_config.mode = CY_WCM_WPS_PIN_MODE;


    /* Here, the WPS PIN is generated by the device. the user has to enter the 
     * pin in the AP to join the network through WPS. Call this API only when
     * WPS PIN mode is configured.
     */
    cy_wcm_wps_generate_pin(pin_string);


    /* Stores the PIN used for WPS. It is unused when PBC mode is employed.*/
    wps_config.password = pin_string;

 

As per the standard, the device scans and tries to connect to the WPS-enabled AP for a duration of 120 s, after which it times out. So, make sure your device is close to the router when cy_wcm_wps_enrollee() is called. Once the credentials are obtained, you can connect to the AP using cy_wcm_connect_ap().

 

We discussed about the link event notifications and re-connection in the previous section. You need to register a network event callback using cy_wcm_register_event_callback() to enable the middleware to inform the application about the nature of event that has occurred. You can register this callback just after cy_wcm_init() or later, but the notifications are received in the callback only after connecting to an AP. The flow chart below summarizes the steps you need to follow in configuring WPS enrollee in your application.

block_diagram_wps.jpg

 

All these features are showcased in mtb-example-anycloud-wps-enrollee code example which you can use as a reference and build more functionality on top of it. The example uses the user button to notify the WPS enrollee task to connect to available networks over WPS. The WPS mode can be configured in a header file (wps_enrollee_task.h). After connecting to the network, the example again waits for notification. Each time you press the button, the task receives a notification, disconnects from the network, and repeats the process again.

 

What's in store?

In this release, WCM provides support for STA mode, IPv4 and IPv6, and WPS Enrollee. In our next releases, we will be adding support for SoftAP, concurrent AP/STA operation, WPS Registrar, and much more! You can also go and explore other interesting libraries that can help in your IoT application development!  You can refer to our AnyCloud code examples in Cypress GitHub repository for reference. Have fun with AnyCloud and ModusToolbox!