-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDoorLockCode.ino
More file actions
320 lines (291 loc) · 7.79 KB
/
DoorLockCode.ino
File metadata and controls
320 lines (291 loc) · 7.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#if defined ARDUINO_ARCH_ESP32
//green
#define W0 27
//white
#define W1 14
#define DoorP 25
#define DoorE 26
#define button 32
#define loadcard 0
#else
//green
#define W0 2
//white
#define W1 3
#define DoorP 7
#define DoorE 4
#define button 8
#define loadcard 6
#endif
#include <Arduino.h>
//#include "codes.h" // also where #define sitecode is
//#define NUM_STATIC_CARDS (sizeof(cards) / sizeof(unsigned long int))
#include <ArduinoJson.h>
#include <SD.h>
#include <SPI.h>
#if defined ARDUINO_ARCH_ESP32
#include <FS.h>
#endif
// Configuration that we'll store on disk
#define sitecode 17
char bits[80];
int bitcnt = 0;
unsigned long long bitw = 0;
unsigned int timeout = 1000;
boolean valid = true;
int parity(unsigned long int x);
const char *filename = "/db.json"; // <- SD library uses 8.3 filenames
const size_t CAPACITY = JSON_ARRAY_SIZE(300);
// allocate the memory for the document
StaticJsonDocument<CAPACITY> doc_read;
StaticJsonDocument<CAPACITY> doc_write;
JsonArray array_read = doc_read.to<JsonArray>();
JsonArray array_write = doc_write.to<JsonArray>();
//portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
// Wiegand 0 bit ISR. Triggered by wiegand 0 wire.
bool loadCardMode = false;
long startLoadCardMode = 0;
#if defined ARDUINO_ARCH_ESP32
void IRAM_ATTR W0ISR() {
#else
void W0ISR() {
#endif
if (digitalRead(W0))
return;
//portEXIT_CRITICAL(&mux);
bitw = (bitw << 1) | 0x0; // shift in a 0 bit.
bitcnt++; // Increment bit count
timeout = millis(); // Reset timeout
//portEXIT_CRITICAL(&mux);
}
// Wiegand 1 bit ISR. Triggered by wiegand 1 wire.
#if defined ARDUINO_ARCH_ESP32
void IRAM_ATTR W1ISR() {
#else
void W1ISR() {
#endif
if (digitalRead(W1))
return;
//portEXIT_CRITICAL(&mux);
bitw = (bitw << 1) | 0x1; // shift in a 1 bit
bitcnt++; // Increment bit count
timeout = millis(); // Reset Timeout
//portEXIT_CRITICAL(&mux);
}
// Prints the content of a file to the Serial
void printFile(const char *filename) {
// Open file for reading
File file = (File) SD.open(filename, FILE_READ);
if (!file) {
Serial.println(F("Failed to read file"));
return;
}
// Extract each characters by one by one
while (file.available()) {
Serial.print((char) file.read());
}
Serial.println();
// Close the file (File's destructor doesn't close the file)
file.close();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
// create an empty array
pinMode(SS, INPUT_PULLUP);
pinMode(SCK, INPUT_PULLUP);
pinMode(MOSI, INPUT_PULLUP);
pinMode(MISO, INPUT_PULLUP);
// Initialize SD library
#if defined ARDUINO_ARCH_ESP32
for (int i=0;i<3&&!SD.begin(SS, SPI);i++) {
#else
for (int i=0;i<2&&!SD.begin(SS );i++) {
#endif
Serial.println(F("Failed to initialize SD library"));
delay(1000);
}
if (!SD.exists(filename)) {
File fileTest = (File) SD.open(filename, FILE_WRITE);
Serial.println(F("Database missing"));
fileTest.close();
//ESP.restart();
}else{
DeserializationError err;
do {
File f_l = (File) SD.open(filename, FILE_READ);
if (f_l) {
Serial.println(
"File " + String(filename) + " timeout: "
);
// // parse a JSON array
err = deserializeJson(doc_read, f_l);
f_l.close();
Serial.println("deserialize result " + String(err.c_str()));
if (err == DeserializationError::Ok) {
Serial.println(F("on boot Print config file..."));
printFile(filename);
Serial.println("Number of cards " + String(array_read.size()));
}
} else {
Serial.println("File open failed!");
}
} while (err != DeserializationError::Ok);
}
// Dump config file
// Serial.println(F("Print config file..."));
// printFile(filename);
pinMode(W0, INPUT_PULLUP);
pinMode(W1, INPUT_PULLUP);
pinMode(button, INPUT_PULLUP);
pinMode(loadcard, INPUT_PULLUP);
pinMode(DoorP, OUTPUT);
pinMode(DoorE, OUTPUT);
digitalWrite(DoorP, LOW);
digitalWrite(DoorE, HIGH);
// Set up edge interrupts on wiegand pins.
// Wiegand is used by many rfid card readers and mag stripe readers.
// It has two wires. a '1' wire and a '0' wire. It will output a short pulse on
// one of these wires to indicate to you that it has read a 1 or a 0 bit.
// you need to count the pulses. It's a lot like rotary phone wheels
// only in binary and with 2 wires.
// make sure W0 ans W1 trigger interrupts on a 1->0 transition.
attachInterrupt(digitalPinToInterrupt(W0), W0ISR, FALLING);
attachInterrupt(digitalPinToInterrupt(W1), W1ISR, FALLING);
for (int i = 0; i < sizeof(bits); i++)
bits[i] = 0;
digitalWrite(DoorP, LOW);
digitalWrite(DoorE, HIGH);
//Keyboard.begin();
}
void open() {
Serial.println("Opening door");
digitalWrite(DoorP, HIGH); // Open door.
delay(1100);
digitalWrite(DoorP, LOW); // close
Serial.println("Locking door");
}
bool haveCard() {
return (((millis() - timeout) > 500) && bitcnt > 30);
}
long int getIDOfCurrentCard() {
unsigned long long bitwtmp = bitw;
int bitcnttmp = bitcnt;
bitcnt = 0;
bitw = 0;
//portEXIT_CRITICAL(&mux);
for (int i = bitcnttmp; i != 0; i--)
Serial.print((unsigned int) (bitwtmp >> (i - 1) & 0x00000001)); // Print the card number in binary
Serial.print(" (");
Serial.print(bitcnttmp);
Serial.println(")");
boolean ep, op;
unsigned int site;
unsigned long int card;
// Pick apart card.
site = (bitwtmp >> 25) & 0x00007f;
card = (bitwtmp >> 1) & 0xffffff;
op = (bitwtmp >> 0) & 0x000001;
ep = (bitwtmp >> 32) & 0x000001;
// Check parity
if (parity(site) != ep)
valid = false;
if (parity(card) == op)
valid = false;
// Print card info
Serial.print("Got " + String());
Serial.print("Site: ");
Serial.println(site);
Serial.print("Card: ");
Serial.println(card);
Serial.print("ep: ");
Serial.print(parity(site));
Serial.println(ep);
Serial.print("op: ");
Serial.print(parity(card));
Serial.println(op);
valid = true;
return card;
}
#if defined ARDUINO_ARCH_ESP32
void IRAM_ATTR loop() {
#else
void loop() {
#endif
if (!digitalRead(button) ) {
open();
return;
}
if (!digitalRead(loadcard) && loadCardMode == false) {
// load card mode
loadCardMode = true;
startLoadCardMode = millis();
Serial.println("Start load card mode");
digitalWrite(DoorE, LOW);
delay(200);
digitalWrite(DoorE, HIGH);
delay(100);
digitalWrite(DoorE, LOW);
delay(200);
digitalWrite(DoorE, HIGH);
delay(100);
}
if (loadCardMode && (((millis() - startLoadCardMode) > 20000)||!digitalRead(loadcard))) {
loadCardMode = false;
Serial.println("End load Card Mode, writing");
// serialize the array and send the result to Serial
File file = (File) SD.open(filename, FILE_WRITE);
serializeJson(doc_read, file);
file.flush();
file.close();
printFile(filename);
digitalWrite(DoorE, LOW);
delay(200);
digitalWrite(DoorE, HIGH);
delay(100);
digitalWrite(DoorE, LOW);
delay(200);
digitalWrite(DoorE, HIGH);
delay(100);
}
if (haveCard()) { // The reader hasn't sent a bit in 2000 units of time. Process card.
int card = getIDOfCurrentCard();
//Keyboard.println(String(card));
for (JsonVariant v : array_read) {
//Serial.println("Checking "+String(cards[i]));
if (v.as<int>() == card) { // Is it in the DB?
Serial.println(
"\t\tMatch! " + String(card) + " to card form list "
+ String(v.as<int>()));
if (!loadCardMode) open();
return;
}
}
if (loadCardMode) {
Serial.println("Adding card! " + String(card));
array_read.add(card);
startLoadCardMode = millis();
} else {
Serial.println("Error! " + String(card));
//digitalWrite(DoorE, HIGH);
digitalWrite(DoorE, LOW);
delay(500);
digitalWrite(DoorE, HIGH);
delay(500);
digitalWrite(DoorE, LOW);
delay(500);
digitalWrite(DoorE, HIGH);
}
} else {
delay(30);
}
}
int parity(unsigned long int x) {
unsigned long int y;
y = x ^ (x >> 1);
y = y ^ (y >> 2);
y = y ^ (y >> 4);
y = y ^ (y >> 8);
y = y ^ (y >> 16);
return y & 1;
}