working version of song control with initialization from sd card
Dependencies: MFRC522 NRF2401P SDFileSystem SPI_TFT_ILI9341 TFT_fonts mbed
Fork of Song_Control by
hub.cpp
- Committer:
- dxyang
- Date:
- 2016-02-29
- Revision:
- 9:72e93d9ddc8c
- Parent:
- 8:b40c4553f6d4
File content as of revision 9:72e93d9ddc8c:
/** * All the code associated to run the mbed as a hub. * Link with locker */ #include "mbed.h" #include "utils.h" #include "NRF2401P.h" #include "MFRC522.h" #include "SPI_TFT_ILI9341.h" #include "Arial24x23.h" #include "SDFileSystem.h" #define debug /*************************************************************************************************/ /* Global variables */ /*************************************************************************************************/ // tx nRF2401 extern char txBuff[]; extern NRF2401P nrf1; extern int channel; long long addrLcker=0xBBBBBBBBBB; // MFRC522 RfChip (SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, MF_RESET); MFRC522 BatteryRfChipH (PTD2, PTD3, PTD1, PTE25, PTB3); MFRC522 PoshoRfChipH (PTD2, PTD3, PTD1, PTB10, PTB11); MFRC522 IncubatorRfChipH (PTD2, PTD3, PTD1, PTC11, PTC10); // tickers and flags for checking rfid statuses Ticker tickBatteryRfidH; Ticker tickPoshoRfidH; Ticker tickIncubatorRfidH; char flagBatteryRfidH = 0; char flagPoshoRfidH = 0; char flagIncubatorRfidH = 0; //SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, // PinName cs, PinName reset, PinName dc, const char* name ="TFT"); SPI_TFT_ILI9341 TFT_H(PTD2, PTD3, PTD1, PTB2, PTB20, PTB18,"TFT"); // button interrupt signals and respective flags InterruptIn buttonOneH(PTC3); InterruptIn buttonTwoH(PTC2); InterruptIn buttonThreeH(PTA2); InterruptIn buttonFourH(PTB23); char flagButtonOneH = 0; char flagButtonTwoH = 0; char flagButtonThreeH = 0; char flagButtonFourH = 0; // ticker that causes time to be displayed Ticker tickTimeCheckH; char flagTimeCheckH = 0; // ticker that causes an interrupt to update the user table every 1/2 an hour Ticker tickerUpdateUserTableH; char flagUpdateUserTableH = 0; // ticker that goes off every second unsigned char flag1sH = 0; Ticker tick1sHub; // Maximum current that each cube can consume. float currentMaxH = 1.5; // A hubUser can be assigned any of four lockers, each with a unique locker address enum LockerAddressH { lockerUnassigned, lockerOne, lockerTwo, lockerThree, lockerFour }; // The hub display screen can involve multiple stages enum HubScreenStageH { initialScanRfid, waitForRfid, batterySelectAction, batterySelectNumberForPickup, batterySelectNumberForDropoff, poshoSelectKilograms }; enum HubScreenStageH currentScreenH = initialScanRfid; // hubUser struct containing the users uid, rfid, number of batteries, current account credit, // an enum corresponding to a locker channel address, and pod ID within a locker struct hubUserH { uint32_t uid; uint32_t rfid; int32_t accountCredit; enum LockerAddressH lockerID; int32_t podID; int32_t batteriesOut; int32_t batterySubscription; }; // community ID should be defined somewhere and accessible globally uint32_t communityID_H = 1; // array to store all users and index of end of the current list hubUserH allUsersH[256]; uint8_t userCountH = 0; uint8_t currentUserH; // Data is being logged and collected // these actions depend on a known user using the system enum HubActionForLoggingH { hubAction_BatteryRfidScanned, hubAction_PoshoRfidScanned, hubAction_Exit, hubAction_OneBatteryDropped, hubAction_TwoBatteryDropped, hubAction_ThreeBatteryDropped, hubAction_OneBatteryPicked, hubAction_TwoBatteryPicked, hubAction_ThreeBatteryPicked, hubAction_OneKiloPosho, hubAction_TwoKiloPosho, hubAction_ThreeKiloPosho }; // any rfid can log errors regarding an unknown tag being read enum HubLoggingRfidSourceH { source_battery, source_posho, source_incubator }; // price per kilogram of material to be used with the posho int poshoPricePerKgH; // flag for if the posho is already in use; multiple people cannot use at once char flagPoshoAlreadyInUseH = 0; Ticker tickPoshoInUseClearH; int timeForOneKgH; int timeForTwoKgH; int timeForThreeKgH; /*************************************************************************************************/ /* Set a flag when an interrupt is detected */ /*************************************************************************************************/ /** * Time check interrupt */ void interruptTimeCheckH() { flagTimeCheckH = 1; } /** * Update user table interrupt */ void interruptUpdateUserTableH() { flagUpdateUserTableH = 1; } /** * Battery RFID reader interrupt */ void interruptBatteryRfidH() { flagBatteryRfidH = 1; } /** * Posho RFID reader interrupt */ void interruptPoshoRfidH() { flagPoshoRfidH = 1; } /** * Incubator RFID reader interrupt */ void interruptIncubatorRfidH() { flagIncubatorRfidH = 1; } /** * buttone one interrupt */ void interruptButtonOneH() { flagButtonOneH = 1; } /** * buttone two interrupt */ void interruptButtonTwoH() { flagButtonTwoH = 1; } /** * buttone three interrupt */ void interruptButtonThreeH() { flagButtonThreeH = 1; } /** * buttone four interrupt */ void interruptButtonFourH() { flagButtonFourH = 1; } /** * Fast interrupt routine for every 1 second */ void int1sH() { flag1sH=1; } /** * interrupt to clear the posho is in use flag after a designated time */ void interruptPoshoInUseClearH() { flagPoshoAlreadyInUseH = 0; tickPoshoInUseClearH.detach(); } /*************************************************************************************************/ /* Transfer Info */ /*************************************************************************************************/ /** * Sends a time stamp */ void txTimeH() { #ifdef debug printf("Send time \n\r"); #endif time_t now= time(NULL); sprintf(txBuff,"T %X",now); nrf1.transmitData(txBuff,strlen(txBuff)); #ifdef debug printf("Tx %s [nrf:%s] \n\r", txBuff,nrf1.statusString()); #endif } /** * Sends max Current */ void txCurrentH() { #ifdef debug printf("Send current \n\r"); #endif sprintf(txBuff,"I %04X", *((int *) ¤tMaxH)); nrf1.transmitData(txBuff,strlen(txBuff)); #ifdef debug printf("Tx %s [nrf:%s] \n\r", txBuff,nrf1.statusString()); #endif } /** * Slow interrupt routine for every 1 second */ void do1sH() { flag1sH = 0; #ifdef debug printf("Hub 1s \n\r"); #endif time_t now= time(NULL); if ((now % 60)==0){ txTimeH(); } txCurrentH(); #ifdef debug printf("Tx %s [nrf:%s] \n\r", txBuff,nrf1.statusString()); #endif } /** * Sends a signal to a locker that the current user is picking up numBatteries batteries * @param numBatteries - int representing number of batteries user is picking up */ void txBatteryPickUp(int numBatteries) { } /** * Sends a signal to a locker that the current user is dropping off numBatteries batteries * @param numBatteries - int representing number of batteries user is dropping off */ void txBatteryDropOff(int numBatteries) { } /** * Sends a signal to a services mbed to schedule the posho/husker for use for x kilograms * @param numKilograms - int representing number of kilograms user is processing */ void txPoshoSerialUse(int numKilograms) { } /*************************************************************************************************/ /* Initialization */ /*************************************************************************************************/ /** * Initialize system on reset and set the time from the terminal */ void initializeTimeH() { // get the current time from the terminal struct tm t; printf("Enter current date :\n\r"); printf("YYYY MM DD [enter]\n\r"); scanf("%d %d %d", &t.tm_year, &t.tm_mon, &t.tm_mday); printf("Enter current time:\n\r"); printf("HH MM SS [enter]\n\r"); scanf("%d %d %d", &t.tm_hour, &t.tm_min, &t.tm_sec); // adjust for tm structure required values t.tm_year = t.tm_year - 1900; t.tm_mon = t.tm_mon - 1; // set the time set_time(mktime(&t)); #ifdef debug printf("Time initialized\n\r"); #endif } /** * Initialize all the interrupts */ void initializeInterruptsH() { tickTimeCheckH.attach(&interruptTimeCheckH, 5.0); tickBatteryRfidH.attach(&interruptBatteryRfidH, 1.0); tickPoshoRfidH.attach(&interruptPoshoRfidH, 1.0); tickIncubatorRfidH.attach(&interruptIncubatorRfidH, 1.0); tickerUpdateUserTableH.attach(&interruptUpdateUserTableH, 1800.0); buttonOneH.rise(&interruptButtonOneH); buttonTwoH.rise(&interruptButtonTwoH); buttonThreeH.rise(&interruptButtonThreeH); buttonFourH.rise(&interruptButtonFourH); tick1sHub.attach(&int1sH, 10.0); #ifdef debug printf("Interrupts initialized\n\r"); #endif } /** * Initialize RFID readers */ void initializeRfidReadersH() { BatteryRfChipH.PCD_Init(); PoshoRfChipH.PCD_Init(); IncubatorRfChipH.PCD_Init(); #ifdef debug uint8_t tempA = BatteryRfChipH.PCD_ReadRegister(MFRC522::VersionReg); printf("Battery MFRC522 version: %d\n\r", tempA & 0x07); printf("\n\r"); uint8_t tempB = PoshoRfChipH.PCD_ReadRegister(MFRC522::VersionReg); printf("Posho MFRC522 version: %d\n\r", tempB & 0x07); printf("\n\r"); uint8_t tempC = IncubatorRfChipH.PCD_ReadRegister(MFRC522::VersionReg); printf("Incubator MFRC522 version: %d\n\r", tempC & 0x07); printf("\n\r"); #endif #ifdef debug printf("RFID readers initialized\n\r"); #endif } /** * Initialize LCD screen */ void initializeLCD_H() { TFT_H.background(Black); // set background to black TFT_H.foreground(White); // set chars to white TFT_H.cls(); // clear the screen TFT_H.set_font((unsigned char*) Arial24x23); TFT_H.set_orientation(3); //Portrait, wiring on left #ifdef debug printf("LCD initialized\n\r"); #endif } /** * Creates a new user by defining user attributes. * @param rfid - uint32_t corresponding to unique id of the RFID tag * @param accountCredit - int32 for user account balance (can be negative) * @param locker - int32_t for which locker (originaly 1-4) user is assigned * @param batterySubscription - max batteries user can get (can be 0) * @param batteriesOut - number of batteries user has out (usually 0 initially) * @param podID - pod associated with the user (originally 0-15) *must be 0 indexed* */ void createNewUserH(uint32_t rfid, int32_t accountCredit, int32_t locker, int32_t batterySubscription, int32_t batteriesOut, int32_t podID) { allUsersH[userCountH].rfid = rfid; allUsersH[userCountH].accountCredit = accountCredit; switch(locker) { case 1: allUsersH[userCountH].lockerID = lockerOne; break; case 2: allUsersH[userCountH].lockerID = lockerTwo; break; case 3: allUsersH[userCountH].lockerID = lockerThree; break; case 4: allUsersH[userCountH].lockerID = lockerFour; break; default: allUsersH[userCountH].lockerID = lockerUnassigned; break; } allUsersH[userCountH].batterySubscription = batterySubscription; allUsersH[userCountH].batteriesOut = batteriesOut; allUsersH[userCountH].podID = podID; // generate the user id, a 32 byte value // [community byte 1][community byte 2][locker byte 3][podID (1/2 byte) | 0000 (1/2 byte)] uint32_t actualUid = ((((uint32_t)communityID_H << 16) | ((uint32_t)locker << 8)) | ((uint32_t)podID << 4)); allUsersH[userCountH].uid = actualUid; userCountH++; #ifdef debug printf("UserID (decimal):%u\n\r", actualUid); printf("**************************\n\r"); #endif } /** * Initialize system with users from users.txt on SD card */ void initializeUsersFromSD_H() { spiSD(); FILE *fp = fopen("/sd/users.txt", "r"); if (fp == NULL) { #ifdef debug printf("User text file can't be opened"); #endif return; } // the first line of the user file has the headers for the following roles - get to the next line char line[180]; if (fgets(line, 180, fp) != NULL) { #ifdef debug printf("Format of text file:\n\r%s\n\r", line); printf("**************************\n\r"); #endif } // read a set of six values at a time, corresponding to a line, from the user text file. Generate a user per line. uint32_t rfid; int32_t accountCredit; int32_t locker; int32_t batterySubscription; int32_t batteriesOut; int32_t podID; while (fscanf(fp, "%u %d %d %d %d %d", &rfid, &accountCredit, &locker, &batterySubscription, &batteriesOut, &podID) != EOF) { #ifdef debug printf("rfid: %u\n\r accountCredit: %d\n\r locker: %d\n\r batterySubscription: %d\n\r batteriesOut: %d\n\r podID: %d\n\r", rfid, accountCredit, locker, batterySubscription, batteriesOut, podID); #endif createNewUserH(rfid, accountCredit, locker, batterySubscription, batteriesOut, podID); } fclose(fp); #ifdef debug printf("Users created\n\r"); #endif } /** * Initialize posho functionality */ void initializePoshoFunctionality() { spiSD(); FILE *fp = fopen("/sd/poshoInit.txt", "r"); if (fp == NULL) { #ifdef debug printf("User text file can't be opened"); #endif return; } // read a price per kg value. int32_t poshoPricePerKg; int32_t timeForOneKg; int32_t timeForTwoKg; int32_t timeForThreeKg; if (fscanf(fp,"%d %*c %*s",&poshoPricePerKg)!= 1) writeError("Posho: cannot read price to use"); if (fscanf(fp,"%d %*c %*s",&timeForOneKg)!= 1) writeError("Posho: cannot read time to use"); if (fscanf(fp,"%d %*c %*s",&timeForTwoKg)!= 1) writeError("Posho: cannot read time to use"); if (fscanf(fp,"%d %*c %*s",&timeForThreeKg)!= 1) writeError("Posho: cannot read time to use"); fclose(fp); poshoPricePerKgH = poshoPricePerKg; timeForOneKgH = timeForOneKg; timeForTwoKgH = timeForTwoKg; timeForThreeKgH = timeForThreeKg; #ifdef debug printf("Posho values initialized\n\r"); printf("Price per kg: %d\n\r", poshoPricePerKgH); printf("Time for 1: %d, 2: %d, and 3: %d kilograms\n\r", timeForOneKgH, timeForTwoKgH, timeForThreeKgH); #endif } /*************************************************************************************************/ /* Logging */ /*************************************************************************************************/ /** * Log an action from a selection of predefined actions done by the current user * Actions used with this method should require a known user to be using system * @param action - enumerated HubActionForLogging that selects from predefined actions * @param userIndex - int corresponding to the index of the user in the user table */ void logActionWithUserInfoH(enum HubActionForLoggingH action, int userIndex) { // Append to a log text file spiSD(); char * name = "/sd/HubLog.txt"; FILE *fp; fp = fopen(name, "a"); // get the time and append it to an output buffer time_t seconds = time(NULL); char logLine[180]; sprintf(logLine, "%x", seconds); // append relevant information for action switch (action) { case hubAction_BatteryRfidScanned: strcat(logLine, " RB "); break; case hubAction_PoshoRfidScanned: strcat(logLine, " RP "); break; case hubAction_Exit: strcat(logLine, " X "); break; case hubAction_OneBatteryDropped: strcat(logLine, " BD 1 "); break; case hubAction_TwoBatteryDropped: strcat(logLine, " BD 2 "); break; case hubAction_ThreeBatteryDropped: strcat(logLine, " BD 3 "); break; case hubAction_OneBatteryPicked: strcat(logLine, " BP 1 "); break; case hubAction_TwoBatteryPicked: strcat(logLine, " BP 2 "); break; case hubAction_ThreeBatteryPicked: strcat(logLine, " BP 3 "); break; case hubAction_OneKiloPosho: strcat(logLine, " PO 1 "); break; case hubAction_TwoKiloPosho: strcat(logLine, " PO 2 "); break; case hubAction_ThreeKiloPosho: strcat(logLine, " PO 3 "); break; } // append general user information char rfidBuffer[20]; char uidBuffer[20]; char acctBalanceBuffer[20]; sprintf(rfidBuffer, "%u ", allUsersH[userIndex].rfid); sprintf(uidBuffer, "%u ", allUsersH[userIndex].uid); sprintf(acctBalanceBuffer, "%d\n", allUsersH[userIndex].accountCredit); strcat(logLine, rfidBuffer); strcat(logLine, uidBuffer); strcat(logLine, acctBalanceBuffer); // write the line to the log file and close the file fputs(logLine, fp); fclose(fp); #ifdef debug printf("%s\n\r", logLine); #endif } /** * Log an error - RFID not associated with a known user is scanned * @param unknownRfid - uint32 for the unique ID of the unknown rfid tag */ void logErrorUnknownRfidScannedH(uint32_t unknownRfid, HubLoggingRfidSourceH source) { // Append to a log text file char * name = "/sd/HubLog.txt"; spiSD(); FILE *fp; fp = fopen(name, "a"); // get the time and append it to an output buffer time_t seconds = time(NULL); char logLine[180]; sprintf(logLine, "%x", seconds); // RFID action switch (source) { case source_battery: strcat(logLine, " R X B "); break; case source_posho: strcat(logLine, " R X P"); break; case source_incubator: strcat(logLine, " R X I"); break; } // include just the RFID (indicates that no known user was found) char rfidBuffer[20]; sprintf(rfidBuffer, "%u ", unknownRfid); strcat(logLine, rfidBuffer); strcat(logLine, "\n"); // write the line to the log file and close the file fputs(logLine, fp); fclose(fp); #ifdef debug printf("%s\n\r", logLine); #endif } /*************************************************************************************************/ /* Housekeeping - flag clearing, cancelling, check time, update user table */ /*************************************************************************************************/ /* * Reset all user initiated flags. Useful after sequences of events where flags may have * piled up from misc inputs and you don't want the system to act seemingly sporadically. */ void clearAllUserInitiatedFlagsH() { flagButtonOneH = 0; flagButtonTwoH = 0; flagButtonThreeH = 0; flagButtonFourH = 0; flagBatteryRfidH = 0; flagPoshoRfidH = 0; flagIncubatorRfidH = 0; } /* * User presses the button corresponding to an exit. Returns to home screen * after logging the action. * @param userIndex - int representing index of user in user table */ void cancelPressedH(int userIndex) { clearAllUserInitiatedFlagsH(); currentScreenH = initialScanRfid; logActionWithUserInfoH(hubAction_Exit, userIndex); } /** * Do if time check flag is set * reads the unix time, converts into human readable format, and displays on PC */ void doTimeCheckH() { flagTimeCheckH = 0; time_t seconds = time(NULL); printf("%s\n\r", ctime(&seconds)); } /** * Do if update user table flag is set */ void doUpdateUserTableH() { flagUpdateUserTableH = 0; // Write to a users.txt file spiSD(); char * name = "/sd/users.txt"; FILE *fp; fp = fopen(name, "w"); // output the header for the users.txt file fputs("rfid accountCredit locker batterySubscription batteriesOut podID\n", fp); // output buffer char logLine[180]; for (int i = 0; i < userCountH; i++) { // get all the needed information in strings sprintf(logLine, "%u ", allUsersH[i].rfid); char accountCreditBuffer[20]; char* lockerBuffer; char batterySubscriptionBuffer[20]; char batteriesOutBuffer[20]; char podIdBuffer[20]; sprintf(accountCreditBuffer, "%d ", allUsersH[i].accountCredit); switch (allUsersH[i].lockerID) { case lockerOne: lockerBuffer = "1 "; break; case lockerTwo: lockerBuffer = "2 "; break; case lockerThree: lockerBuffer = "3 "; break; case lockerFour: lockerBuffer = "4 "; break; case lockerUnassigned: default: lockerBuffer = "0 "; break; } sprintf(batterySubscriptionBuffer, "%d ", allUsersH[i].batterySubscription); sprintf(batteriesOutBuffer, "%d ", allUsersH[i].batteriesOut); sprintf(podIdBuffer, "%d\n", allUsersH[i].podID); // concatenate all the strings strcat(logLine, accountCreditBuffer); strcat(logLine, lockerBuffer); strcat(logLine, batterySubscriptionBuffer); strcat(logLine, batteriesOutBuffer); strcat(logLine, podIdBuffer); // write the line to the log file fputs(logLine, fp); #ifdef debug printf("%s\n\r", logLine); #endif } fclose(fp); } /*************************************************************************************************/ /* Battery Services */ /*************************************************************************************************/ /** * Do if Battery RFID flag is set. Read RFID tag and check user status. * If there's a valid battery subscription, display drop off and/or pick up. * Otherwise, returns to initial screen. */ void doBatteryRfidH() { flagBatteryRfidH = 0; // is there a new readable card? if (!BatteryRfChipH.PICC_IsNewCardPresent()) { return; } if (!BatteryRfChipH.PICC_ReadCardSerial()) { #ifdef debug printf("Card not readable\n\r"); #endif return; } // get the id of the scanned tag uint8_t tempReadingRfid[4]; for(uint8_t i = 0; i < BatteryRfChipH.uid.size; i++) { tempReadingRfid[i] = BatteryRfChipH.uid.uidByte[i]; } // concatenate the 4 bytes into a single integer via bit shifting uint32_t actualRfid = ((((uint32_t)tempReadingRfid[0] << 24) | ((uint32_t)tempReadingRfid[1] << 16)) | (((uint32_t)tempReadingRfid[2] << 8) | ((uint32_t)tempReadingRfid[3] << 0))); // find the user info char foundUserFlag = 0; int foundUserIndex; for (int i = 0; i < userCountH; i++) { if (allUsersH[i].rfid == actualRfid) { currentUserH = i; foundUserIndex = i; foundUserFlag = 1; break; } } // if the user is found, set the global variable for current user interacting with the system // if the user isn't found, log that an rfid without a user was used and display if (!foundUserFlag) { #ifdef debug printf("User not found\n\r"); printf("ID:%u\n\r", actualRfid); #endif // log the error interaction logErrorUnknownRfidScannedH(actualRfid, source_battery); // let user know tag wasn't found TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("User not found\n\r"); TFT_H.printf("ID:%u\n\r", actualRfid); wait(1); currentScreenH = initialScanRfid; return; } // log user scan logActionWithUserInfoH(hubAction_BatteryRfidScanned, foundUserIndex); // Display info about the user char authorizationFlag = 0; TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("UserID: %u\n\r", actualRfid); TFT_H.printf("Balance:%d\n\r", allUsersH[foundUserIndex].accountCredit); if (allUsersH[foundUserIndex].batterySubscription > 0) { authorizationFlag = 1; } TFT_H.printf("Authorization:%s\n\r", (authorizationFlag)? "YES":"NO"); #ifdef debug printf("User:"); for(uint8_t i = 0; i < BatteryRfChipH.uid.size; i++) { uint8_t uidByte = BatteryRfChipH.uid.uidByte[i]; printf(" %d", uidByte); } printf("\n\rUserID: %u\n\r", actualRfid); #endif // if not authorized for batteries, return to main screen wait(1); if (!authorizationFlag) { currentScreenH = initialScanRfid; return; } // otherwise, ask user if the user wants to pick up or drop off batteries? TFT_H.locate(0,160); TFT_H.printf("Battery Action?\n\r"); TFT_H.locate(0,200); uint8_t maxBatteries = allUsersH[foundUserIndex].batterySubscription; uint8_t outBatteries = allUsersH[foundUserIndex].batteriesOut; if ((maxBatteries - outBatteries) == 0) { // can only drop off TFT_H.printf(" drop exit"); } else if (outBatteries == 0) { // can only pick up TFT_H.printf(" pick exit"); } else { // can pickup or dropoff TFT_H.printf(" pick drop exit"); } // go to action selecting screen and clear buttons beforehand currentScreenH = batterySelectAction; clearAllUserInitiatedFlagsH(); return; } /** * Do if user selects to pickup a battery. Determines how many batteries * a user can pickup based off user info and displays corresponding text * @param userIndex - int representing index of user in user table */ void batteryPickUpH(int userIndex) { TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("UserID: %u\n\r\n\r", allUsersH[userIndex].rfid); TFT_H.printf("Action: PICK UP\n\r"); TFT_H.locate(0,160); TFT_H.printf("How many batteries?\n\r"); TFT_H.locate(0,200); switch (allUsersH[userIndex].batterySubscription - allUsersH[userIndex].batteriesOut) { case 1: { TFT_H.printf(" 1 exit"); break; } case 2: { TFT_H.printf(" 1 2 exit"); break; } case 3: { TFT_H.printf(" 1 2 3 exit"); break; } } // go to wait for selection input and reset button flags currentScreenH = batterySelectNumberForPickup; clearAllUserInitiatedFlagsH(); return; } /** * Do if user selects to dropoff a battery. Determines how many batteries * a user can pickup based off user info and displays corresponding text * @param userIndex - int representing index of user in user table */ void batteryDropOffH(int userIndex) { TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("UserID: %u\n\r\n\r", allUsersH[userIndex].rfid); TFT_H.printf("Action: DROP OFF\n\r"); TFT_H.locate(0,160); TFT_H.printf("How many batteries?\n\r"); TFT_H.locate(0,200); switch (allUsersH[userIndex].batteriesOut) { case 1: { TFT_H.printf(" 1 exit"); break; } case 2: { TFT_H.printf(" 1 2 exit"); break; } case 3: { TFT_H.printf(" 1 2 3 exit"); break; } } // go to wait for selection input and reset button flags currentScreenH = batterySelectNumberForDropoff; clearAllUserInitiatedFlagsH(); return; } /** * Do after use selects number of batteries to drop off. * Logs the action, changes user info, transmits instructions to other systems * @param numBatteries - int for number of batteries selected to drop off * @param userIndex - int representing index of user in user table */ void batteryDropOffH(int numBatteries, int userIndex) { switch(numBatteries) { case 1: logActionWithUserInfoH(hubAction_OneBatteryDropped, userIndex); txBatteryDropOff(1); allUsersH[userIndex].batteriesOut--; break; case 2: logActionWithUserInfoH(hubAction_TwoBatteryDropped, userIndex); txBatteryDropOff(2); allUsersH[userIndex].batteriesOut -= 2; break; case 3: logActionWithUserInfoH(hubAction_ThreeBatteryDropped, userIndex); txBatteryDropOff(3); allUsersH[userIndex].batteriesOut -= 3; break; } currentScreenH = initialScanRfid; return; } /** * Do after use selects number of batteries to pick up. * Logs the action, changes user info, transmits instructions to other systems * @param numBatteries - int for number of batteries selected to pick up * @param userIndex - int representing index of user in user table */ void batteryPickUpH(int numBatteries, int userIndex) { switch(numBatteries) { case 1: logActionWithUserInfoH(hubAction_OneBatteryPicked, userIndex); txBatteryPickUp(1); allUsersH[userIndex].batteriesOut++; break; case 2: logActionWithUserInfoH(hubAction_TwoBatteryPicked, userIndex); txBatteryPickUp(2); allUsersH[userIndex].batteriesOut += 2; break; case 3: logActionWithUserInfoH(hubAction_ThreeBatteryPicked, userIndex); txBatteryPickUp(3); allUsersH[userIndex].batteriesOut += 3; break; } currentScreenH = initialScanRfid; return; } /*************************************************************************************************/ /* Misc Services */ /*************************************************************************************************/ /** * Do if Posho RFID flag is set. Reads rfid and checks user table for a positive balance. */ void doPoshoRfidH() { flagPoshoRfidH = 0; // is there a new readable card? if (!PoshoRfChipH.PICC_IsNewCardPresent()) { return; } if (!PoshoRfChipH.PICC_ReadCardSerial()) { #ifdef debug printf("Card not readable\n\r"); #endif return; } // is the posho already in use? if (flagPoshoAlreadyInUseH) { TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("Posho in use\n\r"); wait(1); currentScreenH = initialScanRfid; return; } // get the id of the scanned tag uint8_t tempReadingRfid[4]; for(uint8_t i = 0; i < PoshoRfChipH.uid.size; i++) { tempReadingRfid[i] = PoshoRfChipH.uid.uidByte[i]; } // concatenate the 4 bytes into a single integer via bit shifting uint32_t actualRfid = ((((uint32_t)tempReadingRfid[0] << 24) | ((uint32_t)tempReadingRfid[1] << 16)) | (((uint32_t)tempReadingRfid[2] << 8) | ((uint32_t)tempReadingRfid[3] << 0))); // find the user info char foundUserFlag = 0; int foundUserIndex; for (int i = 0; i < userCountH; i++) { if (allUsersH[i].rfid == actualRfid) { currentUserH = i; foundUserIndex = i; foundUserFlag = 1; break; } } // if the user is found, set the global variable for current user interacting with the system // if the user isn't found, log that an rfid without a user was used and display if (!foundUserFlag) { #ifdef debug printf("User not found\n\r"); printf("ID:%u\n\r", actualRfid); #endif // log the error interaction logErrorUnknownRfidScannedH(actualRfid, source_posho); // let user know tag wasn't found TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("User not found\n\r"); TFT_H.printf("ID:%u\n\r", actualRfid); wait(1); currentScreenH = initialScanRfid; return; } // log user scan logActionWithUserInfoH(hubAction_PoshoRfidScanned, foundUserIndex); // Display info about the user char authorizationFlag = 0; TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("UserID: %u\n\r", actualRfid); int userAccountBalance = allUsersH[foundUserIndex].accountCredit; TFT_H.printf("Balance:%d\n\r", userAccountBalance); if (userAccountBalance > 1*poshoPricePerKgH) { authorizationFlag = 1; } TFT_H.printf("Authorization:%s\n\r", (authorizationFlag)? "YES":"NO"); // if not authorized for batteries, return to main screen wait(1); if (!authorizationFlag) { currentScreenH = initialScanRfid; return; } // otherwise, ask user how may kg of material to process? TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("UserID: %u\n\r\n\r", actualRfid); TFT_H.printf("Action: Posho\n\r"); TFT_H.locate(0,160); TFT_H.printf("How many kilos?\n\r"); TFT_H.locate(0,200); if (userAccountBalance > 3*poshoPricePerKgH) { TFT_H.printf(" 1 2 3 exit"); } else if (userAccountBalance > 2*poshoPricePerKgH) { TFT_H.printf(" 1 2 exit"); } else { TFT_H.printf(" 1 exit"); } // go to wait for selection input and reset button flags currentScreenH = poshoSelectKilograms; clearAllUserInitiatedFlagsH(); return; } /** * Prepare to active the posho and husker for serial use. Change user balance as necessary * and send corresponding signal. * @param numKilograms - int for number of kilograms to be processed * @param userIndex - int representing index of user in user table */ void poshoSerialUse(int numKilograms, int userIndex) { flagPoshoAlreadyInUseH = 1; switch (numKilograms) { case 1: tickPoshoInUseClearH.attach(&interruptPoshoInUseClearH, (float)timeForOneKgH); logActionWithUserInfoH(hubAction_OneKiloPosho, userIndex); break; case 2: tickPoshoInUseClearH.attach(&interruptPoshoInUseClearH, (float)timeForTwoKgH); logActionWithUserInfoH(hubAction_TwoKiloPosho, userIndex); break; case 3: tickPoshoInUseClearH.attach(&interruptPoshoInUseClearH, (float)timeForThreeKgH); logActionWithUserInfoH(hubAction_ThreeKiloPosho, userIndex); break; } allUsersH[userIndex].accountCredit -= numKilograms*poshoPricePerKgH; TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("UserID: %u\n\r\n\r", allUsersH[userIndex].rfid); TFT_H.printf("New balance: %d\n\r", allUsersH[userIndex].accountCredit); txPoshoSerialUse(numKilograms); wait(1); currentScreenH = initialScanRfid; return; } /** * Do if Incubator RFID flag is set. Add incubator functionality later. */ void doIncubatorRfidH() { flagIncubatorRfidH = 0; } /*************************************************************************************************/ /* Public Methods */ /*************************************************************************************************/ /** * Initialise for a hub * fp is the config file if additonal information is needed. */ void initialiseHub(FILE *fp){ #ifdef debug printf("Initializing Hub\n\r"); #endif // Read in hub address and channel if (fscanf (fp,"%x %*c %*s",&channel )!=1) writeError("Hub config: cannot read channel"); if (fscanf (fp,"%llx %*c %*s",&addrLcker )!=1) writeError("Hub config: cannot read hub address"); #ifdef debug printf(" Channel:%x, Hub Address %llx \n\r",channel, addrLcker); #endif // Setup nrf #ifdef debug printf("Steup doNrf \n\r"); #endif spiNrf(); nrf1.quickTxSetup(channel, addrLcker); #ifdef debug nrf1.printDetails(); nrf1.checkStatus(); printf("Setup doNrf complete [nrf:%s]\n\r",nrf1.statusString()); #endif // Other initialization routines initializeTimeH(); initializeInterruptsH(); initializeRfidReadersH(); initializeLCD_H(); initializeUsersFromSD_H(); initializePoshoFunctionality(); } void loopHub(){ while (true) { // put interrupts here that should supercede anything else if (flag1sH) { do1sH(); } // put interrupts here that may be active depending on screen stage switch(currentScreenH) { case initialScanRfid: { TFT_H.cls(); TFT_H.locate(0,0); TFT_H.printf("Please scan your ID"); currentScreenH = waitForRfid; clearAllUserInitiatedFlagsH(); } case waitForRfid: { if (flagTimeCheckH) doTimeCheckH(); if (flagBatteryRfidH) doBatteryRfidH(); if (flagPoshoRfidH) doPoshoRfidH(); if (flagIncubatorRfidH) doIncubatorRfidH(); if (flagUpdateUserTableH) doUpdateUserTableH(); break; } case batterySelectAction: { uint8_t maxBatteries = allUsersH[currentUserH].batterySubscription; uint8_t outBatteries = allUsersH[currentUserH].batteriesOut; if ((maxBatteries - outBatteries) == 0) { if (flagButtonOneH) batteryDropOffH(currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else if (outBatteries == 0) { if (flagButtonOneH) batteryPickUpH(currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else { if (flagButtonOneH) batteryPickUpH(currentUserH); if (flagButtonThreeH) batteryDropOffH(currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } break; } case batterySelectNumberForDropoff: { switch (allUsersH[currentUserH].batteriesOut) { case 1: { if (flagButtonOneH) batteryDropOffH(1, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); break; } case 2: { if (flagButtonOneH) batteryDropOffH(1, currentUserH); if (flagButtonTwoH) batteryDropOffH(2, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); break; } case 3: { if (flagButtonOneH) batteryDropOffH(1, currentUserH); if (flagButtonTwoH) batteryDropOffH(2, currentUserH); if (flagButtonThreeH) batteryDropOffH(3, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); break; } } break; } case batterySelectNumberForPickup: { switch (allUsersH[currentUserH].batterySubscription - allUsersH[currentUserH].batteriesOut) { case 1: { if (flagButtonOneH) batteryPickUpH(1, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); break; } case 2: { if (flagButtonOneH) batteryPickUpH(1, currentUserH); if (flagButtonTwoH) batteryPickUpH(2, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); break; } case 3: { if (flagButtonOneH) batteryPickUpH(1, currentUserH); if (flagButtonTwoH) batteryPickUpH(2, currentUserH); if (flagButtonThreeH) batteryPickUpH(3, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); break; } } break; } case poshoSelectKilograms: { if (allUsersH[currentUserH].accountCredit > 3*poshoPricePerKgH) { if (flagButtonOneH) poshoSerialUse(1, currentUserH); if (flagButtonTwoH) poshoSerialUse(2, currentUserH); if (flagButtonThreeH) poshoSerialUse(3, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else if (allUsersH[currentUserH].accountCredit > 2*poshoPricePerKgH) { if (flagButtonOneH) poshoSerialUse(1, currentUserH); if (flagButtonTwoH) poshoSerialUse(2, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else { if (flagButtonOneH) poshoSerialUse(1, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } } } } }