ThingPlug Test

Dependents:   WizFi310_ThingPlug_Test WizFi310_ThingPlug_Test_P

Fork of WizFi310Interface by WIZnet

WizFi310/WizFi310_msg.cpp

Committer:
jehoon
Date:
2017-06-26
Revision:
5:72212beb817c
Parent:
1:16e57103a7dd
Child:
6:007cec5e96c0

File content as of revision 5:72212beb817c:

/*
/* Copyright (C) 2013 gsfan, MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/* Copyright (C) 2014 Wiznet, MIT License
 *  port to the Wiznet Module WizFi310
 */

#include "WizFi310.h"

#ifdef CFG_ENABLE_RTOS
#undef WIZ_DBG
#define WIZ_DBG(x, ...)
#endif

#define RESP_MSG_OK "[OK]"
#define RESP_MSG_ERROR "[ERROR"
#define RESP_MSG_CONNECT "[CONNECT "
#define RESP_MSG_DISCONNECT "[DISCONNECT "
#define RESP_MSG_LISTEN "[LISTEN "
#define RESP_MSG_MQTTCON "[MQTT CONNECT]"
#define RESP_MSG_MQTTDISCON "[MQTT DISCONNECT]"


// This function is operating in ISR. So you can't use debug message.
void WizFi310::recvData ( char c )
{
    static int cid, sub, len, count;
    static int is_mqtt_data = 0;    
    
    switch(_state.mode)
    { 
        case MODE_COMMAND:
            switch(c)
            {
                case 0:
                case 0x0a:  // LF
                case 0x0d:  // CR
                break;

                case '{':
                _state.buf->flush();
                _state.mode = MODE_DATA_RX;
                sub = 0;
                break;

                default:
                _state.buf->flush();
                _state.buf->queue(c);
                _state.mode = MODE_CMDRESP;
                break;
            }
            break;

        case MODE_CMDRESP:
            switch(c)
            {
                case 0:
                    break;
                case 0x0a: // LF
                    break;
                case 0x0d: // CR
                    if (_flow == 2) setRts(false);      // block
                    _state.mode = MODE_COMMAND;
                    parseMessage();
                    if (_flow == 2) setRts(true);       // release
                    break;
                default:
                    _state.buf->queue(c);
                    break;
            }
            break;

        case MODE_DATA_RX:
            
            switch(sub)
            {
                case 0:
                    // cid
                    if( (c >= '0') && (c <= '9') )
                    {
                        cid = x2i(c);
                    }
                    else if ( c == ',' )
                    {
                        sub++;
                        count = 0;
                        len = 0;
                    }
                    //daniel add for mqtt
                    else if ( c == 'Q' )
                    {
                        cid = 0;
                        is_mqtt_data = 1;
                    }
                    //
                    else
                    {
                        _state.mode = MODE_COMMAND;
                    }
                    break;

                case 1:
                    // ip                
    //                if ((c >= '0' && c <= '9') || c == '.')
                    if (((c >= '0' && c <= '9') || c == '.') && is_mqtt_data == 0 )
                    {
                        _con[cid].ip[count] = c;
                        count++;
                    }
                    else if( c == ',' )
                    {
                        _con[cid].ip[count] = '\0';
                        _con[cid].port = 0;
                        sub++;
                    }
                    //daniel for mqtt
                    else if( is_mqtt_data == 1)
                    {
                        rcvd_mqtt_topic[count] = c;
                        count++;
                    }
    //              else 
                    else if( is_mqtt_data == 0 )
                    {
                        _state.mode = MODE_COMMAND;
                    }
                    break;
    
                case 2:
                    // port
                    if ( c >= '0' && c <= '9' )
                    {
                        _con[cid].port = (_con[cid].port * 10) + ( c - '0' );
                    }
                    else if( c == ',')
                    {
                        sub++;
                        count = 0;
                    }
                    else
                    {
                        _state.mode = MODE_COMMAND;
                    }
                    break;
    
                case 3:
                    // data length
                    if ( c >= '0' && c <= '9' )
                    {
                        //_con[cid].recv_length = (_con[cid].recv_length * 10) + (c - '0');
                        len = (len * 10) + (c - '0');
                    }
                    else if( c == '}' )
                    {
                        sub++;
                        count = 0;
                        _con[cid].recv_length = len;
                    }
                    else
                    {
                        _state.mode = MODE_COMMAND;
                    }
                    break;
    
                default:
    
                    if(_con[cid].buf != NULL)
                    {
                        _con[cid].buf->queue(c);
                        if(_con[cid].buf->available() > CFG_DATA_SIZE - 16 )
                        {
                            setRts(false);     // blcok
                            _con[cid].received = true;
                            WIZ_WARN("buf full");
                        }
                    }
                    _con[cid].recv_length--;
                    if(_con[cid].recv_length == 0)
                    {
                        _con[cid].received = true;
                        _state.mode = MODE_COMMAND;
                    }
                    break;
                }
                break;
    }
}

