ESP32 СКУД через Ethernet

deepcollors

✩✩✩✩✩✩✩
12 Ноя 2024
1
0
Добрый день уважаемые форумчане! пишу здесь так как уже отчаялся совсем..... Может кто сталкивался с похожей задачей, и может подсказать что я не так делаю...
Итак начнем все по порядку:
К идее сделать свой контроллер СКУД я пришел полгода назад, так как то что имеется на рынке или слишком дорогое или не отвечает нужному функционалу.
Рассматривал разные варианты и пришел только к 1 - возьми и сделай сам.
Что имею:
1) Контроллер ESP-WROOM32
2) реле управления замком 1 канальное
3) Считыватель Matrix II wiegand
4) Кнопка выход
5) кнопка reset
6) Ethernet модуль enc28j60
На данный момент реализован функционал:
1) проход по ключу записанному в базе
2) заливание бызы через FTP
3) FTP сервер для обращения к SPIFFS(собственно здесь и хранится вся стартовая конфигурация)
4) кнопка ресет для возвращения стандартных настроек(сеть(ip mask gateway) wifi(ssid и пароль сети по умолчанию для ввода устройства в сеть) время открытия замка, режим accept для сбора базы ключей, перезагрузка контроллера по умолчанию 0)
Что не получается:
Не получается подключить ethernet модуль совместно с реализованными функциями. Это приводит или к работе только ethernet модуля + web server или контроллер начинает уходить в boot loop. Мне нужна помощь знающих людей которые могут посоветовать как обойти данную проблему

Исходный код устройства:
#include <Wiegand.h>
#include <WiFi.h>
#include <SPIFFS.h>
#include <FTPServer.h>
#include <IPAddress.h>
#include <unordered_set>  // Используем unordered_set для быстрого поиска ключей

WIEGAND wg;
const int relayPin = 13;
const char* ip_file = "/ip.cfg";
const char* wifi_file = "/wifi.cfg";
const char* ftp_file = "/ftp.cfg";
const char* keys_file = "/keys.cfg";
const char* lock_time_file = "/lock_time.cfg";
const char* reboot_file = "/reboot.cfg";
const char* accept_file = "/accept.cfg";

FTPServer ftpServer(SPIFFS);

const int resetButtonPin = 15; //Кнопка reset
const int buttonPin = 12;  // Пин для кнопки

std::unordered_set<long> keysSet;  // Используем множество для хранения ключей

int lockTime = 5;  // Время работы реле в секундах

unsigned long lastRebootCheck = 0;
unsigned long rebootStartTime = 0;
bool rebootScheduled = false;
int rebootDelay = 0;

void setup() {
    pinMode(relayPin, OUTPUT);
    digitalWrite(relayPin, HIGH);  // Начальное состояние реле (выключено)

    pinMode(buttonPin, INPUT_PULLUP);  // Настройка кнопки с подтяжкой

    Serial.begin(115200);
    Serial.println("Начинаем настройку...");

    pinMode(resetButtonPin, INPUT_PULLUP);

    if (!SPIFFS.begin(true)) {
        Serial.println("Ошибка инициализации SPIFFS");
        return;
    }
    Serial.println("SPIFFS инициализировано успешно.");

    if (!SPIFFS.exists(wifi_file)) createDefaultWifiConfig();
    if (!SPIFFS.exists(ftp_file)) createDefaultFtpConfig();
    if (!SPIFFS.exists(ip_file)) createDefaultIpConfig();
    if (!SPIFFS.exists(keys_file)) createDefaultKeysConfig();
    if (!SPIFFS.exists(lock_time_file)) createDefaultLockTimeConfig();
    if (!SPIFFS.exists(accept_file)) createDefaultAcceptConfig(); // Создание accept.cfg по умолчанию
    
    // Проверка и инициализация файла reboot.cfg
    if (!SPIFFS.exists(reboot_file)) {
        createDefaultRebootConfig();
    } else {
        File rebootFile = SPIFFS.open(reboot_file, "r");
        if (rebootFile) {
            String rebootStr = rebootFile.readStringUntil('\n');
            rebootStr.trim();  // Обрезаем пробелы
            rebootFile.close();

            if (rebootStr != "0") {
                createDefaultRebootConfig();
            }
        }
    }

    if (digitalRead(resetButtonPin) == LOW) {
        delay(1000);
        if (digitalRead(resetButtonPin) == LOW) {
            resetConfigurations();
            delay(2000);
        }
    }

    readIpConfig();
    readWifiConfig();
    readFtpConfig();
    readKeysConfig();  // Считываем ключи в память
    readLockTimeConfig();

    wg.begin(26, 27);  // Инициализация Wiegand
}

