Changeset 79
- Timestamp:
- 06/03/06 02:06:13 (6 years ago)
- Files:
-
- trunk/soda/src/exception.h (modified) (1 diff)
- trunk/soda/src/soda.cc (modified) (13 diffs)
- trunk/soda/src/soda.h (modified) (4 diffs)
- trunk/soda/src/test.py (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/soda/src/exception.h
r22 r79 40 40 virtual string getString() 41 41 { 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)); 44 44 } 45 45 trunk/soda/src/soda.cc
r78 r79 14 14 extern bool isCurses; 15 15 16 const struct Msg Msg::EmptyMsg(Empty), Msg::InvalidMsg(Invalid); 17 16 18 resources resrc; 17 19 … … 193 195 { 194 196 ostringstream buf; 195 buf << " User" << state.user->PrettyName196 << " is out of money.";197 buf << "You (" << state.user->PrettyName 198 << ") are out of credit."; 197 199 viz->displayMsg(buf.str()); 198 200 viz->refresh(); … … 235 237 //Get next message 236 238 msg = readMsg(); 239 237 240 //If a card is swiped, always return to the cardswipe state 238 241 switch(msg.type) 239 242 { 240 case CardSwipe d:243 case CardSwipe: 241 244 if(state.user) { 242 245 delete state.user; … … 265 268 processButtonMsg(msg); 266 269 break; 270 case Invalid: 271 return; 267 272 case Empty: 268 273 … … 274 279 //Display a thank you message for buying soda 275 280 viz->clearMsg(); 276 viz->displayMsg("Thank you for using caffeine.");281 viz->displayMsg("Thank you for using Caffeine."); 277 282 viz->clearUser(); 278 283 viz->refresh(); … … 297 302 GoToState(Idle); 298 303 } 299 usleep(100000); 304 /* I have no idea what this does other than cause caffeine to hang */ 305 /* usleep(100000); */ 300 306 } 301 307 … … 419 425 switch(msg.type) 420 426 { 421 case Empty:422 break;423 427 case ButtonPress: 424 428 for(int i=0; i < TRAY_COUNT; i++) { … … 442 446 refreshTrays(&msg); 443 447 break; 448 case Empty: 449 case Invalid: 444 450 case CardSwipe: 445 451 break; … … 469 475 470 476 //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(); 472 480 } 473 481 … … 485 493 } 486 494 495 // Read a CR+LF-terminated line of the specified length (0=any) from 496 // the serial port and store it in msg.data 497 void 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 487 517 //Read the message from the serial port 488 518 Msg SodaMachine::readMsg() 489 519 { 490 //variables for select 491 char data[80]; 520 char c; 492 521 struct timeval timeout; 493 522 fd_set rset; 494 523 int res; 495 524 Msg msg; 496 497 int i = 0;498 525 499 526 //Select on the serial port … … 503 530 FD_SET(sport, &rset); 504 531 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; 607 571 } 608 572 … … 723 687 void SodaMachine::ResetController() 724 688 { 725 char msg[3]; 726 msg[0] = 'R'; 727 msg[1] = '\n'; 728 729 sendMsg(msg, 2); 689 sendMsg("R\n", 2); 730 690 } 731 691 … … 812 772 }catch(SodaException & e) { 813 773 LogError(viz,e); 814 throw MachineException("Unable to set LED S", true);774 throw MachineException("Unable to set LEDs", true); 815 775 } 816 776 } trunk/soda/src/soda.h
r58 r79 20 20 //Number of trays in the machine 21 21 #define TRAY_COUNT 5 22 23 //Length of the button data24 //5 chars for the button state25 //1 newline26 #define BUTTON_LEN 627 28 #define SENSE_LEN 629 22 30 23 #define LED_LEN 10 … … 55 48 enum LedColor {Red, Green, Unknown}; 56 49 57 enum MsgType {Empty, CardSwipe, ButtonPress, Sense};50 enum MsgType {Empty, Invalid, CardSwipe, ButtonPress, Sense}; 58 51 59 52 struct Button … … 83 76 MsgType type; 84 77 string data; 78 Msg(MsgType type=Empty) : type(type), data("") {} 79 static const struct Msg EmptyMsg, InvalidMsg; 85 80 }; 86 81 … … 116 111 //Private functions 117 112 Msg readMsg(); 118 113 void readLineAsMsgData(Msg &msg, unsigned len); 119 114 120 115 void sendMsg(char * data, int len); 121 void runLoop();116 void runLoop(); 122 117 123 118 void processButtonMsg(Msg & msg);