#define MSG_TABLE_NUM 7
#define RES_TABLE_NUM 7
int WizFi310::parseMessage () {
    int i;
    char buf[128];

    static const struct MSG_TABLE {
        const char msg[24];
        void (WizFi310::*func)(const char *);
    } msg_table[MSG_TABLE_NUM] = {
        {RESP_MSG_OK,                    &WizFi310::msgOk},
        {RESP_MSG_ERROR,                 &WizFi310::msgError},
//        {"[ERROR:INVALIDINPUT]",    &WizFi310::msgError},
        {RESP_MSG_CONNECT,               &WizFi310::msgConnect},
        {RESP_MSG_DISCONNECT,            &WizFi310::msgDisconnect},
        {RESP_MSG_LISTEN,                &WizFi310::msgListen},
        {RESP_MSG_MQTTCON,               &WizFi310::msgMQTTConnect},
        {RESP_MSG_MQTTDISCON,               &WizFi310::msgMQTTDisconnect},
    };
    static const struct RES_TABLE{
        const Response res;
        void (WizFi310::*func)(const char *);
    }res_table[RES_TABLE_NUM]={
        {RES_NULL,          NULL},
        {RES_MACADDRESS,    &WizFi310::resMacAddress},
//      {RES_WJOIN,         &WizFi310::resWJOIN},
        {RES_CONNECT,       &WizFi310::resConnect},
        {RES_SSEND,         &WizFi310::resSSEND},
        {RES_FDNS,          &WizFi310::resFDNS},
        {RES_SMGMT,         &WizFi310::resSMGMT},
        {RES_WSTATUS,       &WizFi310::resWSTATUS},
    };


    for( i=0; i<sizeof(buf); i++ )
    {
        if( _state.buf->dequeue(&buf[i]) == false ) break;
    }

    buf[i] = '\0';
    
    if(_state.res != RES_NULL)
    {
        for( i=0; i<RES_TABLE_NUM; i++)
        {
            if(res_table[i].res == _state.res)
            {
                if(res_table[i].func != NULL)
                {
                    (this->*(res_table[i].func))(buf);
                }

                if(res_table[i].res == RES_CONNECT && _state.n < 2)
                    return -1;
            }
        }
    }

    for( i=0; i<MSG_TABLE_NUM; i++)
    {
        if( strncmp(buf, msg_table[i].msg, strlen(msg_table[i].msg)) == 0 )
        {
            if(msg_table[i].func != NULL)
            {
                (this->*(msg_table[i].func))(buf);
            }
            return 0;
        }
    }

    return -1;
}


void WizFi310::msgOk (const char *buf)
{
    _state.ok = true;
}

void WizFi310::msgError (const char *buf)
{
    _state.failure = true;
}

void WizFi310::msgConnect (const char *buf)
{
    int cid;

    //if (buf[9] < '0' || buf[9] > '8' || buf[10] != ']') return;
    if( isdigit (buf[9])) return;

    cid = x2i(buf[9]);
    
    initCon(cid, true);
    _state.cid = cid;
    _con[cid].accept = true;
    _con[cid].parent = cid;
}

void WizFi310::msgDisconnect (const char *buf)
{
    int cid;

    //if(buf[12] < '0' || buf[12] > '8' || buf[13] != ']')    return;
    if( isdigit (buf[9])) return;

    cid = x2i(buf[12]);
    _con[cid].connected = false;
}


