Use the aggregator capability

The Wi-Fi hotspot aggregator capability allows an aggregator app to detect and automatically connect to a Wi-Fi hotspot network, performing any required authentication on the user's behalf.

Not applicable

Not applicable

To use the aggregator capability, the app must first initialize the Wi-Fi service and register itself as an aggregator application.

wifi_service_t *wifi_service = NULL;
wifi_aggregator_t *aggregator = NULL;
wifi_result_t ret = WIFI_SUCCESS;

ret = wifi_service_initialize(&wifi_service);
// handle error
...

ret = wifi_aggregator_register(wifi_service, &aggregator, name, true);
// handle error
...
        

The aggregator app learns about any changes in the available networks or the connection state by watching Wi-Fi events. To receive Wi-Fi events, the app needs to get the file descriptor and poll for events.

struct pollfd fds;
int fd = -1; 
          
wifi_service_get_fd(wifi_service, &fd);
fds.fd = fd;
fds.events = POLLRDNORM;
...
poll(&fds, 1, -1);

ret = wifi_service_read_event(wifi_service, &event);
// handle error

wifi_service_get_event_type(event, &event_type);
        
Wi-Fi events are defined in wifi_event_t and include the following event types:
  • WIFI_EVENT_STATION_CONNECTION_STATE
  • WIFI_EVENT_SCAN_RESULTS
  • WIFI_EVENT_AGGREGATOR_PROFILE_ENABLE_CHANGE
  • WIFI_EVENT_AGGREGATOR_LOGIN_TIMEOUT
  • WIFI_EVENT_AGGREGATOR_DEREGISTERED

The WIFI_EVENT_STATION_CONNECTION_STATE event indicates that the Wi-Fi connection state has changed. To determine the current connection state, the app can call wifi_service_event_get_station_connection_state(). The connection state is defined in wifi_station_connection_state_t and can be either WIFI_STATION_CONNECTED or WIFI_STATION_DISCONNECTED. If the station is in the connected state, the app can retrieve the service set identifier (SSID), channel, and basic service set identifier (BSSID) of the connection by calling wifi_station_connection_get_ssid(), wifi_station_connection_get_channel(), and wifi_station_connection_get_bssid().

The aggregator app must also log in to the Wi-Fi hotspot within 60 seconds of receiving the connected event; otherwise, it loses the connection. If authentication is successful, the aggregator app notifies the Wi-Fi service by calling wifi_aggregator_login_complete().

