Step 4: Roaming Between Access Points

Top  Previous  Next

This and other projects in the Code Examples section are published on our website under the name "test_wln_lib".

 

Finally, here is the coolest example of them all -- the code for a mobile device that roams between several access points that all have the same SSID (name). Typically, you use such a setup to create a larger wireless network. The example from the previous topic would work, but not very well if your device was mobile.

Say, you walk around with your GA1000-based gadget in your pocket. At boot, it would execute wln_start(), which would in turn search for the target wireless network, find several access points, and select the one with the strongest signal. The GA1000 would then latch onto this access point and won't let go until the signal gets so bad that the association is lost. The WLN library would then try to find a better access point to work with. Sounds like there is no problem, right?

Wrong! In practice, you will find that at a certain distance from the access point you get into the "grey area of communications" where the link between your gadget and the access point becomes spotty, but not quite bad enough for the association to fail. And, since the association won't quite fail, your device won't try to find a better access point to link to. Meanwhile, you will experience data delivery delays, unstable comms, etc.

Here is the solution. Additional code in on_sys_timer periodically checks current signal strength (wln.rssi). Whenever it falls below a predefined constant RSSI_THRESHOLD, the code will do wln_rescan() in an attempt to "find a better deal". Rescan result is checked in callback_wln_rescan_result(). If a different and better access point is found, wln_change() will switch your device to using it.

It is important to understand why the program searches for better access points only when the signal drops below RSSI_THRESHOLD. Scanning is a disruptive process that temporarily interferes with data comms. There is no reason to scan if the current signal is perfect! Exactly what value should RSSI_THRESHOLD have depends on your device, antenna, etc. Find it through trial and error.

 

global.tbh:

 

'DEFINES-------------------------------------------------------------

 

#define WLN_DEBUG_PRINT 1

#define WLN_WPA 1

 

#if PLATFORM_ID=EM500 or PLATFORM_ID=EM500W

       #define WLN_RESET_MODE 1 'there will be no dedicated reset, and all other lines are fixed

#elif PLATFORM_ID=EM1206 or PLATFORM_ID=EM1206W

       #define WLN_CLK PL_IO_NUM_14

       #define WLN_CS PL_IO_NUM_15

       #define WLN_DI PL_IO_NUM_12

       #define WLN_DO PL_IO_NUM_13

       #define WLN_RST PL_IO_NUM_11

#else

       'EM1000, NB1010,...

       #define WLN_CLK PL_IO_NUM_53

       #define WLN_CS PL_IO_NUM_49

       #define WLN_DI PL_IO_NUM_52

       #define WLN_DO PL_IO_NUM_50

       #define WLN_RST PL_IO_NUM_51

#endif

 

'INCLUDES------------------------------------------------------------

include "sock\trunk\sock.tbh" 'this lib is necessary for the WLN lib's operation

include "settings\trunk\settings.tbh" 'this lib is necessary to save pre-shared master key

includepp "settings.xtxt"

include "wln\trunk\wln.tbh"

 

'DECLARATIONS--------------------------------------------------------

declare function connect_to_ap(byref ap_name as string, security_mode as pl_wln_security_modes, byref key as string, domain as pl_wln_domains) as en_wln_status_codes

declare tcp_sock as byte

 

const RESCAN_PERIOD=30                                                        '<----- change as needed

const RSSI_THRESHOLD=200                                                '<----- change as needed

const AP_NAME="TIBB1"                                                        '<----- change as needed

const AP_PASSWORD="12345678"                                        '<----- change as needed

const AP_SECURITY=WLN_SECURITY_MODE_WPA2                '<----- change as needed

'use WLN_SECURITY_MODE_DISABLED, WLN_SECURITY_MODE_WEP64, WLN_SECURITY_MODE_WEP128, WLN_SECURITY_MODE_WPA1, or WLN_SECURITY_MODE_WPA2

 

 

main.tbs:

 

include "global.tbh"

 

'--------------------------------------------------------------------

dim tcp_sock as byte

dim rescan_tmr as byte

 

'====================================================================

sub on_sys_init()

       wln.ip="192.168.1.50"                                                '<----- set suitable IP here

       

       stg_start()

       

       if connect_to_ap(AP_NAME,AP_SECURITY,AP_PASSWORD,PL_WLN_DOMAIN_FCC)<>WLN_STATUS_OK then

               sys.halt

       end if

 

       'configure loopback socket

       tcp_sock=sock_get("TCP")

       sock.num=tcp_sock

       sock.rxbuffrq(1)

       sock.txbuffrq(1)

       sys.buffalloc

       sock.protocol=PL_SOCK_PROTOCOL_TCP

       sock.targetinterface=PL_SOCK_INTERFACE_WLN

       sock.targetip="192.168.1.67"                                '<----- set suitable target IP here

       sock.targetport=1000                                                '<----- set suitable target port here

