forked from CPL/Simulator
edit proshivka
This commit is contained in:
156
DroneClientCpp/WsServer.h
Normal file
156
DroneClientCpp/WsServer.h
Normal file
@ -0,0 +1,156 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#using <System.dll>
|
||||
#using <System.Net.Http.dll>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct angles_native { float pitch, roll, yaw; };
|
||||
#pragma pack(pop)
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Collections::Generic;
|
||||
using namespace System::Net;
|
||||
using namespace System::Net::WebSockets;
|
||||
using namespace System::Threading;
|
||||
using namespace System::Text;
|
||||
using namespace DroneClient; // ← поправьте, если у вас другое
|
||||
|
||||
|
||||
|
||||
public ref class WsServer // имя можно оставить тем же
|
||||
{
|
||||
public:
|
||||
WsServer() : _connected(false) {}
|
||||
|
||||
/* ---------- подключение --------------------------------------- */
|
||||
bool Connect(String^ uri)
|
||||
{
|
||||
if (_connected) return true; // уже подключены
|
||||
|
||||
_ws = gcnew ClientWebSocket();
|
||||
_cts = gcnew CancellationTokenSource();
|
||||
|
||||
try
|
||||
{
|
||||
// 1) запускаем асинхронное соединение
|
||||
System::Threading::Tasks::Task^ t =
|
||||
_ws->ConnectAsync(gcnew Uri(uri), _cts->Token);
|
||||
|
||||
// 2) ждём завершения
|
||||
t->Wait(); // здесь AggregateException «обёртывает»
|
||||
// все реальные ошибки
|
||||
_connected = true;
|
||||
}
|
||||
catch (AggregateException^ ag)
|
||||
{
|
||||
// сообщений может быть несколько – выводим главное
|
||||
Exception^ ex = ag->InnerExceptions->Count
|
||||
? ag->InnerExceptions[0] : ag;
|
||||
|
||||
System::String^ msg = ex->Message;
|
||||
|
||||
// типовые причины:
|
||||
// • WebSocketException (ошибка DNS / connection refused / timeout)
|
||||
// • NotSupportedException (Windows 7: платформа без WebSocket‑клиента)
|
||||
// • InvalidOperationException (неверный URI)
|
||||
// → выводим в Debug и просто возвращаем false
|
||||
System::Diagnostics::Debug::WriteLine("Connect error: " + msg);
|
||||
_connected = false;
|
||||
}
|
||||
catch (Exception^ ex) // на всякий случай – «прочие»
|
||||
{
|
||||
System::Diagnostics::Debug::WriteLine("Connect error: " + ex->Message);
|
||||
_connected = false;
|
||||
}
|
||||
return _connected;
|
||||
}
|
||||
|
||||
/* ---------- отключение ---------------------------------------- */
|
||||
void Disconnect()
|
||||
{
|
||||
if (!_connected) return;
|
||||
|
||||
try
|
||||
{
|
||||
_ws->CloseAsync(WebSocketCloseStatus::NormalClosure,
|
||||
"bye", CancellationToken::None)->Wait();
|
||||
}
|
||||
catch (Exception^) { /* игнор */ }
|
||||
|
||||
_ws = nullptr;
|
||||
_cts = nullptr;
|
||||
_connected = false;
|
||||
}
|
||||
|
||||
/* ---------- быстрая отправка строки --------------------------- */
|
||||
bool SendString(String^ msg)
|
||||
{
|
||||
if (!_connected) return false;
|
||||
|
||||
array<Byte>^ bytes = Encoding::UTF8->GetBytes(msg);
|
||||
try
|
||||
{
|
||||
_ws->SendAsync(ArraySegment<Byte>(bytes),
|
||||
WebSocketMessageType::Text,
|
||||
true, CancellationToken::None)->Wait();
|
||||
return true;
|
||||
}
|
||||
catch (Exception^) { return false; }
|
||||
}
|
||||
|
||||
/* ---------- состояние ---------------------------------------- */
|
||||
property bool IsConnected
|
||||
{
|
||||
bool get() { return _connected; }
|
||||
}
|
||||
|
||||
void SendAnglesBinary(float p, float r, float y)
|
||||
{
|
||||
angles_native a = { p, r, y };
|
||||
|
||||
// безопасно копируем struct → byte[]
|
||||
array<System::Byte>^ buf = gcnew array<System::Byte>(sizeof(a));
|
||||
System::Runtime::InteropServices::GCHandle h =
|
||||
System::Runtime::InteropServices::GCHandle::Alloc(buf,
|
||||
System::Runtime::InteropServices::GCHandleType::Pinned);
|
||||
|
||||
memcpy(h.AddrOfPinnedObject().ToPointer(), &a, sizeof(a));
|
||||
h.Free();
|
||||
|
||||
// шлём как Binary
|
||||
_ws->SendAsync(System::ArraySegment<Byte>(buf),
|
||||
System::Net::WebSockets::WebSocketMessageType::Binary,
|
||||
true, System::Threading::CancellationToken::None)->Wait();
|
||||
}
|
||||
|
||||
void TxLoop(System::Object^ param)
|
||||
{
|
||||
Drone^ d = safe_cast<Drone^>(param);
|
||||
// 20 мс = 50 Гц
|
||||
const int PERIOD_MS = 20;
|
||||
|
||||
// примерные значения, чтобы «шевелились»
|
||||
float pitch = 0.0f, roll = 0.0f, yaw = 0.0f;
|
||||
|
||||
while (_runTx && _connected)
|
||||
{
|
||||
float p = System::Threading::Volatile::Read(d->pitch);
|
||||
float r = System::Threading::Volatile::Read(d->roll);
|
||||
float y = System::Threading::Volatile::Read(d->yaw);
|
||||
|
||||
SendAnglesBinary(p,r, y);
|
||||
System::Threading::Thread::Sleep(PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
ClientWebSocket^ _ws;
|
||||
CancellationTokenSource^ _cts;
|
||||
bool _connected;
|
||||
|
||||
public:
|
||||
// --- рядом с тем, где уже лежит wsClient ---
|
||||
System::Threading::Thread^ _txThread = nullptr; // поток передатчик
|
||||
bool _runTx = false; // признак «живого» цикла
|
||||
};
|
Reference in New Issue
Block a user