commit f3e1dd6ee8d2c346f17bad670ae0abe32f90e9c1 Author: DashyFox Date: Mon Oct 28 17:55:14 2024 +0300 ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..508d4e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**.vscode \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3be4b5e --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +## Внесение изменений для совместимости + +Для обеспечения совместимости с библиотекой `Ethernet3` потребуется внести изменения в файлы `EthernetClient.h` и `EthernetUdp3.h`. Следуйте инструкциям ниже. + +### Изменение в `EthernetClient.h` + +В файле `EthernetClient.h` замените доступ к переменным с `private` на `protected` для следующих элементов: + +```cpp +class EthernetClient : public Client { + // ... +protected: // <--- замените 'private' на 'protected' + static uint16_t _srcport; + uint8_t _sock; +}; +``` + +### Изменение в `EthernetUdp3.h` + +В файле `EthernetUdp3.h` также замените доступ к переменным с `private` на `protected`: + +```cpp +class EthernetUDP : public UDP { +protected: // <--- замените 'private' на 'protected' + uint8_t _sock; // socket ID for Wiz5100 + // ... +}; +``` + +### Изменение в `EthernetServer.h` + +В файле `EthernetServer.h` также замените доступ к переменным с `private` на `protected`: + +```cpp +class EthernetServer : +public Server { +protected: // <--- замените 'private' на 'protected' + uint16_t _port; + void accept(); +//... +}; +``` + +Эти изменения необходимы для обеспечения доступа к соответствующим членам класса при наследовании. + +## Обратите внимание + +При работе с библиотекой `Ethernet3` версии 3 требуется отдельно указывать CS пин для инициализации. Пример кода: + +```cpp +void setup() { + // ... + Ethernet.setCsPin(W5500_CS_PIN); + Ethernet.init(); + Ethernet.begin(mac, localIP, gateway, gateway, subnet); + // ... +} +``` + +Не забудьте правильно настроить `W5500_CS_PIN` и сетевые параметры (`mac`, `localIP`, `gateway`, `subnet`) в зависимости от вашей конфигурации. +``` \ No newline at end of file diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino new file mode 100644 index 0000000..dab1002 --- /dev/null +++ b/examples/Client/Client.ino @@ -0,0 +1,184 @@ +#include "EthernetMaket.h" // Предполагается, что этот файл подключает Ethernet3.h + +// Настройки для W5500 +#define W5500_CS_PIN PA2 // Пин для CS +#define SOCKET_NUMBER 0 // Используем сокет 0 +#define SERVER_PORT 1337 // Порт на сервере +#define CLIENT_PORT 1337 // Порт клиента + +#define ServerMac {0xDA, 0x7A, 0xFF, 0x00, 0x00, 0x00} +#define ServerIP {192, 168, 254, 254} + +#define IniMac {0xDA, 0x7A, 0xF0, 0x00, 0x00, 0x00} +#define IniIP {192, 168, 254, 253} + +uint8_t gateway[] = {192, 168, 0, 1}; // Шлюз +uint8_t subnet[] = {255, 255, 0, 0}; // Маска подсети + +uint8_t mac[] = IniMac; // MAC-адрес +uint8_t localIP[] = IniIP; // Локальный IP-адрес + +uint8_t serverMac[] = ServerMac; // MAC-адрес сервера +uint8_t serverIP[] = ServerIP; // IP-адрес сервера + +uint8_t buf[512]; // Буфер для передачи данных + +unsigned long previousMillis = 0; // Для хранения времени последней отправки +const long interval = 3750; // Интервал отправки данных (1.75 секунды) +uint32_t ttt; + +EthernetServer server(SERVER_PORT); +EthernetMaketClient client; + +// EthernetMaketClient c; + +uint32_t packetCounter = 0; + +unsigned long lastActivityTime = 0; // Время последней активности +const long timeout = 300; // Таймаут неактивности в миллисекундах + +bool wasConnected = false; +bool dataReady = false; + +void setup() +{ + Serial.begin(115200); + pinMode(LED_BUILTIN, OUTPUT); + Ethernet.setCsPin(W5500_CS_PIN); + Ethernet.init(); + + // Настройка Ethernet с указанием статических параметров + Ethernet.begin(mac, localIP, gateway, gateway, subnet); + + // Ethernet.setRtTimeOut(1000 * 10); + // Ethernet.setRtCount(3); + + // client.setNoDelayedACK(true); // Не ждать ответа от сервера +} + +void loop() +{ + uint32_t currentMillis = millis(); + if (currentMillis - ttt > 75) + { + digitalToggle(PC13); + ttt = currentMillis; // Обновляем время + } + + if (currentMillis - previousMillis >= interval) + { + previousMillis = currentMillis; + + Serial.println("\n\nConnecting..."); + + client.stop(); // Завершаем предыдущее соединение + dataReady = true; + + } + + // Подключаемся к серверу + ConnectionStatusSimple connectStatus; + bool isNonBlocking = true; // Флаг для определения режима подключения + + if (isNonBlocking) + { + connectStatus = client.connectNonBlock(serverIP, SERVER_PORT); + } + else + { + connectStatus = (ConnectionStatusSimple)client.connect(serverIP, SERVER_PORT); + } + + if (connectStatus == CONNECT_SUCCESS) + { + Serial.print("Connection established in "); + Serial.println(isNonBlocking ? "non-blocking mode" : "blocking mode"); + //! Соединение установлено + lastActivityTime = millis(); // Обновляем время последней активности + for (size_t i = 0; i < 3; i++) + { + client.write((uint8_t *)&packetCounter, sizeof(packetCounter)); + + // Печать отправленного пакета + Serial.print("Sending packet: "); + for (size_t j = 0; j < sizeof(packetCounter); j++) + { + Serial.print(((uint8_t *)&packetCounter)[j], HEX); + Serial.print(" "); + } + Serial.println(); + packetCounter++; + lastActivityTime = millis(); // Обновляем время последней активности + } + dataReady = false; + connectStatus = CONNECT_IDLE; + } + else + { + Serial.print("Failed to connect to server in "); + Serial.println(isNonBlocking ? "non-blocking mode" : "blocking mode"); + connectStatus = CONNECT_IDLE; + client.stop(); + } + + // Проверка наличия доступных данных от сервера + if (client.available() > 0) + { + byte response[16]; + int len = client.read(response, sizeof(response)); + + if (len == 16) + { + // Проверка контрольной суммы + uint8_t checksum = 0; + for (int i = 0; i < 15; i++) + { + checksum += response[i]; + } + + Serial.print("RX: "); + for (int i = 0; i < 16; i++) + { + Serial.print(response[i], HEX); + Serial.print(" "); + } + + if (response[15] == checksum) + { + Serial.println("Checksum is OK"); + } + else + { + Serial.println("Checksum is ERROR"); + } + lastActivityTime = millis(); // Обновляем время последней активности + } + else + { + Serial.println("Received an incomplete response"); + } + } + + // Обновление состояния подключения + if (!wasConnected && client.connected()) + { + wasConnected = true; + } + + if (wasConnected && !client.connected()) + { + wasConnected = false; + client.stop(); + Serial.println("Client disconnected"); + } + + // Закрытие соединения по таймеру неактивности + if (client.connected() && (millis() - lastActivityTime > timeout)) + { + wasConnected = false; + Serial.println("Connection closed due to inactivity"); + client.stop(); + } +} + + diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..16ebceb --- /dev/null +++ b/library.properties @@ -0,0 +1,10 @@ +name=MaketEthernet +version=1.0.0 +author=DashyFox +maintainer=DashyFox@yandex.ru +sentence= +paragraph= +category=Other +url= +architectures=* +includes=CEthernetMaket.h diff --git a/src/EthernetMaket.h b/src/EthernetMaket.h new file mode 100644 index 0000000..70a3cc6 --- /dev/null +++ b/src/EthernetMaket.h @@ -0,0 +1,21 @@ +#ifndef __ETHERNETMAKET_H__ +#define __ETHERNETMAKET_H__ + +#include "Ethernet3.h" + + + +enum ConnectionStatusSimple{ + CONNECT_FAIL = 0, + CONNECT_SUCCESS = 1, + CONNECT_CONNECTING = 2, + CONNECT_START = 3, + CONNECT_IDLE = 4 +}; + + + +#include "EthernetOverride/TCP.h" + + +#endif // __ETHERNETMAKET_H__ \ No newline at end of file diff --git a/src/EthernetOverride/Server.cpp b/src/EthernetOverride/Server.cpp new file mode 100644 index 0000000..adf374d --- /dev/null +++ b/src/EthernetOverride/Server.cpp @@ -0,0 +1,64 @@ +#include "Server.h" +#include "utility/w5500.h" +#include "utility/socket.h" + +void EthernetMaketServer::setServerHandler(std::function handler) +{ + serverHandler = handler; +} + +void EthernetMaketServer::resetServerHandler() +{ + serverHandler = [](EthernetMaketClient sclient) {}; +} + +EthernetMaketClient EthernetMaketServer::available(int sock) +{ + accept(sock); + EthernetMaketClient client(sock); + if (EthernetClass::_server_port[sock] == _port && + (client.status() == SnSR::ESTABLISHED || + client.status() == SnSR::CLOSE_WAIT)) + { + if (client.available()) + { + return client; + } + } + return EthernetMaketClient(MAX_SOCK_NUM); +} + +void EthernetMaketServer::accept(int sock) +{ + int listening = 0; + EthernetClient client(sock); + + if (EthernetClass::_server_port[sock] == _port) + { + if (client.status() == SnSR::LISTEN) + { + listening = 1; + } + else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) + { + client.stop(); + } + } + + if (!listening) + { + // begin(); + begin(sock); // added + } +} + +void EthernetMaketServer::begin(int sock) +{ + EthernetClient client(sock); + if (client.status() == SnSR::CLOSED) + { + socket(sock, SnMR::TCP, _port, 0); + listen(sock); + EthernetClass::_server_port[sock] = _port; + } +} \ No newline at end of file diff --git a/src/EthernetOverride/Server.h b/src/EthernetOverride/Server.h new file mode 100644 index 0000000..239d5e0 --- /dev/null +++ b/src/EthernetOverride/Server.h @@ -0,0 +1,24 @@ +#ifndef __MAKET_SERVER_H__ +#define __MAKET_SERVER_H__ + +#include "Ethernet3.h" +#include "TCP.h" +#include + +class EthernetMaketServer : EthernetServer +{ +private: + EthernetClient available(); + void accept(int sock); + std::function serverHandler = [](EthernetMaketClient sclient){}; + +public: + using EthernetServer::EthernetServer; + EthernetMaketClient available(int sock); + + void setServerHandler(std::function handler); + void resetServerHandler(); + void begin(int sock); +}; + +#endif // __MAKET_SERVER_H__ diff --git a/src/EthernetOverride/TCP.cpp b/src/EthernetOverride/TCP.cpp new file mode 100644 index 0000000..3df472f --- /dev/null +++ b/src/EthernetOverride/TCP.cpp @@ -0,0 +1,48 @@ +#include "TCP.h" +#include "utility/w5500.h" +#include "utility/socket.h" + +ConnectionStatusSimple EthernetMaketClient::connectNonBlock(IPAddress ip, uint16_t port) { + + if (_sock != MAX_SOCK_NUM) { + // Serial.println(F("connectNonBlock")); + uint8_t status_ = status(); + switch (status_) { + case SnSR::CLOSED: + // Serial.println(F("CLOSED")); + _sock = MAX_SOCK_NUM; + return CONNECT_FAIL; + break; + case SnSR::ESTABLISHED: + // Serial.println(F("ESTABLISHED")); + return CONNECT_SUCCESS; + break; + default: + // Serial.print(F("status ")); + // Serial.println(status_,HEX); + return CONNECT_CONNECTING; + break; + } + } + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = w5500.readSnSR(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return CONNECT_FAIL; + + _srcport++; + if (_srcport == 0) _srcport = 1024; + socket(_sock, SnMR::TCP, _srcport, 0); + + if (!::connect(_sock, rawIPAddress(ip), port)) { + _sock = MAX_SOCK_NUM; + return CONNECT_FAIL; + } + + return CONNECT_CONNECTING; +} \ No newline at end of file diff --git a/src/EthernetOverride/TCP.h b/src/EthernetOverride/TCP.h new file mode 100644 index 0000000..68eb5c7 --- /dev/null +++ b/src/EthernetOverride/TCP.h @@ -0,0 +1,15 @@ +#ifndef __MAKET_TCP_H__ +#define __MAKET_TCP_H__ + +#include "../EthernetMaket.h" + +class EthernetMaketClient : public EthernetClient +{ +public: + using EthernetClient::EthernetClient; + + ConnectionStatusSimple connectNonBlock(IPAddress ip, uint16_t port); + + +}; +#endif // __MAKET_TCP_H__ \ No newline at end of file diff --git a/src/EthernetOverride/UDP.cpp b/src/EthernetOverride/UDP.cpp new file mode 100644 index 0000000..b934d47 --- /dev/null +++ b/src/EthernetOverride/UDP.cpp @@ -0,0 +1,62 @@ +#include "UDP.h" + +#include "utility/w5500.h" +#include "utility/socket.h" + +void sendUDP_tick(SOCKET s, ConnectionStatusSimple &status) +{ + switch (status) + { + case CONNECT_START: + w5500.execCmdSn(s, Sock_SEND); + status = CONNECT_CONNECTING; + break; + + case CONNECT_CONNECTING: + if ((w5500.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK) + { + if (w5500.readSnIR(s) & SnIR::TIMEOUT) + { + /* +2008.01 [bj]: clear interrupt */ + w5500.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); + status = CONNECT_FAIL; + break; + } + else + { + status = CONNECT_CONNECTING; + break; + } + } + else + { + status = CONNECT_SUCCESS; + w5500.writeSnIR(s, SnIR::SEND_OK); + break; + } + break; + + case CONNECT_FAIL: + status = CONNECT_IDLE; + break; + case CONNECT_SUCCESS: + status = CONNECT_IDLE; + break; + case CONNECT_IDLE: + break; + + default: + break; + } +} + +void EthernetMaketUDP::endPacketNonBlock() +{ + _status = CONNECT_START; + sendUDP_tick(_sock, _status); + return; +} + +void EthernetMaketUDP::tick(){ + sendUDP_tick(_sock, _status); +} diff --git a/src/EthernetOverride/UDP.h b/src/EthernetOverride/UDP.h new file mode 100644 index 0000000..a720f01 --- /dev/null +++ b/src/EthernetOverride/UDP.h @@ -0,0 +1,15 @@ +#ifndef __MAKET_UDP_H__ +#define __MAKET_UDP_H__ + +#include "../EthernetMaket.h" +class EthernetMaketUDP : EthernetUDP +{ +private: + ConnectionStatusSimple _status; // статус соединения +public: + using EthernetUDP::EthernetUDP; + void endPacketNonBlock(); + void tick(); +}; + +#endif // __MAKET_UDP_H__ \ No newline at end of file