void loop() {
    ftpServer.handleFTP();
    checkReboot();  // Проверяем необходимость перезагрузки
    // Проверка нажатия кнопки для активации реле
    if (digitalRead(buttonPin) == LOW) {
        readLockTimeConfig();  // Чтение времени открытия замка
        Serial.println("Кнопка нажата!");
        activateRelay(lockTime);  // Включаем реле на время, указанное в lock_time.cfg
    }

   if (wg.available()) {
        long cardCode = wg.getCode();
        readLockTimeConfig();
        Serial.print("DECIMAL = ");
        Serial.print(cardCode);
        Serial.print(", Type W");
        Serial.println(wg.getWiegandType());

        if (isKeyMatched(cardCode)) {
            readLockTimeConfig();
            Serial.println("Ключ совпал");
            activateRelay(lockTime);
        } else {
            readLockTimeConfig();
            Serial.println("Ключ не найден в базе");
            checkAndAddUnknownKey(cardCode);  // Проверка accept.cfg и добавление нового ключа
        }
    }
}

void checkAndAddUnknownKey(long cardCode) {
    int acceptValue = readAcceptConfig();
    if (acceptValue == 1) {
        addKeyToKeysFile(cardCode);
        activateRelay(lockTime);
        Serial.println("Новый ключ добавлен в keys.cfg и дверь открыта.");
    } else {
        Serial.println("Добавление новых ключей отключено.");
    }
}

void createDefaultAcceptConfig() {
    Serial.println("Создание файла accept.cfg с настройками по умолчанию...");
    File acceptFile = SPIFFS.open(accept_file, "w");
    if (acceptFile) {
        acceptFile.println("0"); // Значение по умолчанию: 0
        acceptFile.close();
        Serial.println("Файл accept.cfg создан успешно.");
    } else {
        Serial.println("Не удалось создать файл accept.cfg.");
    }
}

int readAcceptConfig() {
    File acceptFile = SPIFFS.open(accept_file, "r");
    if (acceptFile) {
        String acceptStr = acceptFile.readStringUntil('\n');
        acceptFile.close();
        return acceptStr.toInt();
    } else {
        Serial.println("Не удалось открыть файл accept.cfg.");
        return 0; // Если файл не доступен, возвращаем значение 0
    }
}

void addKeyToKeysFile(long cardCode) {
    File keysFile = SPIFFS.open(keys_file, "a");  // Открываем файл для добавления
    if (keysFile) {
        keysFile.println(cardCode);  // Добавляем новый ID карты
        keysFile.close();
        keysSet.insert(cardCode);    // Добавляем ключ в множество для быстрого доступа
        Serial.println("Новый ключ добавлен в keys.cfg: " + String(cardCode));
    } else {
        Serial.println("Не удалось открыть файл keys.cfg для записи.");
    }
}

void checkReboot() {
    unsigned long currentMillis = millis();
    if (currentMillis - lastRebootCheck >= 10000) { // Проверяем каждые 10 секунд
        lastRebootCheck = currentMillis;

        File rebootFile = SPIFFS.open(reboot_file, "r");
        if (rebootFile) {
            String rebootStr = rebootFile.readStringUntil('\n');
            rebootDelay = rebootStr.toInt();
            rebootFile.close();

            Serial.println("Содержимое reboot.cfg: " + rebootStr);
            Serial.println("Запланированная задержка перезагрузки: " + String(rebootDelay));

            if (rebootDelay > 0 && !rebootScheduled) {
                Serial.println("Запланирована перезагрузка через " + String(rebootDelay) + " секунд.");
                rebootStartTime = currentMillis;
                rebootScheduled = true;
            }
        } else {
            Serial.println("Не удалось открыть файл reboot.cfg.");
        }
    }

    if (rebootScheduled && (currentMillis - rebootStartTime >= rebootDelay * 1000)) {
        SPIFFS.remove(reboot_file); // Удаляем файл перезагрузки
        Serial.println("Перезагрузка устройства...");
        ESP.restart();
    }
}

