Noah f38e15af2b Cleanup 2
2025-04-29 01:08:14 -04:00

153 lines
3.9 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "LuckyDataTransferSubsystem.h"
#include "JsonUtilities.h"
#include "JsonObjectConverter.h"
#include "WebSocketsModule.h"
#include "Slate/SceneViewport.h"
ULuckyDataTransferSubsystem::ULuckyDataTransferSubsystem()
{
}
void ULuckyDataTransferSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
}
void ULuckyDataTransferSubsystem::Deinitialize()
{
Super::Deinitialize();
if (Socket.IsValid() && Socket->IsConnected())
{
Socket->Close();
}
}
void ULuckyDataTransferSubsystem::Internal_OpenWebsocket(const FString& URL, const FString& Protocol)
{
const FString NewUrl = URL.IsEmpty() ? TEXT("ws://127.0.0.1:3000/ws") : URL;
const FString NewProtocol = Protocol.IsEmpty() ? TEXT("ws") : Protocol;
UE_LOG(LogTemp, Warning, TEXT("Opening WebSocket URL: %s"), *NewUrl);
if (!FModuleManager::Get().IsModuleLoaded("WebSockets"))
{
FModuleManager::Get().LoadModule("WebSockets");
}
Socket = FWebSocketsModule::Get().CreateWebSocket(NewUrl);
Socket->Connect();
//Set up callbacks
Socket->OnConnectionError().AddUObject(this, &ULuckyDataTransferSubsystem::Callback_OnConnectionError);
Socket->OnConnected().AddUObject(this, &ULuckyDataTransferSubsystem::Callback_OnConnected);
Socket->OnMessage().AddUObject(this, &ULuckyDataTransferSubsystem::Callback_OnMessage);
}
//Callbacks
void ULuckyDataTransferSubsystem::Callback_OnConnected()
{
if (OnSocketReady.IsBound())
{
OnSocketReady.Broadcast(true);
UE_LOG(LogTemp, VeryVerbose, TEXT("WebSocket connected successfully"));
}
}
void ULuckyDataTransferSubsystem::Callback_OnConnectionError(const FString& Error)
{
UE_LOG(LogTemp, VeryVerbose, TEXT("Websocket connection error: %s"), *Error)
}
void ULuckyDataTransferSubsystem::Callback_OnMessage(const FString& Message)
{
if (!Message.IsEmpty())
{
CommandReady(InterpretData(Message));
return;
}
UE_LOG(LogTemp, Warning, TEXT("The message received from the websocket is invalid"));
}
void ULuckyDataTransferSubsystem::Internal_OnMessageSent(const FString& Message)
{
}
void ULuckyDataTransferSubsystem::Callback_OnConnectionClosed()
{
}
//Blueprint Exposed Implementation
void ULuckyDataTransferSubsystem::ConnectToWebsocket(const FString& URL, const FString& Protocol)
{
Internal_OpenWebsocket(URL, Protocol);
}
void ULuckyDataTransferSubsystem::SendMessage(const FString& Message)
{
if (Socket.IsValid() && Socket->IsConnected())
{
Socket->Send(Message);
return;
}
UE_LOG(LogTemp, Warning, TEXT("WebSocket outgoing message failed"));
}
FPayload ULuckyDataTransferSubsystem::InterpretData(const FString& Message)
{
FPayload Payload = FPayload();
if (!Message.IsEmpty())
{
TSharedPtr<FJsonObject> JsonObj;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Message);
if (FJsonSerializer::Deserialize(Reader, JsonObj) && JsonObj.IsValid())
{
for (auto& Elem : JsonObj->Values)
{
FCommand Command = FCommand();
Command.Key = FString(Elem.Key);
Command.Value = Elem.Value->AsNumber();
Payload.Commands.Add(Command);
}
}
}
return Payload;
}
void ULuckyDataTransferSubsystem::CommandReady(const FPayload& Payload)
{
if (OnCommandReady.IsBound())
{
OnCommandReady.Broadcast(Payload);
}
}
//Blueprint Callable function - Use CreateJsonPayload_Observation in C++
bool ULuckyDataTransferSubsystem::MakeObservationPayload(const FObservationPayload& Data)
{
return CreateJsonPayload_Observation(Data);
}
bool ULuckyDataTransferSubsystem::CreateJsonPayload_Observation(const FObservationPayload& Data)
{
bool bSuccess = false;
ObservationPayloadString = FString();
if (!Data.ObservationState.IsEmpty())
{
FJsonObjectConverter::UStructToJsonObjectString(Data, ObservationPayloadString);
UE_LOG(LogTemp, Warning, TEXT("Payload observation: %s"), *ObservationPayloadString);
bSuccess = true;
}
return bSuccess;
}