/*******************************************************************************
  MPLAB Harmony Application Source File

  Company:
    Microchip Technology Inc.

  File Name:
    app_drv_winc.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It
    implements the logic of the application's state machine and it may call
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "app_drv_winc.h"
#include "app_drv_usart1.h"
#include "driver/spi/drv_spi.h"
#include "driver/winc/include/wdrv_winc_client_api.h"
#include <stdio.h>
#include <string.h>

// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************
#define WLAN_SSID         "RTC_ROOM"
#define WLAN_AUTH_WPA_PSK
#define WLAN_PSK          "0800717718"
WDRV_WINC_AUTH_CONTEXT authCtx;
WDRV_WINC_BSS_CONTEXT  bssCtx;
WDRV_WINC_BSS_INFO     BSSInfo;
bool foundBSS;

DRV_HANDLE WINCHandle;

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_DRV_WINC_Initialize function.

    Application strings and buffers are be defined outside this structure.
*/

APP_DRV_WINC_DATA app_drv_wincData;

// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************
void DHCPAddressEventCallback(DRV_HANDLE handle, uint32_t ipAddress)
{
    char s[20];

    USART1printf("IP address is %s\r\n", inet_ntop(AF_INET, &ipAddress, s, sizeof(s)));
}

void ConnectNotifyCallback(DRV_HANDLE handle, WDRV_WINC_ASSOC_HANDLE assocHandle, WDRV_WINC_CONN_STATE currentState, WDRV_WINC_CONN_ERROR errorCode)
{
    switch( currentState )
    {
    case WDRV_WINC_CONN_STATE_CONNECTED:
        USART1printf("Connected\r\n");

        app_drv_wincData.state = APP_DRV_WINC_STATE_CONNECTED;
        break;

    case WDRV_WINC_CONN_STATE_DISCONNECTED:
        USART1printf("Disconnected\r\n");

        app_drv_wincData.state = APP_DRV_WINC_STATE_DISCONNECTED;
        break;

#ifdef WDRV_WINC_DEVICE_BSS_ROAMING
    case WDRV_WINC_CONN_STATE_ROAMED:
        break;
#endif
    }
}

// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************


/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_DRV_WINC_Initialize ( void )

  Remarks:
    See prototype in app_drv_winc.h.
 */

void APP_DRV_WINC_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    app_drv_wincData.state = APP_DRV_WINC_STATE_INIT;



    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
}


/******************************************************************************
  Function:
    void APP_DRV_WINC_Tasks ( void )

  Remarks:
    See prototype in app_drv_winc.h.
 */