switch(event_type) {
    case WIFI_EVENT_STATION_CONNECTION_STATE:
        wifi_service_event_get_station_connection_state(event, 
                                                        &connection_state);

        if (connection_state == WIFI_STATION_CONNECTED) {   
            wifi_station_connection_get_ssid(ssid);
            wifi_station_connection_get_channel(&channel);
            wifi_station_connection_get_bssid(bssid);
            
            // log in
            ...
            
            wifi_aggregator_login_complete(aggregator, 
                                           WIFI_AGGREGATOR_LOGIN_SUCCESS);
            ...            
            
        

The WIFI_EVENT_SCAN_RESULTS event tells your app new scan results are available. The app can query the scan results by calling wifi_get_scan_results(). There are two scan report types: WIFI_SCAN_REPORT_UNKOWN and WIFI_SCAN_REPORT_CONNECTION. Your app should watch for WIFI_SCAN_REPORT_CONNECTION, which reports connection and network selection related results. The app can retrieve report details by calling functions prefixed with wifi_get_scan_result_, such as wifi_get_scan_result_ssid().

When an app registers for the Wi-Fi aggregator service, the service creates an empty profile for the app. The app must configure and enable the profile. For example, the app needs to set the SSID and security type by calling wifi_aggregator_set_profile_ssid() and wifi_aggregator_set_profile_security_type().

When the profile configuration is complete, the app enables the profile by calling wifi_aggregator_enable_profile(). When every step completes successfully, the app notifies the Wi-Fi service that a network match has been found by calling wifi_aggregator_network_match() so that the Wi-Fi service tries to connect to the network using the new profile. The wifi_aggregator_network_match() call also serves as a keepalive for the aggregator app, and should be called when processing connection scan results. Otherwise, the aggregator app may be deregistered from the Wi-Fi service.

You may want to retrieve user configured profiles on the device to see if any of the SSIDs match the hotspots your app supports. If so, you may want to prompt the user to delete those profiles and use the aggregator app to log in automatically.

When the app finishes processing the scan results, it must free the memory allocated by calling wifi_free_scan_results().

int num = 0;            
case WIFI_EVENT_SCAN_RESULTS:
{
    ret = wifi_get_scan_results(&results, &report_type, &num);
    // handle error
    ...
    
    if (report_type == WIFI_SCAN_REPORT_CONNECTION) {
        if (!is_profile_configured) {
            for (index = 1; index <= num; index++) {
                wifi_get_scan_result_ssid(results, index, ssid);
                wifi_get_scan_result_bssid(results, index, bssid);
                ...
                
                // set profile
                wifi_aggregator_set_profile_ssid(aggregator, ssid);
                // set the required security type, 
                // e.g., WIFI_SECURITY_TYPE_PSK
                wifi_aggregator_set_profile_security_type(aggregator, 
                                                          WIFI_SECURITY_TYPE_PSK);
                ...
        }
        wifi_aggregator_network_match(aggregator, true);
    }        
    ret = wifi_free_scan_results(results);
    // handle error
    ...
    results = NULL;
}    
        

The WIFI_EVENT_AGGREGATOR_PROFILE_ENABLE_CHANGE event indicates that the status of the aggregator profile has changed. The app can call wifi_service_event_get_aggregator_profile_enable_state() to determine the status of the profile; that is, whether the profile is enabled or disabled. This call returns two flags: enable and user_enable. The aggregator profile is enabled only when both flags are TRUE.

case WIFI_EVENT_AGGREGATOR_PROFILE_ENABLE_CHANGE:
ret = wifi_aggregator_get_profile_enable_status(aggregator, 
                                                &enable, 
                                                &user_enable);
// handle error
...
        

The WIFI_EVENT_AGGREGATOR_LOGIN_TIMEOUT event indicates that the hotspot login timer has expired. When the Wi-Fi network is connected, the Wi-Fi service allows the app 60 seconds to log in to the hotspot. When the login completes, the app must call wifi_aggregator_login_complete() to notify the Wi-Fi service of the completion. If the app fails to do so, the Wi-Fi network is disconnected and this event is sent. If the app needs more time to complete a login, it can send a status of WIFI_AGGREGATOR_LOGIN_NEED_MORE_TIME when calling wifi_aggregator_login_complete().

Before closing the app, you must call wifi_aggregator_deregister() and wifi_service_shutdown() to deregister the app from the Wi-Fi service and clean up.

wifi_aggregator_deregister(wifi_service, aggregator);
aggregator = NULL;
wifi_service_shutdown(wifi_service); 
wifi_service = NULL;
        

Here's a complete code sample that illustrates how a simple aggregator app may work. For demonstration, this code sample simulates a login scenario by prompting the user for login information and declaring the login successful.

Not applicable

Not applicable

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/pps.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <string.h>
            
#include "wifi/wifi_service.h"

wifi_result_t ret = WIFI_SUCCESS;
wifi_aggregator_t *aggregator = NULL;
wifi_service_event_t * event = NULL;
wifi_event_t event_type;
wifi_station_connection_state_t connection_state;
struct pollfd fds;

int fd = -1;
int rc = 0;
bool is_profile_configured = false;

int set_and_enable_aggregator_profile(wifi_aggregator_t *aggregator)
{
    char ssid[WIFI_MAX_SSID_BUFFER_LEN];
    memset(ssid, 0x0, sizeof(ssid));

    // set profile
    printf("Set the hotspot aggregator profile\n");

    printf("Enter SSID:\n");
    gets(ssid);
    ret = wifi_aggregator_set_profile_ssid(aggregator, ssid);
    if (ret != WIFI_SUCCESS) {
        return -1;
    }

    printf("Select the security type:\n");
    printf("1 - OPEN\n");
    printf("2 - WPA-PSK\n");
    printf("3 - WPA-PEAP\n");
    printf("4 - WEP\n");
    gets(input_str);
    option = atoi(input_str);

    switch(option) {
    case 1:
       ret = 
         wifi_aggregator_set_profile_security_type(aggregator, 
                                     WIFI_SECURITY_TYPE_OPEN);
        break;
    case 2:
       ret = 
         wifi_aggregator_set_profile_security_type(aggregator, 
                                      WIFI_SECURITY_TYPE_PSK);
        if (ret == WIFI_SUCCESS) {
            char psk_key[65];
            memset(psk_key, 0x0, sizeof(psk_key));
            printf("Enter PSK password:\n");
            gets(psk_key);
            ret = wifi_aggregator_set_profile_security_psk_passphrase(aggregator, psk_key);
        }
        break;
    case 3:
        ret = wifi_aggregator_set_profile_security_type(aggregator, WIFI_SECURITY_TYPE_PEAP);
        if (ret == WIFI_SUCCESS) {
            char username[65];
            char password[65];

            memset(username, 0x0, sizeof(username));
            memset(password, 0x0, sizeof(password));

            printf("Enter username:\n");
            gets(username);
            printf("Enter password:\n");
            gets(password);
            ret = wifi_aggregator_set_profile_security_user_name_password(aggregator, username, password);
        }
        break;
    case 4:
        ret = wifi_aggregator_set_profile_security_type(aggregator, WIFI_SECURITY_TYPE_WEP);
        if (ret == WIFI_SUCCESS) {
            char wep_key[27];
            memset(wep_key, 0x0, sizeof(wep_key));
            printf("Enter WEP password:\n");
            gets(wep_key);

            /* Use a C string for wep key */
            ret = wifi_aggregator_set_profile_security_wep_key_str(aggregator, wep_key);

            /* To use a uint8 array for wep key:
            ret = wifi_aggregator_set_profile_security_wep_key(aggregator, (uint8_t *)wep_key, strlen(wep_key));
             */
        }
        break;
    default:
        printf("Invalid option. Use OPEN");
        ret = wifi_aggregator_set_profile_security_type(aggregator, WIFI_SECURITY_TYPE_OPEN);
        break;
    } // end of switch

    if (ret != WIFI_SUCCESS) {
        printf("Failed to set security.\n");
        return -1;
    } 
    return 0;
}

int sample_aggregator_app()
{
    char name[WIFI_MAX_AGGREGATOR_NAME_LEN];
    char ssid[WIFI_MAX_SSID_BUFFER_LEN];

    memset(name, 0x0, sizeof(name));
    memset(ssid, 0x0, sizeof(ssid));

    ret = wifi_service_initialize(&wifi_service);
    if (ret != WIFI_SUCCESS) {
        // handle error
    }

    ret = wifi_service_get_fd(wifi_service, &fd);
    if (ret != WIFI_SUCCESS) {
        // handle error
    }

    fds.fd = fd;
    fds.events = POLLRDNORM;
    
    /* Read aggregator profile name */
    printf("Please enter the hotspot aggregator profile name (no longer than %d bytes):\n",
            WIFI_MAX_AGGREGATOR_NAME_LEN-1);
    gets(name);
    
    /* Register as an aggregator application */
    ret = wifi_aggregator_register(wifi_service, &aggregator, 
                                   name, true);
    if (ret != WIFI_SUCCESS) {
        printf("wifi_aggregator_register() failed. [ret=%d]\n", 
               ret);
        wifi_service_shutdown(wifi_service);
        return -1;
    }
    
    while (1) {
        rc = poll(&fds, 1, -1);
            
        if ((rc < 1) ||
            ((fds.revents & POLLRDNORM) == 0)) {
            break;
        }
            
        ret = wifi_service_read_event(wifi_service, &event);
        if(ret != WIFI_SUCCESS) {
           // handle error
        }
            
        wifi_service_get_event_type(event, &event_type);
            
        switch(event_type) {
            case WIFI_EVENT_STATION_CONNECTION_STATE:
                wifi_service_event_get_station_connection_state(event, &connection_state);
    
                if (connection_state == WIFI_STATION_CONNECTED) {
                    int channel = 0;
                    uint8_t bssid[WIFI_BSSID_ADDR_LEN];
                    char username[65];
                    char password[65];
    
                    memset(bssid, 0x0, sizeof(bssid));
                    memset(username, 0x0, sizeof(username));
                    memset(password, 0x0, sizeof(password));
    
                    printf("WIFI_STATION_CONNECTION_STATE_EVENT: state[%d]\n", 
                           connection_state);
    
                    ret = wifi_station_connection_get_ssid(ssid);
                    if (ret != WIFI_SUCCESS) {
                        // handle error
                    }        
            
                    ret = wifi_station_connection_get_channel(&channel);
                    if (ret != WIFI_SUCCESS) {
                        // handle error
                    }
            
                    ret = wifi_station_connection_get_bssid(bssid);
                    if (ret != WIFI_SUCCESS) {
                        // handle error
                    }
            
                    printf("\nWiFi is connected.\nssid: [%s]\tchannel:%d\t"
                           "bssid: [%2x:%2x:%2x:%2x:%2x:%2x]\n",
                           ssid, channel,
                           bssid[0], bssid[1], bssid[2],
                           bssid[3], bssid[4], bssid[5]);
   
                    printf("\nEnter hotspot login username:\n");
                    gets(username);
                    printf("Enter hotspot password:\n");
                    gets(password);
   
                    printf("\nAuthenticating....\n");
                    sleep(2);
   
                    printf("\nDone\n");
   
                    ret = wifi_aggregator_login_complete(aggregator, 
                                                         WIFI_AGGREGATOR_LOGIN_SUCCESS);
                    if (ret != WIFI_SUCCESS) {
                        printf("wifi_aggregator_login_complete() failed. [ret=%d]\n", ret);
                        wifi_aggregator_deregister(wifi_service, aggregator);
                        wifi_service_shutdown(wifi_service);
                        return -1;
                    }
             
                    /* Check if user wants to quit */
                    char answer[16];
                    memset(answer, 0x0, sizeof(answer));
              
                    printf("Quit the hotspot aggregator application?[Y/N]:");
                    gets(answer);
             
                    if (stricmp(answer, "Y") == 0) {
                        // deregister
                        wifi_aggregator_deregister(wifi_service, aggregator);
                        aggregator = NULL;
             
                        // shutdown; clean up
                        wifi_service_shutdown(wifi_service);
                        wifi_service = NULL;
             
                        printf("Bye!\n");
                        return 0;
                    }
                 
                } /* if ((connection_state == WIFI_STATION_CONNECTED) */
                break;
        
            case WIFI_EVENT_SCAN_RESULTS:
                int num = 0;
                char ssid[WIFI_MAX_SSID_BUFFER_LEN];
                wifi_scan_report_t report_type = WIFI_SCAN_REPORT_UNKOWN;
                wifi_scan_results_t *results = NULL;
        
                memset(ssid, 0x0, sizeof(ssid));
        
                /* Read user profiles if needed.
                 * See code sample under "Check user profiles"
                 */
                check_user_profiles();
                
                ret = wifi_get_scan_results(&results, &report_type, &num);
                if (ret != WIFI_SUCCESS) {
                    // handle error
                }
            
                if (report_type == WIFI_SCAN_REPORT_CONNECTION) {
                    if (!is_profile_configured) {
                        printf("Check scan results.\n");
                        /* See code sample under "Receive Wi-Fi events" */
                        check_scan_results(results, num);
                            
                        printf("Set the hotspot aggregator profile\n");
                        if (set_and_enable_aggregator_profile(aggregator) == 0){
                            is_profile_configured = true;
                            wifi_aggregator_enable_profile(aggregator, true);
                        }                           
                    }
                    
                    wifi_aggregator_network_match(aggregator, true);
                }
            
                ret = wifi_free_scan_results(results);
                if (ret != WIFI_SUCCESS) {
                    printf("wifi_free_scan_results() failed. [ret=%d]\n", ret);
                    wifi_aggregator_deregister(wifi_service, aggregator);
                    wifi_service_shutdown(wifi_service);
                    return -1;
                }
                results = NULL;
            
                break;
        
            case WIFI_EVENT_AGGREGATOR_PROFILE_ENABLE_CHANGE:
                bool enable = false;
                bool user_enable = false;
        
                printf("\nWIFI_AGGREGATOR_PROFILE_ENABLE_CHANGE_EVENT\n");
                ret = wifi_aggregator_get_profile_enable_status(aggregator, 
                                                                &enable, 
                                                                &user_enable);
                if (ret != WIFI_SUCCESS) {
                    // handle error
                }
                printf("enable: %d, user_enable: %d\n", enable, user_enable);
                break;    
            case WIFI_EVENT_AGGREGATOR_LOGIN_TIMEOUT:
                printf("\nWIFI_AGGREGATOR_LOGIN_TIMEOUT_EVENT\n");
                break;
            case WIFI_EVENT_AGGREGATOR_DEREGISTERED:
                printf("\nWIFI_AGGREGATOR_DEREGISTERED_EVENT\n");
                break;
            case WIFI_EVENT_IGNORE:
            case WIFI_EVENT_UNKNOWN:
            default:
               break;
        } // end switch      

        wifi_service_free_event(wifi_service, event);
        event = NULL;
    }    
    // deregister
    wifi_aggregator_deregister(wifi_service, aggregator);
    aggregator = NULL;
   
    // shut down and clean up
    wifi_service_shutdown(wifi_service);
    wifi_service = NULL;
    
    printf("Bye!\n");
    return 0;
}       

Last modified: 2015-05-07



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus