beerbox/beerbox.ino

507 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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");
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);
}
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);
read_line_from_file(read, tmp, sizeof(tmp));
sscanf(tmp, " %*s %d", &box->drinks[i].quantity);
} else {
strcpy(box->drinks[i].name, "slot empty");
box->drinks[i].price = -1;
box->drinks[i].quantity = -1;
}
}
Serial.print(i + " drinks read!\n\n");
for (i = 0; (i < NUM_OF_DRINKS) && (box->drinks[i].price != -1); i++) {
sprintf(leckmich, "drink number %i: %s\nprice: %d\nquantity: %d\n\n", i ,box->drinks[i].name, box->drinks[i].price, box->drinks[i].quantity);
Serial.print(leckmich);
}
if (i < NUM_OF_DRINKS) {
sprintf(leckmich, "Slots %d - %d are not in use!\n", i + 1, NUM_OF_DRINKS);
drinksMax = i;
Serial.print(leckmich);
}
read.close();
return box;
}
Person read_person(Beerbox *box, char *filename) {
Person aperson;
File read;
int num_read = 0;
int index;
int tmp_int = 0;
char tmp[(DRINK_NAME_MAX_LENGTH + 1) * NUM_OF_DRINKS];
char tmp_drink_name[DRINK_NAME_MAX_LENGTH + 1];
int i = 0;
int j = 0;
memset(tmp_filename, 0, FILE_NAME_LEN + FILE_EXTENSION_LEN + 2);
strcat(tmp_filename, filename);
strcat(tmp_filename, ".");
strcat(tmp_filename, FILE_EXTENSION);
read = SD.open(tmp_filename, FILE_READ);
if (read == false) {
Serial.print("error while reading!\n");
Serial.print("ABORT!\n\n");
while (-1);
}
strcpy(aperson.file_name, filename);
for (i = 0; i < NUM_OF_DRINKS; i++) {
aperson.drinks_taken[i] = -1;
}
read_line_from_file(read, tmp, sizeof(tmp));
strcpy(aperson.name, tmp);
memset(aperson.rfid_uuid, 0, 13);
read_line_from_file(read, tmp, sizeof(tmp));
sscanf(tmp, " %*s %12s", aperson.rfid_uuid);
Serial.print(aperson.rfid_uuid);
read_line_from_file(read, tmp, sizeof(tmp));
sscanf(tmp, " %*s %d", &aperson.finger_uuid);
Serial.println(aperson.finger_uuid);
j = 0;
while (read_line_from_file(read, tmp, sizeof(tmp)), strlen(tmp) > 0) {
i = 0;
sscanf(tmp, " %*s %s", tmp_drink_name);
for (i = 0; (i < NUM_OF_DRINKS) && (strcmp(box->drinks[i].name, tmp_drink_name)); i++) {
//Serial.print("It´s not drink No %d: %s\n", i+1, box->drinks[i].name );
}
if (i == NUM_OF_DRINKS) {
//Is it in?
//Serial.print("Drink \"%s\" does not exist in box!\n", tmp_drink_name);
} else {
read_line_from_file(read, tmp, sizeof(tmp));
sscanf(tmp, " %*s %d", &aperson.drinks_taken[i]);
//Serial.print(">>Quantity: %d\n", aperson.drinks_taken[i].quantity);
read_line_from_file(read, tmp, sizeof(tmp));
//Serial.print(">>Total: %d\n\n", aperson.drinks_taken[i].total);
}
}
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;
memset(tmp_filename, 0, FILE_NAME_LEN + FILE_EXTENSION_LEN + 2);
strcat(tmp_filename, aperson->file_name);
strcat(tmp_filename, ".");
strcat(tmp_filename, FILE_EXTENSION);
sprintf(leckmich, "\nPerson is called \"%s\" and has the filename \"%s\".\n", aperson->name, tmp_filename);
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);
for (i = 0; i < NUM_OF_DRINKS; i++) {
if (aperson->drinks_taken[i] != -1) {
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;
//write = fopen()
int i = 0;
memset(tmp_filename, 0, FILE_NAME_LEN + FILE_EXTENSION_LEN + 2);
strcat(tmp_filename, aperson->file_name);
strcat(tmp_filename, ".");
strcat(tmp_filename, FILE_EXTENSION);
write = SD.open(tmp_filename, 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;
}
}
}