Skip to content

Commit 2f66ccb

Browse files
1.0
1 parent dcb1642 commit 2f66ccb

File tree

9 files changed

+390
-298
lines changed

9 files changed

+390
-298
lines changed

application/src/DeviceManager/DeviceManager.cpp

Lines changed: 141 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,41 @@
11
#include "DeviceManager.hpp"
22
#include "../../../common/Logger.hpp"
3+
#include <thread>
4+
#include <chrono>
35

46
namespace StayPutVR {
57
bool DeviceManager::Initialize() {
6-
// Connect to IPC server
7-
if (!ipc_client_.Connect()) {
8-
if (Logger::IsInitialized()) {
9-
Logger::Error("Failed to connect to driver IPC server");
10-
}
11-
return false;
12-
}
13-
14-
// Set device update callback
8+
// Set device update callback first
159
ipc_client_.SetDeviceUpdateCallback([this](const std::vector<DevicePositionData>& devices) {
1610
this->OnDeviceUpdate(devices);
1711
});
1812

19-
return true;
13+
// Try initial connection
14+
if (ipc_client_.Connect()) {
15+
if (Logger::IsInitialized()) {
16+
Logger::Info("DeviceManager: Successfully connected to driver IPC server");
17+
}
18+
return true;
19+
}
20+
21+
// If initial connection fails, start auto-reconnection if enabled
22+
if (auto_reconnect_enabled_) {
23+
if (Logger::IsInitialized()) {
24+
Logger::Warning("DeviceManager: Initial connection failed, starting auto-reconnection");
25+
}
26+
StartReconnectThread();
27+
// Return true to allow application to continue running
28+
return true;
29+
} else {
30+
if (Logger::IsInitialized()) {
31+
Logger::Error("DeviceManager: Failed to connect to driver IPC server and auto-reconnect is disabled");
32+
}
33+
return false;
34+
}
2035
}
2136

2237
void DeviceManager::Shutdown() {
38+
StopReconnectThread();
2339
ipc_client_.Disconnect();
2440
}
2541

@@ -30,6 +46,14 @@ namespace StayPutVR {
3046
void DeviceManager::Update() {
3147
// Process IPC messages
3248
ipc_client_.ProcessMessages();
49+
50+
// Check for connection loss and start reconnection if needed
51+
if (auto_reconnect_enabled_ && !ipc_client_.IsConnected() && !reconnect_thread_running_) {
52+
if (Logger::IsInitialized()) {
53+
Logger::Warning("DeviceManager: Connection lost, starting auto-reconnection");
54+
}
55+
StartReconnectThread();
56+
}
3357
}
3458

3559
const std::vector<DevicePositionData>& DeviceManager::GetDevices() const {
@@ -52,4 +76,111 @@ namespace StayPutVR {
5276
device_map_[devices_[i].serial] = i;
5377
}
5478
}
79+
80+
void DeviceManager::StartReconnectThread() {
81+
if (reconnect_thread_running_) {
82+
return; // Already running
83+
}
84+
85+
// Ensure any previous thread is fully cleaned up
86+
if (reconnect_thread_.joinable()) {
87+
reconnect_thread_.join();
88+
}
89+
90+
reconnect_thread_running_ = true;
91+
last_reconnect_attempt_ = std::chrono::steady_clock::now();
92+
reconnect_thread_ = std::thread(&DeviceManager::ReconnectThreadFunction, this);
93+
94+
if (Logger::IsInitialized()) {
95+
Logger::Info("DeviceManager: Auto-reconnection thread started");
96+
}
97+
}
98+
99+
void DeviceManager::StopReconnectThread() {
100+
if (!reconnect_thread_running_) {
101+
return; // Not running
102+
}
103+
104+
reconnect_thread_running_ = false;
105+
106+
if (reconnect_thread_.joinable()) {
107+
reconnect_thread_.join();
108+
}
109+
110+
if (Logger::IsInitialized()) {
111+
Logger::Info("DeviceManager: Auto-reconnection thread stopped");
112+
}
113+
}
114+
115+
void DeviceManager::ReconnectThreadFunction() {
116+
if (Logger::IsInitialized()) {
117+
Logger::Info("DeviceManager: Reconnection thread started");
118+
}
119+
120+
// Wait initial delay before first reconnection attempt
121+
std::this_thread::sleep_for(INITIAL_RECONNECT_DELAY);
122+
123+
while (reconnect_thread_running_ && auto_reconnect_enabled_) {
124+
if (!ipc_client_.IsConnected()) {
125+
auto now = std::chrono::steady_clock::now();
126+
if (now - last_reconnect_attempt_ >= RECONNECT_INTERVAL) {
127+
if (TryReconnect()) {
128+
if (Logger::IsInitialized()) {
129+
Logger::Info("DeviceManager: Successfully reconnected to driver");
130+
}
131+
break; // Exit thread on successful connection
132+
}
133+
last_reconnect_attempt_ = now;
134+
}
135+
} else {
136+
// Already connected, exit thread
137+
break;
138+
}
139+
140+
// Sleep briefly before next check
141+
std::this_thread::sleep_for(std::chrono::milliseconds(500));
142+
}
143+
144+
reconnect_thread_running_ = false;
145+
if (Logger::IsInitialized()) {
146+
Logger::Info("DeviceManager: Reconnection thread exiting");
147+
}
148+
}
149+
150+
bool DeviceManager::TryReconnect() {
151+
if (Logger::IsInitialized()) {
152+
Logger::Debug("DeviceManager: Attempting to reconnect to driver...");
153+
}
154+
155+
// Ensure clean state before reconnecting
156+
if (ipc_client_.IsConnected()) {
157+
ipc_client_.Disconnect();
158+
// Brief delay to ensure cleanup completes
159+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
160+
}
161+
162+
return ipc_client_.Connect();
163+
}
164+
165+
bool DeviceManager::ManualReconnect() {
166+
if (Logger::IsInitialized()) {
167+
Logger::Info("DeviceManager: Manual reconnection requested");
168+
}
169+
170+
// Stop auto-reconnection thread to avoid conflicts
171+
StopReconnectThread();
172+
173+
// Try to reconnect
174+
bool success = TryReconnect();
175+
176+
// If manual reconnection fails and auto-reconnect is enabled, restart the thread
177+
if (!success && auto_reconnect_enabled_) {
178+
if (Logger::IsInitialized()) {
179+
Logger::Info("DeviceManager: Manual reconnection failed, restarting auto-reconnection");
180+
}
181+
StartReconnectThread();
182+
}
183+
184+
return success;
185+
}
55186
}

application/src/DeviceManager/DeviceManager.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
#include <string>
33
#include <vector>
44
#include <unordered_map>
5+
#include <thread>
6+
#include <atomic>
7+
#include <chrono>
58
#include "../../../common/DeviceTypes.hpp"
69
#include "../IPC/IPCClient.hpp"
710

@@ -17,11 +20,30 @@ namespace StayPutVR {
1720
const std::vector<DevicePositionData>& GetDevices() const;
1821
bool LockDevice(const std::string& serial, bool lock);
1922

23+
// Auto-reconnection control
24+
void SetAutoReconnect(bool enabled) { auto_reconnect_enabled_ = enabled; }
25+
bool IsAutoReconnectEnabled() const { return auto_reconnect_enabled_; }
26+
27+
// Manual reconnection (thread-safe, stops auto-reconnection temporarily)
28+
bool ManualReconnect();
29+
2030
private:
2131
IPCClient ipc_client_;
2232
std::vector<DevicePositionData> devices_;
2333
std::unordered_map<std::string, size_t> device_map_; // serial to index
2434

35+
// Auto-reconnection
36+
std::atomic<bool> auto_reconnect_enabled_ = true;
37+
std::atomic<bool> reconnect_thread_running_ = false;
38+
std::thread reconnect_thread_;
39+
std::chrono::steady_clock::time_point last_reconnect_attempt_;
40+
static constexpr std::chrono::seconds RECONNECT_INTERVAL{5};
41+
static constexpr std::chrono::seconds INITIAL_RECONNECT_DELAY{2};
42+
2543
void OnDeviceUpdate(const std::vector<DevicePositionData>& devices);
44+
void ReconnectThreadFunction();
45+
void StartReconnectThread();
46+
void StopReconnectThread();
47+
bool TryReconnect();
2648
};
2749
}