end sub

 

'--------------------------------------------------------------------

sub on_sys_timer()

       wln_proc_timer()

       

       if wln_check_association()=PL_WLN_ASSOCIATED then

               'this code ensures persistent connection to the target IP

               sock.num=tcp_sock

               if sock.statesimple=PL_SSTS_CLOSED then

                       sock.connect

               end if

 

               'this code handles access point roaming

               if rescan_tmr>0 then

                       rescan_tmr=rescan_tmr-1

                       if rescan_tmr=0 then

                               rescan_tmr=RESCAN_PERIOD

                               if wln.rssi<=RSSI_THRESHOLD then

                                       wln_rescan(AP_NAME)

                               end if

                       end if

               end if

       else

               rescan_tmr=RESCAN_PERIOD

       end if

end sub

 

'--------------------------------------------------------------------

sub on_sock_data_arrival()

       wln_proc_data()

 

       'loopback tcp data

       if sock.num=tcp_sock then

               sock.setdata(sock.getdata(sock.txfree))

               sock.send

       end if

end sub

 

'--------------------------------------------------------------------

sub on_wln_task_complete(completed_task as pl_wln_tasks)

       wln_proc_task_complete(completed_task)

end sub

 

'--------------------------------------------------------------------

sub on_wln_event(wln_event as pl_wln_events)

       wln_proc_event(wln_event)

end sub

 

 

device.tbs:

 

include "global.tbh"

 

'====================================================================

function connect_to_ap(byref ap_name as string, security_mode as pl_wln_security_modes, byref key as string, domain as pl_wln_domains) as en_wln_status_codes

       dim pmk as string(32)

 

       #if WLN_WPA

               if security_mode=WLN_SECURITY_MODE_WPA1 or security_mode=WLN_SECURITY_MODE_WPA2 then

                       if stg_get("APN",0)<>ap_name or stg_get("PW",0)<>key or stg_sg("PMK",0,pmk,EN_STG_GET)<>EN_STG_STATUS_OK then

                               'recalculate the key

                               pmk=wln_wpa_mkey_get(key,ap_name)

                               stg_set("PMK",0,pmk)

                               stg_set("APN",0,ap_name)

                               stg_set("PW",0,key)

                       else

                               pmk=stg_get("PMK",0) 'the key stays the same

                       end if

               else

                       pmk=key

               end if

       #else

               pmk=key

       #endif

 

       connect_to_ap=wln_start(ap_name,security_mode,pmk,domain)

end function

 

'--------------------------------------------------------------------

sub callback_wln_ok()

       pat.play("G~",PL_PAT_CANINT)

end sub

 

'--------------------------------------------------------------------

sub callback_wln_failure(wln_state as en_wln_status_codes)

       pat.play("-",PL_PAT_CANINT)

       sock.num=tcp_sock

       sock.discard

end sub

 

'--------------------------------------------------------------------

sub callback_wln_pre_buffrq(required_buff_pages as byte)

end sub

 

'--------------------------------------------------------------------

sub callback_wln_rescan_result(current_rssi as byte, scan_rssi as byte, different_ap as no_yes)

       dim s as string(32)

 

       if different_ap=NO or scan_rssi<current_rssi or scan_rssi-current_rssi<5 then

               exit sub

       end if

       

       select case AP_SECURITY

       case WLN_SECURITY_MODE_DISABLED:

               s=""

       case WLN_SECURITY_MODE_WEP64,WLN_SECURITY_MODE_WEP128:

               s=AP_PASSWORD

       case else:

               s=stg_get("PMK",0)

       end select

 

       wln_change(AP_NAME,AP_SECURITY,s)

end sub

 

'--------------------------------------------------------------------

sub callback_wln_mkey_progress_update(progress as byte)

       pat.play("B-**",PL_PAT_CANINT)

end sub

 

'--------------------------------------------------------------------

sub callback_stg_error(byref stg_name_or_num as string,index as byte,status as en_stg_status_codes)

end sub

 

'--------------------------------------------------------------------

sub callback_stg_pre_get(byref stg_name_or_num as string,index as byte,byref stg_value as string)

end sub

 

'--------------------------------------------------------------------

sub callback_stg_post_set(byref stg_name_or_num as string, index as byte,byref stg_value as string)

end sub

 

 

settings.xtxt (the underlying configuration file):

 

>>APN        E        S        1        0        32        A        ^                                        Access point name

>>PW        E        S        1        0        32        A        ^                                        Password

>>PMK        E        S        1        32        32        A        12345678901234567890123456789012        Pre-shared master key

 

#define STG_DESCRIPTOR_FILE "settings.xtxt"

#define STG_MAX_NUM_SETTINGS 3

#define STG_MAX_SETTING_NAME_LEN 3

#define STG_MAX_SETTING_VALUE_LEN 32