Changeset 79

Show
Ignore:
Timestamp:
06/03/06 02:06:13 (6 years ago)
Author:
njriley
Message:

Better exception printing even when we're in fullscreen mode (need
CR+LF).

A few minor message cleanups. Get rid of usleeps that don't seem to
do anything anyway (what is 'idle' mode supposed to be?). Don't
update LEDs because it doesn't work anyway, and the status storms that
the controller likes to give make the machine hang. Refactor
SodaMachine::readMsg to be less repetitive and easier to understand.
Distinguish between empty and invalid messages.

However, we use 100% CPU now. Grr.

test.py: prints out output from the serial port in a nice way

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/soda/src/exception.h

    r22 r79  
    4040        virtual string getString()  
    4141        { 
    42             return "Function call: \n"  +err_func +  
    43              "\nreturned: " + string(strerror(errno)); 
     42            return "Function call: \r\n"  +err_func +  
     43             "\r\nreturned: " + string(strerror(errno)); 
    4444        } 
    4545     
  • trunk/soda/src/soda.cc

    r78 r79  
    1414extern bool isCurses; 
    1515 
     16const struct Msg Msg::EmptyMsg(Empty), Msg::InvalidMsg(Invalid); 
     17 
    1618resources resrc; 
    1719 
     
    193195            { 
    194196                ostringstream buf; 
    195                 buf << "User " << state.user->PrettyName  
    196                     << " is out of money."; 
     197                buf << "You (" << state.user->PrettyName  
     198                    << ") are out of credit."; 
    197199                viz->displayMsg(buf.str()); 
    198200                viz->refresh(); 
     
    235237    //Get next message 
    236238    msg = readMsg(); 
     239 
    237240    //If a card is swiped, always return to the cardswipe state 
    238241    switch(msg.type) 
    239242    { 
    240         case CardSwiped
     243        case CardSwipe
    241244            if(state.user) { 
    242245                delete state.user; 
     
    265268            processButtonMsg(msg); 
    266269            break; 
     270        case Invalid: 
     271            return; 
    267272        case Empty: 
    268273 
     
    274279                    //Display a thank you message for buying soda 
    275280                    viz->clearMsg(); 
    276                     viz->displayMsg("Thank you for using caffeine."); 
     281                    viz->displayMsg("Thank you for using Caffeine."); 
    277282                    viz->clearUser(); 
    278283                    viz->refresh(); 
     
    297302            GoToState(Idle); 
    298303        } 
    299         usleep(100000); 
     304        /* I have no idea what this does other than cause caffeine to hang */ 
     305        /* usleep(100000); */ 
    300306    } 
    301307 
     
    419425    switch(msg.type) 
    420426    { 
    421         case Empty: 
    422             break; 
    423427        case ButtonPress: 
    424428            for(int i=0; i < TRAY_COUNT; i++) { 
     
    442446            refreshTrays(&msg); 
    443447            break; 
     448        case Empty: 
     449        case Invalid: 
    444450        case CardSwipe: 
    445451            break; 
     
    469475 
    470476    //Refresh LEDs at the end  
    471     refreshLEDs(); 
     477    // XXX we seem to get a huge number of bogus status messages, 
     478    // XXX so don't bother 
     479    // refreshLEDs(); 
    472480} 
    473481 
     
    485493} 
    486494 
     495// Read a CR+LF-terminated line of the specified length (0=any) from 
     496// the serial port and store it in msg.data 
     497void SodaMachine::readLineAsMsgData(Msg &msg, unsigned len=0) 
     498{ 
     499    int res; 
     500    char c; 
     501    msg.data = ""; 
     502    while (1) { 
     503        CHECK_RESULT(res, read(sport, &c, 1)); 
     504        if (c == '\n') 
     505            break; 
     506        /* usage message has some lines which aren't CR-LF terminated */ 
     507        if (c == '\r') 
     508            continue; 
     509        msg.data += c; 
     510    } 
     511    // cout << "READ|" << msg.data << endl; 
     512    if (len != 0 && len != msg.data.length()) { 
     513        msg = Msg::InvalidMsg; 
     514    } 
     515} 
     516 
    487517//Read the message from the serial port 
    488518Msg SodaMachine::readMsg() 
    489519{ 
    490     //variables for select 
    491     char data[80]; 
     520    char c; 
    492521    struct timeval timeout; 
    493522    fd_set rset; 
    494523    int res; 
    495524    Msg msg; 
    496  
    497     int i = 0; 
    498525 
    499526    //Select on the serial port 
     
    503530    FD_SET(sport, &rset); 
    504531 
    505     res = select(sport + 1, &rset, NULL, NULL, &timeout); 
    506  
    507     if(res == -1) { 
    508         //Check to see if it was interrupted 
    509         if(res == EINTR) { 
    510             //TODO back to the top 
    511         } 
    512         //TODO what do we do here? 
    513     } 
    514  
    515     if(FD_ISSET(sport, &rset)) { 
    516         //There has to be at least one byte in the buffer, so read it 
    517         CHECK_RESULT(res, read(sport, data, 1)); 
    518  
    519         switch(data[0]) { 
    520             case 'B': 
    521                 msg.type = ButtonPress; 
    522                 msg.data = ""; 
    523                 do 
    524                 { 
    525                     CHECK_RESULT(res, read(sport, &data[i], 1)); 
    526  
    527                     //Put button 0 in position 0 of the string 
    528                     i++;     
    529                 } while(data[i-1] != '\n'); 
    530                 for(int j =0; j < TRAY_COUNT; j++) 
    531                 { 
    532                     msg.data = msg.data + data[j]; 
    533                 } 
    534                 break; 
    535             case 'C': 
    536                 msg.type = CardSwipe; 
    537                 //Read until we get a carriage return 
    538                 while(data[0] != '\n') 
    539                 { 
    540                     CHECK_RESULT(res, read(sport, data, 1)); 
    541                     msg.data += data[0]; 
    542                 } 
    543  
    544                 if(msg.data[16] != '=') { 
    545                     //TODO: Move this to a better place 
    546                     //Check to see if this is the Banner 
    547                     if(msg.data == "affeine Controller\r\n") 
    548                     { 
    549                         int blank =0; 
    550                         int line =0; 
    551                         //Read the rest of the message 
    552                         while(blank < 2) 
    553                         { 
    554                             msg.data = ""; 
    555                             do 
    556                             { 
    557                                 CHECK_RESULT(res, read(sport, data, 1)); 
    558                                 msg.data += data[0]; 
    559                             }while(data[0] != '\n'); 
    560                             line++; 
    561                             //Hack because a newline isn't always a new line  
    562                             if(msg.data[0] == (char)13 || msg.data[0] == '\n') 
    563                             { 
    564                                 //cout << "Got a blank line at "  
    565                                 //    << line << endl; 
    566                                 blank++; 
    567                             }else 
    568                             { 
    569                                 //cout << msg.data; 
    570                             } 
    571                         } 
    572                         msg.data = ""; 
    573                         msg.type = Empty; 
    574                         return msg; 
    575                     } 
    576                     throw MachineException("Reader error", true); 
    577                 } 
    578  
    579                 //The format is 
    580                 //;|NUM(16)|=|Additional| 
    581                 //We want pos 4-13 of the number. 
    582                 msg.data = msg.data.substr(4,9); 
    583  
    584                 break; 
    585             case 'S': 
    586                 msg.type = Sense; 
    587                 CHECK_RESULT(res, read(sport, data, SENSE_LEN)); 
    588                 data[SENSE_LEN-1] = '\0'; 
    589  
    590                 msg.data = data; 
    591                 break; 
    592  
    593                 //These are the weird extra characters we sometimes get 
    594                 break; 
    595             default: 
    596                 msg.type = Empty; 
    597                 msg.data = ""; 
    598                 //BUGBUG: Don't print out the char because it might corrupt the 
    599                 //screen 
    600  
    601                 break; 
    602         } 
    603     }else { 
    604         //There was no messge 
    605         msg.type = Empty; 
    606         msg.data = ""; 
     532    do { 
     533        res = select(sport + 1, &rset, NULL, NULL, &timeout); 
     534    } while (res == -1); // handle EAGAIN and friends 
     535 
     536    if (!FD_ISSET(sport, &rset)) 
     537        return Msg::EmptyMsg; 
     538 
     539 read_parse: 
     540    CHECK_RESULT(res, read(sport, &c, 1)); 
     541 
     542    // cout << "\r\nDispatching on: " << c 
     543    //  << hex << " (0x" << (int)c << dec << ")\r" << endl; 
     544 
     545    if (c == 'B') { 
     546        msg.type = ButtonPress; 
     547        readLineAsMsgData(msg, TRAY_COUNT); 
     548    } else if (c == 'C') { 
     549        msg.type = CardSwipe; 
     550        readLineAsMsgData(msg); 
     551 
     552        if (msg.data.length() < 17 || msg.data[16] != '=') { 
     553            /* probably some more usage */ 
     554            return Msg::InvalidMsg; 
     555        } 
     556        //The format is ;|NUM(16)|=|Additional|.  We want pos 4-13 of NUM. 
     557        msg.data = msg.data.substr(4,9); 
     558    } else if (c == 'S') { 
     559        msg.type = Sense; 
     560        readLineAsMsgData(msg); /* , TRAY_COUNT); */ 
     561    } else if (c >= '0' && c <= '9') { 
     562        /* most likely bogus data, e.g. 9|2B11111|32 42 31 31 31 31 31 0d 0a */ 
     563        readLineAsMsgData(msg); 
     564        return Msg::InvalidMsg; 
     565    } else if (c == '\0' || (c >= 'A' && c <= 'Z')) { 
     566        /* probably usage information; skip */ 
     567        readLineAsMsgData(msg); 
     568        return Msg::InvalidMsg; 
     569    } else { 
     570        goto read_parse; 
    607571    } 
    608572 
     
    723687void SodaMachine::ResetController() 
    724688{ 
    725     char msg[3]; 
    726     msg[0] = 'R'; 
    727     msg[1] = '\n'; 
    728  
    729     sendMsg(msg, 2); 
     689    sendMsg("R\n", 2); 
    730690} 
    731691 
     
    812772    }catch(SodaException & e) { 
    813773        LogError(viz,e); 
    814         throw MachineException("Unable to set LEDS", true); 
     774        throw MachineException("Unable to set LEDs", true); 
    815775    } 
    816776} 
  • trunk/soda/src/soda.h

    r58 r79  
    2020//Number of trays in the machine 
    2121#define TRAY_COUNT 5 
    22  
    23 //Length of the button data 
    24 //5 chars for the button state 
    25 //1 newline 
    26 #define BUTTON_LEN 6 
    27  
    28 #define SENSE_LEN 6 
    2922 
    3023#define LED_LEN 10 
     
    5548enum LedColor {Red, Green, Unknown}; 
    5649 
    57 enum MsgType {Empty, CardSwipe, ButtonPress, Sense}; 
     50enum MsgType {Empty, Invalid, CardSwipe, ButtonPress, Sense}; 
    5851 
    5952struct Button 
     
    8376    MsgType type; 
    8477    string data; 
     78    Msg(MsgType type=Empty) : type(type), data("") {} 
     79    static const struct Msg EmptyMsg, InvalidMsg; 
    8580}; 
    8681 
     
    116111        //Private functions 
    117112        Msg readMsg(); 
    118        
     113        void readLineAsMsgData(Msg &msg, unsigned len); 
    119114 
    120115        void sendMsg(char * data, int len); 
    121        void runLoop(); 
     116       void runLoop(); 
    122117 
    123118        void processButtonMsg(Msg & msg);