The field version of the solarnano grid on the ionQubes
Fork of SolarNanoGridv3 by
Hmi/Hmi.cpp
- Committer:
- defrost
- Date:
- 2016-09-06
- Revision:
- 36:a5620262f296
- Parent:
- 13:de43f28c0365
File content as of revision 36:a5620262f296:
/** *@section DESCRIPTION * mbed SolarNanogrid Library * Hmi extends SolarNanoGrid. * Hmi does the human interface and talks to the lockers. * The ID must be in FF 00. *@section LICENSE * Copyright (c) 2016, Malcolm McCulloch * * 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. * @file "Hmi.c" */ #include <Hmi/Hmi.h> #define FUNCNAME "HMI" #include "defs.h" Hmi::Hmi(FILE* fp, Serial *pc) : SolarNanoGrid(fp,pc) { DBG("Initialize class"); // No other information needed from the config file fclose(fp); DBG("Create hardware"); // // Create Hardware // // // Setup NRF // baseAddr = ((long long) communityID << 16) + (id & 0XFFFF); utilityAddr = baseAddr & 0XFFFFFF0000 | 0xFE00; //utilityAddr = 0x26c1e10100; DBG(" Channel:%x, Address %llx Utility Address %llx", chan, baseAddr, utilityAddr); spiNRF(); nrf->quickTxSetup(chan, utilityAddr); nrf->setRadio(0x01, 0x03); // 2MB/S 0dB nrf->setTxRetry(0x0F, 0x0F); nrfFlush(); DBG("Nrf Details:"); #ifdef DEBUG nrf->printDetails(); #endif // spiNRF(); // sprintf(dataTx,"Testing"); // DBG("Send :%s",dataTx); // nrf->transmitData(dataTx,strlen(dataTx)); DBG("Create hardware RFID"); // RFID BatteryRfChipH = new MFRC522(PTD2, PTD3, PTD1, PTB2, PTB3); PoshoRfChipH = new MFRC522 (PTD2, PTD3, PTD1, PTB10, PTB11); IncubatorRfChipH = new MFRC522 (PTD2, PTD3, PTD1, PTC11, PTC10); DBG("Create hardware TFT"); //Screen TFT_H = new SPI_TFT_ILI9341(PTD2, PTD3, PTD1, PTE25, PTB20, PTB18,"TFT"); /**< LCD Display */ DBG("Create hardware Buttons"); // Buttons buttonOneH= new InterruptIn(PTC3); // Button one interrupt buttonTwoH = new InterruptIn (PTC2); // Button two interrupt buttonThreeH = new InterruptIn (PTA2); // Button three interrupt buttonFourH = new InterruptIn (PTB23); // Button four interrupt DBG("Create hardware Tickers"); // Create Timers tick1sHub = new Ticker(); /**< Every second time check */ tickBatteryRfidH = new Ticker(); /**< Battery Rfid check */ tickIncubatorRfidH = new Ticker(); /**< Incubator Rfid check */ tickPoshoRfidH = new Ticker(); /**< Posho Rfid check */ tickTimeCheckH = new Ticker(); /**< Time check for terminal display */ tickerUpdateUserTableH = new Ticker(); /**< Update user table to SD card ticker (every 30 min) */ spiSD(); DBG("Initialise flags"); // // Initialise flags // flagBatteryRfidH =0 ; /**< Battery Rfid flag */ flagButtonOneH = 0; /**< Button one flag */ flagButtonTwoH = 0; /**< Button two flag */ flagButtonThreeH = 0; /**< Button three flag */ flagButtonFourH = 0; /**< Button four flag */ flagPoshoRfidH =0; /**< Posho Rfid flag */ flagIncubatorRfidH =0; /**< Incubator Rfid flag */ flagTimeCheckH = 0; flagUpdateUserTableH = 0; /**< Update user table to SD card ticker */ flag1sH = 0; /**< Every second flag */ DBG("Initialise variables"); // // Initialise variables // currentScreenH = initialScanRfid; currentMaxH = 1.5; userCountH = 0; /**< Number of active users on this hub mbed */ currentUserH=0; /**< Index of the current user */ DBG("Initialise variables Posho"); poshoPricePerKgH = -1; /**< price per kg of material to be used with the posho */ timeForOneKgH = 0; /**< time for one kg of material to be used with the posho */ timeForTwoKgH = 0; /**< time for two kg of material to be used with the posho */ timeForThreeKgH=0; /**< time for three kg of material to be used with the posho */ flagPoshoAlreadyInUseH = 0; allUsersH = (HubUser *)calloc(256, sizeof(HubUser)); // // Initialise Hardware // DBG("Initialise hardware RFID"); //RFID BatteryRfChipH->PCD_Init(); PoshoRfChipH->PCD_Init(); IncubatorRfChipH->PCD_Init(); uint8_t tempA = BatteryRfChipH->PCD_ReadRegister(MFRC522::VersionReg); DBG("Battery MFRC522 version: %d\n\r", tempA & 0x07); uint8_t tempB = PoshoRfChipH->PCD_ReadRegister(MFRC522::VersionReg); DBG("Posho MFRC522 version: %d\n\r", tempB & 0x07); uint8_t tempC = IncubatorRfChipH->PCD_ReadRegister(MFRC522::VersionReg); DBG("Incubator MFRC522 version: %d\n\r", tempC & 0x07); DBG("Initialise hardware TFT"); // TFT Screen 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 // // Attach interrupts // DBG("Attach interrupts Buttons"); // Buttons buttonOneH->rise(this, &Hmi::interruptButtonOneH); buttonTwoH->rise(this, &Hmi::interruptButtonTwoH); buttonThreeH->rise(this, &Hmi::interruptButtonThreeH); buttonFourH->rise(this, &Hmi::interruptButtonFourH); DBG("Attach interrupts Timers"); //Timers tick1sHub->attach(this, &Hmi::int1sH, 10.0); tickBatteryRfidH->attach(this, &Hmi::interruptBatteryRfidH, 1.0); tickIncubatorRfidH->attach(this, &Hmi::interruptIncubatorRfidH, 1.0); tickPoshoRfidH->attach(this, &Hmi::interruptPoshoRfidH, 1.0); tickTimeCheckH->attach(this, &Hmi::interruptTimeCheckH, 5.0); tickerUpdateUserTableH->attach(this, &Hmi::interruptUpdateUserTableH, 1800.0); DBG("Posho "); //while (poshoPricePerKgH == -1) initializePoshoFunctionalityH(); DBG("Users "); initializeUsersFromSD_H(); loopHub(); } /** * 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 - int32_t max batteries user can get (can be 0) * @param batteriesOut - int32_t number of batteries user has out (usually 0 initially) * @param pod - int32_t pod associated with the user (originally 0-15) *must be 0 indexed* */ void Hmi::createNewUserH(uint32_t rfid, int32_t accountCredit, int32_t locker, int32_t batterySubscription, int32_t batteriesOut, int32_t pod, char* name) { // uid: [community byte][community byte][locker byte][podID (1/2 byte) | 0000 (1/2 byte)] uint32_t actualUid = ((((uint32_t)communityID << 16) | ((uint32_t)locker << 8)) | ((uint32_t)pod << 4)); allUsersH[userCountH] = HubUser(actualUid, rfid, accountCredit, locker, pod, batteriesOut, batterySubscription, name); userCountH++; DBG("rfid: %u accountCredit: %d", rfid,accountCredit); DBG("UserID (hex):%x Name: %s", actualUid,name); DBG("locker: %d pod: %d ", locker,pod); DBG("batterySubscription: %d batteriesOut: %d", batterySubscription, batteriesOut); } /** * Initialize Global User Table Variable with malloc * @param users - int representing how many users you want the system to hold */ void Hmi::initializeGlobalUserTableH(int users) { allUsersH = (HubUser *)calloc(users, sizeof(HubUser)); } /** * Initialize posho functionality */ void Hmi::initializePoshoFunctionalityH() { spiSD(); FILE *fp = fopen("/sd/poshoInit.txt", "r"); if (fp == NULL) { WARN("Posho text file can't be opened"); return; } if (fscanf(fp,"%d %*c %*s",&poshoPricePerKgH)!= 1) ERR("Posho: cannot read price"); if (fscanf(fp,"%d %*c %*s",&timeForOneKgH)!= 1) ERR("Posho: cannot read time"); if (fscanf(fp,"%d %*c %*s",&timeForTwoKgH)!= 1) ERR("Posho: cannot read time"); if (fscanf(fp,"%d %*c %*s",&timeForThreeKgH)!= 1) ERR("Posho: cannot read time"); fclose(fp); DBG("Posho values initialized\n\r"); DBG("Price per kg: %d\n\r", poshoPricePerKgH); DBG("Time 1: %d, 2: %d, and 3: %d\n\r", timeForOneKgH, timeForTwoKgH, timeForThreeKgH); } /** * Initialize system with users from users.txt on SD card */ void Hmi::initializeUsersFromSD_H() { spiSD(); FILE *fp = fopen("/sd/users.txt", "r"); if (fp == NULL) { WARN("User text file can't be opened\n\r"); return; } // first line of the user file has the headers - get to the next line char line[180]; if (fgets(line, 100, fp) != NULL) { DBG("user.txt: Format of text file:|%s|", line); } // read a set of six values at a time, corresponding to a line, from the user text file uint32_t rfid; int32_t accountCredit; int32_t locker; int32_t batterySubscription; int32_t batteriesOut; int32_t pod; char* name; while(fgets(line, 100, fp) != NULL){ //DBG("Line = [%s]",line); name = (char *) calloc(32,1); // rfid Credit lckr pod maxBatt outBatt Name sscanf(line, "%u %d %d %d %d %d %s", &rfid, &accountCredit, &locker, &pod, &batterySubscription, &batteriesOut, name); createNewUserH(rfid, accountCredit, locker, batterySubscription, batteriesOut, pod,name); //| Rfid number (%d) | Community ID (%d) |Locker ID (%d) |Pod ID (%d)| Battery Subscriptton(%d)| Battery Out| Name } fclose(fp); } /*************************************************************************************************/ /* Set a flag when an interrupt is detected */ /*************************************************************************************************/ /** * Time check interrupt */ void Hmi::interruptTimeCheckH() { flagTimeCheckH = 1; } /** * Update user table interrupt */ void Hmi::interruptUpdateUserTableH() { flagUpdateUserTableH = 1; } /** * Battery RFID reader interrupt */ void Hmi::interruptBatteryRfidH() { flagBatteryRfidH = 1; } /** * Posho RFID reader interrupt */ void Hmi::interruptPoshoRfidH() { flagPoshoRfidH = 1; } /** * Incubator RFID reader interrupt */ void Hmi::interruptIncubatorRfidH() { flagIncubatorRfidH = 1; } /** * buttone one interrupt */ void Hmi::interruptButtonOneH() { flagButtonOneH = 1; } /** * buttone two interrupt */ void Hmi::interruptButtonTwoH() { flagButtonTwoH = 1; } /** * buttone three interrupt */ void Hmi::interruptButtonThreeH() { flagButtonThreeH = 1; } /** * buttone four interrupt */ void Hmi::interruptButtonFourH() { flagButtonFourH = 1; } /** * Fast interrupt routine for every 1 second */ void Hmi::int1sH() { flag1sH=1; } /** * interrupt to clear the posho is in use flag after a designated time */ void Hmi::interruptPoshoInUseClearH() { flagPoshoAlreadyInUseH = 0; tickPoshoInUseClearH.detach(); } /*************************************************************************************************/ /* * 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 Hmi::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 Hmi::cancelPressedH(int userIndex) { clearAllUserInitiatedFlagsH(); currentScreenH = initialScanRfid; logActionWithUserInfo(hubAction_Exit, &allUsersH[userIndex]); } /** * Do if time check flag is set * reads the unix time, converts into human readable format, and displays on PC */ void Hmi::doTimeCheckH() { flagTimeCheckH = 0; time_t seconds = time(NULL); INFO("%s\n\r", ctime(&seconds)); // spiNRF(); // sprintf(dataTx,"hello 1 1"); // DBG("Send :%s",dataTx); // nrf->transmitData(dataTx,strlen(dataTx)); } /** * Do if update user table flag is set */ void Hmi::doUpdateUserTableH() { DBG("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 spiSD(); fputs("rfid Credit lckr pod maxBatt outBatt Name\n\r", fp); // output buffer char logLine[180]; for (int i = 0; i < userCountH; i++) { // get all the needed information in strings spiSD(); fprintf(fp, "%u %d %d %d %d %d %s\n\r", allUsersH[i].getRfid(), allUsersH[i].getCredit(), allUsersH[i].getLocker(), allUsersH[i].getPod(), allUsersH[i].getBatteriesMax(), allUsersH[i].getBatteriesOut(), allUsersH[i].getName()); } spiSD(); fclose(fp); } /*************************************************************************************************/ /* RFID support */ /*************************************************************************************************/ /** * Read Rfid card and parse out the tag id into a single integer. Log if tag is either known * or unknown. Sets the global variable for the current user if a user is found. * @param rfidReader - MFRC522* of the RFID reader * @param source - HubLoggingRfidSource enum for which RFID reader (battery, posho, incubator) * @return int representing the userIndex of the HubUser found by the RFID tag. If no user is found, returns a -1. */ int Hmi::rfidReadHelper(MFRC522 *rfidReader, enum HubLoggingRfidSource source) { if (!rfidReader->PICC_IsNewCardPresent()) { return -1; } if (!rfidReader->PICC_ReadCardSerial()) { #ifdef debug printf("Card not readable\n\r"); #endif return -1; } // if this is for the posho, is the posho already in use? if ((source == source_posho) && flagPoshoAlreadyInUseH) { TFT_H->cls(); TFT_H->locate(0,0); TFT_H->printf("Posho in use\n\r"); wait(1); currentScreenH = initialScanRfid; return -1; } // get the id of the scanned tag uint8_t tempReadingRfid[4]; for(uint8_t i = 0; i < rfidReader->uid.size; i++) { tempReadingRfid[i] = rfidReader->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))); #ifdef debug printf("User:"); for(uint8_t i = 0; i < rfidReader->uid.size; i++) { uint8_t uidByte = rfidReader->uid.uidByte[i]; printf(" %d", uidByte); } printf("\n\rUserID: %u\n\r", actualRfid); #endif // find the user info char foundUserFlag = 0; int foundUserIndex; for (int i = 0; i < userCountH; i++) { if (allUsersH[i].getRfid() == actualRfid) { currentUserH = i; foundUserIndex = i; foundUserFlag = 1; break; } } // if the user isn't found, log that an rfid without a user was used and display home screen if (!foundUserFlag) { #ifdef debug printf("User not found\n\r"); printf("ID:%u\n\r", actualRfid); #endif // log the error interaction logErrorUnknownRfidScanned(actualRfid, source); // 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 -1; } // log user scan switch (source) { case source_battery: logActionWithUserInfo(hubAction_BatteryRfidScanned, &allUsersH[foundUserIndex]); break; case source_posho: logActionWithUserInfo(hubAction_PoshoRfidScanned, &allUsersH[foundUserIndex]); break; case source_incubator: logActionWithUserInfo(hubAction_IncubatorRfidScanned, &allUsersH[foundUserIndex]); break; } return foundUserIndex; } /*************************************************************************************************/ /* 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 Hmi::doBatteryRfidH() { flagBatteryRfidH = 0; // let the RF reader get tag info int foundUserIndex = rfidReadHelper(BatteryRfChipH, source_battery); if (foundUserIndex == -1) return; // Display info about the user - authorized for batteries? char authorizationFlag = 0; TFT_H->cls(); TFT_H->locate(0,0); TFT_H->printf("UserID: %d\n\r", allUsersH[foundUserIndex].getRfid()); TFT_H->printf("Name: %s\n\r", allUsersH[foundUserIndex].getName()); if (allUsersH[foundUserIndex].getBatteriesMax() > 0) { authorizationFlag = 1; } if (authorizationFlag){ TFT_H->printf("Locker: %u\n\r", allUsersH[foundUserIndex].getLocker()); TFT_H->printf("Pod: %u\n\r\n\r", allUsersH[foundUserIndex].getPod()); TFT_H->printf("Balance:%d\n\r", allUsersH[foundUserIndex].getCredit()); }else{ TFT_H->printf("\n\rSorry, you do not \n\rhave any batteries\n\ron this system. \n\r"); } // if not authorized for batteries, return to main screen wait(1); if (!authorizationFlag) { wait(2.0); 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].getBatteriesMax(); uint8_t outBatteries = allUsersH[foundUserIndex].getBatteriesOut(); 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 Hmi::batteryPickUpScreenH(int userIndex) { TFT_H->cls(); TFT_H->locate(0,0); TFT_H->printf("UserID: %u\n\r\n\r", allUsersH[userIndex].getRfid()); 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].getBatteriesMax() - allUsersH[userIndex].getBatteriesOut()) { 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 Hmi::batteryDropOffScreenH(int userIndex) { TFT_H->cls(); TFT_H->locate(0,0); TFT_H->printf("UserID: %u\n\r\n\r", allUsersH[userIndex].getRfid()); 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].getBatteriesOut()) { 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 user 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 Hmi::batteryDropOffH(int numBatteries, int userIndex) { switch(numBatteries) { case 1: logActionWithUserInfo(hubAction_OneBatteryDropped, &allUsersH[userIndex]); txBatteryDropOff(userIndex,1); allUsersH[userIndex].dropOffBattery(1); break; case 2: logActionWithUserInfo(hubAction_TwoBatteryDropped, &allUsersH[userIndex]); txBatteryDropOff(userIndex,2); allUsersH[userIndex].dropOffBattery(2); break; case 3: logActionWithUserInfo(hubAction_ThreeBatteryDropped, &allUsersH[userIndex]); txBatteryDropOff(userIndex,3); allUsersH[userIndex].dropOffBattery(3); break; } currentScreenH = initialScanRfid; return; } /** * Do after user 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 Hmi::batteryPickUpH(int numBatteries, int userIndex) { switch(numBatteries) { case 1: logActionWithUserInfo(hubAction_OneBatteryPicked, &allUsersH[userIndex]); txBatteryPickUp(userIndex,1); allUsersH[userIndex].pickUpBattery(1); break; case 2: logActionWithUserInfo(hubAction_TwoBatteryPicked, &allUsersH[userIndex]); txBatteryPickUp(userIndex,2); allUsersH[userIndex].pickUpBattery(2); break; case 3: logActionWithUserInfo(hubAction_ThreeBatteryPicked, &allUsersH[userIndex]); txBatteryPickUp(userIndex,3); allUsersH[userIndex].pickUpBattery(3); break; } currentScreenH = initialScanRfid; return; } /*************************************************************************************************/ /* Misc Services */ /*************************************************************************************************/ /** * Do if Posho RFID flag is set. Reads rfid and checks user table for a positive balance * capable of paying for the posho. Displays screen info for selecting posho amount to process. */ void Hmi::doPoshoRfidH() { flagPoshoRfidH = 0; // let the RF reader get tag info int foundUserIndex = rfidReadHelper(PoshoRfChipH, source_posho); if (foundUserIndex == -1) return; // Display info about the user char authorizationFlag = 0; TFT_H->cls(); TFT_H->locate(0,0); TFT_H->printf("UserID: %u\n\r", allUsersH[foundUserIndex].getRfid()); int userAccountBalance = allUsersH[foundUserIndex].getCredit(); 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", allUsersH[foundUserIndex].getRfid()); 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. Also sets posho flag to in use and sets an interrupt * to clear that flag after a specified time. * @param numKilograms - int for number of kilograms to be processed * @param userIndex - int representing index of user in user table */ void Hmi::poshoSerialUseH(int numKilograms, int userIndex) { flagPoshoAlreadyInUseH = 1; allUsersH[userIndex].decreaseCredit(numKilograms*poshoPricePerKgH); switch (numKilograms) { case 1: tickPoshoInUseClearH.attach(this, &Hmi::interruptPoshoInUseClearH, (float)timeForOneKgH); logActionWithUserInfo(hubAction_OneKiloPosho, &allUsersH[userIndex]); break; case 2: tickPoshoInUseClearH.attach(this, &Hmi::interruptPoshoInUseClearH, (float)timeForTwoKgH); logActionWithUserInfo(hubAction_TwoKiloPosho, &allUsersH[userIndex]); break; case 3: tickPoshoInUseClearH.attach(this, &Hmi::interruptPoshoInUseClearH, (float)timeForThreeKgH); logActionWithUserInfo(hubAction_ThreeKiloPosho, &allUsersH[userIndex]); break; } TFT_H->cls(); TFT_H->locate(0,0); TFT_H->printf("UserID: %u\n\r\n\r", allUsersH[userIndex].getRfid()); TFT_H->printf("New balance: %d\n\r", allUsersH[userIndex].getCredit()); txPoshoSerialUse(numKilograms); wait(1); currentScreenH = initialScanRfid; return; } /** * Do if Incubator RFID flag is set. Add incubator functionality later. */ void Hmi::doIncubatorRfidH() { flagIncubatorRfidH = 0; } /*************************************************************************************************/ /* Public Methods */ /*************************************************************************************************/ void Hmi::loop(){ loopHub(); } void Hmi::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].getBatteriesMax(); uint8_t outBatteries = allUsersH[currentUserH].getBatteriesOut(); if ((maxBatteries - outBatteries) == 0) { if (flagButtonOneH) batteryDropOffScreenH(currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else if (outBatteries == 0) { if (flagButtonOneH) batteryPickUpScreenH(currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else { if (flagButtonOneH) batteryPickUpScreenH(currentUserH); if (flagButtonThreeH) batteryDropOffScreenH(currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } break; } case batterySelectNumberForDropoff: { switch (allUsersH[currentUserH].getBatteriesOut()) { 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: { uint8_t maxBatteries = allUsersH[currentUserH].getBatteriesMax(); uint8_t outBatteries = allUsersH[currentUserH].getBatteriesOut(); switch (maxBatteries - outBatteries) { 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].getCredit() > 3*poshoPricePerKgH) { if (flagButtonOneH) poshoSerialUseH(1, currentUserH); if (flagButtonTwoH) poshoSerialUseH(2, currentUserH); if (flagButtonThreeH) poshoSerialUseH(3, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else if (allUsersH[currentUserH].getCredit() > 2*poshoPricePerKgH) { if (flagButtonOneH) poshoSerialUseH(1, currentUserH); if (flagButtonTwoH) poshoSerialUseH(2, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } else { if (flagButtonOneH) poshoSerialUseH(1, currentUserH); if (flagButtonFourH) cancelPressedH(currentUserH); } } } } } void Hmi::logActionWithUserInfo(enum HubActionForLogging action, HubUser *user) { // Append to a log text file spiSD(); char * name = "/sd/HubLog.txt"; FILE *fp; fp = fopen(name, "a"); if (fp == NULL) { #ifdef debug printf("Log text file can't be opened (Action log)\n\r"); #endif return; } // 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_IncubatorRfidScanned: strcat(logLine, " RI "); 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]; char maxBatteriesBuffer[20]; sprintf(rfidBuffer, "%u ", user->getRfid()); sprintf(uidBuffer, "%u ", user->getUid()); sprintf(acctBalanceBuffer, "%d ", user->getCredit()); sprintf(maxBatteriesBuffer, "%d\n", user->getBatteriesMax()); strcat(logLine, rfidBuffer); strcat(logLine, uidBuffer); strcat(logLine, acctBalanceBuffer); strcat(logLine, maxBatteriesBuffer); // write the line to the log file and close the file fputs(logLine, fp); fclose(fp); #ifdef debug printf("%s\n\r", logLine); #endif } void Hmi::logErrorUnknownRfidScanned(uint32_t unknownRfid, enum HubLoggingRfidSource source) { // Append to a log text file char * name = "/sd/HubLog.txt"; spiSD(); FILE *fp; fp = fopen(name, "a"); if (fp == NULL) { #ifdef debug printf("Log text file can't be opened (Unknown rfid)\n\r"); #endif return; } // 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\n", unknownRfid); strcat(logLine, rfidBuffer); // write the line to the log file and close the file fputs(logLine, fp); fclose(fp); #ifdef debug printf("%s\n\r", logLine); #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 Hmi::txBatteryPickUp(int userIndex,int numBatteries) { DBG("txBatteryPickup:"); int locker = (allUsersH[userIndex].getUid())&0x0000ff00; lockerAddr = (baseAddr &0xffffff0000)+locker; DBG("txBatteryDropOff: %x base %x lock %x", allUsersH[userIndex].getUid(),(unsigned int) baseAddr,(unsigned int) lockerAddr); spiNRF(); nrf->flushRx(); nrf->flushTx(); nrf->setTxAddress(lockerAddr); #ifdef DEBUG nrf->printDetails(); #endif sprintf(dataTx,"bp %x %x",allUsersH[userIndex].getUid(), numBatteries); DBG("\r\n txBatteryPickup: %s",dataTx); nrf->transmitData(dataTx,strlen(dataTx)); spiSD(); } /** * 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 Hmi::txBatteryDropOff(int userIndex,int numBatteries) { DBG("txBatteryDropOff:"); int locker = (allUsersH[userIndex].getUid())&0x0000ff00; lockerAddr = (baseAddr &0xffffff0000)+locker; DBG("txBatteryDropOff: %x base %x lock %x", allUsersH[userIndex].getUid(),(unsigned int) baseAddr,(unsigned int) lockerAddr); spiNRF(); nrf->flushRx(); nrf->flushTx(); nrf->setTxAddress(lockerAddr); #ifdef DEBUG nrf->printDetails(); #endif sprintf(dataTx,"bd %x %x",allUsersH[userIndex].getUid(), numBatteries); DBG("\r\n txBatteryDropOff: %s",dataTx); nrf->transmitData(dataTx,strlen(dataTx)); spiSD(); } /** * 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 Hmi::txPoshoSerialUse(int numKilograms) { }