Compare commits
14 commits
b055ec3822
...
4cd1434d0e
Author | SHA1 | Date | |
---|---|---|---|
embr | 4cd1434d0e | ||
Laura Hausmann | ac34813571 | ||
Laura Hausmann | f5d6a55b97 | ||
Laura Hausmann | 72ae2d0c75 | ||
Laura Hausmann | b10df2bc20 | ||
Laura Hausmann | da8572d76f | ||
Laura Hausmann | 83f9b57b56 | ||
Laura Hausmann | 30a69aaf00 | ||
Laura Hausmann | da50b2ab99 | ||
Laura Hausmann | 94ca5da794 | ||
Laura Hausmann | 7b487bc137 | ||
Laura Hausmann | de2a3ec163 | ||
Lilian | 40286250dc | ||
Lilian | a8de987d5b |
3593
AfRApay.MateCard/.uncrustify.cfg
Normal file
3593
AfRApay.MateCard/.uncrustify.cfg
Normal file
File diff suppressed because it is too large
Load diff
10
AfRApay.MateCard/README.md
Normal file
10
AfRApay.MateCard/README.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# AfRApay.MateCard
|
||||||
|
This is the software that runs on the MateCard terminal, powered by an ESP32.
|
||||||
|
|
||||||
|
## Setting up dev environment
|
||||||
|
This project uses PlatformIO. Quick setup guide:
|
||||||
|
- Install PlatformIO (macOS: `brew install platformio` / Arch Linux: `yay -S platformio` / Other: [platformio.org](https://platformio.org/install/cli))
|
||||||
|
- To compile, run `pio run`
|
||||||
|
- To compile and upload, run `pio run -t upload`
|
||||||
|
- To run clang-tidy, run `pio check`.
|
||||||
|
- Please run `uncrustify --no-backup -c .uncrustify.cfg src/*.cpp include/*.h` before commiting. To install it as a pre-commit hook, run `ln -s ../../hooks/pre-commit.hook ../.git/hooks/pre-commit` in this directory.
|
28
AfRApay.MateCard/include/cardReader.h
Normal file
28
AfRApay.MateCard/include/cardReader.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <MFRC522.h>
|
||||||
|
#include <rdm6300.h>
|
||||||
|
|
||||||
|
class CardReader {
|
||||||
|
public:
|
||||||
|
virtual bool isNewCardPresent() = 0;
|
||||||
|
virtual String getCardUid() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MFRC522CardReader : public CardReader {
|
||||||
|
private:
|
||||||
|
MFRC522* iReader;
|
||||||
|
public:
|
||||||
|
explicit MFRC522CardReader(MFRC522 *reader);
|
||||||
|
bool isNewCardPresent() override;
|
||||||
|
String getCardUid() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RDM6300CardReader : public CardReader {
|
||||||
|
private:
|
||||||
|
Rdm6300* iReader;
|
||||||
|
public:
|
||||||
|
explicit RDM6300CardReader(Rdm6300 *reader);
|
||||||
|
bool isNewCardPresent() override;
|
||||||
|
String getCardUid() override;
|
||||||
|
};
|
|
@ -1,155 +1,152 @@
|
||||||
#ifndef AFRAPAY_LOGOS_H
|
#pragma once
|
||||||
#define AFRAPAY_LOGOS_H
|
|
||||||
|
|
||||||
enum e_logo {
|
enum e_logo {
|
||||||
LOGO_AFRAPAY, LOGO_CONTACTLESS, LOGO_MATECARD, LOGO_PENDING, LOGO_SUCCESS, LOGO_FAILURE
|
LOGO_AFRAPAY, LOGO_CONTACTLESS, LOGO_MATECARD, LOGO_PENDING, LOGO_SUCCESS, LOGO_FAILURE
|
||||||
};
|
};
|
||||||
|
|
||||||
#define contactless_width 88
|
#define contactless_width 88
|
||||||
#define contactless_height 52
|
#define contactless_height 52
|
||||||
static unsigned char contactless_bits[] = {
|
static unsigned char contactless_bits[] = {
|
||||||
0x00, 0x00, 0x00, 0xE0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0xE0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xE0, 0x07, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
|
0xE0, 0x07, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
|
||||||
0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00,
|
0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00,
|
||||||
0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
|
0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x30, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0,
|
0x30, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x80, 0x01,
|
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x80, 0x01,
|
||||||
0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x03, 0x00,
|
0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x03, 0x00,
|
||||||
0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x06, 0x00, 0x00,
|
0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x06, 0x00, 0x00,
|
||||||
0x60, 0x00, 0x00, 0x00, 0x06, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x20,
|
0x60, 0x00, 0x00, 0x00, 0x06, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x20,
|
||||||
0x00, 0x00, 0x00, 0x0E, 0x1E, 0xE0, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00,
|
0x00, 0x00, 0x00, 0x0E, 0x1E, 0xE0, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00,
|
||||||
0x00, 0x00, 0x1E, 0x1E, 0xB0, 0x3F, 0x10, 0x00, 0x00, 0x18, 0x00, 0x00,
|
0x00, 0x00, 0x1E, 0x1E, 0xB0, 0x3F, 0x10, 0x00, 0x00, 0x18, 0x00, 0x00,
|
||||||
0x00, 0x1E, 0x1E, 0x10, 0xE0, 0x33, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1C,
|
0x00, 0x1E, 0x1E, 0x10, 0xE0, 0x33, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1C,
|
||||||
0x3C, 0x3C, 0x18, 0x00, 0x66, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x3C, 0x3C,
|
0x3C, 0x3C, 0x18, 0x00, 0x66, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x3C, 0x3C,
|
||||||
0x3C, 0x08, 0x00, 0x46, 0x00, 0x00, 0x04, 0x00, 0x00, 0x3C, 0x3C, 0x3C,
|
0x3C, 0x08, 0x00, 0x46, 0x00, 0x00, 0x04, 0x00, 0x00, 0x3C, 0x3C, 0x3C,
|
||||||
0x08, 0x06, 0xFE, 0x01, 0x00, 0x06, 0x00, 0x30, 0x78, 0x78, 0x38, 0x88,
|
0x08, 0x06, 0xFE, 0x01, 0x00, 0x06, 0x00, 0x30, 0x78, 0x78, 0x38, 0x88,
|
||||||
0x1F, 0xFE, 0x07, 0x00, 0x02, 0x00, 0x78, 0x78, 0x78, 0x78, 0x88, 0x70,
|
0x1F, 0xFE, 0x07, 0x00, 0x02, 0x00, 0x78, 0x78, 0x78, 0x78, 0x88, 0x70,
|
||||||
0x02, 0x0C, 0x00, 0x03, 0x00, 0xF0, 0x78, 0x78, 0x78, 0x8C, 0xC0, 0x03,
|
0x02, 0x0C, 0x00, 0x03, 0x00, 0xF0, 0x78, 0x78, 0x78, 0x8C, 0xC0, 0x03,
|
||||||
0x18, 0x00, 0x03, 0x00, 0xF0, 0xF0, 0x70, 0x78, 0x84, 0x00, 0x07, 0x10,
|
0x18, 0x00, 0x03, 0x00, 0xF0, 0xF0, 0x70, 0x78, 0x84, 0x00, 0x07, 0x10,
|
||||||
0x00, 0x03, 0x00, 0xE0, 0xF0, 0x70, 0x78, 0x84, 0x01, 0x0C, 0x20, 0x00,
|
0x00, 0x03, 0x00, 0xE0, 0xF0, 0x70, 0x78, 0x84, 0x01, 0x0C, 0x20, 0x00,
|
||||||
0x03, 0x00, 0xE0, 0xF1, 0x70, 0x78, 0x04, 0x03, 0x30, 0x60, 0x00, 0x03,
|
0x03, 0x00, 0xE0, 0xF1, 0x70, 0x78, 0x04, 0x03, 0x30, 0x60, 0x00, 0x03,
|
||||||
0x00, 0xE0, 0xF1, 0x70, 0x78, 0x0C, 0x04, 0xC0, 0x40, 0x00, 0x03, 0x00,
|
0x00, 0xE0, 0xF1, 0x70, 0x78, 0x0C, 0x04, 0xC0, 0x40, 0x00, 0x03, 0x00,
|
||||||
0xE0, 0xF1, 0x70, 0x78, 0xF8, 0x1D, 0x80, 0x81, 0x00, 0x03, 0x00, 0xE0,
|
0xE0, 0xF1, 0x70, 0x78, 0xF8, 0x1D, 0x80, 0x81, 0x00, 0x03, 0x00, 0xE0,
|
||||||
0xF1, 0x70, 0x78, 0x00, 0x3F, 0x00, 0x80, 0x01, 0x03, 0x00, 0xE0, 0xF0,
|
0xF1, 0x70, 0x78, 0x00, 0x3F, 0x00, 0x80, 0x01, 0x03, 0x00, 0xE0, 0xF0,
|
||||||
0x70, 0x78, 0x00, 0x68, 0x00, 0x00, 0x01, 0x03, 0x00, 0xF0, 0xF0, 0x70,
|
0x70, 0x78, 0x00, 0x68, 0x00, 0x00, 0x01, 0x03, 0x00, 0xF0, 0xF0, 0x70,
|
||||||
0x78, 0x00, 0xC4, 0x00, 0x00, 0x02, 0x03, 0x00, 0xF0, 0x70, 0x78, 0x78,
|
0x78, 0x00, 0xC4, 0x00, 0x00, 0x02, 0x03, 0x00, 0xF0, 0x70, 0x78, 0x78,
|
||||||
0x00, 0x0C, 0x03, 0x00, 0x06, 0x02, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00,
|
0x00, 0x0C, 0x03, 0x00, 0x06, 0x02, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00,
|
||||||
0x18, 0x06, 0x00, 0x04, 0x06, 0x00, 0x30, 0x78, 0x78, 0x38, 0x00, 0x30,
|
0x18, 0x06, 0x00, 0x04, 0x06, 0x00, 0x30, 0x78, 0x78, 0x38, 0x00, 0x30,
|
||||||
0x0C, 0x00, 0x08, 0x04, 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x00, 0x60, 0x18,
|
0x0C, 0x00, 0x08, 0x04, 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x00, 0x60, 0x18,
|
||||||
0x00, 0x18, 0x0C, 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x00, 0x90, 0x31, 0x00,
|
0x00, 0x18, 0x0C, 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x00, 0x90, 0x31, 0x00,
|
||||||
0x10, 0x0C, 0x00, 0x00, 0x1C, 0x3C, 0x3C, 0x00, 0x10, 0x3F, 0x00, 0x20,
|
0x10, 0x0C, 0x00, 0x00, 0x1C, 0x3C, 0x3C, 0x00, 0x10, 0x3F, 0x00, 0x20,
|
||||||
0x18, 0x00, 0x00, 0x00, 0x1E, 0x1E, 0x00, 0x10, 0x60, 0x00, 0x60, 0x30,
|
0x18, 0x00, 0x00, 0x00, 0x1E, 0x1E, 0x00, 0x10, 0x60, 0x00, 0x60, 0x30,
|
||||||
0x00, 0x00, 0x00, 0x1E, 0x1E, 0x00, 0x60, 0x40, 0x00, 0x40, 0x30, 0x00,
|
0x00, 0x00, 0x00, 0x1E, 0x1E, 0x00, 0x60, 0x40, 0x00, 0x40, 0x30, 0x00,
|
||||||
0x00, 0x00, 0x0E, 0x1E, 0x00, 0x80, 0xF3, 0x00, 0x80, 0x60, 0x00, 0x00,
|
0x00, 0x00, 0x0E, 0x1E, 0x00, 0x80, 0xF3, 0x00, 0x80, 0x60, 0x00, 0x00,
|
||||||
0x00, 0x06, 0x0F, 0x00, 0x00, 0x9E, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
|
0x00, 0x06, 0x0F, 0x00, 0x00, 0x9E, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x0F, 0x00, 0x00, 0x06, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
|
0x00, 0x0F, 0x00, 0x00, 0x06, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80,
|
||||||
0x07, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07,
|
0x07, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07,
|
||||||
0x00, 0x80, 0x01, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x80, 0x01, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xE0, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
0xE0, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00,
|
||||||
0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0xE0, 0x07, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0xE0, 0x07, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,};
|
0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,};
|
||||||
#define failure_width 40
|
#define failure_width 40
|
||||||
#define failure_height 40
|
#define failure_height 40
|
||||||
static unsigned char failure_bits[] = {
|
static unsigned char failure_bits[] = {
|
||||||
0x00, 0x80, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0xFC,
|
0x00, 0x80, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0xFC,
|
||||||
0xFF, 0x3F, 0x00, 0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0xFF,
|
0xFF, 0x3F, 0x00, 0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0xFF,
|
||||||
0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xF0,
|
0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xF0,
|
||||||
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF,
|
||||||
0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F,
|
0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||||
0xFE, 0x7F, 0xFF, 0xFE, 0x7F, 0xFE, 0x3F, 0x7E, 0xFC, 0x7F, 0xFE, 0x1F,
|
0xFE, 0x7F, 0xFF, 0xFE, 0x7F, 0xFE, 0x3F, 0x7E, 0xFC, 0x7F, 0xFE, 0x1F,
|
||||||
0x3C, 0xF8, 0x7F, 0xFF, 0x0F, 0x18, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0xF8,
|
0x3C, 0xF8, 0x7F, 0xFF, 0x0F, 0x18, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0xF8,
|
||||||
0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0xFF,
|
0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0xFF,
|
||||||
0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00,
|
0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00,
|
||||||
0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0xF8, 0xFF,
|
0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0xF8, 0xFF,
|
||||||
0xFF, 0x0F, 0x18, 0xF0, 0xFF, 0xFE, 0x1F, 0x3C, 0xF8, 0x7F, 0xFE, 0x3F,
|
0xFF, 0x0F, 0x18, 0xF0, 0xFF, 0xFE, 0x1F, 0x3C, 0xF8, 0x7F, 0xFE, 0x3F,
|
||||||
0x7E, 0xFC, 0x7F, 0xFE, 0x7F, 0xFF, 0xFE, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF,
|
0x7E, 0xFC, 0x7F, 0xFE, 0x7F, 0xFF, 0xFE, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||||
0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0,
|
0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0,
|
||||||
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF,
|
||||||
0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0x01,
|
0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0x01,
|
||||||
0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0x00, 0xF0,
|
0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0x00, 0xF0,
|
||||||
0xFF, 0x0F, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00,};
|
0xFF, 0x0F, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00,};
|
||||||
#define pending_width 40
|
#define pending_width 40
|
||||||
#define pending_height 40
|
#define pending_height 40
|
||||||
static unsigned char pending_bits[] = {
|
static unsigned char pending_bits[] = {
|
||||||
0x00, 0x80, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0xFC,
|
0x00, 0x80, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0xFC,
|
||||||
0xFF, 0x3F, 0x00, 0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0xFF,
|
0xFF, 0x3F, 0x00, 0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0xFF,
|
||||||
0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xF0,
|
0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xF0,
|
||||||
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF,
|
||||||
0xFF, 0x1F, 0xFC, 0xFF, 0xE3, 0xFF, 0x3F, 0xFC, 0xFF, 0xC3, 0xFF, 0x3F,
|
0xFF, 0x1F, 0xFC, 0xFF, 0xE3, 0xFF, 0x3F, 0xFC, 0xFF, 0xC3, 0xFF, 0x3F,
|
||||||
0xFE, 0xFF, 0xC3, 0xFF, 0x7F, 0xFE, 0xFF, 0xC3, 0xFF, 0x7F, 0xFE, 0xFF,
|
0xFE, 0xFF, 0xC3, 0xFF, 0x7F, 0xFE, 0xFF, 0xC3, 0xFF, 0x7F, 0xFE, 0xFF,
|
||||||
0xC3, 0xFF, 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF,
|
0xC3, 0xFF, 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0x03,
|
0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0x03,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF,
|
||||||
0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFE, 0xFF, 0x3F, 0xE0, 0x7F, 0xFE, 0xFF,
|
0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFE, 0xFF, 0x3F, 0xE0, 0x7F, 0xFE, 0xFF,
|
||||||
0x7F, 0xF0, 0x7F, 0xFE, 0xFF, 0xFF, 0xF1, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF,
|
0x7F, 0xF0, 0x7F, 0xFE, 0xFF, 0xFF, 0xF1, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||||
0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0,
|
0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0,
|
||||||
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF,
|
||||||
0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0x01,
|
0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0x01,
|
||||||
0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0x00, 0xF0,
|
0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0x00, 0xF0,
|
||||||
0xFF, 0x0F, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00,};
|
0xFF, 0x0F, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00,};
|
||||||
#define success_width 40
|
#define success_width 40
|
||||||
#define success_height 40
|
#define success_height 40
|
||||||
static unsigned char success_bits[] = {
|
static unsigned char success_bits[] = {
|
||||||
0x00, 0x80, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0xFC,
|
0x00, 0x80, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0xFC,
|
||||||
0xFF, 0x3F, 0x00, 0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0xFF,
|
0xFF, 0x3F, 0x00, 0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0xFF,
|
||||||
0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xF0,
|
0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xF0,
|
||||||
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF,
|
||||||
0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F,
|
0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||||
0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xF3, 0x7F, 0xFE, 0xFF,
|
0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xF3, 0x7F, 0xFE, 0xFF,
|
||||||
0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xE0,
|
0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xE0,
|
||||||
0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF,
|
||||||
0x8F, 0x0F, 0xFC, 0xFF, 0xFF, 0x07, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0x00,
|
0x8F, 0x0F, 0xFC, 0xFF, 0xFF, 0x07, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0x00,
|
||||||
0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0xFF,
|
||||||
0xFF, 0x3F, 0xE0, 0xFF, 0xFF, 0xFE, 0x7F, 0xF0, 0xFF, 0x7F, 0xFE, 0xFF,
|
0xFF, 0x3F, 0xE0, 0xFF, 0xFF, 0xFE, 0x7F, 0xF0, 0xFF, 0x7F, 0xFE, 0xFF,
|
||||||
0xF8, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF,
|
0xF8, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||||
0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0,
|
0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0,
|
||||||
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF,
|
||||||
0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0x01,
|
0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0x01,
|
||||||
0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0x00, 0xF0,
|
0x00, 0xFE, 0xFF, 0x7F, 0x00, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0x00, 0xF0,
|
||||||
0xFF, 0x0F, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00,};
|
0xFF, 0x0F, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00,};
|
||||||
|
|
||||||
#define matecard_width 65
|
#define matecard_width 65
|
||||||
#define matecard_height 40
|
#define matecard_height 40
|
||||||
static unsigned char matecard_bits[] = {
|
static unsigned char matecard_bits[] = {
|
||||||
0x00, 0x80, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xEB,
|
0x00, 0x80, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xEB,
|
||||||
0x0F, 0x00, 0x55, 0x05, 0x00, 0x00, 0x00, 0xB8, 0x5E, 0x1B, 0x20, 0x88,
|
0x0F, 0x00, 0x55, 0x05, 0x00, 0x00, 0x00, 0xB8, 0x5E, 0x1B, 0x20, 0x88,
|
||||||
0x10, 0x00, 0x00, 0x00, 0xEE, 0xF7, 0xF6, 0x90, 0x22, 0x44, 0x00, 0x00,
|
0x10, 0x00, 0x00, 0x00, 0xEE, 0xF7, 0xF6, 0x90, 0x22, 0x44, 0x00, 0x00,
|
||||||
0x00, 0xBB, 0xDA, 0xAF, 0x4A, 0x94, 0x12, 0x01, 0x00, 0x80, 0xDF, 0xFF,
|
0x00, 0xBB, 0xDA, 0xAF, 0x4A, 0x94, 0x12, 0x01, 0x00, 0x80, 0xDF, 0xFF,
|
||||||
0xFA, 0x12, 0x42, 0x44, 0x00, 0x00, 0xE0, 0x7A, 0x55, 0x57, 0x45, 0x09,
|
0xFA, 0x12, 0x42, 0x44, 0x00, 0x00, 0xE0, 0x7A, 0x55, 0x57, 0x45, 0x09,
|
||||||
0x91, 0x02, 0x00, 0xA0, 0xAF, 0xFF, 0xBD, 0x2A, 0xA2, 0x24, 0x08, 0x00,
|
0x91, 0x02, 0x00, 0xA0, 0xAF, 0xFF, 0xBD, 0x2A, 0xA2, 0x24, 0x08, 0x00,
|
||||||
0xF0, 0xFA, 0xAA, 0x57, 0x95, 0x08, 0x92, 0x02, 0x00, 0x78, 0x5F, 0xFF,
|
0xF0, 0xFA, 0xAA, 0x57, 0x95, 0x08, 0x92, 0x02, 0x00, 0x78, 0x5F, 0xFF,
|
||||||
0xAD, 0x2A, 0xA4, 0x44, 0x14, 0x00, 0xA8, 0xF5, 0x55, 0x57, 0x95, 0x12,
|
0xAD, 0x2A, 0xA4, 0x44, 0x14, 0x00, 0xA8, 0xF5, 0x55, 0x57, 0x95, 0x12,
|
||||||
0x11, 0x21, 0x00, 0xFC, 0xBF, 0xFE, 0xAB, 0xAA, 0x40, 0x88, 0x08, 0x00,
|
0x11, 0x21, 0x00, 0xFC, 0xBF, 0xFE, 0xAB, 0xAA, 0x40, 0x88, 0x08, 0x00,
|
||||||
0x54, 0xD5, 0xAB, 0x56, 0x55, 0x8A, 0x22, 0x25, 0x00, 0xFE, 0xFF, 0xFD,
|
0x54, 0xD5, 0xAB, 0x56, 0x55, 0x8A, 0x22, 0x25, 0x00, 0xFE, 0xFF, 0xFD,
|
||||||
0xAB, 0x2A, 0x51, 0x48, 0x48, 0x00, 0xAA, 0xAA, 0x56, 0xD5, 0x56, 0x82,
|
0xAB, 0x2A, 0x51, 0x48, 0x48, 0x00, 0xAA, 0xAA, 0x56, 0xD5, 0x56, 0x82,
|
||||||
0x12, 0x21, 0x00, 0xFE, 0xFF, 0xFF, 0xAB, 0xAA, 0x54, 0x44, 0x8A, 0x00,
|
0x12, 0x21, 0x00, 0xFE, 0xFF, 0xFF, 0xAB, 0xAA, 0x54, 0x44, 0x8A, 0x00,
|
||||||
0x55, 0x55, 0x55, 0x55, 0xB5, 0x80, 0x88, 0x10, 0x00, 0xFE, 0xFF, 0xFF,
|
0x55, 0x55, 0x55, 0x55, 0xB5, 0x80, 0x88, 0x10, 0x00, 0xFE, 0xFF, 0xFF,
|
||||||
0xAD, 0xAA, 0x2A, 0x52, 0xA4, 0x00, 0xAB, 0xAA, 0xAA, 0x55, 0x55, 0x44,
|
0xAD, 0xAA, 0x2A, 0x52, 0xA4, 0x00, 0xAB, 0xAA, 0xAA, 0x55, 0x55, 0x44,
|
||||||
0x81, 0x12, 0x01, 0xFE, 0xFF, 0x7F, 0xAB, 0xAA, 0x22, 0x28, 0x44, 0x00,
|
0x81, 0x12, 0x01, 0xFE, 0xFF, 0x7F, 0xAB, 0xAA, 0x22, 0x28, 0x44, 0x00,
|
||||||
0xAB, 0xAA, 0xEA, 0x6A, 0x55, 0x49, 0x45, 0x11, 0x01, 0xFD, 0xFF, 0xBF,
|
0xAB, 0xAA, 0xEA, 0x6A, 0x55, 0x49, 0x45, 0x11, 0x01, 0xFD, 0xFF, 0xBF,
|
||||||
0xAB, 0xAA, 0x10, 0x20, 0x44, 0x00, 0x57, 0x55, 0xF5, 0xAA, 0x6D, 0xA5,
|
0xAB, 0xAA, 0x10, 0x20, 0x44, 0x00, 0x57, 0x55, 0xF5, 0xAA, 0x6D, 0xA5,
|
||||||
0x8A, 0x28, 0x01, 0xFA, 0xFF, 0xAF, 0x55, 0x95, 0x08, 0x21, 0x05, 0x00,
|
0x8A, 0x28, 0x01, 0xFA, 0xFF, 0xAF, 0x55, 0x95, 0x08, 0x21, 0x05, 0x00,
|
||||||
0xAE, 0xAA, 0x7E, 0xAB, 0x6A, 0x22, 0x4A, 0xA8, 0x00, 0xF6, 0xFF, 0xD5,
|
0xAE, 0xAA, 0x7E, 0xAB, 0x6A, 0x22, 0x4A, 0xA8, 0x00, 0xF6, 0xFF, 0xD5,
|
||||||
0x56, 0x55, 0x91, 0x10, 0x05, 0x00, 0x5A, 0x55, 0xFF, 0x55, 0x55, 0x44,
|
0x56, 0x55, 0x91, 0x10, 0x05, 0x00, 0x5A, 0x55, 0xFF, 0x55, 0x55, 0x44,
|
||||||
0x22, 0xA8, 0x00, 0xFC, 0xFF, 0x57, 0xAF, 0x2A, 0x29, 0x49, 0x05, 0x00,
|
0x22, 0xA8, 0x00, 0xFC, 0xFF, 0x57, 0xAF, 0x2A, 0x29, 0x49, 0x05, 0x00,
|
||||||
0x54, 0x55, 0xFD, 0x6A, 0x55, 0x84, 0x04, 0x28, 0x00, 0xF8, 0xFF, 0x57,
|
0x54, 0x55, 0xFD, 0x6A, 0x55, 0x84, 0x04, 0x28, 0x00, 0xF8, 0xFF, 0x57,
|
||||||
0xAF, 0xAA, 0x22, 0x51, 0x05, 0x00, 0xA8, 0xAA, 0xFE, 0x55, 0x15, 0x88,
|
0xAF, 0xAA, 0x22, 0x51, 0x05, 0x00, 0xA8, 0xAA, 0xFE, 0x55, 0x15, 0x88,
|
||||||
0x84, 0x10, 0x00, 0xF0, 0xFF, 0xAB, 0xBE, 0x96, 0x52, 0x28, 0x0A, 0x00,
|
0x84, 0x10, 0x00, 0xF0, 0xFF, 0xAB, 0xBE, 0x96, 0x52, 0x28, 0x0A, 0x00,
|
||||||
0xA0, 0xAA, 0xFE, 0xAB, 0x4A, 0x04, 0x41, 0x00, 0x00, 0xC0, 0xFF, 0x57,
|
0xA0, 0xAA, 0xFE, 0xAB, 0x4A, 0x04, 0x41, 0x00, 0x00, 0xC0, 0xFF, 0x57,
|
||||||
0xDD, 0x12, 0xA2, 0x94, 0x0A, 0x00, 0x80, 0xAA, 0xFE, 0x77, 0x45, 0x09,
|
0xDD, 0x12, 0xA2, 0x94, 0x0A, 0x00, 0x80, 0xAA, 0xFE, 0x77, 0x45, 0x09,
|
||||||
0x21, 0x00, 0x00, 0x00, 0xFF, 0xAB, 0xBA, 0x21, 0x50, 0x8A, 0x02, 0x00,
|
0x21, 0x00, 0x00, 0x00, 0xFF, 0xAB, 0xBA, 0x21, 0x50, 0x8A, 0x02, 0x00,
|
||||||
0x00, 0xAA, 0xFE, 0x6F, 0x94, 0x82, 0x10, 0x00, 0x00, 0x00, 0xF8, 0xAB,
|
0x00, 0xAA, 0xFE, 0x6F, 0x94, 0x82, 0x10, 0x00, 0x00, 0x00, 0xF8, 0xAB,
|
||||||
0x1A, 0x80, 0x28, 0x4A, 0x00, 0x00, 0x00, 0x40, 0xFF, 0x0B, 0x20, 0xA2,
|
0x1A, 0x80, 0x28, 0x4A, 0x00, 0x00, 0x00, 0x40, 0xFF, 0x0B, 0x20, 0xA2,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x80, 0xAA, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x80, 0xAA, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,15 +1,11 @@
|
||||||
|
#pragma once
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <U8g2lib.h>
|
#include <U8g2lib.h>
|
||||||
#include "logos.h"
|
#include "logos.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#ifndef AFRAPAY_OLED_H
|
|
||||||
#define AFRAPAY_OLED_H
|
|
||||||
|
|
||||||
void drawLogo(U8G2 u8g2, e_logo logo);
|
void drawLogo(U8G2 u8g2, e_logo logo);
|
||||||
void drawStatusText(U8G2 u8g2, String status, String statusRightAligned = "");
|
void drawStatusText(U8G2 u8g2, String status, String statusRightAligned = "");
|
||||||
|
|
||||||
void updateOLED(U8G2 u8g2, e_state state, String statusText, String statusTextRightAligned = "");
|
void updateOLED(U8G2 u8g2, e_state state, String statusText, String statusTextRightAligned = "");
|
||||||
void updateOLED(U8G2 u8g2, e_state state);
|
void updateOLED(U8G2 u8g2, e_state state);
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,5 +1,4 @@
|
||||||
#ifndef AFRAPAY_PITCHES_H
|
#pragma once
|
||||||
#define AFRAPAY_PITCHES_H
|
|
||||||
|
|
||||||
#define NOTE_NONE 0
|
#define NOTE_NONE 0
|
||||||
#define NOTE_B0 31
|
#define NOTE_B0 31
|
||||||
|
@ -91,5 +90,3 @@
|
||||||
#define NOTE_CS8 4435
|
#define NOTE_CS8 4435
|
||||||
#define NOTE_D8 4699
|
#define NOTE_D8 4699
|
||||||
#define NOTE_DS8 4978
|
#define NOTE_DS8 4978
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,26 +1,24 @@
|
||||||
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
|
|
||||||
#ifndef AFRAPAY_UTILS_H
|
|
||||||
#define AFRAPAY_UTILS_H
|
|
||||||
unsigned long cooldownSecondsRemaining(unsigned long timeout, unsigned long timer);
|
unsigned long cooldownSecondsRemaining(unsigned long timeout, unsigned long timer);
|
||||||
String byteArrayAsHexString(byte *buffer, byte bufferSize);
|
String byteArrayAsHexString(byte *buffer, byte bufferSize);
|
||||||
|
String uint32AsHexString(uint32_t input);
|
||||||
String cardLink(WiFiClient* wifi, HTTPClient* http, String apiUrl, String cardId);
|
String cardLink(WiFiClient* wifi, HTTPClient* http, String apiUrl, String cardId);
|
||||||
String cardBalance(WiFiClient* wifi, HTTPClient* http, String apiUrl, String cardId);
|
String cardBalance(WiFiClient* wifi, HTTPClient* http, String apiUrl, String cardId);
|
||||||
String cardTransaction(WiFiClient* wifi, HTTPClient* http, String apiUrl, String cardId, String amount);
|
String cardTransaction(WiFiClient* wifi, HTTPClient* http, String apiUrl, String cardId, String amount);
|
||||||
String splitString(String data, char separator, int index);
|
String splitString(String data, char separator, int index);
|
||||||
|
|
||||||
enum e_state {
|
enum e_state {
|
||||||
STATE_IDLE,
|
STATE_IDLE,
|
||||||
STATE_TRANSACT_CARDSCAN,
|
STATE_TRANSACT_CARDSCAN,
|
||||||
STATE_TRANSACT_VERIFY,
|
STATE_TRANSACT_VERIFY,
|
||||||
STATE_LINK_CARDSCAN,
|
STATE_LINK_CARDSCAN,
|
||||||
STATE_LINK_VERIFY,
|
STATE_LINK_VERIFY,
|
||||||
STATE_BALANCE_CARDSCAN,
|
STATE_BALANCE_CARDSCAN,
|
||||||
STATE_BALANCE_VERIFY,
|
STATE_BALANCE_VERIFY,
|
||||||
STATE_RESULT_SUCCESS,
|
STATE_RESULT_SUCCESS,
|
||||||
STATE_RESULT_FAILURE,
|
STATE_RESULT_FAILURE,
|
||||||
STATE_RESULT_DISPLAY,
|
STATE_RESULT_DISPLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,9 +1,6 @@
|
||||||
#ifndef AFRAPAY_WIFIFIX_H
|
#pragma once
|
||||||
#define AFRAPAY_WIFIFIX_H
|
|
||||||
|
|
||||||
class WiFiClientFixed : public WiFiClient {
|
class WiFiClientFixed : public WiFiClient {
|
||||||
public:
|
public:
|
||||||
void flush() override;
|
void flush() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
|
@ -20,3 +20,7 @@ lib_deps =
|
||||||
miguelbalboa/MFRC522@^1.4.10
|
miguelbalboa/MFRC522@^1.4.10
|
||||||
arduino-libraries/NTPClient@^3.2.1
|
arduino-libraries/NTPClient@^3.2.1
|
||||||
mcxiaoke/ESPDateTime@^1.0.4
|
mcxiaoke/ESPDateTime@^1.0.4
|
||||||
|
arduino12/rdm6300@^2.0.0
|
||||||
|
check_tool = clangtidy
|
||||||
|
check_flags =
|
||||||
|
clangtidy: --checks=*,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-modernize-macro-to-enum
|
||||||
|
|
32
AfRApay.MateCard/src/cardReader.cpp
Normal file
32
AfRApay.MateCard/src/cardReader.cpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <MFRC522.h>
|
||||||
|
#include <rdm6300.h>
|
||||||
|
#include "utils.h"
|
||||||
|
#include "cardReader.h"
|
||||||
|
|
||||||
|
MFRC522CardReader::MFRC522CardReader(MFRC522 *reader) {
|
||||||
|
iReader = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MFRC522CardReader::isNewCardPresent() {
|
||||||
|
return iReader->PICC_IsNewCardPresent() && iReader->PICC_ReadCardSerial();
|
||||||
|
}
|
||||||
|
|
||||||
|
String MFRC522CardReader::getCardUid() {
|
||||||
|
return byteArrayAsHexString(iReader->uid.uidByte, iReader->uid.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
RDM6300CardReader::RDM6300CardReader(Rdm6300 *reader) {
|
||||||
|
iReader = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RDM6300CardReader::isNewCardPresent() {
|
||||||
|
return iReader->get_new_tag_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
String RDM6300CardReader::getCardUid() {
|
||||||
|
auto uid = iReader->get_tag_id();
|
||||||
|
char buf[16];
|
||||||
|
sprintf(buf, "%010u", uid);
|
||||||
|
return {buf};
|
||||||
|
}
|
|
@ -9,24 +9,44 @@
|
||||||
#include <MFRC522.h>
|
#include <MFRC522.h>
|
||||||
#include <ESPDateTime.h>
|
#include <ESPDateTime.h>
|
||||||
#include <DateTimeTZ.h>
|
#include <DateTimeTZ.h>
|
||||||
|
#include <rdm6300.h>
|
||||||
|
|
||||||
#include "wifiFix.h"
|
#include "wifiFix.h"
|
||||||
#include "pitches.h"
|
#include "pitches.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "oled.h"
|
#include "oled.h"
|
||||||
|
#include "cardReader.h"
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
|
||||||
|
|
||||||
|
//MFRC522 pinout (front) 3V3 RST GND IRQ MISO MOSI SCK SDA
|
||||||
|
//MFRC522 pinout (rear) SDA SCK MOSI MISO IRQ GND RST 3V3
|
||||||
|
|
||||||
|
#define HSPI_RST 4
|
||||||
#define HSPI_MISO 12
|
#define HSPI_MISO 12
|
||||||
#define HSPI_MOSI 13
|
#define HSPI_MOSI 13
|
||||||
#define HSPI_SCLK 14
|
#define HSPI_SCLK 14
|
||||||
#define HSPI_SS 15
|
#define HSPI_SS 15
|
||||||
#define HSPI_RST 16
|
#define PIN_HWSERIAL_RX 16
|
||||||
|
#define PIN_HWSERIAL_TX 17
|
||||||
#define BUZZER_PIN 26
|
#define PIN_BUZZER 19
|
||||||
|
#define PIN_OLED_SDA 21
|
||||||
|
#define PIN_OLED_SCL 22
|
||||||
|
#define PIN_INTERRUPT_TRANSACT 26
|
||||||
|
#define PIN_INTERRUPT_BALANCE 25
|
||||||
|
#define PIN_INTERRUPT_LINK 33
|
||||||
|
#define PIN_INTERRUPT_CANCEL 32
|
||||||
|
|
||||||
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
|
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
|
||||||
MFRC522 mfrc522(HSPI_SS, HSPI_RST);
|
MFRC522 mfrc522(HSPI_SS, HSPI_RST);
|
||||||
WiFiClient *wifi = new WiFiClientFixed();
|
WiFiClient *wifi = new WiFiClientFixed();
|
||||||
HTTPClient *http = new HTTPClient();
|
HTTPClient *http = new HTTPClient();
|
||||||
|
Rdm6300 rdm6300;
|
||||||
|
|
||||||
|
auto mfrc522reader = MFRC522CardReader(&mfrc522);
|
||||||
|
auto rdm6300reader = RDM6300CardReader(&rdm6300);
|
||||||
|
CardReader* readers[2] = {&mfrc522reader, &rdm6300reader};
|
||||||
|
|
||||||
e_state state = STATE_IDLE;
|
e_state state = STATE_IDLE;
|
||||||
String apiUrl = "";
|
String apiUrl = "";
|
||||||
|
@ -36,179 +56,190 @@ const int scanTimeout = 15000;
|
||||||
String scannedCardId = "";
|
String scannedCardId = "";
|
||||||
String lastStatusText = "";
|
String lastStatusText = "";
|
||||||
|
|
||||||
|
bool interruptFired = false;
|
||||||
unsigned long timer = 0;
|
unsigned long timer = 0;
|
||||||
|
|
||||||
void IRAM_ATTR TransactInterruptHandler() {
|
void IRAM_ATTR TransactInterruptHandler() {
|
||||||
if (state != STATE_IDLE) {
|
if (interruptFired || state != STATE_IDLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timer = millis();
|
interruptFired = true;
|
||||||
state = STATE_TRANSACT_CARDSCAN;
|
state = STATE_TRANSACT_CARDSCAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR LinkInterruptHandler() {
|
void IRAM_ATTR LinkInterruptHandler() {
|
||||||
if (state != STATE_IDLE) {
|
if (interruptFired || state != STATE_IDLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timer = millis();
|
interruptFired = true;
|
||||||
state = STATE_LINK_CARDSCAN;
|
state = STATE_LINK_CARDSCAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR BalanceInterruptHandler() {
|
void IRAM_ATTR BalanceInterruptHandler() {
|
||||||
if (state != STATE_IDLE) {
|
if (interruptFired || state != STATE_IDLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timer = millis();
|
interruptFired = true;
|
||||||
state = STATE_BALANCE_CARDSCAN;
|
state = STATE_BALANCE_CARDSCAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cooldownCheck(long timeout) {
|
bool cooldownCheck(long timeout) {
|
||||||
if (millis() - timer > timeout) {
|
if (millis() - timer > timeout) {
|
||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
updateOLED(u8g2, state);
|
updateOLED(u8g2, state);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
u8g2.begin();
|
Serial2.begin(115200, SERIAL_8N1, PIN_HWSERIAL_RX, PIN_HWSERIAL_TX);
|
||||||
drawLogo(u8g2, LOGO_MATECARD);
|
u8g2.begin();
|
||||||
u8g2.sendBuffer();
|
drawLogo(u8g2, LOGO_MATECARD);
|
||||||
SPI.begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI);
|
u8g2.sendBuffer();
|
||||||
SPIFFS.begin(true);
|
SPI.begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI);
|
||||||
WiFiSettings.hostname = "afrapay-";
|
SPIFFS.begin(true);
|
||||||
apiUrl = WiFiSettings.string("AfRApay.Web API", "http://192.168.50.170:5296");
|
WiFiSettings.hostname = "afrapay-";
|
||||||
WiFiSettings.connect();
|
apiUrl = WiFiSettings.string("AfRApay.Web API", "http://192.168.50.170:5296");
|
||||||
mfrc522.PCD_Init();
|
WiFiSettings.connect();
|
||||||
DateTime.setTimeZone(TZ_Europe_Berlin);
|
rdm6300.begin(PIN_HWSERIAL_RX);
|
||||||
DateTime.begin();
|
mfrc522.PCD_Init();
|
||||||
updateOLED(u8g2, state);
|
mfrc522.PCD_DumpVersionToSerial();
|
||||||
|
DateTime.setTimeZone(TZ_Europe_Berlin);
|
||||||
|
DateTime.begin();
|
||||||
|
updateOLED(u8g2, state);
|
||||||
|
|
||||||
ledcSetup(0, 5000, 12);
|
ledcSetup(0, 5000, 12);
|
||||||
pinMode(25, INPUT_PULLUP);
|
pinMode(PIN_INTERRUPT_TRANSACT, INPUT_PULLUP);
|
||||||
pinMode(32, INPUT_PULLUP);
|
pinMode(PIN_INTERRUPT_BALANCE, INPUT_PULLUP);
|
||||||
pinMode(33, INPUT_PULLUP);
|
pinMode(PIN_INTERRUPT_CANCEL, INPUT_PULLUP);
|
||||||
attachInterrupt(25, BalanceInterruptHandler, FALLING);
|
pinMode(PIN_INTERRUPT_LINK, INPUT_PULLUP);
|
||||||
attachInterrupt(32, LinkInterruptHandler, FALLING);
|
attachInterrupt(PIN_INTERRUPT_TRANSACT, TransactInterruptHandler, FALLING);
|
||||||
attachInterrupt(33, TransactInterruptHandler, FALLING);
|
attachInterrupt(PIN_INTERRUPT_BALANCE, BalanceInterruptHandler, FALLING);
|
||||||
|
attachInterrupt(PIN_INTERRUPT_LINK, LinkInterruptHandler, FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
updateOLED(u8g2, state, "WiFi disconnected :(");
|
updateOLED(u8g2, state, "WiFi disconnected :(");
|
||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
WiFi.reconnect();
|
WiFi.reconnect();
|
||||||
delay(50);
|
delay(50);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
if (interruptFired) {
|
||||||
case STATE_IDLE:
|
timer = millis();
|
||||||
updateOLED(u8g2, state);
|
interruptFired = false;
|
||||||
break;
|
}
|
||||||
case STATE_TRANSACT_CARDSCAN:
|
|
||||||
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
|
|
||||||
scannedCardId = byteArrayAsHexString(mfrc522.uid.uidByte, mfrc522.uid.size);
|
|
||||||
mfrc522.PICC_HaltA();
|
|
||||||
lastStatusText = "Card #" + scannedCardId;
|
|
||||||
state = STATE_TRANSACT_VERIFY;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (!cooldownCheck(scanTimeout)) {
|
|
||||||
updateOLED(u8g2, state, String("1.50€"), String(cooldownSecondsRemaining(scanTimeout, timer)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATE_TRANSACT_VERIFY:
|
|
||||||
updateOLED(u8g2, state, lastStatusText);
|
|
||||||
tone(BUZZER_PIN, NOTE_A5, 25);
|
|
||||||
tone(BUZZER_PIN, NOTE_NONE, 150);
|
|
||||||
lastStatusText = cardTransaction(wifi, http, apiUrl, scannedCardId, "1.50");
|
|
||||||
if (lastStatusText.startsWith("S:")) {
|
|
||||||
tone(BUZZER_PIN, NOTE_C7, 650);
|
|
||||||
lastStatusText += "€";
|
|
||||||
state = STATE_RESULT_SUCCESS;
|
|
||||||
} else {
|
|
||||||
tone(BUZZER_PIN, NOTE_CS5, 100);
|
|
||||||
tone(BUZZER_PIN, NOTE_NONE, 25);
|
|
||||||
tone(BUZZER_PIN, NOTE_CS5, 400);
|
|
||||||
state = STATE_RESULT_FAILURE;
|
|
||||||
}
|
|
||||||
lastStatusText = lastStatusText.substring(2);
|
|
||||||
timer = millis();
|
|
||||||
return;
|
|
||||||
case STATE_LINK_CARDSCAN:
|
|
||||||
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
|
|
||||||
scannedCardId = byteArrayAsHexString(mfrc522.uid.uidByte, mfrc522.uid.size);
|
|
||||||
mfrc522.PICC_HaltA();
|
|
||||||
lastStatusText = "Card #" + scannedCardId;
|
|
||||||
state = STATE_LINK_VERIFY;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (!cooldownCheck(scanTimeout)) {
|
|
||||||
updateOLED(u8g2, state, "Link", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATE_LINK_VERIFY:
|
|
||||||
updateOLED(u8g2, state, lastStatusText);
|
|
||||||
tone(BUZZER_PIN, NOTE_A5, 25);
|
|
||||||
tone(BUZZER_PIN, NOTE_NONE, 150);
|
|
||||||
lastStatusText = cardLink(wifi, http, apiUrl, scannedCardId);
|
|
||||||
if (lastStatusText.startsWith("S:")) {
|
|
||||||
tone(BUZZER_PIN, NOTE_C6, 100);
|
|
||||||
tone(BUZZER_PIN, NOTE_NONE, 10);
|
|
||||||
tone(BUZZER_PIN, NOTE_C6, 100);
|
|
||||||
state = STATE_RESULT_SUCCESS;
|
|
||||||
} else {
|
|
||||||
tone(BUZZER_PIN, NOTE_CS5, 100);
|
|
||||||
tone(BUZZER_PIN, NOTE_NONE, 25);
|
|
||||||
tone(BUZZER_PIN, NOTE_CS5, 400);
|
|
||||||
state = STATE_RESULT_FAILURE;
|
|
||||||
}
|
|
||||||
lastStatusText = lastStatusText.substring(2);
|
|
||||||
timer = millis();
|
|
||||||
return;
|
|
||||||
case STATE_BALANCE_CARDSCAN:
|
|
||||||
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
|
|
||||||
scannedCardId = byteArrayAsHexString(mfrc522.uid.uidByte, mfrc522.uid.size);
|
|
||||||
mfrc522.PICC_HaltA();
|
|
||||||
lastStatusText = "Card #" + scannedCardId;
|
|
||||||
state = STATE_BALANCE_VERIFY;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (!cooldownCheck(scanTimeout)) {
|
|
||||||
updateOLED(u8g2, state, "Balance", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATE_BALANCE_VERIFY:
|
|
||||||
updateOLED(u8g2, state, lastStatusText);
|
|
||||||
tone(BUZZER_PIN, NOTE_A5, 25);
|
|
||||||
tone(BUZZER_PIN, NOTE_NONE, 150);
|
|
||||||
lastStatusText = cardBalance(wifi, http, apiUrl, scannedCardId);
|
|
||||||
if (lastStatusText.startsWith("S:")) {
|
|
||||||
lastStatusText = lastStatusText + ":Card #" + scannedCardId;
|
|
||||||
state = STATE_RESULT_DISPLAY;
|
|
||||||
} else {
|
|
||||||
tone(BUZZER_PIN, NOTE_CS5, 100);
|
|
||||||
tone(BUZZER_PIN, NOTE_NONE, 25);
|
|
||||||
tone(BUZZER_PIN, NOTE_CS5, 400);
|
|
||||||
state = STATE_RESULT_FAILURE;
|
|
||||||
}
|
|
||||||
lastStatusText = lastStatusText.substring(2);
|
|
||||||
timer = millis();
|
|
||||||
case STATE_RESULT_SUCCESS:
|
|
||||||
case STATE_RESULT_FAILURE:
|
|
||||||
case STATE_RESULT_DISPLAY:
|
|
||||||
if (!cooldownCheck(gTimeout)) {
|
|
||||||
updateOLED(u8g2, state, lastStatusText, String(cooldownSecondsRemaining(gTimeout, timer)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
delay(50);
|
switch (state) {
|
||||||
}
|
case STATE_IDLE:
|
||||||
|
updateOLED(u8g2, state);
|
||||||
|
break;
|
||||||
|
case STATE_TRANSACT_CARDSCAN:
|
||||||
|
for (CardReader *reader : readers) {
|
||||||
|
if (reader->isNewCardPresent()) {
|
||||||
|
scannedCardId = reader->getCardUid();
|
||||||
|
lastStatusText = "Card #" + scannedCardId;
|
||||||
|
state = STATE_TRANSACT_VERIFY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cooldownCheck(scanTimeout)) {
|
||||||
|
updateOLED(u8g2, state, String("1.50€"), String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_TRANSACT_VERIFY:
|
||||||
|
updateOLED(u8g2, state, lastStatusText);
|
||||||
|
tone(PIN_BUZZER, NOTE_A5, 25);
|
||||||
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
||||||
|
lastStatusText = cardTransaction(wifi, http, apiUrl, scannedCardId, "1.50");
|
||||||
|
if (lastStatusText.startsWith("S:")) {
|
||||||
|
tone(PIN_BUZZER, NOTE_C7, 650);
|
||||||
|
lastStatusText += "€";
|
||||||
|
state = STATE_RESULT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
tone(PIN_BUZZER, NOTE_CS5, 100);
|
||||||
|
tone(PIN_BUZZER, NOTE_NONE, 25);
|
||||||
|
tone(PIN_BUZZER, NOTE_CS5, 400);
|
||||||
|
state = STATE_RESULT_FAILURE;
|
||||||
|
}
|
||||||
|
lastStatusText = lastStatusText.substring(2);
|
||||||
|
timer = millis();
|
||||||
|
return;
|
||||||
|
case STATE_LINK_CARDSCAN:
|
||||||
|
for (CardReader *reader : readers) {
|
||||||
|
if (reader->isNewCardPresent()) {
|
||||||
|
scannedCardId = reader->getCardUid();
|
||||||
|
lastStatusText = "Card #" + scannedCardId;
|
||||||
|
state = STATE_LINK_VERIFY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cooldownCheck(scanTimeout)) {
|
||||||
|
updateOLED(u8g2, state, "Link", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_LINK_VERIFY:
|
||||||
|
updateOLED(u8g2, state, lastStatusText);
|
||||||
|
tone(PIN_BUZZER, NOTE_A5, 25);
|
||||||
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
||||||
|
lastStatusText = cardLink(wifi, http, apiUrl, scannedCardId);
|
||||||
|
if (lastStatusText.startsWith("S:")) {
|
||||||
|
tone(PIN_BUZZER, NOTE_C6, 100);
|
||||||
|
tone(PIN_BUZZER, NOTE_NONE, 10);
|
||||||
|
tone(PIN_BUZZER, NOTE_C6, 100);
|
||||||
|
state = STATE_RESULT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
tone(PIN_BUZZER, NOTE_CS5, 100);
|
||||||
|
tone(PIN_BUZZER, NOTE_NONE, 25);
|
||||||
|
tone(PIN_BUZZER, NOTE_CS5, 400);
|
||||||
|
state = STATE_RESULT_FAILURE;
|
||||||
|
}
|
||||||
|
lastStatusText = lastStatusText.substring(2);
|
||||||
|
timer = millis();
|
||||||
|
return;
|
||||||
|
case STATE_BALANCE_CARDSCAN:
|
||||||
|
for (CardReader *reader : readers) {
|
||||||
|
if (reader->isNewCardPresent()) {
|
||||||
|
scannedCardId = reader->getCardUid();
|
||||||
|
lastStatusText = "Card #" + scannedCardId;
|
||||||
|
state = STATE_BALANCE_VERIFY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cooldownCheck(scanTimeout)) {
|
||||||
|
updateOLED(u8g2, state, "Balance", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATE_BALANCE_VERIFY:
|
||||||
|
updateOLED(u8g2, state, lastStatusText);
|
||||||
|
tone(PIN_BUZZER, NOTE_A5, 25);
|
||||||
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
||||||
|
lastStatusText = cardBalance(wifi, http, apiUrl, scannedCardId);
|
||||||
|
if (lastStatusText.startsWith("S:")) {
|
||||||
|
lastStatusText = lastStatusText + ":Card #" + scannedCardId;
|
||||||
|
state = STATE_RESULT_DISPLAY;
|
||||||
|
} else {
|
||||||
|
tone(PIN_BUZZER, NOTE_CS5, 100);
|
||||||
|
tone(PIN_BUZZER, NOTE_NONE, 25);
|
||||||
|
tone(PIN_BUZZER, NOTE_CS5, 400);
|
||||||
|
state = STATE_RESULT_FAILURE;
|
||||||
|
}
|
||||||
|
lastStatusText = lastStatusText.substring(2);
|
||||||
|
timer = millis();
|
||||||
|
case STATE_RESULT_SUCCESS:
|
||||||
|
case STATE_RESULT_FAILURE:
|
||||||
|
case STATE_RESULT_DISPLAY:
|
||||||
|
if (!cooldownCheck(gTimeout)) {
|
||||||
|
updateOLED(u8g2, state, lastStatusText, String(cooldownSecondsRemaining(gTimeout, timer)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(50);
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
|
@ -6,125 +6,125 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
void drawCurvedLineV(U8G2 u8g2, int xStart, int yStart, int vert, int horiz) {
|
void drawCurvedLineV(U8G2 u8g2, int xStart, int yStart, int vert, int horiz) {
|
||||||
u8g2.drawVLine(xStart, yStart + 1, vert);
|
u8g2.drawVLine(xStart, yStart + 1, vert);
|
||||||
u8g2.drawVLine(xStart + 1, yStart, vert);
|
u8g2.drawVLine(xStart + 1, yStart, vert);
|
||||||
|
|
||||||
u8g2.drawHLine(xStart, yStart + vert, horiz);
|
u8g2.drawHLine(xStart, yStart + vert, horiz);
|
||||||
u8g2.drawHLine(xStart + 1, yStart + vert + 1, horiz);
|
u8g2.drawHLine(xStart + 1, yStart + vert + 1, horiz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawCurvedLine(U8G2 u8g2, int xStart, int yStart, int horiz, int vert) {
|
void drawCurvedLine(U8G2 u8g2, int xStart, int yStart, int horiz, int vert) {
|
||||||
u8g2.drawHLine(xStart, yStart, horiz);
|
u8g2.drawHLine(xStart, yStart, horiz);
|
||||||
u8g2.drawHLine(xStart, yStart + 1, horiz);
|
u8g2.drawHLine(xStart, yStart + 1, horiz);
|
||||||
|
|
||||||
u8g2.drawVLine(xStart + horiz, yStart, vert);
|
u8g2.drawVLine(xStart + horiz, yStart, vert);
|
||||||
u8g2.drawVLine(xStart + horiz + 1, yStart + 1, vert);
|
u8g2.drawVLine(xStart + horiz + 1, yStart + 1, vert);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawLogoAfraPay(U8G2 u8g2) {
|
void drawLogoAfraPay(U8G2 u8g2) {
|
||||||
u8g2.setFontMode(1);
|
u8g2.setFontMode(1);
|
||||||
u8g2.setFontDirection(0);
|
u8g2.setFontDirection(0);
|
||||||
|
|
||||||
int xOffset = 12;
|
int xOffset = 12;
|
||||||
int yOffset = 23;
|
int yOffset = 23;
|
||||||
|
|
||||||
u8g2.setFont(u8g2_font_maniac_tr);
|
u8g2.setFont(u8g2_font_maniac_tr);
|
||||||
u8g2.drawStr(xOffset, yOffset, "AfRA");
|
u8g2.drawStr(xOffset, yOffset, "AfRA");
|
||||||
|
|
||||||
u8g2.setFont(u8g2_font_tenthinguys_tr);
|
u8g2.setFont(u8g2_font_tenthinguys_tr);
|
||||||
u8g2.drawStr(xOffset + 73, yOffset + 3, "pay");
|
u8g2.drawStr(xOffset + 73, yOffset + 3, "pay");
|
||||||
|
|
||||||
// uncomment to verify distance to screen gap is equal on both sides
|
// uncomment to verify distance to screen gap is equal on both sides
|
||||||
//u8g2.drawHLine(0, yOffset-12, xOffset);
|
//u8g2.drawHLine(0, yOffset-12, xOffset);
|
||||||
//u8g2.drawHLine(127-xOffset-1, yOffset, xOffset);
|
//u8g2.drawHLine(127-xOffset-1, yOffset, xOffset);
|
||||||
|
|
||||||
drawCurvedLineV(u8g2, xOffset + 69, yOffset, 7, 32);
|
drawCurvedLineV(u8g2, xOffset + 69, yOffset, 7, 32);
|
||||||
drawCurvedLine(u8g2, xOffset + 73, yOffset - 8, 28, 15);
|
drawCurvedLine(u8g2, xOffset + 73, yOffset - 8, 28, 15);
|
||||||
u8g2.drawPixel(xOffset + 101, yOffset + 7);
|
u8g2.drawPixel(xOffset + 101, yOffset + 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawLogoBitmap(U8G2 u8g2, int width, int height, unsigned char bits[], int yOffset = 0) {
|
void drawLogoBitmap(U8G2 u8g2, int width, int height, unsigned char bits[], int yOffset = 0) {
|
||||||
int offset = (128 - width) / 2;
|
int offset = (128 - width) / 2;
|
||||||
u8g2.drawXBM(offset, yOffset, width, height, bits);
|
u8g2.drawXBM(offset, yOffset, width, height, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawLogo(U8G2 u8g2, e_logo logo) {
|
void drawLogo(U8G2 u8g2, e_logo logo) {
|
||||||
switch (logo) {
|
switch (logo) {
|
||||||
case LOGO_AFRAPAY:
|
case LOGO_AFRAPAY:
|
||||||
drawLogoAfraPay(u8g2);
|
drawLogoAfraPay(u8g2);
|
||||||
break;
|
break;
|
||||||
case LOGO_CONTACTLESS:
|
case LOGO_CONTACTLESS:
|
||||||
drawLogoBitmap(u8g2, contactless_width, contactless_height, contactless_bits);
|
drawLogoBitmap(u8g2, contactless_width, contactless_height, contactless_bits);
|
||||||
break;
|
break;
|
||||||
case LOGO_MATECARD:
|
case LOGO_MATECARD:
|
||||||
drawLogoBitmap(u8g2, matecard_width, matecard_height, matecard_bits, 5);
|
drawLogoBitmap(u8g2, matecard_width, matecard_height, matecard_bits, 5);
|
||||||
u8g2.setFont(u8g2_font_bpixeldouble_tr);
|
u8g2.setFont(u8g2_font_bpixeldouble_tr);
|
||||||
u8g2.drawStr((126 - u8g2.getStrWidth("matecard")) / 2, 57, "matecard");
|
u8g2.drawStr((126 - u8g2.getStrWidth("matecard")) / 2, 57, "matecard");
|
||||||
break;
|
break;
|
||||||
case LOGO_PENDING:
|
case LOGO_PENDING:
|
||||||
drawLogoBitmap(u8g2, pending_width, pending_height, pending_bits, 5);
|
drawLogoBitmap(u8g2, pending_width, pending_height, pending_bits, 5);
|
||||||
break;
|
break;
|
||||||
case LOGO_SUCCESS:
|
case LOGO_SUCCESS:
|
||||||
drawLogoBitmap(u8g2, success_width, success_height, success_bits, 5);
|
drawLogoBitmap(u8g2, success_width, success_height, success_bits, 5);
|
||||||
break;
|
break;
|
||||||
case LOGO_FAILURE:
|
case LOGO_FAILURE:
|
||||||
drawLogoBitmap(u8g2, failure_width, failure_height, failure_bits, 5);
|
drawLogoBitmap(u8g2, failure_width, failure_height, failure_bits, 5);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawStatusText(U8G2 u8g2, String status, String statusRightAligned = "") {
|
void drawStatusText(U8G2 u8g2, String status, String statusRightAligned = "") {
|
||||||
u8g2.setFont(u8g2_font_bpixel_te);
|
u8g2.setFont(u8g2_font_bpixel_te);
|
||||||
u8g2.drawUTF8(0, 61, status.c_str());
|
u8g2.drawUTF8(0, 61, status.c_str());
|
||||||
|
|
||||||
if (!statusRightAligned.isEmpty()) {
|
if (!statusRightAligned.isEmpty()) {
|
||||||
int textWidth = u8g2.getUTF8Width(statusRightAligned.c_str());
|
int textWidth = u8g2.getUTF8Width(statusRightAligned.c_str());
|
||||||
u8g2.drawUTF8(126 - textWidth, 61, statusRightAligned.c_str());
|
u8g2.drawUTF8(126 - textWidth, 61, statusRightAligned.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawFullScreenText(U8G2 u8g2, String textTop, String textBottom) {
|
void drawFullScreenText(U8G2 u8g2, String textTop, String textBottom) {
|
||||||
u8g2.setFont(u8g2_font_chargen_92_tr);
|
u8g2.setFont(u8g2_font_chargen_92_tr);
|
||||||
u8g2.drawUTF8((127-u8g2.getUTF8Width(textTop.c_str()))/2, 13, textTop.c_str());
|
u8g2.drawUTF8((127-u8g2.getUTF8Width(textTop.c_str()))/2, 13, textTop.c_str());
|
||||||
u8g2.setFont(u8g2_font_maniac_te);
|
u8g2.setFont(u8g2_font_maniac_te);
|
||||||
u8g2.drawUTF8((127-u8g2.getUTF8Width(textBottom.c_str()))/2, 45, textBottom.c_str());
|
u8g2.drawUTF8((127-u8g2.getUTF8Width(textBottom.c_str()))/2, 45, textBottom.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateOLED(U8G2 u8g2, e_state state, String statusText, String statusTextRightAligned = "") {
|
void updateOLED(U8G2 u8g2, e_state state, String statusText, String statusTextRightAligned = "") {
|
||||||
u8g2.clearBuffer();
|
u8g2.clearBuffer();
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_IDLE:
|
case STATE_IDLE:
|
||||||
drawLogo(u8g2, LOGO_AFRAPAY);
|
drawLogo(u8g2, LOGO_AFRAPAY);
|
||||||
break;
|
break;
|
||||||
case STATE_TRANSACT_CARDSCAN:
|
case STATE_TRANSACT_CARDSCAN:
|
||||||
case STATE_BALANCE_CARDSCAN:
|
case STATE_BALANCE_CARDSCAN:
|
||||||
case STATE_LINK_CARDSCAN:
|
case STATE_LINK_CARDSCAN:
|
||||||
drawLogo(u8g2, LOGO_CONTACTLESS);
|
drawLogo(u8g2, LOGO_CONTACTLESS);
|
||||||
break;
|
break;
|
||||||
case STATE_RESULT_SUCCESS:
|
case STATE_RESULT_SUCCESS:
|
||||||
drawLogo(u8g2, LOGO_SUCCESS);
|
drawLogo(u8g2, LOGO_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case STATE_RESULT_FAILURE:
|
case STATE_RESULT_FAILURE:
|
||||||
drawLogo(u8g2, LOGO_FAILURE);
|
drawLogo(u8g2, LOGO_FAILURE);
|
||||||
break;
|
break;
|
||||||
case STATE_RESULT_DISPLAY:
|
case STATE_RESULT_DISPLAY:
|
||||||
drawFullScreenText(u8g2, splitString(statusText, ':', 0), splitString(statusText, ':', 1) + "€");
|
drawFullScreenText(u8g2, splitString(statusText, ':', 0), splitString(statusText, ':', 1) + "€");
|
||||||
drawStatusText(u8g2, splitString(statusText, ':', 2), statusTextRightAligned);
|
drawStatusText(u8g2, splitString(statusText, ':', 2), statusTextRightAligned);
|
||||||
u8g2.sendBuffer();
|
u8g2.sendBuffer();
|
||||||
return;
|
return;
|
||||||
case STATE_TRANSACT_VERIFY:
|
case STATE_TRANSACT_VERIFY:
|
||||||
case STATE_BALANCE_VERIFY:
|
case STATE_BALANCE_VERIFY:
|
||||||
case STATE_LINK_VERIFY:
|
case STATE_LINK_VERIFY:
|
||||||
drawLogo(u8g2, LOGO_PENDING);
|
drawLogo(u8g2, LOGO_PENDING);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawStatusText(u8g2, statusText, statusTextRightAligned);
|
drawStatusText(u8g2, statusText, statusTextRightAligned);
|
||||||
u8g2.sendBuffer();
|
u8g2.sendBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateOLED(U8G2 u8g2, e_state state) {
|
void updateOLED(U8G2 u8g2, e_state state) {
|
||||||
String time = DateTime.format(DateFormatter::TIME_ONLY);
|
String time = DateTime.format(DateFormatter::TIME_ONLY);
|
||||||
updateOLED(u8g2, state, time, WiFi.localIP().toString());
|
updateOLED(u8g2, state, time, WiFi.localIP().toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,78 +3,82 @@
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
|
|
||||||
String byteArrayAsHexString(byte *buffer, byte bufferSize) {
|
String byteArrayAsHexString(byte *buffer, byte bufferSize) {
|
||||||
String s = "";
|
String s = "";
|
||||||
for (byte i = 0; i < bufferSize; i++) {
|
for (byte i = 0; i < bufferSize; i++) {
|
||||||
s += (buffer[i] < 0x10 ? "0" : "");
|
s += (buffer[i] < 0x10 ? "0" : "");
|
||||||
s += String(buffer[i], HEX);
|
s += String(buffer[i], HEX);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
String uint32AsHexString(uint32_t input) {
|
||||||
|
return byteArrayAsHexString(reinterpret_cast<byte *>(&input), sizeof input);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long cooldownSecondsRemaining(unsigned long timeout, unsigned long timer) {
|
unsigned long cooldownSecondsRemaining(unsigned long timeout, unsigned long timer) {
|
||||||
return (timeout - (millis() - timer)) / 1000 + 1;
|
return (timeout - (millis() - timer)) / 1000 + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
String splitString(String data, char separator, int index) {
|
String splitString(String data, char separator, int index) {
|
||||||
int found = 0;
|
int found = 0;
|
||||||
int strIndex[] = {0, -1};
|
int strIndex[] = {0, -1};
|
||||||
int maxIndex = data.length() - 1;
|
int maxIndex = data.length() - 1;
|
||||||
|
|
||||||
for (int i = 0; i <= maxIndex && found <= index; i++) {
|
for (int i = 0; i <= maxIndex && found <= index; i++) {
|
||||||
if (data.charAt(i) == separator || i == maxIndex) {
|
if (data.charAt(i) == separator || i == maxIndex) {
|
||||||
found++;
|
found++;
|
||||||
strIndex[0] = strIndex[1] + 1;
|
strIndex[0] = strIndex[1] + 1;
|
||||||
strIndex[1] = (i == maxIndex) ? i + 1 : i;
|
strIndex[1] = (i == maxIndex) ? i + 1 : i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String cardLink(WiFiClient *wifi, HTTPClient *http, String apiUrl, String cardId) {
|
String cardLink(WiFiClient *wifi, HTTPClient *http, String apiUrl, String cardId) {
|
||||||
String finalRequestUrl = apiUrl + "/api/card/link?card=" + cardId;
|
String finalRequestUrl = apiUrl + "/api/card/link?card=" + cardId;
|
||||||
http->begin(*wifi, finalRequestUrl.c_str());
|
http->begin(*wifi, finalRequestUrl.c_str());
|
||||||
int httpResponseCode = http->GET();
|
int httpResponseCode = http->GET();
|
||||||
if (httpResponseCode == 200) {
|
if (httpResponseCode == 200) {
|
||||||
String payload = http->getString();
|
String payload = http->getString();
|
||||||
http->end();
|
http->end();
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
http->end();
|
http->end();
|
||||||
if (httpResponseCode > 0) {
|
if (httpResponseCode > 0) {
|
||||||
return String("E:HTTP Error ") + httpResponseCode;
|
return String("E:HTTP Error ") + httpResponseCode;
|
||||||
}
|
}
|
||||||
return String("E:Internal Error ") + httpResponseCode;
|
return String("E:Internal Error ") + httpResponseCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
String cardBalance(WiFiClient *wifi, HTTPClient *http, String apiUrl, String cardId) {
|
String cardBalance(WiFiClient *wifi, HTTPClient *http, String apiUrl, String cardId) {
|
||||||
String finalRequestUrl = apiUrl + "/api/card/balance?card=" + cardId;
|
String finalRequestUrl = apiUrl + "/api/card/balance?card=" + cardId;
|
||||||
http->begin(*wifi, finalRequestUrl.c_str());
|
http->begin(*wifi, finalRequestUrl.c_str());
|
||||||
int httpResponseCode = http->GET();
|
int httpResponseCode = http->GET();
|
||||||
if (httpResponseCode == 200) {
|
if (httpResponseCode == 200) {
|
||||||
String payload = http->getString();
|
String payload = http->getString();
|
||||||
http->end();
|
http->end();
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
http->end();
|
http->end();
|
||||||
if (httpResponseCode > 0) {
|
if (httpResponseCode > 0) {
|
||||||
return String("E:HTTP Error ") + httpResponseCode;
|
return String("E:HTTP Error ") + httpResponseCode;
|
||||||
}
|
}
|
||||||
return String("E:Internal Error ") + httpResponseCode;
|
return String("E:Internal Error ") + httpResponseCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
String cardTransaction(WiFiClient *wifi, HTTPClient *http, String apiUrl, String cardId, String amount) {
|
String cardTransaction(WiFiClient *wifi, HTTPClient *http, String apiUrl, String cardId, String amount) {
|
||||||
String finalRequestUrl = apiUrl + "/api/card/transaction?card=" + cardId + "&amount=" + amount;
|
String finalRequestUrl = apiUrl + "/api/card/transaction?card=" + cardId + "&amount=" + amount;
|
||||||
http->begin(*wifi, finalRequestUrl.c_str());
|
http->begin(*wifi, finalRequestUrl.c_str());
|
||||||
int httpResponseCode = http->GET();
|
int httpResponseCode = http->GET();
|
||||||
if (httpResponseCode == 200) {
|
if (httpResponseCode == 200) {
|
||||||
String payload = http->getString();
|
String payload = http->getString();
|
||||||
http->end();
|
http->end();
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
http->end();
|
http->end();
|
||||||
if (httpResponseCode > 0) {
|
if (httpResponseCode > 0) {
|
||||||
return String("E:HTTP Error ") + httpResponseCode;
|
return String("E:HTTP Error ") + httpResponseCode;
|
||||||
}
|
}
|
||||||
return String("E:Internal Error ") + httpResponseCode;
|
return String("E:Internal Error ") + httpResponseCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,29 @@
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <lwip/sockets.h>
|
#include <lwip/sockets.h>
|
||||||
|
#include "wifiFix.h"
|
||||||
|
|
||||||
#define WIFI_CLIENT_FLUSH_BUFFER_SIZE (1024)
|
#define WIFI_CLIENT_FLUSH_BUFFER_SIZE (1024)
|
||||||
|
|
||||||
class WiFiClientFixed : public WiFiClient {
|
|
||||||
public:
|
|
||||||
void flush() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
void WiFiClientFixed::flush() {
|
void WiFiClientFixed::flush() {
|
||||||
int res;
|
int res;
|
||||||
size_t a = available(), toRead = 0;
|
size_t a = available();
|
||||||
if (!a) {
|
if (!a) {
|
||||||
return;//nothing to flush
|
return;//nothing to flush
|
||||||
}
|
}
|
||||||
uint8_t *buf = (uint8_t *) malloc(WIFI_CLIENT_FLUSH_BUFFER_SIZE);
|
auto *buf = (uint8_t *) malloc(WIFI_CLIENT_FLUSH_BUFFER_SIZE);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
return;//memory error
|
return;//memory error
|
||||||
}
|
}
|
||||||
while (a) {
|
while (a) {
|
||||||
toRead = (a > WIFI_CLIENT_FLUSH_BUFFER_SIZE) ? WIFI_CLIENT_FLUSH_BUFFER_SIZE : a;
|
// override broken WiFiClient flush method, ref https://github.com/espressif/arduino-esp32/issues/6129#issuecomment-1237417915
|
||||||
// override broken WiFiClient flush method, ref https://github.com/espressif/arduino-esp32/issues/6129#issuecomment-1237417915
|
//res = recv(fd(), buf, toRead, MSG_DONTWAIT);
|
||||||
//res = recv(fd(), buf, toRead, MSG_DONTWAIT);
|
res = read(buf, a);
|
||||||
res = read(buf, a);
|
if (res < 0) {
|
||||||
if (res < 0) {
|
log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno));
|
||||||
log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno));
|
stop();
|
||||||
stop();
|
break;
|
||||||
break;
|
}
|
||||||
}
|
a -= res;
|
||||||
a -= res;
|
}
|
||||||
}
|
free(buf);
|
||||||
free(buf);
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="linq2db" Version="4.4.1" />
|
<PackageReference Include="linq2db" Version="4.4.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.2" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.6" />
|
||||||
<PackageReference Include="System.Data.SQLite" Version="1.0.115" />
|
<PackageReference Include="System.Data.SQLite" Version="1.0.115" />
|
||||||
<PackageReference Include="System.Data.SQLite.Core.osx.arm64" Version="1.0.117" />
|
<PackageReference Include="System.Data.SQLite.Core.osx.arm64" Version="1.0.117" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Reflection;
|
||||||
using AfRApay.Web.Backend;
|
using AfRApay.Web.Backend;
|
||||||
using LinqToDB.Data;
|
using LinqToDB.Data;
|
||||||
|
|
||||||
|
@ -6,8 +7,11 @@ Migrations.RunMigrations();
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
|
builder.Services.AddSwaggerGen(options => {
|
||||||
|
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||||
|
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
|
||||||
|
});
|
||||||
|
|
||||||
#if (DEBUG)
|
#if (DEBUG)
|
||||||
builder.Services.AddControllers().AddRazorRuntimeCompilation();
|
builder.Services.AddControllers().AddRazorRuntimeCompilation();
|
||||||
|
@ -18,14 +22,13 @@ builder.Services.AddControllers();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
if (!app.Environment.IsDevelopment()) {
|
if (app.Environment.IsDevelopment()) {
|
||||||
app.UseExceptionHandler("/Error");
|
app.UseSwagger();
|
||||||
app.UseHsts();
|
app.UseSwaggerUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseStatusCodePagesWithReExecute("/error");
|
app.UseStatusCodePagesWithReExecute("/Error");
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
15
AfRApay.Web/Controllers/Schema/ErrorResponse.cs
Normal file
15
AfRApay.Web/Controllers/Schema/ErrorResponse.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using AfRApay.Web.Backend.Tables;
|
||||||
|
using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
|
||||||
|
|
||||||
|
namespace AfRApay.Web.Controllers.Schema;
|
||||||
|
|
||||||
|
public class ErrorResponse {
|
||||||
|
[J("status")] [DefaultValue("error")] public string Status { get; set; }
|
||||||
|
[J("message")] public string Message { get; set; }
|
||||||
|
|
||||||
|
public ErrorResponse(string message) {
|
||||||
|
Status = "error";
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
}
|
15
AfRApay.Web/Controllers/Schema/UserResponse.cs
Normal file
15
AfRApay.Web/Controllers/Schema/UserResponse.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using AfRApay.Web.Backend.Tables;
|
||||||
|
using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
|
||||||
|
|
||||||
|
namespace AfRApay.Web.Controllers.Schema;
|
||||||
|
|
||||||
|
public class UserResponse {
|
||||||
|
[J("data")] public User? Data { get; set; }
|
||||||
|
[J("status")] [DefaultValue("success")] public string Status { get; set; } = "success";
|
||||||
|
[J("message")] [DefaultValue("")] public string Message { get; set; } = "";
|
||||||
|
|
||||||
|
public UserResponse(User data) {
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
}
|
37
AfRApay.Web/Controllers/UserController.cs
Normal file
37
AfRApay.Web/Controllers/UserController.cs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
using AfRApay.Web.Backend;
|
||||||
|
using AfRApay.Web.Controllers.Schema;
|
||||||
|
using LinqToDB;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Swashbuckle.AspNetCore.Filters;
|
||||||
|
|
||||||
|
namespace AfRApay.Web.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
public class UserController : Controller {
|
||||||
|
/// <summary>
|
||||||
|
/// Renames the specified user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">The ID of the user to be renamed</param>
|
||||||
|
/// <param name="newName">The new name of the user</param>
|
||||||
|
/// <response code="200">Returns 200 if user was renamed successfully</response>
|
||||||
|
/// <response code="400">Returns 400 if newName isn't unique</response>
|
||||||
|
/// <response code="404">Returns 404 if no user matching the UID was found</response>
|
||||||
|
[HttpPut]
|
||||||
|
[Produces("application/json")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserResponse))]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ErrorResponse))]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponse))]
|
||||||
|
//[SwaggerResponseExample(400, typeof(new )]
|
||||||
|
[Route("/api/user/{uid:int}/name")]
|
||||||
|
public async Task<IActionResult> Rename(int uid, [FromQuery] string newName) {
|
||||||
|
var db = new Database.DbConn();
|
||||||
|
if (db.Users.Any(p => p.Id == uid)) {
|
||||||
|
var user = db.Users.First(p => p.Id == uid);
|
||||||
|
user.Nickname = newName;
|
||||||
|
await db.UpdateAsync(user);
|
||||||
|
return new OkObjectResult(new UserResponse(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NotFound(new ErrorResponse("Unknown user"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,8 +23,8 @@
|
||||||
<label for="nickname" class="form-label">Nickname</label>
|
<label for="nickname" class="form-label">Nickname</label>
|
||||||
<input type="text" maxlength="10" class="form-control" id="nickname" name="nickname" value="@user.Nickname" required>
|
<input type="text" maxlength="10" class="form-control" id="nickname" name="nickname" value="@user.Nickname" required>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary" name="action" value="save">Save</button>
|
<button type="submit" class="btn btn-lg btn-primary" name="action" value="save">Save</button>
|
||||||
<button type="button" class="btn btn-danger" name="action" data-bs-toggle="modal" data-bs-target="#deleteConfirmModal">Delete</button> <!-- Calls the below modal dialog to confirm user deletetion -->
|
<button type="button" class="btn btn-lg btn-danger" name="action" data-bs-toggle="modal" data-bs-target="#deleteConfirmModal">Delete</button> <!-- Calls the below modal dialog to confirm user deletetion -->
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- Modal dialog to confirm user deletion -->
|
<!-- Modal dialog to confirm user deletion -->
|
||||||
|
@ -39,8 +39,8 @@
|
||||||
Are you sure you want to delete this user?<br>This cannot be undone.
|
Are you sure you want to delete this user?<br>This cannot be undone.
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-lg btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
<button type="submit" form="change_user" class="btn btn-danger" name="action" value="delete">Delete User</button>
|
<button type="submit" form="change_user" class="btn btn-lg btn-danger" name="action" value="delete">Delete User</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,18 +48,13 @@
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<h3 class="text-center">Cards</h3>
|
<h3 class="text-center">Cards</h3>
|
||||||
@if (!cards.Any()) {
|
@{ <!-- We add all the cards here! -->
|
||||||
<div>
|
|
||||||
No linked cards found.
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
@foreach (var card in cards) {
|
@foreach (var card in cards) {
|
||||||
<div class="fake-card-wrapper m-2">
|
<div class="fake-card-wrapper blur-true m-2">
|
||||||
<div class="fake-card">
|
<div class="fake-card">
|
||||||
<div class="hover-overlay"></div>
|
<div class="hover-overlay"></div>
|
||||||
<button type="button" class="btn btn-danger btn-lg hover-button">Delete</button>
|
<a class="btn btn-danger btn-lg hover-button">Delete</a>
|
||||||
<div class="face-card front">
|
<div class="face-card front">
|
||||||
<div class="chip">
|
<div class="chip">
|
||||||
<div>
|
<div>
|
||||||
|
@ -87,5 +82,35 @@ else {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<!-- Here we display a faded placholder card, with the add button at its center -->
|
||||||
|
<div class="fake-card-wrapper m-2">
|
||||||
|
<div class="fake-card">
|
||||||
|
<a class="btn btn-success btn-lg add-card-button" href="/LinkCard/@user.Id">Add Card</a>
|
||||||
|
<div class="face-card ghost-card front">
|
||||||
|
<div class="chip">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2 class="card-number">Awooo!</h2>
|
||||||
|
<h3 class="card-holder">@user.Nickname</h3>
|
||||||
|
<span class="validity">
|
||||||
|
<span class="small">VALID<br>THRU</span>
|
||||||
|
<span>01/2038</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="fake-card-logo-top">
|
||||||
|
<img src="/img/afra.png" class="fake-card-logo-inner" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="fake-card-logo-bottom">
|
||||||
|
<img src="/img/matecard.png" class="fake-card-logo-inner" alt="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,15 +67,14 @@
|
||||||
<td> <!-- Displayed when in big layout -->
|
<td> <!-- Displayed when in big layout -->
|
||||||
<div class="d-none d-md-flex btn-group btn-group-lg" role="group">
|
<div class="d-none d-md-flex btn-group btn-group-lg" role="group">
|
||||||
<!-- Make sure these buttons match the small/mobile layout ones below -->
|
<!-- Make sure these buttons match the small/mobile layout ones below -->
|
||||||
<a class="btn px-auto btn-danger" href="/UpdateBalance/@user.Id/-1.50">-1.50€</a>
|
<a class="btn px-3 btn-danger" href="/UpdateBalance/@user.Id/-1.50">-1.50€</a>
|
||||||
<a class="btn px-auto btn-success" href="/UpdateBalance/@user.Id/5">+5€</a>
|
<a class="btn px-3 btn-success" href="/UpdateBalance/@user.Id/5">+5€</a>
|
||||||
<a class="btn px-auto btn-success" href="/UpdateBalance/@user.Id/10">+10€</a>
|
<a class="btn px-3 btn-success" href="/UpdateBalance/@user.Id/10">+10€</a>
|
||||||
<a class="btn px-2 btn-secondary text-nowrap" href="/LinkCard/@user.Id">Link card</a>
|
|
||||||
<a class="btn px-2 btn-primary" href="/EditUser/@user.Id">Edit</a>
|
<a class="btn px-2 btn-primary" href="/EditUser/@user.Id">Edit</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- Displayed when in compact/phone layout -->
|
<!-- Displayed when in compact/phone layout -->
|
||||||
<div class="dropdown d-md-none">
|
<div class="dropdown d-md-none">
|
||||||
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
|
<a class="btn btn-lg px-1 btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
Actions
|
Actions
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu p-1" aria-labelledby="dropdownMenuLink" style="min-width: max-content;"> <!-- Inline CSS, sets minimum width of drop down to maxium size of content -->
|
<div class="dropdown-menu p-1" aria-labelledby="dropdownMenuLink" style="min-width: max-content;"> <!-- Inline CSS, sets minimum width of drop down to maxium size of content -->
|
||||||
|
@ -84,7 +83,6 @@
|
||||||
<a class="btn btn-lg btn-danger" href="/UpdateBalance/@user.Id/-1.50">-1.50€</a>
|
<a class="btn btn-lg btn-danger" href="/UpdateBalance/@user.Id/-1.50">-1.50€</a>
|
||||||
<a class="btn btn-lg btn-success" href="/UpdateBalance/@user.Id/5">+5€</a>
|
<a class="btn btn-lg btn-success" href="/UpdateBalance/@user.Id/5">+5€</a>
|
||||||
<a class="btn btn-lg btn-success" href="/UpdateBalance/@user.Id/10">+10€</a>
|
<a class="btn btn-lg btn-success" href="/UpdateBalance/@user.Id/10">+10€</a>
|
||||||
<a class="btn btn-lg btn-secondary" href="/LinkCard/@user.Id">Link card</a>
|
|
||||||
<a class="btn btn-lg btn-primary" href="/EditUser/@user.Id">Edit</a>
|
<a class="btn btn-lg btn-primary" href="/EditUser/@user.Id">Edit</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,15 +8,6 @@
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": false,
|
|
||||||
"applicationUrl": "https://0.0.0.0:7115;http://localhost:5296",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,6 +258,17 @@ button.accept-policy {
|
||||||
margin-bottom: 60px;
|
margin-bottom: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ghost-card {
|
||||||
|
filter:grayscale(100%) blur(4px);
|
||||||
|
}
|
||||||
|
.add-card-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 2;
|
||||||
|
filter: grayscale(0%)
|
||||||
|
}
|
||||||
.hover-button {
|
.hover-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
@ -268,20 +279,13 @@ button.accept-policy {
|
||||||
transition: .5s ease;
|
transition: .5s ease;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.hover-overlay {
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
opacity: 0;
|
|
||||||
border-radius: 15px;
|
|
||||||
transition: .5s ease;
|
|
||||||
background-color: #808080;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.fake-card-wrapper:hover .hover-button {
|
.fake-card-wrapper:hover .hover-button {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
.fake-card-wrapper:hover .hover-overlay {
|
|
||||||
opacity: 0.75;
|
.fake-card-wrapper:hover.blur-true .face-card{
|
||||||
|
transition: 0.3s ease;
|
||||||
|
filter:blur(4px) grayscale(100%);
|
||||||
}
|
}
|
40
hooks/pre-commit.hook
Executable file
40
hooks/pre-commit.hook
Executable file
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Regexp for grep to only choose some file extensions for formatting
|
||||||
|
exts="\.\(cpp\|h\)$"
|
||||||
|
|
||||||
|
# The formatter to use
|
||||||
|
formatter=`which uncrustify`
|
||||||
|
|
||||||
|
# Check availability of the formatter
|
||||||
|
if [ -z "$formatter" ]
|
||||||
|
then
|
||||||
|
1>&2 echo "$formatter not found. Pre-commit formatting will not be done."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Format staged files
|
||||||
|
for file in `git diff --cached --name-only --diff-filter=ACMR | grep $exts`
|
||||||
|
do
|
||||||
|
echo "Formatting $file"
|
||||||
|
# get tmpfile
|
||||||
|
tmpfile="${file//.cpp/.tmp.cpp}"
|
||||||
|
tmpfile="${file//.h/.tmp.h}"
|
||||||
|
# Get the file from index
|
||||||
|
git show ":$file" > "$tmpfile"
|
||||||
|
# Format it
|
||||||
|
"$formatter" --no-backup -c AfRApay.MateCard/.uncrustify.cfg "$tmpfile"
|
||||||
|
# Create a blob object from the formatted file
|
||||||
|
hash=`git hash-object -w "$tmpfile"`
|
||||||
|
# Add it back to index
|
||||||
|
git update-index --add --cacheinfo 100644 "$hash" "$file"
|
||||||
|
# Remove the tmp file
|
||||||
|
rm "$tmpfile"
|
||||||
|
done
|
||||||
|
|
||||||
|
# If no files left in index after formatting - fail
|
||||||
|
ret=0
|
||||||
|
if [ ! "`git diff --cached --name-only`" ]; then
|
||||||
|
1>&2 echo "No files left after formatting"
|
||||||
|
exit 1
|
||||||
|
fi
|
Loading…
Reference in a new issue