Skip to content

Commit 21f73dc

Browse files
committed
add wifi rssi facts
1 parent f95dcf8 commit 21f73dc

File tree

7 files changed

+241
-1
lines changed

7 files changed

+241
-1
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ set(SOURCE_FILES
140140
src/main.h
141141
src/wfbcli.hpp
142142
src/wfbcli.cpp
143+
src/WiFiRSSIMonitor.hpp
144+
src/WiFiRSSIMonitor.cpp
143145
src/scheduling_helper.hpp
144146
src/gstrtpreceiver.cpp
145147
src/gstrtpreceiver.h)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ lot of facts to which widgets can subscribe to:
158158
| `video.decoder_feed_time_ms` | uint | Time to feed the video packet to hardware decoder |
159159
| `gstreamer.received_bytes` | uint | Number of bytes received from gstreamer (published for each packet) |
160160
| `osd.custom_message` | str | The custom message passed via `--osd-custom-message` feature |
161+
| `os_mon.wifi.rssi` | uint | rssi as reported from /proc/net/rtl88x2eu/<interface>/trx_info_debug |
161162

162163
There are many facts based on Mavlink telemetry, see `mavlink.c`. All of them have tags "sysid" and
163164
"compid", but some have extra tags.

src/WiFiRSSIMonitor.cpp

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#include "WiFiRSSIMonitor.hpp"
2+
#include <iostream>
3+
#include <fstream>
4+
#include <string>
5+
#include <vector>
6+
#include <unordered_map>
7+
#include <regex>
8+
#include <filesystem>
9+
#include "spdlog/spdlog.h"
10+
11+
extern "C" {
12+
#include "osd.h"
13+
}
14+
15+
namespace fs = std::filesystem;
16+
17+
// Constructor implementation
18+
WiFiRSSIMonitor::WiFiRSSIMonitor() : base_path_("/proc/net/rtl88x2eu") {}
19+
20+
// WiFiStats constructor implementation
21+
WiFiRSSIMonitor::WiFiStats::WiFiStats() : rssi_a(0), rssi_b(0), rssi_min(0), rssi_percent(0), is_linked(false) {}
22+
23+
void WiFiRSSIMonitor::run() {
24+
25+
if (!fs::exists(base_path_)) {
26+
spdlog::error("RTL88x2eu proc path not found: {}", base_path_);
27+
return;
28+
}
29+
30+
// Initialize batch - estimate 5 facts per interface
31+
void* batch = osd_batch_init(20);
32+
33+
// Find all WiFi interfaces and collect their stats
34+
for (const auto& entry : fs::directory_iterator(base_path_)) {
35+
if (!entry.is_directory()) continue;
36+
37+
std::string interface_name = entry.path().filename();
38+
std::string debug_file = entry.path() / "trx_info_debug";
39+
40+
if (fs::exists(debug_file)) {
41+
WiFiStats stats = parse_interface_stats(debug_file);
42+
add_interface_stats_to_batch(batch, interface_name, stats);
43+
}
44+
}
45+
46+
// Publish all collected facts
47+
osd_publish_batch(batch);
48+
}
49+
50+
WiFiRSSIMonitor::WiFiStats WiFiRSSIMonitor::parse_interface_stats(const std::string& file_path) {
51+
52+
WiFiStats stats;
53+
std::ifstream file(file_path);
54+
55+
if (!file.is_open()) {
56+
return stats;
57+
}
58+
59+
std::string line;
60+
while (std::getline(file, line)) {
61+
// Parse RSSI A and B
62+
if (line.find("rssi_a =") != std::string::npos) {
63+
std::regex rssi_ab_regex(R"(rssi_a\s*=\s*(\d+)\(%\),\s*rssi_b\s*=\s*(\d+)\(%\))");
64+
std::smatch match;
65+
if (std::regex_search(line, match, rssi_ab_regex) && match.size() == 3) {
66+
stats.rssi_a = std::stoi(match[1]);
67+
stats.rssi_b = std::stoi(match[2]);
68+
}
69+
}
70+
// Parse RSSI percentage
71+
else if (line.find("rssi :") != std::string::npos) {
72+
std::regex rssi_regex(R"(rssi\s*:\s*(\d+)\s*\(\%\))");
73+
std::smatch match;
74+
if (std::regex_search(line, match, rssi_regex) && match.size() > 1) {
75+
stats.rssi_percent = std::stoi(match[1]);
76+
}
77+
}
78+
else if (line.find("is_linked =") != std::string::npos) {
79+
std::regex linked_regex(R"(is_linked\s*=\s*(\d+))");
80+
std::smatch match;
81+
if (std::regex_search(line, match, linked_regex) && match.size() > 1) {
82+
stats.is_linked = (std::stoi(match[1]) == 1);
83+
}
84+
}
85+
}
86+
87+
file.close();
88+
return stats;
89+
}
90+
91+
void WiFiRSSIMonitor::add_interface_stats_to_batch(void* batch, const std::string& interface_name, const WiFiStats& stats) {
92+
if (!stats.is_linked) {
93+
return; // Don't publish stats for disconnected interfaces
94+
}
95+
96+
// Prepare common tags
97+
osd_tag interface_tag;
98+
strncpy(interface_tag.key, "interface", TAG_MAX_LEN - 1);
99+
strncpy(interface_tag.val, interface_name.c_str(), TAG_MAX_LEN - 1);
100+
interface_tag.key[TAG_MAX_LEN - 1] = '\0';
101+
interface_tag.val[TAG_MAX_LEN - 1] = '\0';
102+
103+
// Publish RSSI A
104+
add_rssi_fact_to_batch(batch, "rssi_a", stats.rssi_a, &interface_tag);
105+
106+
// Publish RSSI B
107+
add_rssi_fact_to_batch(batch, "rssi_b", stats.rssi_b, &interface_tag);
108+
109+
// Publish RSSI Overall Percentage
110+
add_rssi_fact_to_batch(batch, "rssi_percent", stats.rssi_percent, &interface_tag);
111+
112+
// Publish connection status
113+
add_rssi_fact_to_batch(batch, "connected", 1, &interface_tag);
114+
}
115+
116+
void WiFiRSSIMonitor::add_rssi_fact_to_batch(void* batch, const std::string& rssi_type, int value, osd_tag* interface_tag) {
117+
osd_tag tags[2];
118+
119+
// Copy interface tag
120+
memcpy(&tags[0], interface_tag, sizeof(osd_tag));
121+
122+
// Add type tag
123+
strncpy(tags[1].key, "type", TAG_MAX_LEN - 1);
124+
strncpy(tags[1].val, rssi_type.c_str(), TAG_MAX_LEN - 1);
125+
tags[1].key[TAG_MAX_LEN - 1] = '\0';
126+
tags[1].val[TAG_MAX_LEN - 1] = '\0';
127+
128+
// Add fact to batch
129+
std::string fact_name = "os_mon.wifi.rssi";
130+
osd_add_int_fact(batch, fact_name.c_str(), tags, 2, value);
131+
}
132+
133+
void WiFiRSSIMonitor::publish_reset() {
134+
if (!fs::exists(base_path_)) {
135+
spdlog::warn("RTL88x2eu proc path not found for reset: {}", base_path_);
136+
return;
137+
}
138+
139+
// Initialize batch - estimate 5 facts per interface
140+
void* batch = osd_batch_init(20);
141+
142+
// Find all WiFi interfaces and publish reset values
143+
for (const auto& entry : fs::directory_iterator(base_path_)) {
144+
if (!entry.is_directory()) continue;
145+
146+
std::string interface_name = entry.path().filename();
147+
publish_interface_reset(batch, interface_name);
148+
}
149+
150+
// Publish all reset facts
151+
osd_publish_batch(batch);
152+
153+
spdlog::debug("Published WiFi RSSI reset values for all interfaces");
154+
}
155+
156+
void WiFiRSSIMonitor::publish_interface_reset(void* batch, const std::string& interface_name) {
157+
// Prepare common tags
158+
osd_tag interface_tag;
159+
strncpy(interface_tag.key, "interface", TAG_MAX_LEN - 1);
160+
strncpy(interface_tag.val, interface_name.c_str(), TAG_MAX_LEN - 1);
161+
interface_tag.key[TAG_MAX_LEN - 1] = '\0';
162+
interface_tag.val[TAG_MAX_LEN - 1] = '\0';
163+
164+
// Publish all RSSI values as -1 (reset/error value)
165+
add_rssi_fact_to_batch(batch, "rssi_a", -1, &interface_tag);
166+
add_rssi_fact_to_batch(batch, "rssi_b", -1, &interface_tag);
167+
add_rssi_fact_to_batch(batch, "rssi_min", -1, &interface_tag);
168+
add_rssi_fact_to_batch(batch, "rssi_percent", -1, &interface_tag);
169+
add_rssi_fact_to_batch(batch, "connected", 0, &interface_tag); // 0 = disconnected
170+
}
171+
172+
// C-callable function implementations
173+
extern "C" {
174+
175+
void wifi_rssi_monitor_reset(void) {
176+
static WiFiRSSIMonitor monitor;
177+
monitor.publish_reset();
178+
}
179+
180+
} // extern "C"

