mirror of
https://gitlab.com/fabinfra/fabhardware/fabreader3.git
synced 2025-03-12 22:51:42 +01:00
added wrong V2, added PlatformIO Project now
This commit is contained in:
parent
53cad5130d
commit
f4b1639f89
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
Software/.DS_Store
|
6
Software/.gitignore
vendored
Normal file
6
Software/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
|
src/config.h
|
10
Software/.vscode/extensions.json
vendored
Normal file
10
Software/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
|
// for the documentation about the extensions.json format
|
||||||
|
"recommendations": [
|
||||||
|
"platformio.platformio-ide"
|
||||||
|
],
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
"ms-vscode.cpptools-extension-pack"
|
||||||
|
]
|
||||||
|
}
|
16
Software/.vscode/settings.json
vendored
Normal file
16
Software/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"random": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"ranges": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"*.desfire": "cpp",
|
||||||
|
"*.old": "cpp",
|
||||||
|
"*.deprecated": "cpp"
|
||||||
|
}
|
||||||
|
}
|
30
Software/README.txt
Normal file
30
Software/README.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# OTA
|
||||||
|
## Protocol:
|
||||||
|
READERID is 5 Digits
|
||||||
|
1. Hello: Topic="fabreader", Payload="READERID"
|
||||||
|
1. Start: Topic="fabreader/READERID/startOTA", Payload=UID of Card
|
||||||
|
1. Request: Topic="fabreader/READERID/requestOTA", Payload=256 Bytes APDU Command
|
||||||
|
1. Response: Topic="fabreader/READERID/responseOTA", Payload=256 Bytes APDU Response
|
||||||
|
1. Stop: Topic="fabreader/READERID/stopOTA", Payload=NULL
|
||||||
|
1. Cancel: Topic="fabreader/READERID/cancelOTA", Payload=UID of Card
|
||||||
|
1. Restart: Topic="fabreader/READERID/restartOTA", Payload=NULL
|
||||||
|
|
||||||
|
## Procedure:
|
||||||
|
After Start Reader sends "Hello".
|
||||||
|
|
||||||
|
After new Card is on Reader:
|
||||||
|
"Start" -> to Server
|
||||||
|
"Request" <- from Server
|
||||||
|
"Response" -> to Server
|
||||||
|
|
||||||
|
Repeat Request and Response until:
|
||||||
|
"Stop" <- from Server
|
||||||
|
"Cancel" -> to Server
|
||||||
|
|
||||||
|
If FabReader works as deadmen switch the OTA connection is not stopped and the next check can be started with restartOTA.
|
||||||
|
If DESFire Card uses Random UID the UID changes every new connection, so the connections stays active until the server restartsOTA and performs new OTA.
|
||||||
|
|
||||||
|
# Display
|
||||||
|
## Protocol
|
||||||
|
1. Title: Topic="fabreader/READERID/display/title", Payload=Title Text
|
||||||
|
2. Info: Topic="fabreader/READERID/display/info", Payload=Info Text
|
39
Software/include/README
Normal file
39
Software/include/README
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
Software/lib/README
Normal file
46
Software/lib/README
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
23
Software/platformio.ini
Normal file
23
Software/platformio.ini
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env:esp12e]
|
||||||
|
platform = espressif8266
|
||||||
|
board = esp12e
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
lib_deps =
|
||||||
|
knolleary/PubSubClient@^2.8
|
||||||
|
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.3.0
|
||||||
|
miguelbalboa/MFRC522@^1.4.10
|
||||||
|
thijse/ArduinoLog@^1.1.1
|
||||||
|
uipethernet/UIPEthernet@^2.0.12
|
||||||
|
bblanchon/ArduinoJson@^6.19.4
|
||||||
|
mbed-feb11/Crypto@0.0.0+sha.f04410cef037
|
37
Software/src/Deprecated/config.cpp.old
Normal file
37
Software/src/Deprecated/config.cpp.old
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "Config.h"
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
Config::Config()
|
||||||
|
{
|
||||||
|
EEPROM.begin(512);
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::Config(int ID, char mqtt_broker[], int mqtt_port, char mqtt_username[], char mqtt_password[], char wlan_ssid[], char wlan_password[])
|
||||||
|
{
|
||||||
|
Data.ID = ID;
|
||||||
|
strcpy(Data.MQTT_Broker, mqtt_broker);
|
||||||
|
Data.MQTT_Port = mqtt_port;
|
||||||
|
strcpy(Data.MQTT_Username, mqtt_username);
|
||||||
|
strcpy(Data.MQTT_Password, mqtt_password);
|
||||||
|
strcpy(Data.WLAN_SSID, wlan_ssid);
|
||||||
|
strcpy(Data.WLAN_Password, wlan_password);
|
||||||
|
|
||||||
|
EEPROM.begin(512);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::Load()
|
||||||
|
{
|
||||||
|
EEPROM.get(0, this->Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::Save()
|
||||||
|
{
|
||||||
|
EEPROM.put(0, this->Data);
|
||||||
|
EEPROM.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Config::IsEmpty()
|
||||||
|
{
|
||||||
|
return this->Data.ID == 0;
|
||||||
|
}
|
32
Software/src/Deprecated/config.h.old
Normal file
32
Software/src/Deprecated/config.h.old
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
struct Config_Data
|
||||||
|
{
|
||||||
|
int ID = 0;
|
||||||
|
|
||||||
|
char MQTT_Broker[256];
|
||||||
|
int MQTT_Port = 1883;
|
||||||
|
char MQTT_Username[64];
|
||||||
|
char MQTT_Password[64];
|
||||||
|
|
||||||
|
char WLAN_SSID[65];
|
||||||
|
char WLAN_Password[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
public:
|
||||||
|
const char WLANAP_SSID[32] = "FabReader";
|
||||||
|
const char WLANAP_Password[64] = "FabReader";
|
||||||
|
|
||||||
|
Config_Data Data;
|
||||||
|
|
||||||
|
Config();
|
||||||
|
Config(int ID, char mqtt_broker[], int mqtt_port, char mqtt_username[], char mqtt_password[], char wlan_ssid[], char wlan_password[]);
|
||||||
|
|
||||||
|
void Load();
|
||||||
|
void Save();
|
||||||
|
|
||||||
|
bool IsEmpty();
|
||||||
|
};
|
||||||
|
#endif
|
60
Software/src/Deprecated/website.h
Normal file
60
Software/src/Deprecated/website.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef WEBSITE_H
|
||||||
|
#define WEBSITE_H
|
||||||
|
const struct Website
|
||||||
|
{
|
||||||
|
const char INDEX[] =
|
||||||
|
"<!DOCTYPE HTML>"
|
||||||
|
"<html>"
|
||||||
|
"<head>"
|
||||||
|
"<meta content=\"text/html; charset=ISO-8859-1\""
|
||||||
|
" http-equiv=\"content-type\">"
|
||||||
|
"<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0\">"
|
||||||
|
"<title>Verbindungsdaten RFID-Reader</title>"
|
||||||
|
"<style>"
|
||||||
|
"\"body { background-color: #808080; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }\""
|
||||||
|
"</style>"
|
||||||
|
"</head>"
|
||||||
|
"<body>"
|
||||||
|
"<h1>Verbindungsdaten RFID-Reader</h1>"
|
||||||
|
"<FORM action=\"/\" method=\"post\">"
|
||||||
|
"<P>"
|
||||||
|
"<label>ssid: </label><input maxlength=\"30\" name=\"ssid\"><br>"
|
||||||
|
"<label>Passwort: </label><input maxlength=\"30\" name=\"Passwort\"><br>"
|
||||||
|
"<label>BrokerIP: </label><input maxlength=\"15\" name=\"BrokerIP\"><br>"
|
||||||
|
"<label>ReaderID: </label><input maxlength=\"3\" name=\"ReaderID\"><br>"
|
||||||
|
"Connection<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"ConType\" value=\"1\">Ehternet<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"ConType\" value=\"0\">WiFi<BR>"
|
||||||
|
"RFID-Type<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"RFIDType\" value=\"0\">Mifare Classic<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"RFIDType\" value=\"1\">Mifare Classic + Timestamp<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"RFIDType\" value=\"2\">Mifare DESFire<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"RFIDType\" value=\"3\">Mifar Ultralight C<BR>"
|
||||||
|
"Data Package Format<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"DatFormat\" value=\"0\">JSON<BR>"
|
||||||
|
"<INPUT type=\"radio\" name=\"DatFormat\" value=\"1\">Text <BR>"
|
||||||
|
"<INPUT type=\"submit\" value=\"Send\"> <INPUT type=\"reset\">"
|
||||||
|
"</P>"
|
||||||
|
"</FORM>"
|
||||||
|
"</body>"
|
||||||
|
"</html>";
|
||||||
|
|
||||||
|
const char SAVED[] =
|
||||||
|
"<!DOCTYPE HTML>"
|
||||||
|
"<html>"
|
||||||
|
"<head>"
|
||||||
|
"<meta content=\"text/html; charset=ISO-8859-1\""
|
||||||
|
" http-equiv=\"content-type\">"
|
||||||
|
"<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0\">"
|
||||||
|
"<title>Verbindungsdaten RFID-Reader</title>"
|
||||||
|
"<style>"
|
||||||
|
"\"body { background-color: #808080; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }\""
|
||||||
|
"</style>"
|
||||||
|
"</head>"
|
||||||
|
"<body>"
|
||||||
|
"<h1>Saved</h1>"
|
||||||
|
"<h2><a href=\"/\">go back</a></h2>"
|
||||||
|
"</body>"
|
||||||
|
"</html>";
|
||||||
|
};
|
||||||
|
#endif
|
100
Software/src/Display.cpp
Normal file
100
Software/src/Display.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include "display.h"
|
||||||
|
#include <SSD1306Wire.h>
|
||||||
|
|
||||||
|
Display::Display(int sda, int scl, int readerid)
|
||||||
|
{
|
||||||
|
this->readerid = readerid;
|
||||||
|
display = new SSD1306Wire(0x3c, sda, scl);
|
||||||
|
display->init();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->flipScreenVertically();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::clearReaderInfo()
|
||||||
|
{
|
||||||
|
char buffer [DISPLAY_BUFFER_SIZE];
|
||||||
|
sprintf(buffer, "%05d", readerid);
|
||||||
|
writeReaderInfo(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::createReaderInfo(char state[])
|
||||||
|
{
|
||||||
|
if(strlen(state) < DISPLAY_BUFFER_SIZE - 1 - 6)
|
||||||
|
{
|
||||||
|
char buffer [DISPLAY_BUFFER_SIZE];
|
||||||
|
sprintf(buffer, "%s %05d", state, readerid);
|
||||||
|
writeReaderInfo(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::writeReaderInfo(char text[])
|
||||||
|
{
|
||||||
|
if(strlen(text) < DISPLAY_BUFFER_SIZE - 1)
|
||||||
|
{
|
||||||
|
strcpy(ReaderInfo, text);
|
||||||
|
}
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::writeTitle(char text[])
|
||||||
|
{
|
||||||
|
if(strlen(text) < DISPLAY_BUFFER_SIZE - 1)
|
||||||
|
{
|
||||||
|
strcpy(Title, text);
|
||||||
|
}
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::writeInfo(char text[])
|
||||||
|
{
|
||||||
|
if(strlen(text) < DISPLAY_BUFFER_SIZE - 1)
|
||||||
|
{
|
||||||
|
strcpy(Info, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::updateDisplay()
|
||||||
|
{
|
||||||
|
display->clear();
|
||||||
|
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
display->drawString(64, 0, ReaderInfo);
|
||||||
|
|
||||||
|
display->setFont(ArialMT_Plain_24);
|
||||||
|
display->drawString(64, 13, Title);
|
||||||
|
|
||||||
|
display->setFont(ArialMT_Plain_16);
|
||||||
|
display->drawString(64, 40, Info);
|
||||||
|
|
||||||
|
display->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::updateByMQTT(char* topic, byte* payload, unsigned int length)
|
||||||
|
{
|
||||||
|
char topic_displayTitle[] = "fabreader/00000/display/title";
|
||||||
|
sprintf(topic_displayTitle, "fabreader/%05d/display/title", readerid);
|
||||||
|
|
||||||
|
char topic_displayInfo[] = "fabreader/00000/display/info";
|
||||||
|
sprintf(topic_displayInfo, "fabreader/%05d/display/info", readerid);
|
||||||
|
|
||||||
|
char topic_stopOTA[] = "fabreader/00000/stopOTA";
|
||||||
|
sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", readerid);
|
||||||
|
|
||||||
|
char buffer[length + 1] = {0};
|
||||||
|
memcpy(buffer, payload, length);
|
||||||
|
|
||||||
|
if(!strcmp(topic, topic_displayTitle))
|
||||||
|
{
|
||||||
|
writeTitle(buffer);
|
||||||
|
}
|
||||||
|
else if(!strcmp(topic, topic_displayInfo))
|
||||||
|
{
|
||||||
|
writeInfo(buffer);
|
||||||
|
}
|
||||||
|
else if(!strcmp(topic, topic_stopOTA))
|
||||||
|
{
|
||||||
|
clearReaderInfo();
|
||||||
|
}
|
||||||
|
}
|
26
Software/src/Display.h
Normal file
26
Software/src/Display.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef DISPLAY_H
|
||||||
|
#define DISPLAY_H
|
||||||
|
#include <SSD1306Wire.h>
|
||||||
|
|
||||||
|
#define DISPLAY_BUFFER_SIZE 30
|
||||||
|
|
||||||
|
class Display
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SSD1306Wire* display;
|
||||||
|
int readerid;
|
||||||
|
char ReaderInfo[DISPLAY_BUFFER_SIZE] = "";
|
||||||
|
char Title[DISPLAY_BUFFER_SIZE] = "Boot ...";
|
||||||
|
char Info[DISPLAY_BUFFER_SIZE] = "";
|
||||||
|
|
||||||
|
public:
|
||||||
|
Display(int sda, int scl, int readerid);
|
||||||
|
void createReaderInfo(char* state);
|
||||||
|
void clearReaderInfo();
|
||||||
|
void writeReaderInfo(char* text);
|
||||||
|
void writeTitle(char* text);
|
||||||
|
void writeInfo(char* text);
|
||||||
|
void updateDisplay();
|
||||||
|
void updateByMQTT(char* topic, byte* payload, unsigned int length);
|
||||||
|
};
|
||||||
|
#endif
|
144
Software/src/NFC.cpp
Normal file
144
Software/src/NFC.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "nfc.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
#include <DESFire.h>
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
NFC::NFC(int pin_ss, int pin_rst)
|
||||||
|
{
|
||||||
|
rfid = new DESFire(pin_ss, pin_rst);
|
||||||
|
|
||||||
|
SPI.begin();
|
||||||
|
rfid->PCD_Init();
|
||||||
|
rfid->PCD_DumpVersionToSerial();
|
||||||
|
}
|
||||||
|
|
||||||
|
MFRC522::Uid NFC::getUID()
|
||||||
|
{
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NFC::hasCardSelected()
|
||||||
|
{
|
||||||
|
return cardSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NFC::testNFC()
|
||||||
|
{
|
||||||
|
return rfid->PCD_PerformSelfTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NFC::checkforCard()
|
||||||
|
{
|
||||||
|
// RequestA
|
||||||
|
if ( ! rfid->PICC_IsNewCardPresent())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PICC_Select ???
|
||||||
|
if ( ! rfid->PICC_ReadCardSerial())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for DESFire
|
||||||
|
if (rfid->uid.sak != 0x20)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NFC::connecttoCard()
|
||||||
|
{
|
||||||
|
// RATS
|
||||||
|
byte ats[16];
|
||||||
|
byte atsLength = 16;
|
||||||
|
MFRC522::StatusCode state = rfid->PICC_RequestATS(ats, &atsLength);
|
||||||
|
if (state != MFRC522::STATUS_OK) {
|
||||||
|
Serial.println(F("Failed ATS"));
|
||||||
|
Serial.println(state);
|
||||||
|
rfid->PICC_HaltA();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PPS
|
||||||
|
state = rfid->PICC_ProtocolAndParameterSelection(0x00, 0x11, 0x00);
|
||||||
|
if (state != MFRC522::STATUS_OK)
|
||||||
|
{
|
||||||
|
Serial.println("Failed PPS");
|
||||||
|
Serial.println(state);
|
||||||
|
rfid->PICC_HaltA();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cardSelected = true;
|
||||||
|
uid = rfid->uid;
|
||||||
|
pcb = 0x0A;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NFC::disconnectCard()
|
||||||
|
{
|
||||||
|
MFRC522::StatusCode state = rfid->PICC_HaltA();
|
||||||
|
if (state != MFRC522::STATUS_OK)
|
||||||
|
{
|
||||||
|
Serial.println(F("Failed PICC_HaltA"));
|
||||||
|
Serial.println(state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NFC::testCard()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MFRC522::StatusCode NFC::Transceive(byte* command, byte command_len, byte* response, byte* response_len)
|
||||||
|
{
|
||||||
|
if(command_len >= 0xFF - 4)
|
||||||
|
{
|
||||||
|
return MFRC522::STATUS_NO_ROOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
MFRC522::StatusCode state;
|
||||||
|
byte request_buffer[APDU_BUFFER_SIZE + 4]; // APDU Size + PCB + CID + 2x CRC
|
||||||
|
byte request_buffer_size = command_len + 4;
|
||||||
|
|
||||||
|
request_buffer[0] = pcb;
|
||||||
|
request_buffer[1] = cid;
|
||||||
|
|
||||||
|
memcpy(&request_buffer[2], command, command_len);
|
||||||
|
|
||||||
|
// Update the PCB
|
||||||
|
if (pcb == 0x0A)
|
||||||
|
pcb = 0x0B;
|
||||||
|
else
|
||||||
|
pcb = 0x0A;
|
||||||
|
|
||||||
|
// Calculate CRC_A
|
||||||
|
state = rfid->PCD_CalculateCRC(request_buffer, request_buffer_size - 2, &request_buffer[request_buffer_size - 2]);
|
||||||
|
if (state != MFRC522::STATUS_OK)
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte response_buffer[APDU_BUFFER_SIZE + 4] = {0}; // APDU Size + PCB + CID + 2x CRC
|
||||||
|
byte response_buffer_size = 0xFF;
|
||||||
|
|
||||||
|
printbytes(request_buffer, request_buffer_size);
|
||||||
|
state = rfid->PCD_TransceiveData(request_buffer, request_buffer_size, response_buffer, &response_buffer_size);
|
||||||
|
if (state != MFRC522::STATUS_OK)
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(response, response_buffer + 2, response_buffer_size - 4);
|
||||||
|
*response_len = response_buffer_size - 4;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
31
Software/src/NFC.h
Normal file
31
Software/src/NFC.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef NFC_H
|
||||||
|
#define NFC_H
|
||||||
|
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
#include <DESFire.h>
|
||||||
|
#define APDU_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
class NFC
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
MFRC522::Uid uid;
|
||||||
|
byte pcb = 0x0A;
|
||||||
|
byte cid = 0x00;
|
||||||
|
bool cardSelected = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DESFire* rfid;
|
||||||
|
NFC(int pin_ss, int pin_rst);
|
||||||
|
bool testNFC();
|
||||||
|
bool checkforCard();
|
||||||
|
bool connecttoCard();
|
||||||
|
bool disconnectCard();
|
||||||
|
bool testCard();
|
||||||
|
bool hasCardSelected();
|
||||||
|
MFRC522::Uid getUID();
|
||||||
|
|
||||||
|
MFRC522::StatusCode Transceive(byte* command, byte command_len, byte* response, byte* response_len);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
96
Software/src/OTAProxy.cpp
Normal file
96
Software/src/OTAProxy.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include "otaproxy.h"
|
||||||
|
#include "nfc.h"
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
|
OTAProxy::OTAProxy(PubSubClient* mqttClient, NFC* nfc, int id)
|
||||||
|
{
|
||||||
|
this->mqtt = mqttClient;
|
||||||
|
this->nfc = nfc;
|
||||||
|
this->id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OTAProxy::hasActiveOTA()
|
||||||
|
{
|
||||||
|
return activeOTA;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTAProxy::startOTA()
|
||||||
|
{
|
||||||
|
if(!(nfc->hasCardSelected()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activeOTA = true;
|
||||||
|
|
||||||
|
char topic[] = "fabreader/00000/startOTA";
|
||||||
|
sprintf(topic, "fabreader/%05d/startOTA", id);
|
||||||
|
MFRC522::Uid uid = nfc->getUID();
|
||||||
|
mqtt->publish(topic, uid.uidByte, uid.size);
|
||||||
|
|
||||||
|
Serial.println("Start OTA");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTAProxy::continueOTA(char* topic, byte* payload, unsigned int length)
|
||||||
|
{
|
||||||
|
char topic_requestOTA[] = "fabreader/00000/requestOTA";
|
||||||
|
sprintf(topic_requestOTA, "fabreader/%05d/requestOTA", id);
|
||||||
|
|
||||||
|
char topic_responseOTA[] = "fabreader/00000/responseOTA";
|
||||||
|
sprintf(topic_responseOTA, "fabreader/%05d/responseOTA", id);
|
||||||
|
|
||||||
|
char topic_stopOTA[] = "fabreader/00000/stopOTA";
|
||||||
|
sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", id);
|
||||||
|
|
||||||
|
char topic_restartOTA[] = "fabreader/00000/restartOTA";
|
||||||
|
sprintf(topic_restartOTA, "fabreader/%05d/restartOTA", id);
|
||||||
|
|
||||||
|
if(!strcmp(topic, topic_requestOTA))
|
||||||
|
{
|
||||||
|
Serial.println("Request OTA");
|
||||||
|
byte response[APDU_BUFFER_SIZE] = {0};
|
||||||
|
byte response_len;
|
||||||
|
|
||||||
|
MFRC522::StatusCode status;
|
||||||
|
|
||||||
|
Serial.println("Run Transceive");
|
||||||
|
status = nfc->Transceive(payload, length, response, &response_len);
|
||||||
|
Serial.printf("PICC_Tranceive: 0x%02x\n", status);
|
||||||
|
|
||||||
|
if(status != MFRC522::STATUS_OK)
|
||||||
|
{
|
||||||
|
cancelOTA();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mqtt->publish(topic_responseOTA, response, response_len);
|
||||||
|
Serial.println("Response OTA");
|
||||||
|
}
|
||||||
|
else if(!strcmp(topic, topic_stopOTA))
|
||||||
|
{
|
||||||
|
Serial.println("Stop OTA");
|
||||||
|
nfc->disconnectCard();
|
||||||
|
activeOTA = false;
|
||||||
|
}
|
||||||
|
// else if(!strcmp(topic, topic_restartOTA))
|
||||||
|
// {
|
||||||
|
// Serial.println("Restart OTA");
|
||||||
|
// while(!(nfc->deselectCard()));
|
||||||
|
// // if(nfc->hasNewCard())
|
||||||
|
// // {
|
||||||
|
// // startOTA();
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void OTAProxy::cancelOTA()
|
||||||
|
{
|
||||||
|
char topic_cancelOTA[] = "fabreader/00000/cancelOTA";
|
||||||
|
sprintf(topic_cancelOTA, "fabreader/%05d/cancelOTA", id);
|
||||||
|
MFRC522::Uid uid = nfc->getUID();
|
||||||
|
mqtt->publish(topic_cancelOTA, uid.uidByte, uid.size);
|
||||||
|
|
||||||
|
while(!(nfc->disconnectCard()));
|
||||||
|
activeOTA = false;
|
||||||
|
|
||||||
|
Serial.println("Cancel OTA");
|
||||||
|
}
|
25
Software/src/OTAProxy.h
Normal file
25
Software/src/OTAProxy.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef OTAProxy_H
|
||||||
|
#define OTAProxy_H
|
||||||
|
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
#include "nfc.h"
|
||||||
|
#define MSG_BUFFER_SIZE 50
|
||||||
|
|
||||||
|
class OTAProxy
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool activeOTA = false;
|
||||||
|
PubSubClient* mqtt;
|
||||||
|
NFC* nfc;
|
||||||
|
int id;
|
||||||
|
char msg[MSG_BUFFER_SIZE];
|
||||||
|
public:
|
||||||
|
OTAProxy(PubSubClient* mqtt, NFC* nfc, int id);
|
||||||
|
bool hasActiveOTA();
|
||||||
|
|
||||||
|
void startOTA();
|
||||||
|
void continueOTA(char* topic, byte* payload, unsigned int length);
|
||||||
|
void cancelOTA();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
18
Software/src/Pins.h
Normal file
18
Software/src/Pins.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef PINS_H
|
||||||
|
#define PINS_H
|
||||||
|
|
||||||
|
// Pins for ESP8266
|
||||||
|
#define PIN_SDA 4
|
||||||
|
#define PIN_SCL 5
|
||||||
|
|
||||||
|
#define PIN_SPI_MOSI 13
|
||||||
|
#define PIN_SPI_MISO 12
|
||||||
|
#define PIN_SPI_SCK 14
|
||||||
|
|
||||||
|
#define PIN_RFID_RST 0
|
||||||
|
#define PIN_RFID_SPI_SS 2
|
||||||
|
#define PIN_ETH_SPI_SS 15
|
||||||
|
|
||||||
|
#define PIN_BUZZER 16
|
||||||
|
#define PIN_BUTTON A0
|
||||||
|
#endif
|
6
Software/src/config.h.example
Normal file
6
Software/src/config.h.example
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#define WLAN_SSID ""
|
||||||
|
#define WLAN_PASS ""
|
||||||
|
#define MQTT_BROKER ""
|
||||||
|
#define MQTT_USERNAME ""
|
||||||
|
#define MQTT_PASSWORD ""
|
||||||
|
#define FABREADERID 1
|
71
Software/src/helpers.cpp
Normal file
71
Software/src/helpers.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
void char2byte(char* str, byte* array)
|
||||||
|
{
|
||||||
|
for(int i=0; i <2 ; i++)
|
||||||
|
{
|
||||||
|
char c = *str;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
*array *= 16;
|
||||||
|
*array += c - '0';
|
||||||
|
}
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
{
|
||||||
|
*array *= 16;
|
||||||
|
*array += (c - 'A') + 10;
|
||||||
|
}
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
{
|
||||||
|
*array *= 16;
|
||||||
|
*array += (c - 'a') + 10;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void chars2bytes(char* str, byte* array, bool msb)
|
||||||
|
{
|
||||||
|
int len = strlen(str);
|
||||||
|
for(int i = 0; i < len; i += 2)
|
||||||
|
{
|
||||||
|
if(msb)
|
||||||
|
{
|
||||||
|
char2byte(&str[i], &array[i/2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char2byte(&str[i], &array[len-2 - i/2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void byte2char(byte* array, char* str)
|
||||||
|
{
|
||||||
|
sprintf(str, "%02x", *array);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bytes2chars(byte* array, byte array_len, char* str, bool msb)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < array_len; i++)
|
||||||
|
{
|
||||||
|
if(msb)
|
||||||
|
{
|
||||||
|
byte2char(&array[i], &str[i*2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte2char(&array[array_len-2 - i], &str[i*2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printbytes(byte* array, byte array_len)
|
||||||
|
{
|
||||||
|
Serial.print("0x");
|
||||||
|
for(int i = 0; i < array_len; i++)
|
||||||
|
{
|
||||||
|
Serial.printf("%02x", array[i]);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
}
|
13
Software/src/helpers.h
Normal file
13
Software/src/helpers.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef HELPERS_H
|
||||||
|
#define HELPERS_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
void char2byte(char* str, byte* array);
|
||||||
|
void chars2bytes(char* str, byte* array, bool msb);
|
||||||
|
|
||||||
|
void byte2char(byte* array, char* str);
|
||||||
|
void bytes2chars(byte* array, byte array_len, char* str, bool msb);
|
||||||
|
|
||||||
|
void printbytes(byte* array, byte array_len);
|
||||||
|
|
||||||
|
#endif
|
181
Software/src/main.cpp
Normal file
181
Software/src/main.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoLog.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "pins.h"
|
||||||
|
#include "nfc.h"
|
||||||
|
#include "otaproxy.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "Desfire.h"
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WebServer.h>
|
||||||
|
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
WiFiClient espClient;
|
||||||
|
//Config_Data config;
|
||||||
|
|
||||||
|
PubSubClient* mqtt;
|
||||||
|
NFC* nfc;
|
||||||
|
OTAProxy* ota;
|
||||||
|
Display* display;
|
||||||
|
|
||||||
|
unsigned long otatimeout = 3000;
|
||||||
|
unsigned long lastotatime;
|
||||||
|
|
||||||
|
void setup_wifi()
|
||||||
|
{
|
||||||
|
delay(10);
|
||||||
|
Serial.println("Connecting Wifi ...");
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(WLAN_SSID, WLAN_PASS);
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
randomSeed(micros());
|
||||||
|
Serial.println("WiFi connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
void reconnect()
|
||||||
|
{
|
||||||
|
while (!mqtt->connected())
|
||||||
|
{
|
||||||
|
String clientId = "FabReader_";
|
||||||
|
clientId += String(FABREADERID);
|
||||||
|
|
||||||
|
Serial.println("Connecting MQTT ...");
|
||||||
|
bool connected = false;
|
||||||
|
if(MQTT_USERNAME == "")
|
||||||
|
{
|
||||||
|
connected = mqtt->connect(clientId.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connected = mqtt->connect(clientId.c_str(), MQTT_USERNAME, MQTT_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connected)
|
||||||
|
{
|
||||||
|
Serial.println("MQTT connected");
|
||||||
|
char id[6] = "00000";
|
||||||
|
sprintf(id, "%05d", FABREADERID);
|
||||||
|
mqtt->publish("fabreader", id);
|
||||||
|
|
||||||
|
char topic_requestOTA[] = "fabreader/00000/requestOTA";
|
||||||
|
sprintf(topic_requestOTA, "fabreader/%05d/requestOTA", FABREADERID);
|
||||||
|
mqtt->subscribe(topic_requestOTA);
|
||||||
|
|
||||||
|
char topic_stopOTA[] = "fabreader/00000/stopOTA";
|
||||||
|
sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", FABREADERID);
|
||||||
|
mqtt->subscribe(topic_stopOTA);
|
||||||
|
|
||||||
|
char topic_display[] = "fabreader/00000/display/#";
|
||||||
|
sprintf(topic_display, "fabreader/%05d/display/#", FABREADERID);
|
||||||
|
mqtt->subscribe(topic_display);
|
||||||
|
|
||||||
|
display->writeTitle("Connected");
|
||||||
|
display->writeInfo("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display->writeTitle("Reconnect");
|
||||||
|
display->writeInfo("MQTT");
|
||||||
|
|
||||||
|
Serial.print("failed, rc=");
|
||||||
|
Serial.print(mqtt->state());
|
||||||
|
Serial.println(" try again in 5 seconds");
|
||||||
|
delay(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback(char* topic, byte* payload, unsigned int length)
|
||||||
|
{
|
||||||
|
Serial.println("Receive Message");
|
||||||
|
Serial.println(topic);
|
||||||
|
if(ota->hasActiveOTA())
|
||||||
|
{
|
||||||
|
ota->continueOTA(topic, payload, length);
|
||||||
|
}
|
||||||
|
display->updateByMQTT(topic, payload, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.print("\n\n\n");
|
||||||
|
Serial.println("Booting ...");
|
||||||
|
|
||||||
|
pinMode(PIN_BUZZER, OUTPUT);
|
||||||
|
pinMode(PIN_BUTTON, INPUT);
|
||||||
|
pinMode(PIN_ETH_SPI_SS, OUTPUT);
|
||||||
|
digitalWrite(PIN_ETH_SPI_SS, HIGH);
|
||||||
|
|
||||||
|
display = new Display(PIN_SDA, PIN_SCL, FABREADERID);
|
||||||
|
display->clearReaderInfo();
|
||||||
|
|
||||||
|
display->writeInfo("Start NFC ...");
|
||||||
|
Serial.println("Connecting NFC ...");
|
||||||
|
nfc = new NFC(PIN_RFID_SPI_SS, PIN_RFID_RST);
|
||||||
|
if(!(nfc->rfid->PCD_PerformSelfTest()))
|
||||||
|
{
|
||||||
|
Serial.println("NFC Test failed");
|
||||||
|
}
|
||||||
|
Serial.println("NFC connected");
|
||||||
|
|
||||||
|
display->writeInfo("Start WIFI ...");
|
||||||
|
setup_wifi();
|
||||||
|
|
||||||
|
display->writeInfo("Start MQTT ...");
|
||||||
|
mqtt = new PubSubClient(espClient);
|
||||||
|
mqtt->setServer(MQTT_BROKER, 1883);
|
||||||
|
mqtt->setCallback(callback);
|
||||||
|
|
||||||
|
display->writeInfo("Start OTA ...");
|
||||||
|
ota = new OTAProxy(mqtt, nfc, FABREADERID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (!mqtt->connected())
|
||||||
|
{
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
mqtt->loop();
|
||||||
|
|
||||||
|
if(!ota->hasActiveOTA())
|
||||||
|
{
|
||||||
|
if(nfc->checkforCard())
|
||||||
|
{
|
||||||
|
Serial.println("Card detected");
|
||||||
|
if(nfc->connecttoCard())
|
||||||
|
{
|
||||||
|
Serial.println("Card connected");
|
||||||
|
lastotatime = millis();
|
||||||
|
|
||||||
|
display->createReaderInfo("Run OTA");
|
||||||
|
ota->startOTA();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display->createReaderInfo("Retry Card");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ota->hasActiveOTA())
|
||||||
|
{
|
||||||
|
if(millis() - lastotatime > otatimeout)
|
||||||
|
{
|
||||||
|
ota->cancelOTA();
|
||||||
|
display->clearReaderInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1418
Software/src/main.cpp.deprecated
Normal file
1418
Software/src/main.cpp.deprecated
Normal file
File diff suppressed because it is too large
Load Diff
146
Software/src/main.cpp.desfire
Normal file
146
Software/src/main.cpp.desfire
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------------------------------------------------------
|
||||||
|
* Example sketch/program showing how to read data from a PICC to serial.
|
||||||
|
* --------------------------------------------------------------------------------------------------------------------
|
||||||
|
* This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
|
||||||
|
*
|
||||||
|
* Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
|
||||||
|
* Reader on the Arduino SPI interface.
|
||||||
|
*
|
||||||
|
* When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
|
||||||
|
* then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
|
||||||
|
* you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
|
||||||
|
* will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages
|
||||||
|
* when removing the PICC from reading distance too early.
|
||||||
|
*
|
||||||
|
* If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading).
|
||||||
|
* So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all
|
||||||
|
* details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so
|
||||||
|
* keep the PICCs at reading distance until complete.
|
||||||
|
*
|
||||||
|
* @license Released into the public domain.
|
||||||
|
*
|
||||||
|
* Typical pin layout used:
|
||||||
|
* -----------------------------------------------------------------------------------------
|
||||||
|
* MFRC522 Arduino Arduino Arduino Arduino Arduino
|
||||||
|
* Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
|
||||||
|
* Signal Pin Pin Pin Pin Pin Pin
|
||||||
|
* -----------------------------------------------------------------------------------------
|
||||||
|
* RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
|
||||||
|
* SPI SS SDA(SS) 10 53 D10 10 10
|
||||||
|
* SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
|
||||||
|
* SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
|
||||||
|
* SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <MFRC522.h>
|
||||||
|
#include <Desfire.h>
|
||||||
|
|
||||||
|
#define RST_PIN 9 // Configurable, see typical pin layout above
|
||||||
|
#define SS_PIN 10 // Configurable, see typical pin layout above
|
||||||
|
|
||||||
|
#include "Pins.h"
|
||||||
|
|
||||||
|
DESFire mfrc522(PIN_RFID_SPI_SS, PIN_RFID_RST); // Create MFRC522 instance
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200); // Initialize serial communications with the PC
|
||||||
|
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
|
||||||
|
SPI.begin(); // Init SPI bus
|
||||||
|
mfrc522.PCD_Init(); // Init MFRC522
|
||||||
|
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
|
||||||
|
mfrc522.PCD_PerformSelfTest();
|
||||||
|
Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Look for new cards
|
||||||
|
if ( ! mfrc522.PICC_IsNewCardPresent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select one of the cards
|
||||||
|
if ( ! mfrc522.PICC_ReadCardSerial()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mfrc522.uid.sak != 0x20) {
|
||||||
|
// Dump debug info about the card; PICC_HaltA() is automatically called
|
||||||
|
mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show an extra line
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
DESFire::mifare_desfire_tag tag;
|
||||||
|
DESFire::StatusCode response;
|
||||||
|
|
||||||
|
tag.pcb = 0x0A;
|
||||||
|
tag.cid = 0x00;
|
||||||
|
memset(tag.selected_application, 0, 3);
|
||||||
|
|
||||||
|
// Make sure none DESFire status codes have DESFireStatus code to OK
|
||||||
|
response.desfire = DESFire::MF_OPERATION_OK;
|
||||||
|
|
||||||
|
byte ats[16];
|
||||||
|
byte atsLength = 16;
|
||||||
|
response.mfrc522 = mfrc522.PICC_RequestATS(ats, &atsLength);
|
||||||
|
if ( ! mfrc522.IsStatusCodeOK(response)) {
|
||||||
|
Serial.println(F("Failed to get ATS!"));
|
||||||
|
Serial.println(mfrc522.GetStatusCodeName(response));
|
||||||
|
Serial.println(response.mfrc522);
|
||||||
|
|
||||||
|
mfrc522.PICC_HaltA();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should do checks but since I know my DESFire allows and requires PPS...
|
||||||
|
// PPS1 is ommitted and, therefore, 0x00 is used (106kBd)
|
||||||
|
response.mfrc522 = mfrc522.PICC_ProtocolAndParameterSelection(0x00, 0x11);
|
||||||
|
if ( ! mfrc522.IsStatusCodeOK(response)) {
|
||||||
|
Serial.println(F("Failed to perform protocol and parameter selection (PPS)!"));
|
||||||
|
Serial.println(mfrc522.GetStatusCodeName(response));
|
||||||
|
mfrc522.PICC_HaltA();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MIFARE DESFire should respond to a GetVersion command
|
||||||
|
DESFire::MIFARE_DESFIRE_Version_t desfireVersion;
|
||||||
|
response = mfrc522.MIFARE_DESFIRE_GetVersion(&tag, &desfireVersion);
|
||||||
|
if ( ! mfrc522.IsStatusCodeOK(response)) {
|
||||||
|
Serial.println(F("Failed to get a response for GetVersion!"));
|
||||||
|
Serial.println(mfrc522.GetStatusCodeName(response));
|
||||||
|
mfrc522.PICC_HaltA();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump MIFARE DESFire version information.
|
||||||
|
// NOTE: KEEP YOUR CARD CLOSE TO THE READER!
|
||||||
|
// This method takes some time and the card will be read
|
||||||
|
// once output ends! If you remove the card too fast
|
||||||
|
// a timeout will occur!
|
||||||
|
mfrc522.PICC_DumpMifareDesfireVersion(&tag, &desfireVersion);
|
||||||
|
|
||||||
|
mfrc522.PICC_DumpMifareDesfireMasterKey(&tag);
|
||||||
|
|
||||||
|
DESFire::mifare_desfire_aid_t aids[MIFARE_MAX_APPLICATION_COUNT];
|
||||||
|
byte applicationCount = 0;
|
||||||
|
response = mfrc522.MIFARE_DESFIRE_GetApplicationIds(&tag, aids, &applicationCount);
|
||||||
|
if ( ! mfrc522.IsStatusCodeOK(response)) {
|
||||||
|
Serial.println(F("Failed to get application IDs!"));
|
||||||
|
Serial.println(mfrc522.GetStatusCodeName(response));
|
||||||
|
mfrc522.PICC_HaltA();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump all applications
|
||||||
|
for (byte aidIndex = 0; aidIndex < applicationCount; aidIndex++) {
|
||||||
|
mfrc522.PICC_DumpMifareDesfireApplication(&tag, &(aids[aidIndex]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call PICC_HaltA()
|
||||||
|
mfrc522.PICC_HaltA();
|
||||||
|
Serial.println();
|
||||||
|
}
|
189
Software/src/main.cpp.display
Normal file
189
Software/src/main.cpp.display
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/**
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
|
||||||
|
Copyright (c) 2018 by Fabrice Weinberg
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
ThingPulse invests considerable time and money to develop these open source libraries.
|
||||||
|
Please support us by buying our products (and not the clones) from
|
||||||
|
https://thingpulse.com
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Include the correct display library
|
||||||
|
|
||||||
|
// For a connection via I2C using the Arduino Wire include:
|
||||||
|
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||||
|
#include "SSD1306Wire.h" // legacy: #include "SSD1306.h"
|
||||||
|
// OR #include "SH1106Wire.h" // legacy: #include "SH1106.h"
|
||||||
|
|
||||||
|
// For a connection via I2C using brzo_i2c (must be installed) include:
|
||||||
|
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
|
||||||
|
// #include "SSD1306Brzo.h"
|
||||||
|
// OR #include "SH1106Brzo.h"
|
||||||
|
|
||||||
|
// For a connection via SPI include:
|
||||||
|
// #include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
|
||||||
|
// #include "SSD1306Spi.h"
|
||||||
|
// OR #include "SH1106SPi.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize the OLED display using Arduino Wire:
|
||||||
|
SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h
|
||||||
|
// SSD1306Wire display(0x3c, D3, D5); // ADDRESS, SDA, SCL - If not, they can be specified manually.
|
||||||
|
// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, OLEDDISPLAY_GEOMETRY - Extra param required for 128x32 displays.
|
||||||
|
// SH1106Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
|
||||||
|
|
||||||
|
// Initialize the OLED display using brzo_i2c:
|
||||||
|
// SSD1306Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL
|
||||||
|
// or
|
||||||
|
// SH1106Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL
|
||||||
|
|
||||||
|
// Initialize the OLED display using SPI:
|
||||||
|
// D5 -> CLK
|
||||||
|
// D7 -> MOSI (DOUT)
|
||||||
|
// D0 -> RES
|
||||||
|
// D2 -> DC
|
||||||
|
// D8 -> CS
|
||||||
|
// SSD1306Spi display(D0, D2, D8); // RES, DC, CS
|
||||||
|
// or
|
||||||
|
// SH1106Spi display(D0, D2); // RES, DC
|
||||||
|
|
||||||
|
|
||||||
|
#define DEMO_DURATION 3000
|
||||||
|
typedef void (*Demo)(void);
|
||||||
|
|
||||||
|
int demoMode = 0;
|
||||||
|
int counter = 1;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println();
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
|
||||||
|
// Initialising the UI will init the display too.
|
||||||
|
display.init();
|
||||||
|
|
||||||
|
display.flipScreenVertically();
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawFontFaceDemo() {
|
||||||
|
// Font Demo1
|
||||||
|
// create more fonts at http://oleddisplay.squix.ch/
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.drawString(0, 0, "Hello world");
|
||||||
|
display.setFont(ArialMT_Plain_16);
|
||||||
|
display.drawString(0, 10, "Hello world");
|
||||||
|
display.setFont(ArialMT_Plain_24);
|
||||||
|
display.drawString(0, 26, "Hello world");
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawTextFlowDemo() {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawStringMaxWidth(0, 0, 128,
|
||||||
|
"Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore." );
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawTextAlignmentDemo() {
|
||||||
|
// Text alignment demo
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
|
||||||
|
// The coordinates define the left starting point of the text
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawString(0, 10, "Left aligned (0,10)");
|
||||||
|
|
||||||
|
// The coordinates define the center of the text
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(64, 22, "Center aligned (64,22)");
|
||||||
|
|
||||||
|
// The coordinates define the right end of the text
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display.drawString(128, 33, "Right aligned (128,33)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawRectDemo() {
|
||||||
|
// Draw a pixel at given position
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
display.setPixel(i, i);
|
||||||
|
display.setPixel(10 - i, i);
|
||||||
|
}
|
||||||
|
display.drawRect(12, 12, 20, 20);
|
||||||
|
|
||||||
|
// Fill the rectangle
|
||||||
|
display.fillRect(14, 14, 17, 17);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawHorizontalLine(0, 40, 20);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawVerticalLine(40, 0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawCircleDemo() {
|
||||||
|
for (int i = 1; i < 8; i++) {
|
||||||
|
display.setColor(WHITE);
|
||||||
|
display.drawCircle(32, 32, i * 3);
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
display.setColor(BLACK);
|
||||||
|
}
|
||||||
|
display.fillCircle(96, 32, 32 - i * 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawProgressBarDemo() {
|
||||||
|
int progress = (counter / 5) % 100;
|
||||||
|
// draw the progress bar
|
||||||
|
display.drawProgressBar(0, 32, 120, 10, progress);
|
||||||
|
|
||||||
|
// draw the percentage as String
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(64, 15, String(progress) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, drawRectDemo, drawCircleDemo, drawProgressBarDemo};
|
||||||
|
int demoLength = (sizeof(demos) / sizeof(Demo));
|
||||||
|
long timeSinceLastModeSwitch = 0;
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// clear the display
|
||||||
|
display.clear();
|
||||||
|
// draw the current demo method
|
||||||
|
demos[demoMode]();
|
||||||
|
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display.drawString(128, 54, String(millis()));
|
||||||
|
// write the buffer to the display
|
||||||
|
display.display();
|
||||||
|
|
||||||
|
if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) {
|
||||||
|
demoMode = (demoMode + 1) % demoLength;
|
||||||
|
timeSinceLastModeSwitch = millis();
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
delay(10);
|
||||||
|
}
|
58
Software/src/main.cpp.test
Normal file
58
Software/src/main.cpp.test
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <SPI.h>
|
||||||
|
#include <MFRC522.h>
|
||||||
|
#include <Desfire.h>
|
||||||
|
|
||||||
|
#include "nfc.h"
|
||||||
|
#include "pins.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
NFC* nfc;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200); // Initialize serial communications with the PC
|
||||||
|
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
|
||||||
|
|
||||||
|
nfc = new NFC(PIN_RFID_SPI_SS, PIN_RFID_RST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if(nfc->checkforCard())
|
||||||
|
{
|
||||||
|
Serial.println("Card detected");
|
||||||
|
if(nfc->connecttoCard())
|
||||||
|
{
|
||||||
|
Serial.println("Card connected");
|
||||||
|
|
||||||
|
MFRC522::StatusCode state;
|
||||||
|
|
||||||
|
byte request_buffer[APDU_BUFFER_SIZE] = {0x90, 0x5A, 0x00, 0x00, 0x03, 0x42, 0x41, 0x46, 0x00};
|
||||||
|
byte request_buffer_size = 9;
|
||||||
|
byte response_buffer[APDU_BUFFER_SIZE] = {0};
|
||||||
|
byte response_buffer_size;
|
||||||
|
printbytes(request_buffer, request_buffer_size);
|
||||||
|
|
||||||
|
state = nfc->Transceive(request_buffer, request_buffer_size, response_buffer, &response_buffer_size);
|
||||||
|
if (state != MFRC522::STATUS_OK)
|
||||||
|
{
|
||||||
|
Serial.println("Data Exchange failed");
|
||||||
|
Serial.println(state);
|
||||||
|
}
|
||||||
|
Serial.println("Data Exchange complete");
|
||||||
|
printbytes(response_buffer, response_buffer_size);
|
||||||
|
|
||||||
|
state = nfc->Transceive(request_buffer, request_buffer_size, response_buffer, &response_buffer_size);
|
||||||
|
if (state != MFRC522::STATUS_OK)
|
||||||
|
{
|
||||||
|
Serial.println("Data Exchange failed");
|
||||||
|
Serial.println(state);
|
||||||
|
}
|
||||||
|
Serial.println("Data Exchange complete");
|
||||||
|
printbytes(response_buffer, response_buffer_size);
|
||||||
|
|
||||||
|
nfc->disconnectCard();
|
||||||
|
Serial.println("Card disconnected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Software/test/README
Normal file
11
Software/test/README
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
This directory is intended for PlatformIO Test Runner and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PlatformIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
Loading…
x
Reference in New Issue
Block a user