Wi-Fi SSID and RSSI

This commit is contained in:
2026-04-09 21:16:01 -03:00
parent 5b20d2089a
commit b5fe066316
2 changed files with 152 additions and 1 deletions

View File

@@ -73,7 +73,13 @@ add_executable(${PROJECT_NAME}
# another_file.cpp
# )
target_link_libraries(${PROJECT_NAME} PRIVATE gfx_linux_fb)
find_package(PkgConfig REQUIRED)
set(ENV{PKG_CONFIG_SYSROOT_DIR} "${CMAKE_SYSROOT}")
set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig")
pkg_check_modules(LIBNL_GENL REQUIRED libnl-genl-3.0)
target_include_directories(${PROJECT_NAME} PRIVATE ${LIBNL_GENL_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE gfx_linux_fb ${LIBNL_GENL_LIBRARIES})
# Install rule (optional)
install(TARGETS ${PROJECT_NAME} DESTINATION bin)

145
main.cpp
View File

@@ -17,9 +17,15 @@
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <signal.h>
#include <unistd.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/nl80211.h>
// ---------------------------------------------------------------------------
// Configuration
// ---------------------------------------------------------------------------
@@ -53,6 +59,132 @@ static std::string get_ip(const char* iface_name) {
return result;
}
// ---------------------------------------------------------------------------
// Wi-Fi helper — SSID and RSSI via nl80211 / libnl-genl
// ---------------------------------------------------------------------------
struct WifiScanResult {
char ssid[33];
uint8_t bssid[6];
bool have_ssid = false;
bool have_bssid = false;
};
struct WifiStationResult {
int rssi = 0;
bool have_rssi = false;
};
static int scan_handler(struct nl_msg* msg, void* arg) {
auto* result = static_cast<WifiScanResult*>(arg);
auto* gnlh = static_cast<genlmsghdr*>(nlmsg_data(nlmsg_hdr(msg)));
struct nlattr* tb[NL80211_ATTR_MAX + 1];
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), nullptr);
if (!tb[NL80211_ATTR_BSS]) return NL_SKIP;
struct nlattr* bss[NL80211_BSS_MAX + 1];
nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], nullptr);
// Only process the BSS we are associated with.
if (!bss[NL80211_BSS_STATUS]) return NL_SKIP;
if (nla_get_u32(bss[NL80211_BSS_STATUS]) != NL80211_BSS_STATUS_ASSOCIATED)
return NL_SKIP;
if (bss[NL80211_BSS_BSSID]) {
std::memcpy(result->bssid, nla_data(bss[NL80211_BSS_BSSID]), 6);
result->have_bssid = true;
}
// Walk Information Elements to find SSID (IE id 0).
if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
const auto* ie = static_cast<const uint8_t*>(
nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
int ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
while (ie_len >= 2) {
if (ie[0] == 0 && ie[1] > 0 && ie[1] <= 32) {
std::memcpy(result->ssid, ie + 2, ie[1]);
result->ssid[ie[1]] = '\0';
result->have_ssid = true;
break;
}
ie_len -= 2 + ie[1];
ie += 2 + ie[1];
}
}
return NL_SKIP;
}
static int station_handler(struct nl_msg* msg, void* arg) {
auto* result = static_cast<WifiStationResult*>(arg);
auto* gnlh = static_cast<genlmsghdr*>(nlmsg_data(nlmsg_hdr(msg)));
struct nlattr* tb[NL80211_ATTR_MAX + 1];
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), nullptr);
if (!tb[NL80211_ATTR_STA_INFO]) return NL_SKIP;
struct nlattr* sta[NL80211_STA_INFO_MAX + 1];
nla_parse_nested(sta, NL80211_STA_INFO_MAX,
tb[NL80211_ATTR_STA_INFO], nullptr);
if (sta[NL80211_STA_INFO_SIGNAL]) {
result->rssi = static_cast<int8_t>(
nla_get_u8(sta[NL80211_STA_INFO_SIGNAL]));
result->have_rssi = true;
}
return NL_SKIP;
}
static bool get_wifi_info(const char* iface, char* ssid_out, int* rssi_out) {
struct nl_sock* sock = nl_socket_alloc();
if (!sock) return false;
if (genl_connect(sock) < 0) { nl_socket_free(sock); return false; }
int nl80211_id = genl_ctrl_resolve(sock, "nl80211");
if (nl80211_id < 0) { nl_socket_free(sock); return false; }
unsigned int if_index = if_nametoindex(iface);
if (!if_index) { nl_socket_free(sock); return false; }
// --- GET_SCAN dump → find associated BSS, extract SSID ---
WifiScanResult scan{};
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, scan_handler, &scan);
struct nl_msg* msg = nlmsg_alloc();
genlmsg_put(msg, 0, 0, nl80211_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);
nl_send_auto(sock, msg);
nlmsg_free(msg);
nl_recvmsgs_default(sock);
if (!scan.have_ssid) { nl_socket_free(sock); return false; }
std::strncpy(ssid_out, scan.ssid, 32);
ssid_out[32] = '\0';
// --- GET_STATION for the AP → extract RSSI ---
WifiStationResult station{};
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, station_handler, &station);
msg = nlmsg_alloc();
genlmsg_put(msg, 0, 0, nl80211_id, 0, 0, NL80211_CMD_GET_STATION, 0);
nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);
nla_put(msg, NL80211_ATTR_MAC, 6, scan.bssid);
nl_send_auto(sock, msg);
nlmsg_free(msg);
nl_recvmsgs_default(sock);
if (station.have_rssi) *rssi_out = station.rssi;
nl_socket_free(sock);
return true;
}
// ---------------------------------------------------------------------------
// Text centering helper
// ---------------------------------------------------------------------------
@@ -124,6 +256,19 @@ int main(int argc, char* argv[]) {
display.setCursor(0, 24);
display.print(line_buf);
// --- Wi-Fi SSID / RSSI ---
char ssid[33] = {};
int rssi = 0;
if (get_wifi_info(WLAN_IFACE, ssid, &rssi)) {
std::snprintf(line_buf, sizeof(line_buf), "SSID: %s", ssid);
display.setCursor(0, 32);
display.print(line_buf);
std::snprintf(line_buf, sizeof(line_buf), "RSSI: %d dBm", rssi);
display.setCursor(0, 40);
display.print(line_buf);
}
display.update();
// --- Sleep aligned to next whole second ---