src/WiFiRSSIMonitor.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
// C-callable functions
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
void wifi_rssi_monitor_reset(void);
9+
10+
#ifdef __cplusplus
11+
}
12+
#endif

src/WiFiRSSIMonitor.hpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef WIFI_RSSI_MONITOR_H
2+
#define WIFI_RSSI_MONITOR_H
3+
4+
#include <string>
5+
6+
extern "C" {
7+
#include "osd.h"
8+
}
9+
10+
class WiFiRSSIMonitor {
11+
public:
12+
WiFiRSSIMonitor();
13+
void run();
14+
void publish_reset();
15+
16+
private:
17+
struct WiFiStats {
18+
int rssi_a;
19+
int rssi_b;
20+
int rssi_min;
21+
int rssi_percent;
22+
bool is_linked;
23+
24+
WiFiStats();
25+
};
26+
27+
std::string base_path_;
28+
29+
WiFiStats parse_interface_stats(const std::string& file_path);
30+
void add_interface_stats_to_batch(void* batch, const std::string& interface_name, const WiFiStats& stats);
31+
void add_rssi_fact_to_batch(void* batch, const std::string& rssi_type, int value, osd_tag* interface_tag);
32+
void publish_interface_reset(void* batch, const std::string& interface_name);
33+
34+
};
35+
36+
#endif