void APP_DRV_WINC_Tasks ( void )
{
    switch ( app_drv_wincData.state )
    {
    case APP_DRV_WINC_STATE_INIT:
        if(WDRV_WINC_Status(sysObj.drvWifiWinc) == SYS_STATUS_READY)
        {
            app_drv_wincData.state = APP_DRV_WINC_STATE_OPEN;
        }
        break;

    case APP_DRV_WINC_STATE_OPEN:
        WINCHandle = WDRV_WINC_Open(0, 0);
        if(WINCHandle == DRV_HANDLE_INVALID)
        {
            app_drv_wincData.state = APP_DRV_WINC_STATE_ERROR;
            break;
        }
        app_drv_wincData.state = APP_DRV_WINC_STATE_SCAN_START;
        break;

    case APP_DRV_WINC_STATE_SCAN_START:
        WDRV_WINC_IPUseDHCPSet( WINCHandle, &DHCPAddressEventCallback );
		
        if( WDRV_WINC_BSSFindFirst(WINCHandle, WDRV_WINC_ALL_CHANNELS, true, NULL, NULL) == WDRV_WINC_STATUS_OK )
        {
            app_drv_wincData.state = APP_DRV_WINC_STATE_SCANNING;
            foundBSS = false;
        }
        break;

    case APP_DRV_WINC_STATE_SCANNING:
        if( WDRV_WINC_BSSFindInProgress(WINCHandle) == false )
        {
            USART1printf("Scan complete, %d AP(s) found\r\n", WDRV_WINC_BSSFindGetNumBSSResults(WINCHandle));
            app_drv_wincData.state = APP_DRV_WINC_STATE_SCAN_GET_RESULT;
        }
        break;

    case APP_DRV_WINC_STATE_SCAN_GET_RESULT:
        if( WDRV_WINC_BSSFindGetInfo(WINCHandle, &BSSInfo) == WDRV_WINC_STATUS_OK )
        {
            USART1printf("AP found: RSSI: %d %s\r\n", BSSInfo.rssi, BSSInfo.ctx.ssid.name);

            if( ((sizeof(WLAN_SSID)-1) == BSSInfo.ctx.ssid.length) && (0 == memcmp(BSSInfo.ctx.ssid.name, WLAN_SSID, BSSInfo.ctx.ssid.length)) )
            {
                foundBSS = true;
            }
            switch( WDRV_WINC_BSSFindNext(WINCHandle, NULL) )
            {
            case WDRV_WINC_STATUS_BSS_FIND_END:
                if( foundBSS == true )
                {
                    USART1printf("Target AP found, trying to connect\r\n");
                    app_drv_wincData.state = APP_DRV_WINC_STATE_SCAN_DONE;
                }
                else
                {
                    USART1printf("Target BSS not found\r\n");
                    app_drv_wincData.state = APP_DRV_WINC_STATE_IDLE;
                }
                break;
            case WDRV_WINC_STATUS_NOT_OPEN:
            case WDRV_WINC_STATUS_INVALID_ARG:
                app_drv_wincData.state = APP_DRV_WINC_STATE_ERROR;
                break;
            default:
                break;
            }
        }
        break;

    case APP_DRV_WINC_STATE_SCAN_DONE :
        app_drv_wincData.state = APP_DRV_WINC_STATE_ERROR;

        if( WDRV_WINC_BSSCtxSetDefaults(&bssCtx) != WDRV_WINC_STATUS_OK )
        { break; }

        if( WDRV_WINC_BSSCtxSetSSID(&bssCtx, (uint8_t*)WLAN_SSID, strlen(WLAN_SSID) ) != WDRV_WINC_STATUS_OK )
        { break; }

#if defined(WLAN_AUTH_OPEN)
        if( WDRV_WINC_AuthCtxSetOpen(&authCtx) ) != WDRV_WINC_STATUS_OK )
#elif defined(WLAN_AUTH_WPA_PSK)
        if( WDRV_WINC_AuthCtxSetWPA(&authCtx, (uint8_t*)WLAN_PSK, strlen(WLAN_PSK) ) != WDRV_WINC_STATUS_OK )
#endif
        { break; }

        if( WDRV_WINC_BSSConnect(WINCHandle, &bssCtx, &authCtx, &ConnectNotifyCallback) == WDRV_WINC_STATUS_OK )
        {
            app_drv_wincData.state = APP_DRV_WINC_STATE_CONNECTING;
        }
        break;

    case APP_DRV_WINC_STATE_CONNECTING:
        break;
        
    case APP_DRV_WINC_STATE_CONNECTED:
        WDRV_WINC_IPLinkActive( WINCHandle );
        break;

    case APP_DRV_WINC_STATE_DISCONNECTED:
        if( WDRV_WINC_BSSReconnect(WINCHandle, &ConnectNotifyCallback) == WDRV_WINC_STATUS_OK )
        {
            app_drv_wincData.state = APP_DRV_WINC_STATE_CONNECTING;
        }
        break;

    case APP_DRV_WINC_STATE_ERROR:
        USART1printf("DRV_WINC error!\r\n");

        app_drv_wincData.state = APP_DRV_WINC_STATE_IDLE;
        break;

    case APP_DRV_WINC_STATE_IDLE:
        break;
    }
}


/*******************************************************************************
 End of File
 */
