2023-02-06 02:23:00 +01:00
|
|
|
#include <Arduino.h>
|
|
|
|
#include <U8g2lib.h>
|
|
|
|
#include <Wire.h>
|
|
|
|
#include <SPIFFS.h>
|
|
|
|
#include <WiFiSettings.h>
|
|
|
|
#include <WiFi.h>
|
|
|
|
#include <HTTPClient.h>
|
|
|
|
#include <SPI.h>
|
|
|
|
#include <ESPDateTime.h>
|
|
|
|
#include <DateTimeTZ.h>
|
|
|
|
|
|
|
|
#include "wifiFix.h"
|
|
|
|
#include "pitches.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "oled.h"
|
2023-04-20 15:18:00 +02:00
|
|
|
#include "readers.h"
|
2023-02-10 01:25:30 +01:00
|
|
|
#include "vars.h"
|
2023-02-06 02:23:00 +01:00
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
OLED oled(U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, U8X8_PIN_NONE));
|
2023-04-20 16:26:43 +02:00
|
|
|
WiFiClient* wifi = new WiFiClientFixed();
|
|
|
|
HTTPClient* http = new HTTPClient();
|
2023-02-08 02:25:12 +01:00
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
Reader* readers[] = {
|
|
|
|
//new MFRC522CardReader(PIN_HSPI_SS, PIN_HSPI_RST),
|
2023-04-22 03:10:58 +02:00
|
|
|
new PN532Reader(PIN_HSPI_CS0),
|
2023-04-22 03:13:28 +02:00
|
|
|
new RDM6300Reader(PIN_HWSERIAL_RX),
|
2023-04-20 15:18:00 +02:00
|
|
|
};
|
2023-02-06 02:23:00 +01:00
|
|
|
|
|
|
|
e_state state = STATE_IDLE;
|
2023-04-20 15:18:00 +02:00
|
|
|
e_scanstate scanstate = SCANSTATE_IDLE;
|
2023-02-06 02:23:00 +01:00
|
|
|
String apiUrl = "";
|
|
|
|
const int gTimeout = 5000;
|
|
|
|
const int scanTimeout = 15000;
|
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
Reader* scannedCardReader;
|
2023-02-06 02:23:00 +01:00
|
|
|
String scannedCardId = "";
|
|
|
|
String lastStatusText = "";
|
|
|
|
|
2023-05-18 23:04:50 +02:00
|
|
|
bool deposit = false;
|
|
|
|
int transactionAmountIndex = 0;
|
|
|
|
int transactionAmountsDebit[] = {-150, -200};
|
|
|
|
int transactionAmountsCredit[] = {+100, +200, +500, +1000};
|
2023-04-20 15:18:00 +02:00
|
|
|
|
2023-05-18 23:04:50 +02:00
|
|
|
volatile bool toggleTransactionAmountDebit = false;
|
|
|
|
volatile bool toggleTransactionAmountCredit = false;
|
2023-02-09 20:44:30 +01:00
|
|
|
volatile bool interruptFired = false;
|
2023-02-06 02:23:00 +01:00
|
|
|
unsigned long timer = 0;
|
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
void IRAM_ATTR PN532_IRQ() {
|
|
|
|
PN532Reader::irq++;
|
|
|
|
}
|
|
|
|
|
2023-04-22 03:08:11 +02:00
|
|
|
void IRAM_ATTR FeliCaInterruptHandler() {
|
|
|
|
if (PN532Reader::toggleMode || scanstate != SCANSTATE_ACTIVE || digitalRead(PIN_INTERRUPT_FELICA)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PN532Reader::toggleMode = true;
|
|
|
|
}
|
|
|
|
|
2023-02-06 02:23:00 +01:00
|
|
|
void IRAM_ATTR TransactInterruptHandler() {
|
2023-04-22 15:10:26 +02:00
|
|
|
if (interruptFired || digitalRead(PIN_INTERRUPT_TRANSACT)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (state == STATE_IDLE) {
|
|
|
|
interruptFired = true;
|
|
|
|
state = STATE_TRANSACT_CARDSCAN;
|
|
|
|
}
|
|
|
|
else if (state == STATE_TRANSACT_CARDSCAN) {
|
|
|
|
PN532Reader::toggleMode = true;
|
|
|
|
}
|
|
|
|
else {
|
2023-02-08 16:42:47 +01:00
|
|
|
return;
|
|
|
|
}
|
2023-02-06 02:23:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void IRAM_ATTR LinkInterruptHandler() {
|
2023-04-22 15:10:26 +02:00
|
|
|
if (interruptFired || digitalRead(PIN_INTERRUPT_LINK)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (state == STATE_IDLE) {
|
|
|
|
interruptFired = true;
|
|
|
|
state = STATE_LINK_CARD_SCAN;
|
|
|
|
}
|
|
|
|
else if (state == STATE_LINK_CARD_SCAN) {
|
|
|
|
PN532Reader::toggleMode = true;
|
|
|
|
}
|
2023-05-18 23:04:50 +02:00
|
|
|
else if (state == STATE_TRANSACT_CARDSCAN) {
|
|
|
|
toggleTransactionAmountCredit = true;
|
|
|
|
}
|
2023-04-22 15:10:26 +02:00
|
|
|
else {
|
2023-02-08 16:42:47 +01:00
|
|
|
return;
|
|
|
|
}
|
2023-02-06 02:23:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void IRAM_ATTR BalanceInterruptHandler() {
|
2023-04-22 15:10:26 +02:00
|
|
|
if (interruptFired || digitalRead(PIN_INTERRUPT_BALANCE)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (state == STATE_IDLE) {
|
|
|
|
interruptFired = true;
|
|
|
|
state = STATE_BALANCE_CARDSCAN;
|
|
|
|
}
|
|
|
|
else if (state == STATE_BALANCE_CARDSCAN) {
|
|
|
|
PN532Reader::toggleMode = true;
|
|
|
|
}
|
2023-05-18 22:19:56 +02:00
|
|
|
else if (state == STATE_TRANSACT_CARDSCAN) {
|
2023-05-18 23:04:50 +02:00
|
|
|
toggleTransactionAmountDebit = true;
|
2023-05-18 22:19:56 +02:00
|
|
|
}
|
2023-04-22 15:10:26 +02:00
|
|
|
else {
|
2023-02-08 16:42:47 +01:00
|
|
|
return;
|
|
|
|
}
|
2023-02-06 02:23:00 +01:00
|
|
|
}
|
|
|
|
|
2023-02-08 19:54:30 +01:00
|
|
|
void IRAM_ATTR CancelInterruptHandler() {
|
2023-02-10 00:26:44 +01:00
|
|
|
if (digitalRead(PIN_INTERRUPT_CANCEL))
|
2023-02-09 20:44:30 +01:00
|
|
|
return;
|
2023-02-08 19:54:30 +01:00
|
|
|
state = STATE_IDLE;
|
|
|
|
}
|
|
|
|
|
2023-05-18 23:04:50 +02:00
|
|
|
int GetTransactionAmount() {
|
|
|
|
if (deposit)
|
|
|
|
return transactionAmountsCredit[transactionAmountIndex];
|
|
|
|
else
|
|
|
|
return transactionAmountsDebit[transactionAmountIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
String GetDisplayTransactionAmount() {
|
|
|
|
String result = "";
|
|
|
|
int total = abs(GetTransactionAmount());
|
|
|
|
int cents = total % 100;
|
|
|
|
|
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A) {
|
|
|
|
if (deposit)
|
|
|
|
result += "Deposit: ";
|
|
|
|
|
|
|
|
result += total / 100;
|
|
|
|
result += ".";
|
|
|
|
result += cents;
|
|
|
|
|
|
|
|
if (cents < 10)
|
|
|
|
result += "0";
|
|
|
|
|
|
|
|
result += "€";
|
|
|
|
}
|
|
|
|
else { // TOKYO MODE
|
|
|
|
if (deposit)
|
|
|
|
result += "Deposit: ";
|
|
|
|
|
|
|
|
result += "¥";
|
|
|
|
result += total;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-02-06 02:23:00 +01:00
|
|
|
bool cooldownCheck(long timeout) {
|
2023-02-08 16:42:47 +01:00
|
|
|
if (millis() - timer > timeout) {
|
|
|
|
state = STATE_IDLE;
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.updateOLED(state);
|
2023-02-08 16:42:47 +01:00
|
|
|
return true;
|
|
|
|
}
|
2023-02-06 02:23:00 +01:00
|
|
|
|
2023-02-08 16:42:47 +01:00
|
|
|
return false;
|
2023-02-06 02:23:00 +01:00
|
|
|
}
|
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
void updateCardscan() {
|
|
|
|
switch (state) {
|
|
|
|
case STATE_TRANSACT_CARDSCAN:
|
|
|
|
case STATE_LINK_CARD_SCAN:
|
|
|
|
case STATE_LINK_CARD_RESCAN:
|
|
|
|
case STATE_BALANCE_CARDSCAN:
|
|
|
|
if (scanstate == SCANSTATE_ACTIVE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (Reader* reader : readers) {
|
|
|
|
reader->begin();
|
|
|
|
}
|
|
|
|
scanstate = SCANSTATE_ACTIVE;
|
|
|
|
break;
|
|
|
|
case STATE_IDLE:
|
|
|
|
case STATE_TRANSACT_VERIFY:
|
|
|
|
case STATE_LINK_VERIFY:
|
|
|
|
case STATE_BALANCE_VERIFY:
|
|
|
|
case STATE_RESULT_SUCCESS:
|
|
|
|
case STATE_RESULT_FAILURE:
|
|
|
|
case STATE_RESULT_DISPLAY:
|
|
|
|
if (scanstate == SCANSTATE_IDLE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (Reader* reader : readers) {
|
|
|
|
reader->end();
|
|
|
|
}
|
|
|
|
scanstate = SCANSTATE_IDLE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-06 02:23:00 +01:00
|
|
|
void setup() {
|
2023-02-08 16:42:47 +01:00
|
|
|
Serial.begin(115200);
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.begin();
|
2023-02-08 16:42:47 +01:00
|
|
|
Serial2.begin(115200, SERIAL_8N1, PIN_HWSERIAL_RX, PIN_HWSERIAL_TX);
|
2023-02-14 02:55:30 +01:00
|
|
|
SPI.begin(PIN_HSPI_SCLK, PIN_HSPI_MISO, PIN_HSPI_MOSI);
|
2023-02-14 02:24:57 +01:00
|
|
|
|
|
|
|
ledcSetup(0, 5000, 12);
|
2023-04-20 15:18:00 +02:00
|
|
|
pinMode(PIN_INTERRUPT_IRQ_PN532, INPUT_PULLUP);
|
2023-02-14 02:24:57 +01:00
|
|
|
pinMode(PIN_INTERRUPT_TRANSACT, INPUT_PULLUP);
|
|
|
|
pinMode(PIN_INTERRUPT_BALANCE, INPUT_PULLUP);
|
2023-04-22 03:08:11 +02:00
|
|
|
pinMode(PIN_INTERRUPT_FELICA, INPUT_PULLUP);
|
2023-02-14 02:24:57 +01:00
|
|
|
pinMode(PIN_INTERRUPT_CANCEL, INPUT_PULLUP);
|
|
|
|
pinMode(PIN_INTERRUPT_LINK, INPUT_PULLUP);
|
|
|
|
|
2023-02-08 16:42:47 +01:00
|
|
|
SPIFFS.begin(true);
|
|
|
|
WiFiSettings.hostname = "afrapay-";
|
|
|
|
apiUrl = WiFiSettings.string("AfRApay.Web API", "http://192.168.50.170:5296");
|
2023-02-14 02:55:30 +01:00
|
|
|
if (!digitalRead(PIN_INTERRUPT_CANCEL))
|
|
|
|
WiFiSettings.portal();
|
|
|
|
else
|
|
|
|
WiFiSettings.connect();
|
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
for (Reader* reader : readers) {
|
|
|
|
reader->init();
|
|
|
|
}
|
|
|
|
|
2023-02-08 16:42:47 +01:00
|
|
|
DateTime.setTimeZone(TZ_Europe_Berlin);
|
|
|
|
DateTime.begin();
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.updateOLED(state);
|
2023-02-08 16:42:47 +01:00
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
attachInterrupt(PIN_INTERRUPT_IRQ_PN532, PN532_IRQ, FALLING);
|
2023-02-08 16:42:47 +01:00
|
|
|
attachInterrupt(PIN_INTERRUPT_TRANSACT, TransactInterruptHandler, FALLING);
|
|
|
|
attachInterrupt(PIN_INTERRUPT_BALANCE, BalanceInterruptHandler, FALLING);
|
2023-04-22 03:08:11 +02:00
|
|
|
attachInterrupt(PIN_INTERRUPT_FELICA, FeliCaInterruptHandler, FALLING);
|
2023-02-08 19:54:30 +01:00
|
|
|
attachInterrupt(PIN_INTERRUPT_CANCEL, CancelInterruptHandler, FALLING);
|
2023-02-08 16:42:47 +01:00
|
|
|
attachInterrupt(PIN_INTERRUPT_LINK, LinkInterruptHandler, FALLING);
|
2023-02-06 02:23:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void loop() {
|
2023-02-10 03:09:50 +01:00
|
|
|
if (WiFiClass::status() != WL_CONNECTED) {
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.updateOLED(state, "WiFi disconnected :(");
|
2023-02-08 16:42:47 +01:00
|
|
|
state = STATE_IDLE;
|
|
|
|
WiFi.reconnect();
|
|
|
|
delay(50);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
updateCardscan();
|
|
|
|
|
2023-04-22 03:43:14 +02:00
|
|
|
if (PN532Reader::toggleMode)
|
|
|
|
timer = millis();
|
|
|
|
|
2023-02-08 16:42:47 +01:00
|
|
|
if (interruptFired) {
|
|
|
|
timer = millis();
|
|
|
|
interruptFired = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case STATE_IDLE:
|
2023-04-22 15:10:26 +02:00
|
|
|
if (PN532Reader::mode != PN532_MIFARE_ISO14443A)
|
|
|
|
PN532Reader::mode = PN532_MIFARE_ISO14443A;
|
|
|
|
|
2023-05-18 23:04:50 +02:00
|
|
|
if (deposit == true)
|
|
|
|
deposit = false;
|
|
|
|
|
|
|
|
if (transactionAmountIndex != 0)
|
|
|
|
transactionAmountIndex = 0;
|
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.updateOLED(state);
|
2023-02-08 16:42:47 +01:00
|
|
|
break;
|
|
|
|
case STATE_TRANSACT_CARDSCAN:
|
2023-05-18 23:04:50 +02:00
|
|
|
if (toggleTransactionAmountDebit) {
|
|
|
|
if (millis() - timer > 250) {
|
|
|
|
if (deposit) {
|
|
|
|
deposit = false;
|
|
|
|
transactionAmountIndex = -1;
|
|
|
|
}
|
|
|
|
transactionAmountIndex = ++transactionAmountIndex % 2;
|
|
|
|
timer = millis();
|
2023-05-18 22:27:20 +02:00
|
|
|
}
|
2023-05-18 23:04:50 +02:00
|
|
|
toggleTransactionAmountDebit = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (toggleTransactionAmountCredit) {
|
|
|
|
if (millis() - timer > 250) {
|
|
|
|
if (!deposit) {
|
|
|
|
deposit = true;
|
|
|
|
transactionAmountIndex = -1;
|
|
|
|
}
|
|
|
|
transactionAmountIndex = ++transactionAmountIndex % 4;
|
|
|
|
timer = millis();
|
2023-05-18 22:27:20 +02:00
|
|
|
}
|
2023-05-18 23:04:50 +02:00
|
|
|
toggleTransactionAmountCredit = false;
|
2023-05-18 22:27:20 +02:00
|
|
|
}
|
|
|
|
|
2023-04-20 15:18:00 +02:00
|
|
|
for (Reader* reader : readers) {
|
2023-02-08 16:42:47 +01:00
|
|
|
if (reader->isNewCardPresent()) {
|
|
|
|
scannedCardId = reader->getCardUid();
|
2023-04-22 02:17:55 +02:00
|
|
|
lastStatusText = cardIdDisplay(scannedCardId);
|
2023-04-20 15:42:55 +02:00
|
|
|
scannedCardReader = reader;
|
2023-02-08 16:42:47 +01:00
|
|
|
state = STATE_TRANSACT_VERIFY;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-05-18 22:27:20 +02:00
|
|
|
|
2023-05-18 23:04:50 +02:00
|
|
|
if (!cooldownCheck(scanTimeout))
|
|
|
|
oled.updateOLED(state, GetDisplayTransactionAmount(), String(cooldownSecondsRemaining(scanTimeout, timer)));
|
|
|
|
|
2023-02-08 16:42:47 +01:00
|
|
|
break;
|
|
|
|
case STATE_TRANSACT_VERIFY:
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.updateOLED(state, lastStatusText);
|
2023-04-22 16:28:26 +02:00
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A) {
|
|
|
|
tone(PIN_BUZZER, NOTE_A5, 25);
|
|
|
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tone(PIN_BUZZER, NOTE_FS7, 100);
|
|
|
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
|
|
|
}
|
|
|
|
|
2023-05-18 23:04:50 +02:00
|
|
|
lastStatusText = cardTransaction(wifi, http, apiUrl, scannedCardId, String(GetTransactionAmount()));
|
2023-02-08 16:42:47 +01:00
|
|
|
if (lastStatusText.startsWith("S:")) {
|
|
|
|
tone(PIN_BUZZER, NOTE_C7, 650);
|
|
|
|
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;
|
2023-04-20 15:42:55 +02:00
|
|
|
case STATE_LINK_CARD_SCAN:
|
2023-04-20 15:18:00 +02:00
|
|
|
for (Reader* reader : readers) {
|
2023-02-08 16:42:47 +01:00
|
|
|
if (reader->isNewCardPresent()) {
|
2023-04-20 15:42:55 +02:00
|
|
|
scannedCardReader = reader;
|
2023-02-08 16:42:47 +01:00
|
|
|
scannedCardId = reader->getCardUid();
|
2023-04-20 15:42:55 +02:00
|
|
|
if (reader->canHaveUnstableIdentifier()) {
|
|
|
|
reader->reset();
|
|
|
|
timer = millis();
|
|
|
|
state = STATE_LINK_CARD_RESCAN;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
2023-04-22 02:17:55 +02:00
|
|
|
lastStatusText = cardIdDisplay(scannedCardId);
|
2023-04-20 15:42:55 +02:00
|
|
|
state = STATE_LINK_VERIFY;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!cooldownCheck(scanTimeout)) {
|
2023-04-22 15:10:26 +02:00
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A)
|
|
|
|
oled.updateOLED(state, "Link", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
|
|
|
else
|
|
|
|
oled.updateOLED(state, "リンク", String(cooldownSecondsRemaining(scanTimeout, timer)), true);
|
2023-04-20 15:42:55 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_LINK_CARD_RESCAN:
|
|
|
|
if (scannedCardReader->isNewCardPresent()) {
|
|
|
|
if (scannedCardId == scannedCardReader->getCardUid()) {
|
2023-04-22 02:17:55 +02:00
|
|
|
lastStatusText = cardIdDisplay(scannedCardId);
|
2023-02-08 16:42:47 +01:00
|
|
|
state = STATE_LINK_VERIFY;
|
|
|
|
return;
|
|
|
|
}
|
2023-04-20 15:42:55 +02:00
|
|
|
else {
|
|
|
|
lastStatusText = "Unstable identifier";
|
|
|
|
state = STATE_RESULT_FAILURE;
|
2023-04-22 03:39:41 +02:00
|
|
|
timer = millis();
|
2023-04-20 15:42:55 +02:00
|
|
|
return;
|
|
|
|
}
|
2023-02-08 16:42:47 +01:00
|
|
|
}
|
|
|
|
if (!cooldownCheck(scanTimeout)) {
|
2023-04-22 15:10:26 +02:00
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A)
|
|
|
|
oled.updateOLED(state, "Link - rescan ", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
|
|
|
else
|
|
|
|
oled.updateOLED(state, "リンク - rescan ", String(cooldownSecondsRemaining(scanTimeout, timer)), true);
|
2023-02-08 16:42:47 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_LINK_VERIFY:
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.updateOLED(state, lastStatusText);
|
2023-04-22 16:28:26 +02:00
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A) {
|
|
|
|
tone(PIN_BUZZER, NOTE_A5, 25);
|
|
|
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tone(PIN_BUZZER, NOTE_FS7, 100);
|
|
|
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
|
|
|
}
|
|
|
|
|
2023-02-08 16:42:47 +01:00
|
|
|
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:
|
2023-04-20 15:18:00 +02:00
|
|
|
for (Reader* reader : readers) {
|
2023-02-08 16:42:47 +01:00
|
|
|
if (reader->isNewCardPresent()) {
|
|
|
|
scannedCardId = reader->getCardUid();
|
2023-04-22 02:17:55 +02:00
|
|
|
lastStatusText = cardIdDisplay(scannedCardId);
|
2023-02-08 16:42:47 +01:00
|
|
|
state = STATE_BALANCE_VERIFY;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!cooldownCheck(scanTimeout)) {
|
2023-04-22 15:10:26 +02:00
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A)
|
|
|
|
oled.updateOLED(state, "Balance", String(cooldownSecondsRemaining(scanTimeout, timer)));
|
|
|
|
else
|
|
|
|
oled.updateOLED(state, "残高", String(cooldownSecondsRemaining(scanTimeout, timer)), true);
|
2023-02-08 16:42:47 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_BALANCE_VERIFY:
|
2023-04-20 15:18:00 +02:00
|
|
|
oled.updateOLED(state, lastStatusText);
|
2023-04-22 16:28:26 +02:00
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A) {
|
|
|
|
tone(PIN_BUZZER, NOTE_A5, 25);
|
|
|
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tone(PIN_BUZZER, NOTE_FS7, 100);
|
|
|
|
tone(PIN_BUZZER, NOTE_NONE, 150);
|
|
|
|
}
|
|
|
|
|
2023-02-08 16:42:47 +01:00
|
|
|
lastStatusText = cardBalance(wifi, http, apiUrl, scannedCardId);
|
|
|
|
if (lastStatusText.startsWith("S:")) {
|
2023-04-22 02:17:55 +02:00
|
|
|
lastStatusText = lastStatusText + ":" + cardIdDisplay(scannedCardId);
|
2023-02-08 16:42:47 +01:00
|
|
|
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:
|
2023-02-10 01:25:30 +01:00
|
|
|
if (cooldownSecondsRemaining(gTimeout, timer) <= 4) {
|
2023-04-22 02:17:55 +02:00
|
|
|
lastStatusText = lastStatusText + ":" + cardIdDisplay(scannedCardId);
|
2023-02-10 01:25:30 +01:00
|
|
|
state = STATE_RESULT_DISPLAY;
|
|
|
|
}
|
2023-02-08 16:42:47 +01:00
|
|
|
case STATE_RESULT_FAILURE:
|
|
|
|
case STATE_RESULT_DISPLAY:
|
|
|
|
if (!cooldownCheck(gTimeout)) {
|
2023-04-22 15:28:25 +02:00
|
|
|
if (PN532Reader::mode == PN532_MIFARE_ISO14443A)
|
|
|
|
oled.updateOLED(state, lastStatusText, String(cooldownSecondsRemaining(gTimeout, timer)));
|
|
|
|
else
|
|
|
|
oled.updateOLED(state, lastStatusText, String(cooldownSecondsRemaining(gTimeout, timer)), true);
|
2023-02-08 16:42:47 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
delay(50);
|
2023-02-07 23:02:05 +01:00
|
|
|
}
|
2023-02-08 16:42:47 +01:00
|
|
|
#pragma clang diagnostic pop
|