void activateRelay(int duration) {
    digitalWrite(relayPin, LOW);  // Включаем реле
    Serial.println("Relay is ON");
    delay(duration * 1000);        // Задержка по времени
    digitalWrite(relayPin, HIGH); // Выключаем реле
    Serial.println("Relay is OFF");
}

void createDefaultRebootConfig() {
    Serial.println("Создание файла reboot.cfg с настройками по умолчанию...");
    File rebootFile = SPIFFS.open(reboot_file, "w");
    if (rebootFile) {
        rebootFile.println("0"); // Значение по умолчанию
        rebootFile.close();
        Serial.println("Файл reboot.cfg создан успешно.");
    } else {
        Serial.println("Не удалось создать файл reboot.cfg.");
    }
}

bool isKeyMatched(long cardCode) {
    return keysSet.find(cardCode) != keysSet.end();  // Быстрый поиск ключа в множестве
}

void resetConfigurations() {
    SPIFFS.remove(wifi_file);
    SPIFFS.remove(ftp_file);
    SPIFFS.remove(ip_file);
    SPIFFS.remove(lock_time_file);
    createDefaultWifiConfig();
    createDefaultFtpConfig();
    createDefaultIpConfig();
    createDefaultLockTimeConfig();
    Serial.println("Настройки сброшены до заводских.");
}

void createDefaultKeysConfig() {
    Serial.println("Создание файла keys.cfg с настройками по умолчанию...");
    File keysFile = SPIFFS.open(keys_file, "w");
    if (keysFile) {
        keysFile.println("9178396"); // Пример ключа
        keysFile.close();
        Serial.println("Файл keys.cfg создан успешно.");
    } else {
        Serial.println("Не удалось создать файл keys.cfg.");
    }
}

void createDefaultLockTimeConfig() {
    Serial.println("Создание файла lock_time.cfg с настройками по умолчанию...");
    File lockTimeFile = SPIFFS.open(lock_time_file, "w");
    if (lockTimeFile) {
        lockTimeFile.println("5"); // Время открытия замка по умолчанию (в секундах)
        lockTimeFile.close();
        Serial.println("Файл lock_time.cfg создан успешно.");
    } else {
        Serial.println("Не удалось создать файл lock_time.cfg.");
    }
}

void readKeysConfig() {
    File keysFile = SPIFFS.open(keys_file, "r");
    if (keysFile) {
        while (keysFile.available()) {
            long key = keysFile.readStringUntil('\n').toInt();
            keysSet.insert(key);  // Вставляем ключ в множество
        }
        keysFile.close();
        Serial.println("Прочитанные ключи:");
        for (auto key : keysSet) {
            Serial.println(key);  // Печатаем все ключи
        }
    } else {
        Serial.println("Не удалось открыть файл keys.cfg.");
    }
}

void readLockTimeConfig() {
    File lockTimeFile = SPIFFS.open(lock_time_file, "r");
    if (lockTimeFile) {
        String lockTimeStr = lockTimeFile.readStringUntil('\n');
        lockTime = lockTimeStr.toInt();
        lockTimeFile.close();
        Serial.println("Время открытия замка: " + String(lockTime) + " секунд");
    } else {
        Serial.println("Не удалось открыть файл lock_time.cfg.");
    }
}

// Чтение и создание других конфигурационных файлов...

void createDefaultWifiConfig() {
    Serial.println("Создание файла wifi.cfg с настройками по умолчанию...");
    File wifiFile = SPIFFS.open(wifi_file, "w");
    if (wifiFile) {
        wifiFile.println("WIFINETWORK"); // SSID
        wifiFile.println("12345678"); // Пароль
        wifiFile.close();
        Serial.println("Файл wifi.cfg создан успешно.");
    } else {
        Serial.println("Не удалось создать файл wifi.cfg.");
    }
}

