Lukas Bachschwell
df94ff0654
moved drinksMax to beerbox struct and refactored to maxDrink added if(debug) to all serial write and serial print statements Moved BLE com to seperat file and added command and subcommandparsing Added filename JSON method
421 lines
9.6 KiB
C++
421 lines
9.6 KiB
C++
#include <SPI.h>
|
|
#include <Wire.h>
|
|
#include <SD.h>
|
|
#include "beerbox.h"
|
|
#include <LiquidCrystal_I2C.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <Adafruit_Fingerprint.h>
|
|
|
|
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&Serial2);
|
|
LiquidCrystal_I2C lcd(0x38, 8, 2); // 0x38 for PCF***A on address 000
|
|
|
|
|
|
#define debug 0 //General debug out on/off
|
|
|
|
File myFile;
|
|
const int chipSelect = 53;
|
|
|
|
char toprint[255]; // General print Buffer
|
|
Beerbox *box;
|
|
|
|
//int maxDrink = 1; // TODO add this to the box struct
|
|
int lastButtonState = 1;
|
|
|
|
int currentDrink = 0;
|
|
int lastPersonIndex = -1;
|
|
|
|
Person* persons;
|
|
int personCount;
|
|
String rfID;
|
|
|
|
unsigned long oldTime = 0;
|
|
unsigned long ledTime = 0;
|
|
|
|
void setup() {
|
|
//generall debugging
|
|
Serial.begin(115200);
|
|
|
|
//LCD init
|
|
lcd.init();
|
|
pinMode(2, INPUT_PULLUP);
|
|
|
|
pinMode(3, OUTPUT);
|
|
pinMode(led, OUTPUT);
|
|
//tone(3,440,5000);
|
|
|
|
//Fingerprint init
|
|
finger.begin(57600);
|
|
if (finger.verifyPassword()) {
|
|
if(debug)Serial.println("Found fingerprint sensor!");
|
|
} else {
|
|
if(debug)Serial.println("Did not find fingerprint sensor :(");
|
|
while (1);
|
|
}
|
|
|
|
// RFID Reader init
|
|
Serial1.begin(9600);
|
|
|
|
// BLE Com init
|
|
Serial3.begin(115200);
|
|
|
|
|
|
if(debug)Serial.print("Initializing SD card...");
|
|
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
|
|
// Note that even if it's not used as the CS pin, the hardware SS pin
|
|
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
|
|
// or the SD library functions will not work.
|
|
pinMode(SS, OUTPUT);
|
|
|
|
if (!SD.begin(chipSelect)) {
|
|
if(debug)Serial.println("initialization failed!");
|
|
return;
|
|
}
|
|
if(debug)Serial.println("initialization done.");
|
|
|
|
//check_for_file("p001", "per");
|
|
|
|
box = new Beerbox;
|
|
box = read_beerbox(box);
|
|
|
|
persons = readAllPersons();
|
|
|
|
lcd.print("Drink: _");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(box->drinks[0].name);
|
|
currentDrink = 0;
|
|
box->waiting = false;
|
|
|
|
//turnOn led
|
|
digitalWrite(led,HIGH);
|
|
ledTime = millis();
|
|
|
|
}
|
|
|
|
|
|
void loop() {
|
|
|
|
checkFinger();
|
|
checkRFID();
|
|
checkButton();
|
|
|
|
boxTimer();
|
|
ledTimer();
|
|
|
|
bluetoothCommands();
|
|
|
|
}//end loop
|
|
|
|
|
|
|
|
|
|
void check_for_file(String filename, String extension) {
|
|
String str = filename + '.' + extension;
|
|
char* buf = NULL;
|
|
str.toCharArray(buf, str.length() + 1);
|
|
|
|
if (SD.exists("p001.per")) {
|
|
if(debug)Serial.println(str + " exists.");
|
|
}
|
|
else {
|
|
if(debug)Serial.println(str + " doesn't exist.");
|
|
}
|
|
}
|
|
|
|
//BEYOND THIS POINT IS THE LEYER OF BEERBOX -- ENTER AT YOUR OWN RISK######################################
|
|
|
|
char tmp_filename[FILE_NAME_LEN + FILE_EXTENSION_LEN + 2];
|
|
|
|
Beerbox* read_beerbox(Beerbox *box) {
|
|
|
|
File read;
|
|
int num_read = 0;
|
|
int index;
|
|
|
|
char tmp[(DRINK_NAME_MAX_LENGTH + 1) * NUM_OF_DRINKS];
|
|
|
|
int i = 0;
|
|
|
|
|
|
read = SD.open("bb.con", FILE_READ);
|
|
if (read == false) {
|
|
|
|
if(debug)Serial.print("error while reading!\n");
|
|
if(debug)Serial.print("-ABORT!\n\n");
|
|
while (1);
|
|
|
|
}
|
|
|
|
//get drinks
|
|
for (i = 0 ; i < NUM_OF_DRINKS ; i++) {
|
|
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
|
|
if (strlen(tmp)) {
|
|
sscanf(tmp, " drink number %d: %s", &index, &box->drinks[i].name);
|
|
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
sscanf(tmp, " %*s %d ", &box->drinks[i].price);
|
|
|
|
} else {
|
|
strcpy(box->drinks[i].name, "slot empty");
|
|
box->drinks[i].price = -1;
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; (i < NUM_OF_DRINKS) && (box->drinks[i].price != -1); i++) {
|
|
|
|
sprintf(toprint, "drink number %i: %s\nprice: %d\n", i , box->drinks[i].name, box->drinks[i].price);
|
|
if(debug)Serial.println(toprint);
|
|
}
|
|
|
|
if (i < NUM_OF_DRINKS) {
|
|
sprintf(toprint, "Slots %d - %d are not in use!\n", i + 1, NUM_OF_DRINKS);
|
|
box->maxDrink = i;
|
|
if(debug)Serial.println(toprint);
|
|
}
|
|
|
|
read.close();
|
|
return box;
|
|
|
|
}
|
|
|
|
Person read_person(Beerbox *box, char *filename) {
|
|
|
|
Person aperson;
|
|
File read;
|
|
|
|
char tmp[25];//longest line is rfid_uuid
|
|
|
|
|
|
//giving the full filename here, since it makes stuff easier
|
|
//if(debug)Serial.print("The filename is: ");
|
|
//if(debug)Serial.println(filename);
|
|
read = SD.open(filename, FILE_READ);
|
|
if (read == false) {
|
|
|
|
if(debug)Serial.print("error while reading!\n");
|
|
if(debug)Serial.print("ABORT!\n\n");
|
|
while (-1);
|
|
|
|
}
|
|
|
|
strcpy(aperson.file_name, filename);
|
|
|
|
//reset momentary array
|
|
for (int i = 0; i < NUM_OF_DRINKS; i++) {
|
|
aperson.drinks_taken[i] = -1;
|
|
}
|
|
|
|
//First read all the metadata
|
|
//name
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
strcpy(aperson.name, tmp);
|
|
//rfid_uuid
|
|
memset(aperson.rfid_uuid, 0, 13);
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
sscanf(tmp, "rfid_uuid: %12s", &aperson.rfid_uuid);
|
|
if(debug)Serial.println(aperson.rfid_uuid);
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
sscanf(tmp, "finger_uuid: %d", &aperson.finger_uuid);
|
|
//if(debug)Serial.println(aperson.finger_uuid);
|
|
//credits_left
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
sscanf(tmp, "credits_left: %d", &aperson.credits_left);
|
|
//if(debug)Serial.println(aperson.credits_left);
|
|
|
|
while (read_line_from_file(read, tmp, sizeof(tmp)), strlen(tmp) > 0) {
|
|
int tmpCount = 0;
|
|
int tmpDrink = 0;
|
|
sscanf(tmp, "drink_Count_%d: %d", &tmpDrink, &tmpCount);
|
|
if (strlen(tmp)) {
|
|
//if(debug)Serial.print("drink: ");
|
|
//if(debug)Serial.print(tmpDrink);
|
|
//if(debug)Serial.print(" count: ");
|
|
//if(debug)Serial.println(tmpCount);
|
|
aperson.drinks_taken[tmpDrink] = tmpCount;
|
|
}
|
|
}
|
|
if (aperson.finger_uuid > box->maxID) box->maxID = aperson.finger_uuid;
|
|
|
|
print_person(box, &aperson);
|
|
//comment back in once it is fixed
|
|
//update_pers_file(box, &aperson);
|
|
|
|
read.close();
|
|
return aperson;
|
|
}
|
|
|
|
void print_person(Beerbox *box, Person *aperson) {
|
|
|
|
int i = 0;
|
|
sprintf(toprint, "\nPerson is called \"%s\" and has the filename \"%s\".\n", aperson->name, aperson->file_name);
|
|
if(debug)Serial.write(toprint);
|
|
sprintf(toprint, "rfid_uuid: %s\n", aperson->rfid_uuid);
|
|
if(debug)Serial.write(toprint);
|
|
sprintf(toprint, "finger_uuid: %u\n", aperson->finger_uuid);
|
|
if(debug)Serial.print(toprint);
|
|
sprintf(toprint, "credits_left: %u\n", aperson->credits_left);
|
|
if(debug)Serial.print(toprint);
|
|
|
|
for (i = 0; i < box->maxDrink; i++) {
|
|
|
|
if (aperson->drinks_taken[i] != -1) {
|
|
sprintf(toprint, "\nDrink: %s\n", box->drinks[i].name);
|
|
if(debug)Serial.write(toprint);
|
|
sprintf(toprint, "Drink %d: %d\n", i, aperson->drinks_taken[i]);
|
|
if(debug)Serial.write(toprint);
|
|
sprintf(toprint, "Total: %d.%02d Euro\n", aperson->drinks_taken[i]*box->drinks[i].price / 100, (aperson->drinks_taken[i]*box->drinks[i].price) % 100);
|
|
if(debug)Serial.write(toprint);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int update_pers_file() {
|
|
Person thisPerson = persons[lastPersonIndex];
|
|
File write;
|
|
char tmp[25];
|
|
|
|
int i = 0;
|
|
//if(debug)Serial.println(thisPerson.file_name);
|
|
write = SD.open(thisPerson.file_name, FILE_WRITE);
|
|
|
|
if (write == NULL) {
|
|
if(debug)Serial.print("error while reading!\n");
|
|
if(debug)Serial.print("ABORT!\n\n");
|
|
while (-1);
|
|
}
|
|
write.seek(0);
|
|
|
|
|
|
sprintf(tmp, "%s\n", thisPerson.name);
|
|
write.write(tmp, strlen(tmp));
|
|
sprintf(tmp, "rfid_uuid: %s\n", thisPerson.rfid_uuid);
|
|
write.write(tmp, strlen(tmp));
|
|
sprintf(tmp, "finger_uuid: %u\n", thisPerson.finger_uuid);
|
|
write.write(tmp, strlen(tmp));
|
|
sprintf(tmp, "credits_left: %u\n", thisPerson.credits_left);
|
|
write.write(tmp, strlen(tmp));
|
|
|
|
for (i = 0; i < box->maxDrink; i++) {
|
|
|
|
if (thisPerson.drinks_taken[i] != -1) {
|
|
sprintf(tmp, "\ndrink_Count_%d: %d\n", i, thisPerson.drinks_taken[i]);
|
|
write.write(tmp, strlen(tmp));
|
|
if(debug)Serial.println(tmp);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
write.close();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
char* read_from_file_until(File stream, char *str, int max_len, char until) {
|
|
|
|
int i = 0;
|
|
int tmp_int = 0;
|
|
|
|
memset(str, 0, max_len);
|
|
|
|
for (i = 0; (tmp_int != until) && (i < (max_len - 1)) && (tmp_int != -1); i++) {
|
|
tmp_int = stream.read();
|
|
//if(debug)Serial.print("%c", tmp_int);
|
|
str[i] = tmp_int;
|
|
}
|
|
|
|
|
|
if (tmp_int == -1) {
|
|
|
|
//May occur more often as the function tries to read a certain number of drinks.
|
|
//if(debug)Serial.print("END OF FILE REACHED!\nABORT!!\n\n");
|
|
|
|
str[0] = 0;
|
|
return str;
|
|
}
|
|
|
|
if (str[0] != '\n')str[i - 1] = 0;
|
|
|
|
|
|
return str;
|
|
}
|
|
|
|
char *read_line_from_file(File stream, char *str, int max_len) {
|
|
|
|
do {
|
|
str = read_from_file_until(stream, str, max_len, '\n');
|
|
} while ((str[0] == '\n'));
|
|
|
|
|
|
return str;
|
|
}
|
|
|
|
|
|
|
|
Person* readAllPersons () {
|
|
|
|
File dir = SD.open("/");
|
|
dir.rewindDirectory();
|
|
|
|
personCount = 0;
|
|
//count the valid persons:
|
|
while (true) {
|
|
File entry = dir.openNextFile();
|
|
if (! entry) {// no more files
|
|
break;
|
|
}
|
|
if (!entry.isDirectory()) {
|
|
if (strcmp(strlwr(entry.name() + (strlen(entry.name()) - 4)), ".per")==0)
|
|
{
|
|
personCount++; //Yeah it is a person!
|
|
}
|
|
|
|
|
|
}
|
|
entry.close();
|
|
}
|
|
//now store them
|
|
//if(debug)Serial.print("count:");
|
|
//if(debug)Serial.print(personCount);
|
|
Person* readPersons = new Person[personCount];
|
|
int counter = 0;
|
|
dir.rewindDirectory();
|
|
while (true) {
|
|
File entry = dir.openNextFile();
|
|
if (! entry) {// no more files
|
|
break;
|
|
}
|
|
if (!entry.isDirectory()) {
|
|
int8_t len = strlen(entry.name());
|
|
if (strstr(strlwr(entry.name() + (len - 4)), ".per"))
|
|
{
|
|
//Yeah it is a person!
|
|
//if(debug)Serial.print("Person: ");
|
|
//if(debug)Serial.println(entry.name());
|
|
Person thisPerson = read_person(box, entry.name());
|
|
readPersons[counter] = thisPerson;
|
|
counter++;
|
|
}
|
|
}
|
|
entry.close();
|
|
}
|
|
dir.close();
|
|
if(debug)Serial.println("Read all!");
|
|
return readPersons;
|
|
}
|
|
|
|
|
|
|
|
|