application/src/IPC/IPCClient.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,27 @@ namespace StayPutVR {
1616
}
1717

1818
bool IPCClient::Connect() {
19+
std::lock_guard<std::mutex> lock(mutex_);
20+
1921
Logger::Info("IPCClient: Connecting to pipe");
2022

2123
if (connected_) {
2224
Logger::Warning("IPCClient: Already connected");
2325
return true;
2426
}
2527

28+
// Ensure we're in a clean state before connecting
29+
if (pipe_handle_ != INVALID_HANDLE_VALUE) {
30+
CloseHandle(pipe_handle_);
31+
pipe_handle_ = INVALID_HANDLE_VALUE;
32+
}
33+
34+
// Ensure reader thread is stopped
35+
if (reader_thread_.joinable()) {
36+
running_ = false;
37+
reader_thread_.join();
38+
}
39+
2640
// Try to connect to the named pipe
2741
HANDLE pipe_handle = CreateFileA(
2842
PIPE_NAME, // Pipe name
@@ -87,6 +101,8 @@ namespace StayPutVR {
87101
}
88102

89103
void IPCClient::Disconnect() {
104+
std::lock_guard<std::mutex> lock(mutex_);
105+
90106
Logger::Info("IPCClient: Disconnecting");
91107

92108
// Check if we're already disconnected

application/src/ui/UIManager.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,11 +1213,8 @@ namespace StayPutVR {
12131213

12141214
if (ImGui::Button("Retry Connection")) {
12151215
if (device_manager_) {
1216-
// First disconnect if needed
1217-
device_manager_->Shutdown();
1218-
1219-
// Then try to reconnect
1220-
if (device_manager_->Initialize()) {
1216+
// Use the new thread-safe manual reconnection method
1217+
if (device_manager_->ManualReconnect()) {
12211218
if (StayPutVR::Logger::IsInitialized()) {
12221219
StayPutVR::Logger::Info("Successfully reconnected to driver");
12231220
}

common/PiShockManager.hpp

Lines changed: 0 additions & 107 deletions
This file was deleted.

0 commit comments

Comments
 (0)