forked from Wien60Pioneers/beerbox
515 lines
12 KiB
C++
515 lines
12 KiB
C++
#include <SPI.h>
|
|
#include <Wire.h>
|
|
#include <SD.h>
|
|
|
|
#include <LiquidCrystal_I2C.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "beerbox.h"
|
|
#include <Adafruit_Fingerprint.h>
|
|
|
|
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&Serial2);
|
|
LiquidCrystal_I2C lcd(0x38, 8, 2); // 0x38 for PCF***A on address 000
|
|
|
|
|
|
//######### RFID CONSTANTS ##########
|
|
const int startZeichen = 02; // Chip-Kennung beginnt mit 02
|
|
const int endeZeichen = 03; // ASCII CR bendet Code
|
|
const int kennungLaenge = 12; // Laenge Chip-Code 10 ASCII-Zeichen
|
|
const int gesamtKennungLaenge = 14; // Code-Laenge + Start- und Ende-Byte
|
|
char code[kennungLaenge + 1]; // fuer den Code und abschliessende Null
|
|
int bytesGelesen = 0;
|
|
int zaehlerFehlerCode = 0;
|
|
String zugang = "000000000000"; // zugangscode zwischenspeicher, Standard
|
|
//#######################
|
|
|
|
|
|
File myFile;
|
|
const int chipSelect = 53;
|
|
|
|
char leckmich[255];
|
|
Beerbox *box;
|
|
|
|
int drinksMax = 1;
|
|
int lastButtonState = 1;
|
|
int currentDrink = 0;
|
|
|
|
|
|
void setup() {
|
|
//generall debugging
|
|
Serial.begin(115200);
|
|
|
|
//LCD init
|
|
lcd.init();
|
|
pinMode(2, INPUT_PULLUP);
|
|
|
|
//Fingerprint init
|
|
finger.begin(57600);
|
|
if (finger.verifyPassword()) {
|
|
Serial.println("Found fingerprint sensor!");
|
|
} else {
|
|
Serial.println("Did not find fingerprint sensor :(");
|
|
while (1);
|
|
}
|
|
|
|
// RFID Reader init
|
|
Serial1.begin(9600);
|
|
|
|
|
|
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)) {
|
|
Serial.println("initialization failed!");
|
|
return;
|
|
}
|
|
Serial.println("initialization done.");
|
|
|
|
//check_for_file("p001", "per");
|
|
readAllPersons();
|
|
|
|
box = new Beerbox;
|
|
box = read_beerbox(box);
|
|
|
|
|
|
lcd.print("BOXready");
|
|
lcd.setCursor(0, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
void loop() {
|
|
|
|
checkFinger();
|
|
checkRFID();
|
|
checkButton();
|
|
|
|
//Person myPerson = read_person(box, "p001");
|
|
//read_person(box, "p002");
|
|
|
|
|
|
|
|
}//end loop
|
|
|
|
void checkButton() {
|
|
//one change per click to make seleting drinks easier for the drunken
|
|
//if (digitalRead(2) != lastButtonState) {
|
|
//delayMicroseconds(50); //debounce delay
|
|
if (digitalRead(2) != lastButtonState) {
|
|
//ok we have a change!
|
|
if (digitalRead(2) == LOW) {
|
|
//pushed
|
|
if (currentDrink == drinksMax - 1) currentDrink = -1;
|
|
currentDrink++;
|
|
Serial.println(box->drinks[currentDrink].name);
|
|
lcd.clear();
|
|
lcd.print("Drink:");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print(box->drinks[currentDrink].name);
|
|
|
|
}
|
|
else {//released
|
|
}
|
|
lastButtonState = digitalRead(2);
|
|
}
|
|
//}
|
|
}
|
|
|
|
bool checkFinger() {
|
|
|
|
uint8_t p = finger.getImage();
|
|
if (p != FINGERPRINT_OK) return -1;
|
|
|
|
p = finger.image2Tz();
|
|
if (p != FINGERPRINT_OK) return -1;
|
|
|
|
p = finger.fingerFastSearch();
|
|
if (p != FINGERPRINT_OK) return -1;
|
|
|
|
// found a match!
|
|
Serial.print("Found ID #"); Serial.print(finger.fingerID);
|
|
Serial.print(" with confidence of "); Serial.println(finger.confidence);
|
|
|
|
|
|
//TODO @ALEX Do something with finger ID
|
|
// finger.fingerID
|
|
|
|
//int getFingerIndex(Person* persons, finger.fingerID)
|
|
|
|
}
|
|
|
|
void checkRFID() {
|
|
Serial1.flush();
|
|
if (Serial1.available() >= gesamtKennungLaenge) // wenn genug Zeichen eingegangen ...
|
|
{
|
|
if (Serial1.read() == startZeichen) // und das Startzeichen erkannt wurde ...
|
|
{
|
|
//Serial.print("Start-Byte erkannt ... ");
|
|
bytesGelesen = 0; // starten Lesen, also Zaehler auf 0
|
|
while (bytesGelesen < kennungLaenge) // lese 12-stelligen Code
|
|
{
|
|
char zeichen = Serial1.read(); // lesen Zeichen
|
|
//Serial.print(zeichen); // zur Kontrolle
|
|
//Serial.print(" ");
|
|
if (zeichen == endeZeichen) // suche nach Ende-Befehl
|
|
{
|
|
//Serial.println("CR erkannt ...");
|
|
break;
|
|
}
|
|
code[bytesGelesen] = zeichen; // speicher Zeichen im Puffer
|
|
bytesGelesen = bytesGelesen + 1; // ein Zeichen weiter
|
|
}
|
|
code[bytesGelesen] = 0; // beende Zeichenkette
|
|
Serial.print("RFID-Code lautet: ");
|
|
Serial.println(code);
|
|
zugang = code; // Umwandlung Code in String
|
|
//TODO @Alex
|
|
// Do something with the 12 char string code
|
|
zugang = "";
|
|
delay(1000); // debounce time
|
|
serial1_flush_buffer();
|
|
}
|
|
}
|
|
}
|
|
|
|
void serial1_flush_buffer()
|
|
{
|
|
while (Serial1.read() >= 0)
|
|
; // do nothing
|
|
}
|
|
|
|
|
|
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")) {
|
|
Serial.println(str + " exists.");
|
|
}
|
|
else {
|
|
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) {
|
|
|
|
Serial.print("error while reading!\n");
|
|
Serial.print("-ABORT!\n\n");
|
|
while (1);
|
|
|
|
}
|
|
// get personcount Basically not needed...
|
|
// char tmpStr[19];
|
|
// read_line_from_file(read, tmpStr, sizeof(tmpStr));
|
|
// if (strlen(tmpStr)) {
|
|
// sscanf(tmpStr, "personCount: %d", &box->personCount);
|
|
// }
|
|
//
|
|
// sprintf(leckmich, "%i persons known!\n", box->personCount );
|
|
// Serial.print(leckmich);
|
|
|
|
//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;
|
|
}
|
|
|
|
}
|
|
Serial.print(i);
|
|
Serial.println(" drinks read!\n");
|
|
|
|
for (i = 0; (i < NUM_OF_DRINKS) && (box->drinks[i].price != -1); i++) {
|
|
|
|
|
|
sprintf(leckmich, "drink number %i: %s\nprice: %d\n", i , box->drinks[i].name, box->drinks[i].price);
|
|
Serial.println(leckmich);
|
|
}
|
|
|
|
if (i < NUM_OF_DRINKS) {
|
|
sprintf(leckmich, "Slots %d - %d are not in use!\n", i + 1, NUM_OF_DRINKS);
|
|
drinksMax = i;
|
|
Serial.println(leckmich);
|
|
}
|
|
|
|
read.close();
|
|
return box;
|
|
|
|
}
|
|
|
|
Person read_person(Beerbox *box, char *filename) {
|
|
|
|
Person aperson;
|
|
File read;
|
|
|
|
char tmp[21];//longest line is rfid_uuid
|
|
|
|
|
|
//giving the full filename here, since it makes stuff easier
|
|
Serial.print("The filename is: ");
|
|
Serial.println(filename);
|
|
read = SD.open(filename, FILE_READ);
|
|
if (read == false) {
|
|
|
|
Serial.print("error while reading!\n");
|
|
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);
|
|
Serial.println(aperson.rfid_uuid);
|
|
//finger_uuid
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
sscanf(tmp, "finger_uuid: %d", &aperson.finger_uuid);
|
|
Serial.println(aperson.finger_uuid);
|
|
//credits_left
|
|
read_line_from_file(read, tmp, sizeof(tmp));
|
|
sscanf(tmp, "credits_left: %d", &aperson.credits_left);
|
|
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)) {
|
|
Serial.print("drink: ");
|
|
Serial.print(tmpDrink);
|
|
Serial.print(" count: ");
|
|
Serial.println(tmpCount);
|
|
}
|
|
}
|
|
|
|
|
|
//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(leckmich, "\nPerson is called \"%s\" and has the filename \"%s\".\n", aperson->name, aperson->file_name);
|
|
Serial.write(leckmich);
|
|
sprintf(leckmich, "rfid_uuid: %s\n", aperson->rfid_uuid);
|
|
Serial.write(leckmich);
|
|
sprintf(leckmich, "finger_uuid: %u\n", aperson->finger_uuid);
|
|
Serial.print(leckmich);
|
|
sprintf(leckmich, "credits_left: %u\n", aperson->credits_left);
|
|
Serial.print(leckmich);
|
|
|
|
|
|
for (i = 0; i < NUM_OF_DRINKS; i++) {
|
|
|
|
if (aperson->drinks_taken[i] != -1) {
|
|
/* //Rework that
|
|
sprintf(leckmich, "\nDrink: %s\n", box->drinks[i].name);
|
|
Serial.write(leckmich);
|
|
sprintf(leckmich, "Consumed: %d\n", aperson->drinks_taken[i]);
|
|
Serial.write(leckmich);
|
|
sprintf(leckmich, "Total: %d.%02d Euro\n", aperson->drinks_taken[i]*box->drinks[i].price / 100, (aperson->drinks_taken[i]*box->drinks[i].price) % 100);
|
|
Serial.write(leckmich);
|
|
*/
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
int update_pers_file(Beerbox *box, Person *aperson) {
|
|
File write;
|
|
char *tmp = NULL;
|
|
|
|
int i = 0;
|
|
|
|
write = SD.open(aperson->file_name, FILE_WRITE);
|
|
write.seek(0);
|
|
|
|
if (write == NULL) {
|
|
Serial.print("error while reading!\n");
|
|
Serial.print("ABORT!\n\n");
|
|
while (-1);
|
|
|
|
}
|
|
|
|
sprintf(leckmich, " %s\n", aperson->name);
|
|
write.write(tmp, strlen(tmp));
|
|
sprintf(leckmich, "rfid_uuid: %s\n", aperson->rfid_uuid);
|
|
write.write(tmp, strlen(tmp));
|
|
sprintf(leckmich, "finger_uuid: %u\n", aperson->finger_uuid);
|
|
write.write(tmp, strlen(tmp));
|
|
|
|
for (i = 0; i < NUM_OF_DRINKS; i++) {
|
|
|
|
if (aperson->drinks_taken[i] != -1) {
|
|
|
|
sprintf(leckmich, "\nDrink: %s\n", box->drinks[i].name);
|
|
write.write(tmp, strlen(tmp));
|
|
sprintf(leckmich, "Consumed: %d\n", aperson->drinks_taken[i]);
|
|
write.write(tmp, strlen(tmp));
|
|
sprintf(leckmich, "Total: %d\n\n", aperson->drinks_taken[i]*box->drinks[i].price);
|
|
write.write(tmp, strlen(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();
|
|
//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.
|
|
//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;
|
|
}
|
|
//
|
|
//LB
|
|
//Funktion schreiben, welche ein Array vom struct Person (Beliebige Groesse) sowie eine rfid-kennung uebernimmt und den Index der entsprechenden Person im array (beginnend bei 0)zurueckgiebt.
|
|
int getRFIDIndex(Person* persons, char* rfid) {
|
|
|
|
for (int i = 0; i < sizeof(persons) / sizeof(Person); i++) {
|
|
if (!strcmp(persons[i].rfid_uuid, rfid)) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
int getFingerIndex(Person* persons, uint8_t fingerID) {
|
|
|
|
for (int i = 0; i < sizeof(persons) / sizeof(Person); i++) {
|
|
if (persons[i].finger_uuid == fingerID) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void readAllPersons () {
|
|
|
|
File dir = SD.open("/");
|
|
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!
|
|
Serial.print("Person: ");
|
|
Serial.println(entry.name());
|
|
Person thisPerson = read_person(box, entry.name());
|
|
//print_person(box, &thisPerson);
|
|
|
|
|
|
}
|
|
}
|
|
entry.close();
|
|
}
|
|
|
|
Serial.println("Read all!");
|
|
}
|
|
|
|
|
|
|