generated from Projetos/RaspberryPi_app
137 lines
4.4 KiB
C++
137 lines
4.4 KiB
C++
// main.cpp — Info display for SSD1306 128x64 using gfx::LinuxFBDisplay.
|
|
//
|
|
// Build: see CMakeLists.txt
|
|
// Run: ./gfx_info_display # defaults to /dev/fb1
|
|
// ./gfx_info_display /dev/fb0 # override
|
|
|
|
#include "gfx_canvas.h"
|
|
#include "gfx_font_5x7.h"
|
|
#include "linux_fb_display.h"
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <ctime>
|
|
#include <string>
|
|
|
|
#include <ifaddrs.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Configuration
|
|
// ---------------------------------------------------------------------------
|
|
constexpr int16_t SCREEN_W = 128;
|
|
constexpr int16_t SCREEN_H = 64; // 16 yellow on top and 48 blue on bottom
|
|
|
|
constexpr const char* ETH_IFACE = "eth0";
|
|
constexpr const char* WLAN_IFACE = "wlan0";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Network helper
|
|
// ---------------------------------------------------------------------------
|
|
static std::string get_ip(const char* iface_name) {
|
|
struct ifaddrs* ifaddr = nullptr;
|
|
if (getifaddrs(&ifaddr) == -1) return "err";
|
|
|
|
std::string result = "down";
|
|
for (auto* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
|
if (!ifa->ifa_addr) continue;
|
|
if (ifa->ifa_addr->sa_family != AF_INET) continue;
|
|
if (std::strcmp(ifa->ifa_name, iface_name) != 0) continue;
|
|
|
|
char buf[INET_ADDRSTRLEN];
|
|
auto* sa = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
|
|
inet_ntop(AF_INET, &sa->sin_addr, buf, sizeof(buf));
|
|
result = buf;
|
|
break;
|
|
}
|
|
|
|
freeifaddrs(ifaddr);
|
|
return result;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Text centering helper
|
|
// ---------------------------------------------------------------------------
|
|
static void draw_centered(gfx::GfxCanvas& disp, int16_t y, const char* text) {
|
|
int16_t bx, by;
|
|
uint16_t bw, bh;
|
|
disp.getTextBounds(text, 0, 0, bx, by, bw, bh);
|
|
disp.drawString((SCREEN_W - static_cast<int16_t>(bw)) / 2, y, text,
|
|
gfx::colors::white);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Signal handling
|
|
// ---------------------------------------------------------------------------
|
|
static volatile sig_atomic_t g_running = 1;
|
|
|
|
static void signal_handler(int) { g_running = 0; }
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Main
|
|
// ---------------------------------------------------------------------------
|
|
int main(int argc, char* argv[]) {
|
|
const char* fb_device = "/dev/fb1";
|
|
if (argc > 1) fb_device = argv[1];
|
|
|
|
gfx::LinuxFBDisplay display(SCREEN_W, SCREEN_H);
|
|
if (!display.open(fb_device)) return EXIT_FAILURE;
|
|
|
|
display.setFont(gfx::font_5x7);
|
|
display.setTextColor(gfx::colors::white);
|
|
display.setTextWrap(false);
|
|
|
|
signal(SIGINT, signal_handler);
|
|
signal(SIGTERM, signal_handler);
|
|
|
|
char line_buf[64];
|
|
|
|
while (g_running) {
|
|
display.fillScreen(gfx::colors::black);
|
|
|
|
// --- Network info ---
|
|
std::string eth_ip = get_ip(ETH_IFACE);
|
|
std::string wlan_ip = get_ip(WLAN_IFACE);
|
|
|
|
std::snprintf(line_buf, sizeof(line_buf), "ETH: %s", eth_ip.c_str());
|
|
display.setCursor(0, 0);
|
|
display.print(line_buf);
|
|
|
|
std::snprintf(line_buf, sizeof(line_buf), "WLAN: %s", wlan_ip.c_str());
|
|
display.setCursor(0, 8);
|
|
display.print(line_buf);
|
|
|
|
// --- Separator ---
|
|
display.drawHLine(0, 17, SCREEN_W, gfx::colors::white);
|
|
|
|
// --- Date and time ---
|
|
std::time_t now = std::time(nullptr);
|
|
std::tm* tm = std::localtime(&now);
|
|
|
|
std::snprintf(line_buf, sizeof(line_buf), "%04d-%02d-%02d",
|
|
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
|
draw_centered(display, 29, line_buf);
|
|
|
|
std::snprintf(line_buf, sizeof(line_buf), "%02d:%02d:%02d",
|
|
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
|
draw_centered(display, 41, line_buf);
|
|
|
|
display.update();
|
|
|
|
// --- Sleep aligned to next whole second ---
|
|
struct timespec ts{};
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
ts.tv_sec += 1;
|
|
ts.tv_nsec = 0;
|
|
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, nullptr);
|
|
}
|
|
|
|
display.fillScreen(gfx::colors::black);
|
|
std::printf("Exiting.\n");
|
|
return EXIT_SUCCESS;
|
|
}
|