grove_esp8266

grove_esp8266.cpp

Committer:
JackyZhangFromSeeed
Date:
2015-06-09
Revision:
0:0ac7892e440f

File content as of revision 0:0ac7892e440f:



#include "suli2.h"
#include "grove_esp8266.h"



//local functions
static void _uart_rx_callback(void);
static bool esp8266_send_cmd(UART_T *uart, char *command, char *content, unsigned int timeout);
__weak static void esp8266_callback(char *msg, unsigned int len);


//local variables
static char content_buffer[CONTENT_BUF_LEN];
static char rx_buf[RX_BUF_LEN];
static unsigned int rx_buf_ptr = 0;//point to the next unused char of rx_buf
static char cmd[70];
static char cmd_buf[70];
static char *WaitForAnswer_cmd_Buffer;
static char *WaitForAnswer_ans_Buffer;
static char *WaitForAnswer_data_Buffer;
static ESP8266_RecvStateMachine recv_machine = RECV_DATA;
static bool flag_recved_cmd = false;
static bool flag_recved_end = false;
static bool flag_send_ok = false;

static UART_T *_uart;
static user_cb_fun_ptr user_cb_fun;
EVENT_T event_esp8266;

void grove_esp8266_init(UART_T *uart, int pintx, int pinrx)
{
    suli_uart_init(uart, pintx, pinrx, 115200);
}

bool grove_esp8266_write_setup(UART_T *uart)
{
    memset((void *)rx_buf, 0, RX_BUF_LEN);
    memset((void *)content_buffer, 0, CONTENT_BUF_LEN);
    _uart = uart;
    suli_uart_rx_event_attach(uart, (cb_fun_ptr)&_uart_rx_callback);
    grove_esp8266_write_setcbfun(esp8266_callback);
    
    return true;
}

void grove_esp8266_write_setcbfun(user_cb_fun_ptr fun)
{
    user_cb_fun = fun;
}