void WizFi310::msgMQTTConnect (const char *buf)
{
    int cid = 0;

    initCon(cid, true);
    _state.cid = cid;
    _con[cid].accept = true;
    _con[cid].parent = cid;
    
    _con[cid].connected = true;
    _state.res = RES_NULL;
    _state.ok = true;
}

void WizFi310::msgMQTTDisconnect (const char *buf)
{
    int cid = 0;
    _con[cid].connected = false;
}


void WizFi310::msgListen (const char *buf)
{
    int cid;

    //if(buf[8] < '0' || buf[8] > '8' || buf[9] != ']')   return;
    if( isdigit (buf[9])) return;

    cid = x2i(buf[8]);
    _state.cid = cid;
}

void WizFi310::resMacAddress (const char *buf)
{
    if( buf[2] == ':' && buf[5] == ':')
    {
        strncpy(_state.mac, buf, sizeof(_state.mac));
        _state.mac[17] = 0;
        _state.res = RES_NULL;

        if(strncmp(_state.mac,CFG_DEFAULT_MAC,sizeof(CFG_DEFAULT_MAC)) == 0){
            _state.ok = false;
        }
        _state.ok = true;
    }
}

void WizFi310::resConnect (const char *buf)
{
    int cid;

    if( strstr((char*)buf, RESP_MSG_OK) != NULL){
        _state.n++;
    }
    else if( strstr((char*)buf, RESP_MSG_CONNECT) != NULL){
        cid = x2i(buf[9]);
        _state.cid = cid;
        _state.n++;
    }

    if(_state.n >= 2)
    {
        _state.res = RES_NULL;
        _state.ok = true;
    }
}

void WizFi310::resSSEND (const char *buf)
{
    if(_state.cid != -1)
    {
        _state.res = RES_NULL;
        _state.ok = true;
    }
}

void WizFi310::resFDNS (const char *buf)
{
    int i;

    for(i=0; i<strlen(buf); i++)
    {
        if( (buf[i] < '0' || buf[i] > '9') && buf[i] != '.' )
        {
            return;
        }
    }

    strncpy(_state.resolv, buf, sizeof(_state.resolv));
    _state.res = RES_NULL;
}

void WizFi310::resSMGMT (const char *buf)
{
    int cid, i;
    char *c;

//    if( (buf[0] < '0' || buf[0] > '8') )    return;
    if( isdigit (buf[9])) return;

    cid = x2i(buf[0]);
    if( cid != _state.cid )                 return;

    // IP
    c = (char*)(buf+6);
    for( i=0; i<16; i++ )
    {
        if( *(c+i) == ':')
        {
            _con[cid].ip[i] = '\0';
            i++;
            break;
        }
        if( ( *(c+i) < '0' || *(c+i) > '9') && *(c+i) != '.' )  return;
        _con[cid].ip[i] = *(c+i);
    }

    // Port
    c = (c+i);
    _con[cid].port = 0;
    for( i=0; i<5; i++ )
    {
        if( *(c+i) == '/')                  break;
        if( *(c+i) < '0' || *(c+i) > '9' )  return;

        _con[cid].port = (_con[cid].port * 10) + ( *(c+i) - '0' );
    }

    _state.res = RES_NULL;
}

void WizFi310::resWSTATUS (const char *buf)
{
    char* idx_ptr;
 
    if(_state.n == 0)
    {
        _state.n++;
    }
    else if(_state.n == 1)
    {
        idx_ptr = strtok((char*)buf, "/");  // Interface STA or AP
        idx_ptr = strtok( NULL, "/");       // SSID
        idx_ptr = strtok( NULL, "/");       // IP Addr
        memset(_state.ip, 0, sizeof(_state.ip));
        memcpy(_state.ip, idx_ptr, strlen(idx_ptr)+1);
        
        idx_ptr = strtok( NULL, "/");       // Gateway Addr
        memset(_state.gateway, 0, sizeof(_state.gateway));
        memcpy(_state.gateway, idx_ptr, strlen(idx_ptr)+1);

        _state.res = RES_NULL;
    }

}