-

Dependencies:   EthernetInterface TCPSocket_HelloWorld mbed-rtos mbed

Fork of TCPSocket_HelloWorld by mbed official

main.cpp

Committer:
offroad
Date:
2016-02-09
Revision:
16:22169975b5d8
Parent:
15:10c1be621ad6

File content as of revision 16:22169975b5d8:

#include "mbed.h"
#include "EthernetInterface.h"
LocalFileSystem local("local");    

#define NPORTS 30
static char FSM_buf[16];
#define FSM_STATE_IDLE      0
#define FSM_STATE_READNUM   1
static int FSM_state1 = FSM_STATE_IDLE;
static int FSM_state2 = 0;
static char FSM_cmd = 'x';

static void FSM_reset(){
    FSM_state1 = FSM_STATE_IDLE;
    FSM_state2 = 0;
    FSM_cmd = 'x';
}

static void FSM_handleChar(DigitalOut* gpo, char inputChar, char** bufOut){

    // === handle incoming char ===
    switch (FSM_state1){
        case FSM_STATE_IDLE:
            // === handle new command char ===
            switch(inputChar){
                case '+':
                case '-':
                case '?': 
                    FSM_cmd = inputChar;
                    FSM_state1 = FSM_STATE_READNUM;
                    goto doneCont;
                default: 
                    goto reset;
            } // switch inputChar
            goto lockup;
        case FSM_STATE_READNUM:
            if (FSM_state2 > 8)
                goto reset; // too many digits
            
            if ((inputChar == 32 || inputChar == 9 || inputChar == 13 || inputChar == 10) && (FSM_state2 > 0)){
                // === got command terminated by whitespace, and at least one digit
                FSM_buf[FSM_state2] = 0;
                int ixGpio = atoi(FSM_buf);
                if (ixGpio < 0 || ixGpio >= NPORTS)
                    goto reset; // invalid port number
                switch(FSM_cmd){
                    case '+':
                        // === set GPO ===
                        *(gpo+ixGpio) = 1; 
                        goto reset; // success
                    case '-':
                        // === clear GPO ===
                        *(gpo+ixGpio) = 0;
                        goto reset; // success
                    case '?':
                        // === query GPO state (verify) ===
                        *((*bufOut)++) = *(gpo+ixGpio) ? '1' : '0';
                        *((*bufOut)++) = 13;
                        *((*bufOut)++) = 10;
                        goto reset; // success   
                    default:
                        goto reset; // invalid command byte
                }
            }
            
            if (inputChar >= '0' && inputChar <= '9'){
                // === append digit ===
                FSM_buf[FSM_state2++] = inputChar;
                goto doneCont;
            }
            
            // invalid character (not digit)
            goto reset;
        default:
            // === invalid FSM state ===
            goto lockup;
    } // switch FSM_state1

    // === internal error. Should never be reached. ===
lockup: 
    goto lockup; 

    // === reset state machine (on completion and any invalid input ===
reset:
    FSM_reset();

doneCont:
    return;
}

int main() {
    printf("\r\nLANGPIO server v2.1 20151107 mn\r\n");
    fflush(stdout);
    static DigitalOut myGpo[NPORTS] = {
        DigitalOut(LED1),
        DigitalOut(LED2),
        DigitalOut(LED3),
        DigitalOut(LED4),
        DigitalOut(p5),
        DigitalOut(p6),
        DigitalOut(p7),
        DigitalOut(p8),
        DigitalOut(p9),
        DigitalOut(p10),
        DigitalOut(p11),
        DigitalOut(p12),
        DigitalOut(p13),
        DigitalOut(p14),
        DigitalOut(p15),
        DigitalOut(p16),
        DigitalOut(p17),
        DigitalOut(p18),
        DigitalOut(p19),
        DigitalOut(p20),
        DigitalOut(p21),
        DigitalOut(p22),
        DigitalOut(p23),
        DigitalOut(p24),
        DigitalOut(p25),
        DigitalOut(p26),
        DigitalOut(p27),
        DigitalOut(p28),
        DigitalOut(p29),
        DigitalOut(p30)};

    char buffer[256];
    char ipAddress[256];
    char subnetMask[256];
    sprintf(ipAddress, "%s", "192.168.1.10");
    sprintf(subnetMask, "%s", "255.255.255.0");
    int port = 7;

    FILE* f = fopen("/local/config.txt", "r");
    if (f != NULL){
        int n = fscanf(f, "%s", ipAddress); if (n <= 0) goto endOfFile;
        n = fscanf(f, "%s", subnetMask); if (n <= 0) goto endOfFile;
        n = fscanf(f, "%s", buffer); if (n <= 0) goto endOfFile;
        port = atoi(buffer);
    endOfFile:
        fclose(f);
    }

    EthernetInterface eth;
    eth.init(ipAddress, subnetMask, "");
    eth.connect();
    printf("IP address: %s (configured: %s) port %i\r\n", eth.getIPAddress(), ipAddress, port);
    
    TCPSocketServer server;
    server.bind(port);
    server.listen();

    while (true) {
        printf("\nWait for new connection...\n");
        TCPSocketConnection client;
        server.accept(client);
        client.set_blocking(true, 0);
        
        printf("Connection from: %s\n", client.get_address());
        client.send_all(">\r\n", 3);
        FSM_reset();
        
        // === main loop ===
        while (true) {

            // === read data from socket ===
            int n = client.receive(buffer, sizeof(buffer));

            // === detect connection break ===
            if (n < 0)
                goto conn_exit;
            
            // maximum length of a single reply. Anything longer will be split.
            #define MAX_PACKETLEN (1024)
            // maximum length of a single message to guarantee there is enough output buffer
            #define MAX_MSGLEN (16)
            char bufOut[MAX_PACKETLEN];
            char* pWriteStart = &bufOut[0];
            char* pWrite = pWriteStart;

            // === iterate over input characters ===
            int ix;
            for (ix = 0; ix < n; ++ix){
                FSM_handleChar(&myGpo[0], buffer[ix], &pWrite);

                // === send reply, if there is any ===
                // - when processing last char of incoming packet
                // - when output buffer is too full
                int nInBuf = pWrite - pWriteStart;
                if (nInBuf > 0)
                    if ((ix == n-1) || (nInBuf > MAX_PACKETLEN - MAX_MSGLEN)){
                        client.send_all(bufOut, nInBuf);
                        pWrite = pWriteStart;
                    }
            } // for input character
        } // while connection
        
    conn_exit:
        client.close();
    } // eternal main loop
} // void main