bool grove_esp8266_attach_event_handler(CALLBACK_T handler)
{
    suli_event_init(&event_esp8266, handler);
//    pinMode(13, INPUT_PULLUP);
//    attachInterrupt(13, _trigger, FALLING);
    return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool grove_esp8266_read_getversion(UART_T *uart)
{
    //read version information
    while(esp8266_send_cmd(uart, (char*)"AT+GMR", content_buffer, 200) != true)
    {
        printf("try again\r\n");
        wait(0.5);
    }
    printf("Version: %s\r\n", content_buffer);
    
    return true;
}

bool grove_esp8266_write_joinwifi(UART_T *uart, char *ssid, char *pwd)
{
    //set to station mode
    printf("set mode to STATION\r\n");
    wait(0.1);
    while(esp8266_send_cmd(uart, (char*)"AT+CWMODE=1", content_buffer, 200) != true)
    {
        printf("try again\r\n");
        wait(0.5);
    }
    printf("OK\r\n\r\n");
    
    //join router
    printf("joining specified router\r\n");
    wait(0.1);
    while(esp8266_send_cmd(uart, (char*)"AT+CWJAP=\"stu.se.private\",\"depot0510se\"", content_buffer, 5000) != true)
    {
        printf("try again\r\n");
        wait(0.5);
    }
    printf("joined\r\n");
    wait(0.1);
    while(esp8266_send_cmd(uart, (char*)"AT+CWJAP?", content_buffer, 1000) != true)
    {
        printf("try again\r\n");
        wait(0.5);
    }
    printf("joined indeed\r\n\r\n");
    
    return true;
}

bool grove_esp8266_write_socketasclient(UART_T *uart, char *ip, unsigned int port)
{
    //enable mux connection
    printf("enable mux connection\r\n");
    wait(0.1);
    while(esp8266_send_cmd(uart, (char*)"AT+CIPMUX=1", content_buffer, 200) != true)
    {
        printf("try again\r\n");
        wait(0.5);
    }
    printf("OK\r\n\r\n");
    
    //connect to tcp server
    printf("connect to tcp server\r\n");
    wait(0.1);
    while(esp8266_send_cmd(uart, (char*)"AT+CIPSTART=4,\"TCP\",\"192.168.21.159\",6320", content_buffer, 2000) != true)
    {
        printf("try again\r\n");
        wait(0.5);
    }
    printf("OK\r\n\r\n");
    
    return true;
}

bool grove_esp8266_read_aplist(UART_T *uart)
{
    //list all AP
    printf("list all AP around\r\n");
    wait(0.1);
    while(esp8266_send_cmd(uart, (char*)"AT+CWLAP", content_buffer, 10000) != true)
    {
        printf("try again\r\n");
        wait(0.5);
    }
    printf("%s\r\n", content_buffer);
    
    return true;
}

/*
function: internal function, uart callback
*/
static void _uart_rx_callback(void)
{
    unsigned int payload_len, header_len;
    unsigned int port;
    int res;
    char *payload_str;
    
    while(suli_uart_readable(_uart))
    {
        if(rx_buf_ptr < RX_BUF_LEN - 2)
        {
            rx_buf[rx_buf_ptr++] = suli_uart_read(_uart);
        }
    }
    //receiving state machine after recved all data for now
    switch(recv_machine)
    {
        case RECV_DATA:
            WaitForAnswer_data_Buffer = strstr(rx_buf, "\r\n+IPD");//check the "+IPD" response
            if(WaitForAnswer_data_Buffer != NULL)//user data recved
            {
                res = sscanf(rx_buf,"\r\n+IPD,%d,%d:", &port, &payload_len);
                payload_str = strtok(rx_buf, ":");
                header_len = strlen(payload_str) + 1;
                if((res == 2) && (payload_len == rx_buf_ptr - header_len))
                {
                    memcpy(content_buffer, rx_buf + header_len, payload_len);
                    user_cb_fun(content_buffer, payload_len);
                    memset(rx_buf, 0, rx_buf_ptr);//clear the buffer for next recv
                    rx_buf_ptr = 0;
                }
            }
            break;
        case RECV_CMD:
            WaitForAnswer_cmd_Buffer = strstr(rx_buf, cmd_buf);//check the cmd
            if(WaitForAnswer_cmd_Buffer != NULL)//right cmd
            {
                flag_recved_cmd = true;
                recv_machine = RECV_END;
            }
            break;
        case RECV_END:
            //check the "OK" response
            WaitForAnswer_ans_Buffer = strstr(WaitForAnswer_cmd_Buffer, "\r\nOK\r\n");
            if(WaitForAnswer_ans_Buffer != NULL)//"OK"recved
            {
                //recv cmd response
                flag_recved_end = true;
            }
            //check the "ERROR" response
            WaitForAnswer_ans_Buffer = strstr(WaitForAnswer_cmd_Buffer, "\r\nERROR\r\n");
            if(WaitForAnswer_ans_Buffer != NULL)//"ERROR"recved
            {
                flag_recved_end = true;
            }
            //check the "SEND OK" response
            WaitForAnswer_ans_Buffer = strstr(WaitForAnswer_cmd_Buffer, "\r\nSEND OK\r\n");
            if(WaitForAnswer_ans_Buffer != NULL)//"SEND OK"recved
            {
                flag_send_ok = true;
            }
            break;
        default:
            break;
    }
}

/*
function: send data through ESP8266
const char *command: AT command to be send
char *content: returned data from ESP8266
unsigned int timeout: timeout
*/
static bool esp8266_send_cmd(UART_T *uart, char *command, char *content, unsigned int timeout)
{
    volatile uint32_t TxWaitForResponse_TimeStmp;
    unsigned int len;
    
    //reset flags and state machine
    recv_machine = RECV_CMD;
    flag_recved_cmd = false;
    flag_recved_end = false;
    //clear the buffer
    memset(rx_buf, 0, rx_buf_ptr);//clear the buffer for next recv
    rx_buf_ptr = 0;
    //save the cmd just sent
    strcpy(cmd_buf, command);
    sprintf(cmd, "%s\r\n", command);
    //send cmd
    suli_uart_write_bytes(_uart, (uint8_t*)cmd, strlen(cmd));
    
    //wait for response
    TxWaitForResponse_TimeStmp = millis();
    while(millis() - TxWaitForResponse_TimeStmp < timeout)//timeout control
    {
        if(flag_recved_cmd == true)
        {
            if(flag_recved_end == true)
            {
                WaitForAnswer_ans_Buffer = strstr(WaitForAnswer_cmd_Buffer, "\r\nOK\r\n");//check the "OK" response
                if(WaitForAnswer_ans_Buffer != NULL)
                {
                    len = WaitForAnswer_ans_Buffer - WaitForAnswer_cmd_Buffer - strlen(cmd_buf) - 3;
                    memset(content, 0, CONTENT_BUF_LEN);
                    memcpy(content, WaitForAnswer_ans_Buffer - len, len);
                    memset(rx_buf, 0, rx_buf_ptr);//clear the buffer for next recv
                    rx_buf_ptr = 0;
                    recv_machine = RECV_DATA;
                    return true;
                }
            }
        }
        wait(0.1);
    }
    memset(rx_buf, 0, rx_buf_ptr);//clear the buffer for next recv
    rx_buf_ptr = 0;
    recv_machine = RECV_DATA;
    return false;
}

/*
function: send data through ESP8266
char *data: data will be send
unsigned int len: data length in byte
*/
bool grove_esp8266_write_msg(UART_T *uart, char *msg, unsigned int len)
{
    volatile uint32_t TxWaitForResponse_TimeStmp;
    unsigned ptr = 0;
    
    if(len > 2048)
        return false;
    
    //send cmd
    sprintf(cmd, "AT+CIPSEND=4,%d", len);
    if(esp8266_send_cmd(uart, cmd, content_buffer, 200) != true)
    {
        return false;
    }
    //send user data
    while(len--)
    {
        suli_uart_write(uart, msg[ptr++]);
    }
    
    //reset flags and state machine
    recv_machine = RECV_END;
    flag_recved_cmd = false;
    flag_recved_end = false;
    flag_send_ok = false;
    
    //wait for response
    TxWaitForResponse_TimeStmp = millis();
    while(millis() - TxWaitForResponse_TimeStmp < 500)//timeout control
    {
        if(flag_send_ok == true)
        {
            memset(rx_buf, 0, rx_buf_ptr);//clear the buffer for next recv
            rx_buf_ptr = 0;
            recv_machine = RECV_DATA;
            return true;
        }
        wait(0.01);
    }
    memset(rx_buf, 0, rx_buf_ptr);//clear the buffer for next recv
    rx_buf_ptr = 0;
    recv_machine = RECV_DATA;
    return false;
}

/*
callback function when a piece of message arrived
this is a WEAK declaration
*/
__weak static void esp8266_callback(char *msg, unsigned int len)
{
    msg[len] = '\0';
    printf("esp8266 driver recv%3d bytes: %s\r\n", len, msg);
    printf("user can add his own callback function instead\r\n");
}