From 6f6ea0e0fd38824646179f9dd4518bd8c7cf1f11 Mon Sep 17 00:00:00 2001 From: jarnokie Date: Wed, 24 Jun 2026 17:08:45 +0300 Subject: [PATCH] added wifi connection and menu showing connection details --- .gitignore | 1 + include/menu.h | 1 + include/screens.h | 2 + include/wifi_connection.h | 34 ++++++++++++ include/wifi_credentials.example.h | 7 +++ src/main.cpp | 16 ++++++ src/menu.cpp | 5 +- src/screens.cpp | 22 ++++++++ src/wifi_connection.cpp | 84 ++++++++++++++++++++++++++++++ 9 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 include/wifi_connection.h create mode 100644 include/wifi_credentials.example.h create mode 100644 src/wifi_connection.cpp diff --git a/.gitignore b/.gitignore index 89cc49c..449d5ed 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch +include/wifi_credentials.h diff --git a/include/menu.h b/include/menu.h index 575c334..a6641e2 100644 --- a/include/menu.h +++ b/include/menu.h @@ -6,6 +6,7 @@ enum class MenuAction { + ShowInternetDetails, ShowHelloWorld, BackToCarousel }; diff --git a/include/screens.h b/include/screens.h index 4d4ee0f..05f6907 100644 --- a/include/screens.h +++ b/include/screens.h @@ -4,9 +4,11 @@ #include #include "am2302_sensor.h" +#include "wifi_connection.h" void drawScreen1(U8G2 &u8g2); void drawHelloWorldScreen(U8G2 &u8g2); +void drawInternetConnectionScreen(U8G2 &u8g2, WifiConnectionInfo wifiInfo); void setEnvironmentReading(Am2302Reading reading); void drawEnvironmentScreen(U8G2 &u8g2); void drawWeatherIconScreen(U8G2 &u8g2); diff --git a/include/wifi_connection.h b/include/wifi_connection.h new file mode 100644 index 0000000..157ab92 --- /dev/null +++ b/include/wifi_connection.h @@ -0,0 +1,34 @@ +#ifndef WIFI_CONNECTION_H +#define WIFI_CONNECTION_H + +#include +#include + +struct WifiConnectionInfo +{ + bool shieldAvailable; + bool connected; + IPAddress ipAddress; +}; + +class WifiConnection +{ +public: + WifiConnection(); + void begin(unsigned long now); + void update(unsigned long now); + WifiConnectionInfo info() const; + bool consumeDirty(); + +private: + void connect(unsigned long now); + void recordStatus(); + + unsigned long nextAttempt_; + bool shieldAvailable_; + bool connected_; + IPAddress ipAddress_; + bool dirty_; +}; + +#endif diff --git a/include/wifi_credentials.example.h b/include/wifi_credentials.example.h new file mode 100644 index 0000000..c2b1a7f --- /dev/null +++ b/include/wifi_credentials.example.h @@ -0,0 +1,7 @@ +#ifndef WIFI_CREDENTIALS_H +#define WIFI_CREDENTIALS_H + +const char WIFI_SSID[] = "your-wifi-name"; +const char WIFI_PASSWORD[] = "your-wifi-password"; + +#endif diff --git a/src/main.cpp b/src/main.cpp index 5ac3def..3d32040 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "carousel.h" #include "menu.h" #include "screens.h" +#include "wifi_connection.h" U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, U8X8_PIN_NONE); @@ -14,11 +15,13 @@ int lastButtonSelectState = LOW; uint8_t buttonNext = A4; uint8_t buttonSelect = A5; Am2302Sensor am2302(A3); +WifiConnection wifiConnection; enum class AppMode { Carousel, Menu, + InternetDetails, HelloWorld }; @@ -36,6 +39,7 @@ void setup() { pinMode(buttonNext, INPUT); pinMode(buttonSelect, INPUT); am2302.begin(); + wifiConnection.begin(millis()); u8g2.begin(); u8g2.clearBuffer(); @@ -52,6 +56,9 @@ void openMenu() void selectMenuOption() { switch (menu.select()) { + case MenuAction::ShowInternetDetails: + appMode = AppMode::InternetDetails; + break; case MenuAction::ShowHelloWorld: appMode = AppMode::HelloWorld; break; @@ -73,6 +80,7 @@ void handleNextButton() case AppMode::Menu: menu.nextOption(); break; + case AppMode::InternetDetails: case AppMode::HelloWorld: break; } @@ -82,6 +90,7 @@ void handleSelectButton() { switch (appMode) { case AppMode::Carousel: + case AppMode::InternetDetails: case AppMode::HelloWorld: openMenu(); break; @@ -103,6 +112,8 @@ bool displayNeedsRedraw() return carousel.consumeDirty(); case AppMode::Menu: return menu.consumeDirty(); + case AppMode::InternetDetails: + return wifiConnection.consumeDirty(); case AppMode::HelloWorld: return false; } @@ -119,6 +130,9 @@ void drawActiveView() case AppMode::Menu: menu.draw(u8g2); break; + case AppMode::InternetDetails: + drawInternetConnectionScreen(u8g2, wifiConnection.info()); + break; case AppMode::HelloWorld: drawHelloWorldScreen(u8g2); break; @@ -127,6 +141,8 @@ void drawActiveView() void loop(){ const unsigned long now = millis(); + wifiConnection.update(now); + if (appMode == AppMode::Carousel) { carousel.update(now); } diff --git a/src/menu.cpp b/src/menu.cpp index 8ab1bfe..904d789 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -3,6 +3,7 @@ namespace { const char *menuOptions[] = { + "Internet", "Hello world", "Back" }; @@ -13,6 +14,8 @@ MenuAction actionForIndex(size_t index) { switch (index) { case 0: + return MenuAction::ShowInternetDetails; + case 1: return MenuAction::ShowHelloWorld; default: return MenuAction::BackToCarousel; @@ -30,7 +33,7 @@ void Menu::draw(U8G2 &u8g2) u8g2.drawStr(0, 12, "Menu"); for (size_t i = 0; i < menuOptionCount; i++) { - const uint8_t y = 32 + (i * 18); + const uint8_t y = 28 + (i * 14); if (i == selectedIndex_) { u8g2.drawStr(0, y, ">"); } diff --git a/src/screens.cpp b/src/screens.cpp index 0d565fc..5957c13 100644 --- a/src/screens.cpp +++ b/src/screens.cpp @@ -40,6 +40,28 @@ void drawHelloWorldScreen(U8G2 &u8g2) u8g2.drawStr(0, 54, "world"); } +void drawInternetConnectionScreen(U8G2 &u8g2, WifiConnectionInfo wifiInfo) +{ + u8g2.setFont(u8g2_font_6x12_tr); + u8g2.drawStr(0, 12, "Internet"); + + if (!wifiInfo.shieldAvailable) { + u8g2.drawStr(0, 34, "WiFi shield missing"); + return; + } + + if (!wifiInfo.connected) { + u8g2.setFont(u8g2_font_ncenB14_tr); + u8g2.drawStr(0, 42, "Disconnected"); + return; + } + + u8g2.drawStr(0, 32, "Connected"); + u8g2.drawStr(0, 48, "IP address:"); + u8g2.setCursor(0, 64); + u8g2.print(wifiInfo.ipAddress); +} + void setEnvironmentReading(Am2302Reading reading) { environmentReading = reading; diff --git a/src/wifi_connection.cpp b/src/wifi_connection.cpp new file mode 100644 index 0000000..4d75751 --- /dev/null +++ b/src/wifi_connection.cpp @@ -0,0 +1,84 @@ +#include "wifi_connection.h" + +#include + +#include "wifi_credentials.h" + +namespace +{ +const unsigned long reconnectInterval = 30000; +} + +WifiConnection::WifiConnection() + : nextAttempt_(0), + shieldAvailable_(true), + connected_(false), + ipAddress_(0, 0, 0, 0), + dirty_(true) {} + +void WifiConnection::begin(unsigned long now) +{ + shieldAvailable_ = WiFi.status() != WL_NO_SHIELD; + connect(now); + recordStatus(); +} + +void WifiConnection::update(unsigned long now) +{ + if (!shieldAvailable_) { + return; + } + + if (WiFi.status() == WL_CONNECTED) { + recordStatus(); + return; + } + + if (now >= nextAttempt_) { + connect(now); + } + + recordStatus(); +} + +WifiConnectionInfo WifiConnection::info() const +{ + WifiConnectionInfo current = { + shieldAvailable_, + connected_, + ipAddress_ + }; + return current; +} + +bool WifiConnection::consumeDirty() +{ + const bool d = dirty_; + dirty_ = false; + return d; +} + +void WifiConnection::connect(unsigned long now) +{ + if (!shieldAvailable_) { + return; + } + + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + nextAttempt_ = now + reconnectInterval; +} + +void WifiConnection::recordStatus() +{ + const bool currentConnected = WiFi.status() == WL_CONNECTED; + IPAddress currentIpAddress(0, 0, 0, 0); + if (currentConnected) { + currentIpAddress = WiFi.localIP(); + } + + if (connected_ != currentConnected || ipAddress_ != currentIpAddress) { + connected_ = currentConnected; + ipAddress_ = currentIpAddress; + dirty_ = true; + } +}