src/gsmenu/helper.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "styles.h"
99
#include "ui.h"
1010
#include "executor.h"
11+
#include "../WiFiRSSIMonitor.h"
1112

1213
extern enum RXMode RXMODE;
1314

@@ -932,6 +933,7 @@ void gsmenu_toggle_rxmode() {
932933
lv_obj_add_flag(air_aalink_cont, LV_OBJ_FLAG_HIDDEN);
933934
setenv("REMOTE_IP" , "10.5.0.10", 1);
934935
setenv("AIR_FIRMWARE_TYPE" , "wfb", 1);
936+
wifi_rssi_monitor_reset();
935937
break;
936938

937939
default:

src/main.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ extern "C" {
5454
#include "time_util.h"
5555
#include "pixelpilot_config.h"
5656
#include <iostream>
57-
57+
#include "WiFiRSSIMonitor.hpp"
58+
#include "gsmenu/gs_system.h"
5859

5960
#define READ_BUF_SIZE (1024*1024) // SZ_1M https://github.com/rockchip-linux/mpp/blob/ed377c99a733e2cdbcc457a6aa3f0fcd438a9dff/osal/inc/mpp_common.h#L179
6061
#define MAX_FRAMES 24 // min 16 and 20+ recommended (mpp/readme.txt)
@@ -106,6 +107,9 @@ Dvr *dvr = NULL;
106107
uint32_t video_plane_id_override = 0;
107108
uint32_t osd_plane_id_override = 0;
108109

110+
WiFiRSSIMonitor wifi_monitor;
111+
extern enum RXMode RXMODE;
112+
109113
void init_buffer(MppFrame frame) {
110114
output_list->video_frm_width = mpp_frame_get_width(frame);
111115
output_list->video_frm_height = mpp_frame_get_height(frame);
@@ -536,6 +540,9 @@ void main_loop() {
536540
while (!signal_flag) {
537541
// TODO: put gsmenu main loop here
538542
msg_manager.check_message();
543+
if (RXMODE == APFPV) {
544+
wifi_monitor.run();
545+
}
539546
sleep(1);
540547
}
541548
return;

0 commit comments

Comments
 (0)