basic serial reader
This commit is contained in:
commit
c55bd0f87c
16 changed files with 595 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
include/secrets.h
|
||||
.DS_Store
|
||||
upload_params.ini
|
10
.vscode/extensions.json
vendored
Normal file
10
.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"
|
||||
]
|
||||
}
|
13
.vscode/settings.json
vendored
Normal file
13
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"string_view": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"regex": "cpp"
|
||||
}
|
||||
}
|
15
README
Normal file
15
README
Normal file
|
@ -0,0 +1,15 @@
|
|||
This project is a card reader system for Techinc that uses a WIEGAND based reader and allows platform.io based user flags to allow change of certain features.
|
||||
|
||||
This project is designed to work over serial with an external computer that decides who has access.
|
||||
|
||||
|
||||
# Currently supported flags:
|
||||
|
||||
-DBOARD1 : Used to set Pins for BOARD1 config
|
||||
-DBOARD2 : Used to set Pins for BOARD2 config
|
||||
-DRELAY1 : Enable the First Relay
|
||||
-DRELAY2 : Not implemented yet
|
||||
|
||||
|
||||
# Important Notes:
|
||||
* None
|
45
include/ACL.h
Normal file
45
include/ACL.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef ACL_H
|
||||
#define ACL_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <initializer_list>
|
||||
#include <EEPROM.h>
|
||||
|
||||
#include <Preferences.h>
|
||||
|
||||
#ifdef WEB_SERVER
|
||||
#ifdef WEB_SERIAL_DEBUG
|
||||
#include <WebSerial.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct User {
|
||||
String cardId;
|
||||
String desc;
|
||||
};
|
||||
|
||||
class ACL {
|
||||
public:
|
||||
ACL();
|
||||
ACL(std::initializer_list<User> userList);
|
||||
~ACL();
|
||||
|
||||
|
||||
void addUser(const String& cardId, const String& desc);
|
||||
void updateUser(const String& cardId, const String& newCardId, const String& newdesc);
|
||||
bool removeUser(const String& cardId);
|
||||
bool validateAccess(const String& cardId);
|
||||
int getACLSize() const;
|
||||
|
||||
// Additional EEPROM functions
|
||||
void saveToEEPROM();
|
||||
void loadFromEEPROM();
|
||||
|
||||
const User* getACL() const { return acl; } // Getter for acl
|
||||
|
||||
private:
|
||||
User* acl;
|
||||
int aclSize;
|
||||
};
|
||||
|
||||
#endif
|
39
include/README
Normal file
39
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
|
11
include/buzzer_ctl.h
Normal file
11
include/buzzer_ctl.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef BUZZER_CTL_H
|
||||
#define BUZZER_CTL_H
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
void short_beep();
|
||||
void granted_beep();
|
||||
void denied_beep();
|
||||
void clear_states();
|
||||
|
||||
#endif
|
38
include/hardware.h
Normal file
38
include/hardware.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef HARDWARE_H
|
||||
#define HARDWARE_H
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef WEB_SERVER
|
||||
#ifdef WEB_SERIAL_DEBUG
|
||||
#include <WebSerial.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOARD1
|
||||
#define TAMPER_PIN 26
|
||||
#define LEDCTL_PIN 32
|
||||
#define DATA0_PIN 34
|
||||
#define DATA1_PIN 36
|
||||
#define RELAY1_PIN 32
|
||||
#define RELAY2_PIN 33
|
||||
#define RELAY_DELAY 3000
|
||||
#endif
|
||||
|
||||
#ifdef BOARD2
|
||||
#define TAMPER_PIN 0
|
||||
#define ALARM_PIN 33
|
||||
#define WIEGAND_PIN 32
|
||||
#define LEDCTL_PIN 25
|
||||
#define DATA0_PIN 26
|
||||
#define DATA1_PIN 27
|
||||
#define RELAY1_PIN 13
|
||||
#define RELAY_DELAY 3000
|
||||
#endif
|
||||
|
||||
void controlRelay();
|
||||
void unlockDoor(bool silent);
|
||||
void lockDoor();
|
||||
void toggleDoor();
|
||||
String stateDoor();
|
||||
|
||||
#endif
|
14
include/main.h
Normal file
14
include/main.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include "hardware.h"
|
||||
#include <Arduino.h>
|
||||
#include "settings.h"
|
||||
|
||||
Settings settings;
|
||||
|
||||
#ifdef BUZZER
|
||||
#include "buzzer_ctl.h"
|
||||
#endif
|
||||
|
||||
#endif
|
20
include/settings.h
Normal file
20
include/settings.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <Preferences.h>
|
||||
|
||||
class Settings {
|
||||
private:
|
||||
bool disableDoor;
|
||||
|
||||
public:
|
||||
Settings();
|
||||
|
||||
void loadFromEEPROM();
|
||||
void saveToEEPROM();
|
||||
|
||||
void setDisableDoor(bool value);
|
||||
bool DoorDisabled();
|
||||
};
|
||||
|
||||
#endif // SETTINGS_H
|
46
lib/README
Normal file
46
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
|
47
platformio.ini
Normal file
47
platformio.ini
Normal file
|
@ -0,0 +1,47 @@
|
|||
; 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
|
||||
|
||||
[platformio]
|
||||
extra_configs = upload_params.ini
|
||||
|
||||
[env:esp32-evb]
|
||||
platform = espressif32
|
||||
board = esp32-evb
|
||||
framework = arduino
|
||||
build_flags = -DBOARD1 -DRELAY1 -DWIFI -DWEB_SERVER -DNET_FAIL_SAFE -DWEB_OTA_UPDATE -DLOCAL_ACL -DLOCAL_ACL_API -DLATCH_DOOR
|
||||
lib_deps =
|
||||
ottowinter/ESPAsyncWebServer-esphome@^3.0.0
|
||||
ayushsharma82/WebSerial@^1.4.0
|
||||
ayushsharma82/AsyncElegantOTA@^2.2.7
|
||||
bblanchon/ArduinoJson@^6.21.2
|
||||
|
||||
[env:mcu-esp32s]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = nodemcu-32s
|
||||
build_flags = -DBOARD2 -DBUZZER -DRELAY1 -DWIFI -DWEB_SERVER -DNET_FAIL_SAFE -DWEB_OTA_UPDATE -DLOCAL_ACL -DLOCAL_ACL_API -DLATCH_DOOR
|
||||
lib_deps =
|
||||
ottowinter/ESPAsyncWebServer-esphome@^3.0.0
|
||||
ayushsharma82/WebSerial@^1.4.0
|
||||
ayushsharma82/AsyncElegantOTA@^2.2.7
|
||||
bblanchon/ArduinoJson@^6.21.2
|
||||
|
||||
[env:mcu-esp32s-ota]
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = nodemcu-32s
|
||||
build_flags = -DBOARD2 -DBUZZER -DRELAY1 -DWIFI -DWEB_SERVER -DNET_FAIL_SAFE -DWEB_OTA_UPDATE -DLOCAL_ACL -DLOCAL_ACL_API -DLATCH_DOOR
|
||||
lib_deps =
|
||||
ottowinter/ESPAsyncWebServer-esphome@^3.0.0
|
||||
ayushsharma82/WebSerial@^1.4.0
|
||||
ayushsharma82/AsyncElegantOTA@^2.2.7
|
||||
bblanchon/ArduinoJson@^6.21.2
|
||||
extra_scripts = platformio_upload.py
|
||||
|
40
src/buzzer_ctl.cpp
Normal file
40
src/buzzer_ctl.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include "buzzer_ctl.h"
|
||||
|
||||
void short_beep()
|
||||
{
|
||||
#ifdef ALARM_PIN
|
||||
digitalWrite(ALARM_PIN, LOW);
|
||||
delay(50);
|
||||
digitalWrite(ALARM_PIN, HIGH);
|
||||
#endif
|
||||
}
|
||||
|
||||
void granted_beep()
|
||||
{
|
||||
#ifdef ALARM_PIN
|
||||
digitalWrite(ALARM_PIN, LOW);
|
||||
delay(50);
|
||||
digitalWrite(ALARM_PIN, HIGH);
|
||||
delay(50);
|
||||
digitalWrite(ALARM_PIN, LOW);
|
||||
delay(50);
|
||||
digitalWrite(ALARM_PIN, HIGH);
|
||||
delay(50);
|
||||
digitalWrite(ALARM_PIN, LOW);
|
||||
delay(50);
|
||||
digitalWrite(ALARM_PIN, HIGH);
|
||||
#endif
|
||||
}
|
||||
|
||||
void denied_beep(void)
|
||||
{
|
||||
#ifdef ALARM_PIN
|
||||
for (int i=0; i<100; i++)
|
||||
{
|
||||
delay(4);
|
||||
digitalWrite(ALARM_PIN, LOW);
|
||||
delay(4);
|
||||
digitalWrite(ALARM_PIN, HIGH);
|
||||
}
|
||||
#endif
|
||||
}
|
86
src/hardware.cpp
Normal file
86
src/hardware.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
#include "hardware.h"
|
||||
#include "buzzer_ctl.h"
|
||||
void controlRelay(int relayPin, bool on) {
|
||||
digitalWrite(relayPin, on ? HIGH : LOW); // Turn the relay on or off
|
||||
}
|
||||
|
||||
void unlockDoor(bool silent) {
|
||||
#ifdef BUZZER
|
||||
if (!silent) {
|
||||
granted_beep();
|
||||
}
|
||||
#endif
|
||||
#ifdef RELAY1
|
||||
#ifdef RELAY1_REVERSED
|
||||
controlRelay(RELAY1_PIN,true);
|
||||
#else
|
||||
controlRelay(RELAY1_PIN,false);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.println("door unlocked");
|
||||
#endif
|
||||
|
||||
#ifdef LEDCTL_PIN
|
||||
digitalWrite(LEDCTL_PIN,LOW);
|
||||
#endif
|
||||
|
||||
#ifdef WEB_SERIAL_DEBUG
|
||||
WebSerial.println("door unlocked");
|
||||
#endif
|
||||
}
|
||||
|
||||
void lockDoor() {
|
||||
#ifdef RELAY1
|
||||
#ifdef RELAY1_REVERSED
|
||||
controlRelay(RELAY1_PIN,false);
|
||||
#else
|
||||
controlRelay(RELAY1_PIN,true);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.println("door locked");
|
||||
#endif
|
||||
|
||||
#ifdef LEDCTL_PIN
|
||||
digitalWrite(LEDCTL_PIN,HIGH);
|
||||
#endif
|
||||
|
||||
#ifdef WEB_SERIAL_DEBUG
|
||||
WebSerial.println("door locked");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void toggleDoor() {
|
||||
#ifdef RELAY1
|
||||
int relayState = digitalRead(RELAY1_PIN);
|
||||
// Toggle the relay based on the current state
|
||||
#ifdef RELAY1_REVERSED
|
||||
if (relayState == HIGH) {
|
||||
lockDoor();
|
||||
} else {
|
||||
unlockDoor(false);
|
||||
}
|
||||
#else
|
||||
if (relayState == LOW) {
|
||||
lockDoor();
|
||||
} else {
|
||||
unlockDoor(false);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
String stateDoor() {
|
||||
#ifdef RELAY1
|
||||
int relayState = digitalRead(RELAY1_PIN);
|
||||
// Toggle the relay based on the current state
|
||||
if (relayState == LOW) {
|
||||
return "Unlocked";
|
||||
} else {
|
||||
return "Locked";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
133
src/main.cpp
Normal file
133
src/main.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
#include "main.h"
|
||||
|
||||
volatile uint64_t cardData = 0;
|
||||
volatile bool newDataAvailable = false;
|
||||
unsigned long lastDataTime = 0;
|
||||
const unsigned long displayDelay = 1000; // Delay in milliseconds after which the data is displayed
|
||||
unsigned int bitCount = 0; // Variable to keep track of the bit count
|
||||
unsigned int maxReaderWaitTime = 9000; // Variable to timeout reader after too long of no data.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void handleInterrupt(int bitValue) {
|
||||
static unsigned long lastInterruptTime = 0;
|
||||
unsigned long interruptTime = micros();
|
||||
|
||||
if (interruptTime - lastInterruptTime > 200) {
|
||||
cardData <<= 1;
|
||||
cardData |= bitValue;
|
||||
newDataAvailable = true;
|
||||
bitCount++; // Increment the bit count
|
||||
}
|
||||
|
||||
lastInterruptTime = interruptTime;
|
||||
lastDataTime = millis(); // Update the time of last received data
|
||||
}
|
||||
|
||||
void handleData0Interrupt() {
|
||||
handleInterrupt(0);
|
||||
}
|
||||
|
||||
void handleData1Interrupt() {
|
||||
handleInterrupt(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
|
||||
pinMode(DATA0_PIN, INPUT_PULLUP);
|
||||
pinMode(DATA1_PIN, INPUT_PULLUP);
|
||||
|
||||
#ifdef LEDCTL_PIN
|
||||
pinMode(LEDCTL_PIN, OUTPUT);
|
||||
#endif
|
||||
|
||||
#ifdef RELAY1
|
||||
pinMode(RELAY1_PIN, OUTPUT);
|
||||
#endif
|
||||
|
||||
attachInterrupt(digitalPinToInterrupt(DATA0_PIN), handleData0Interrupt, FALLING);
|
||||
attachInterrupt(digitalPinToInterrupt(DATA1_PIN), handleData1Interrupt, FALLING);
|
||||
|
||||
#ifdef RELAY1
|
||||
#ifdef SERIAL_DEBUG
|
||||
Serial.println("Enabling Relay: Locking Door");
|
||||
#endif
|
||||
lockDoor();
|
||||
#endif
|
||||
|
||||
#ifdef RELAY2
|
||||
pinMode(RELAY2_PIN, OUTPUT);
|
||||
#endif
|
||||
|
||||
#ifdef BUZZER
|
||||
pinMode(ALARM_PIN, OUTPUT);
|
||||
digitalWrite(ALARM_PIN, HIGH); // Do not set to low or it will constantly beep.
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
#ifdef LOCAL_ACL
|
||||
#ifdef SERIAL_ACL
|
||||
checkSerialCommand();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
if (newDataAvailable) {
|
||||
newDataAvailable = false;
|
||||
lastDataTime = millis(); // Reset the time of last received data
|
||||
}
|
||||
|
||||
if (millis() - lastDataTime >= displayDelay && cardData != 0) {
|
||||
|
||||
|
||||
uint64_t facilityID = (cardData >> 17) & 0xFFFF;
|
||||
uint64_t cardID = (cardData >> 1) & 0xFFFF;
|
||||
|
||||
Serial.print("Facility ID (Decimal): ");
|
||||
Serial.println(facilityID);
|
||||
Serial.print("Facility ID (Binary): ");
|
||||
Serial.println(facilityID, BIN);
|
||||
|
||||
Serial.print("Card ID (Decimal): ");
|
||||
Serial.println(cardID);
|
||||
Serial.print("Card ID (Binary): ");
|
||||
Serial.println(cardID, BIN);
|
||||
|
||||
Serial.print("Card Data (Binary): ");
|
||||
Serial.println(cardData, BIN);
|
||||
Serial.print("Total Bits Received: ");
|
||||
Serial.println(bitCount);
|
||||
|
||||
String fullCardID = String(facilityID)+":"+String(cardID);
|
||||
|
||||
Serial.print("Full Card (Tinance2): ");
|
||||
Serial.println(fullCardID);
|
||||
|
||||
|
||||
cardData = 0; // Reset the card data
|
||||
lastDataTime = millis(); // Reset the time of last received data
|
||||
bitCount = 0; // Reset the bit count
|
||||
|
||||
}
|
||||
else if (millis() - lastDataTime >= maxReaderWaitTime) {
|
||||
cardData = 0; // Reset the card data
|
||||
lastDataTime = millis(); // Reset the time of last received data
|
||||
bitCount = 0; // Reset the bit count
|
||||
|
||||
}
|
||||
}
|
30
src/settings.cpp
Normal file
30
src/settings.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "settings.h"
|
||||
|
||||
|
||||
Preferences settings_preferences;
|
||||
|
||||
Settings::Settings() {
|
||||
// Set default value for disableDoor
|
||||
disableDoor = false;
|
||||
}
|
||||
|
||||
void Settings::loadFromEEPROM() {
|
||||
settings_preferences.begin("settings");
|
||||
disableDoor = settings_preferences.getBool("disableDoor", false);
|
||||
settings_preferences.end();
|
||||
}
|
||||
|
||||
void Settings::saveToEEPROM() {
|
||||
settings_preferences.begin("settings");
|
||||
settings_preferences.putBool("disableDoor", disableDoor);
|
||||
settings_preferences.end();
|
||||
}
|
||||
|
||||
void Settings::setDisableDoor(bool value) {
|
||||
disableDoor = value;
|
||||
saveToEEPROM(); // Save the setting immediately to Preferences
|
||||
}
|
||||
|
||||
bool Settings::DoorDisabled() {
|
||||
return disableDoor;
|
||||
}
|
Loading…
Reference in a new issue