void createDefaultFtpConfig() {
    Serial.println("Создание файла ftp.cfg с настройками по умолчанию...");
    File ftpFile = SPIFFS.open(ftp_file, "w");
    if (ftpFile) {
        ftpFile.println("user"); // Имя пользователя
        ftpFile.println("password"); // Пароль
        ftpFile.close();
        Serial.println("Файл ftp.cfg создан успешно.");
    } else {
        Serial.println("Не удалось создать файл ftp.cfg.");
    }
}

void createDefaultIpConfig() {
    Serial.println("Создание файла ip.cfg с настройками по умолчанию...");
    File ipFile = SPIFFS.open(ip_file, "w");
    if (ipFile) {
        ipFile.println("192.168.1.108"); // IP
        ipFile.println("255.255.255.0"); // Маска
        ipFile.println("192.168.1.1"); // Шлюз
        ipFile.close();
        Serial.println("Файл ip.cfg создан успешно.");
    } else {
        Serial.println("Не удалось создать файл ip.cfg.");
    }
}

void readWifiConfig() {
    File wifiFile = SPIFFS.open(wifi_file, "r");
    if (wifiFile) {
        String ssid = wifiFile.readStringUntil('\n');
        String password = wifiFile.readStringUntil('\n');
        wifiFile.close();
        
        ssid.trim();
        password.trim();

        Serial.println("Прочитанные настройки Wi-Fi:");
        Serial.println("SSID: " + ssid);
        Serial.println("Пароль: " + password);

        Serial.println("Подключение к Wi-Fi...");
        WiFi.begin(ssid.c_str(), password.c_str());
        
        unsigned long startAttemptTime = millis();
        while (WiFi.status() != WL_CONNECTED) {
            delay(1000);
            Serial.print("Подключение...");
            if (millis() - startAttemptTime > 15000) {
                Serial.println("Не удалось подключиться к Wi-Fi в течение 15 секунд.");
                return;
            }
        }
        Serial.println("Подключено к Wi-Fi: " + ssid);
    } else {
        Serial.println("Не удалось открыть файл wifi.cfg.");
    }
}

void readFtpConfig() {
    File ftpFile = SPIFFS.open(ftp_file, "r");
    if (ftpFile) {
        String user = ftpFile.readStringUntil('\n');
        String password = ftpFile.readStringUntil('\n');
        ftpFile.close();

        user.trim();
        password.trim();

        Serial.println("Прочитанные настройки FTP:");
        Serial.println("Пользователь: " + user);
        Serial.println("Пароль: " + password);

        ftpServer.begin(user.c_str(), password.c_str());
        Serial.println("FTP-сервер запущен.");
    } else {
        Serial.println("Не удалось открыть файл ftp.cfg.");
    }
}

void readIpConfig() {
    File ipFile = SPIFFS.open(ip_file, "r");
    if (ipFile) {
        String ip = ipFile.readStringUntil('\n');
        String mask = ipFile.readStringUntil('\n');
        String gateway = ipFile.readStringUntil('\n');
        ipFile.close();

        ip.trim();
        mask.trim();
        gateway.trim();

        Serial.println("Прочитанные настройки IP:");
        Serial.println("IP: " + ip);
        Serial.println("Маска: " + mask);
        Serial.println("Шлюз: " + gateway);

        IPAddress localIP, localMask, localGateway;
        if (!localIP.fromString(ip) || !localMask.fromString(mask) || !localGateway.fromString(gateway)) {
            Serial.println("Ошибка: некорректный IP, маска или шлюз в файле конфигурации.");
            return;
        }

        if (!WiFi.config(localIP, localGateway, localMask)) {
            Serial.println("Ошибка установки статического IP.");
        } else {
            Serial.println("Статический IP установлен: " + ip);
        }
    } else {
        Serial.println("Не удалось открыть файл ip.cfg.");
    }
}
Предлагайте идеи для реализации нужного функционала(совет ставить маршрутизатор не подойдёт, так как бывает такое что нет возможности разместить его рядом с контроллером)

Схему подключения прилогаю
 

Вложения