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"
0 commit comments