commit 47711e93b5ae25e78047cf043f01a0858375d003 Author: Jordon Brooks Date: Tue Jun 6 01:53:11 2023 +0100 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b60f01 --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# Ignore all files by default, but scan all directories. +* +!*/ + +# Do not ignore git files in the root of the repo. +!/.git* + +# Do not ignore current project's `.uproject`. +!/*.uproject + +!/*.uplugin + +# Do not ignore source, config and plugins dirs. +!/Source/** +!/Config/** +!/Plugins/** +!/Resources/** + +# Only allow .uasset and .umap files from /Content dir. +# They're tracked by git-lfs, don't forget to track other +# files if adding them here. +!/Content/**/*.uasset +!/Content/**/*.umap + +# Allow any files from /RawContent dir. +# Any file in /RawContent dir will be managed by git lfs. +!/RawContent/**/* + +# OS/platform generated files. + +# Windows +ehthumbs.db +Thumbs.db + +# Mac OS X +.DS_Store +.DS_Store? +.AppleDouble +.LSOverride +._* + +# Linux +*~ +.directory + +# vim +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist + +# Visual Studio +.vs \ No newline at end of file diff --git a/HarmonyLinkUE.uplugin b/HarmonyLinkUE.uplugin new file mode 100644 index 0000000..4c6cce4 --- /dev/null +++ b/HarmonyLinkUE.uplugin @@ -0,0 +1,24 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "HarmonyLinkUE", + "Description": "", + "Category": "Other", + "CreatedBy": "Jordon Brooks", + "CreatedByURL": "https://jordongamedev.co.uk", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": true, + "IsExperimentalVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "HarmonyLinkUE", + "Type": "Runtime", + "LoadingPhase": "PreLoadingScreen" + } + ] +} \ No newline at end of file diff --git a/Resources/Icon128.png b/Resources/Icon128.png new file mode 100644 index 0000000..1231d4a Binary files /dev/null and b/Resources/Icon128.png differ diff --git a/Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs b/Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs new file mode 100644 index 0000000..2c8ad84 --- /dev/null +++ b/Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs @@ -0,0 +1,56 @@ +// Some copyright should be here... + +using UnrealBuildTool; + +public class HarmonyLinkUE : ModuleRules +{ + public HarmonyLinkUE(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "HTTP", + "Json", + "JsonUtilities" + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Source/HarmonyLinkUE/Private/DataRefreshActor.cpp b/Source/HarmonyLinkUE/Private/DataRefreshActor.cpp new file mode 100644 index 0000000..74b8734 --- /dev/null +++ b/Source/HarmonyLinkUE/Private/DataRefreshActor.cpp @@ -0,0 +1,70 @@ +// DataRefreshActor.cpp + +#include "DataRefreshActor.h" +#include "HarmonyLinkUEBPLibrary.h" + +// Sets default values +ADataRefreshActor::ADataRefreshActor() +{ + // Set default refresh interval to 1 second + RefreshInterval = 1.0f; + + // Create a SceneComponent for the actor + USceneComponent* SceneComponent = CreateDefaultSubobject(TEXT("DataRefreshSceneComponent")); + SetRootComponent(SceneComponent); +} + +// Called when the game starts or when spawned +void ADataRefreshActor::BeginPlay() +{ + Super::BeginPlay(); + + // Bind the delegate + ServerStatusCallback.BindUFunction(this, FName("OnServerStatusChecked")); + + // Start the timer for data refreshing + GetWorldTimerManager().SetTimer(RefreshTimerHandle, this, &ADataRefreshActor::RefreshData, RefreshInterval, true); +} + +void ADataRefreshActor::Destroyed() +{ + // Unbind the delegate + ServerStatusCallback.Unbind(); + + // Remember to call the parent class's Destroyed function at the end. + Super::Destroyed(); +} + + +// Called every frame +void ADataRefreshActor::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + // ... +} + +void ADataRefreshActor::OnServerStatusChecked(bool connected) +{ + UE_LOG(LogTemp, Display, TEXT("Refreshing")); + if (connected) + { + // Refresh the data and update the cached information + UHarmonyLinkUEBPLibrary::RefreshAllInfo(FDeviceInfoCallback()); + UHarmonyLinkUEBPLibrary::RefreshVersionInfo(FVersionInfoCallback()); + } +} + +// Function to refresh data +void ADataRefreshActor::RefreshData() +{ + // Only refresh data if the Harmony Link library is available + if (UHarmonyLinkUEBPLibrary::StaticClass()) + { + // Check server status asynchronously + UHarmonyLinkUEBPLibrary::CheckServerStatus(ServerStatusCallback); + } +} + + + diff --git a/Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp b/Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp new file mode 100644 index 0000000..75162f5 --- /dev/null +++ b/Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp @@ -0,0 +1,22 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "HarmonyLinkUE.h" + +#define LOCTEXT_NAMESPACE "FHarmonyLinkUEModule" + +void FHarmonyLinkUEModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + +} + +void FHarmonyLinkUEModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. + +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FHarmonyLinkUEModule, HarmonyLinkUE) \ No newline at end of file diff --git a/Source/HarmonyLinkUE/Private/HarmonyLinkUEBPLibrary.cpp b/Source/HarmonyLinkUE/Private/HarmonyLinkUEBPLibrary.cpp new file mode 100644 index 0000000..d10b10f --- /dev/null +++ b/Source/HarmonyLinkUE/Private/HarmonyLinkUEBPLibrary.cpp @@ -0,0 +1,289 @@ +// .cpp file + +#include "HarmonyLinkUEBPLibrary.h" +#include "Interfaces/IHttpResponse.h" + +FAllInfo UHarmonyLinkUEBPLibrary::CachedAllInfo; +FHarmonyLinkVersionData UHarmonyLinkUEBPLibrary::CachedVersionData; +bool UHarmonyLinkUEBPLibrary::Connected; + +UHarmonyLinkUEBPLibrary::UHarmonyLinkUEBPLibrary(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +void UHarmonyLinkUEBPLibrary::CheckServerStatus(FServerStatusCallback Callback) +{ + TSharedPtr Request = FHttpModule::Get().CreateRequest(); + Request->SetURL(TEXT("http://localhost:9000/are_you_there")); + Request->SetVerb(TEXT("GET")); + + Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkUEBPLibrary::OnCheckServerStatusResponseReceived, Callback); + + Request->ProcessRequest(); +} + +void UHarmonyLinkUEBPLibrary::RefreshOSInfo(FOSInfoCallback Callback) +{ + TSharedPtr Request = FHttpModule::Get().CreateRequest(); + Request->SetURL(TEXT("http://localhost:9000/os_info")); + Request->SetVerb(TEXT("GET")); + + Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkUEBPLibrary::OnOSInfoResponseReceived, Callback); + + Request->ProcessRequest(); +} + +void UHarmonyLinkUEBPLibrary::RefreshBatteryInfo(FBatteryInfoCallback Callback) +{ + TSharedPtr Request = FHttpModule::Get().CreateRequest(); + Request->SetURL(TEXT("http://localhost:9000/battery_info")); + Request->SetVerb(TEXT("GET")); + + Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkUEBPLibrary::OnBatteryInfoResponseReceived, Callback); + + Request->ProcessRequest(); +} + +void UHarmonyLinkUEBPLibrary::RefreshAllInfo(FDeviceInfoCallback Callback) +{ + TSharedPtr Request = FHttpModule::Get().CreateRequest(); + Request->SetURL(TEXT("http://localhost:9000/all_info")); + Request->SetVerb(TEXT("GET")); + + Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkUEBPLibrary::OnDeviceInfoResponseReceived, Callback); + + Request->ProcessRequest(); +} + +void UHarmonyLinkUEBPLibrary::RefreshVersionInfo(FVersionInfoCallback Callback) +{ + TSharedPtr Request = FHttpModule::Get().CreateRequest(); + Request->SetURL(TEXT("http://localhost:9000/version_info")); + Request->SetVerb(TEXT("GET")); + + Request->OnProcessRequestComplete().BindLambda(&UHarmonyLinkUEBPLibrary::OnVersionInfoResponseReceived, Callback); + + Request->ProcessRequest(); +} + +void UHarmonyLinkUEBPLibrary::OnCheckServerStatusResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FServerStatusCallback Callback) +{ + if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) + { + bool bConnected = Response->GetContentAsString().ToBool(); + + Connected = bConnected; + + Callback.ExecuteIfBound(bConnected); + } + else + { + Connected = false; + + Callback.ExecuteIfBound(false); + // The server returned an error, or the request failed. + // Handle the error here. + } +} + +void UHarmonyLinkUEBPLibrary::OnOSInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FOSInfoCallback Callback) +{ + if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) + { + FString ResponseString = Response->GetContentAsString(); + UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); + + // Parse the JSON response + TSharedPtr JsonObject; + TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); + if (FJsonSerializer::Deserialize(Reader, JsonObject)) + { + // Parse the OSInfo + FOSInfo OSInfo; + if (JsonObject->HasField("os_info")) + { + TSharedPtr OSInfoObject = JsonObject->GetObjectField("os_info"); + OSInfo.OSType = OSInfoObject->GetStringField("os_type"); + OSInfo.OSVersion = OSInfoObject->GetStringField("os_version"); + OSInfo.OSEdition = OSInfoObject->GetStringField("os_edition"); + OSInfo.OSBits = OSInfoObject->GetStringField("os_bits"); + } + + CachedAllInfo.OSInfo = OSInfo; + Callback.ExecuteIfBound(OSInfo); + } + } + else + { + // The server returned an error, or the request failed. + // Handle the error here. + } +} + +void UHarmonyLinkUEBPLibrary::OnBatteryInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FBatteryInfoCallback Callback) +{ + if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) + { + FString ResponseString = Response->GetContentAsString(); + UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); + + // Parse the JSON response + TSharedPtr JsonObject; + TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); + if (FJsonSerializer::Deserialize(Reader, JsonObject)) + { + // Parse the BatteryInfo + FBatteryInfo BatteryInfo; + BatteryInfo.bHasBattery = JsonObject->GetBoolField("has_battery"); + BatteryInfo.BatteryPercent = JsonObject->GetIntegerField("battery_percent"); + FString ChargingStatusString = JsonObject->GetStringField("charging_status"); + if (ChargingStatusString == "charging") + { + BatteryInfo.ChargingStatus = EChargingStatus::Charging; + } + else if (ChargingStatusString == "battery") + { + BatteryInfo.ChargingStatus = EChargingStatus::Battery; + } + else + { + BatteryInfo.ChargingStatus = EChargingStatus::Unknown; + } + + CachedAllInfo.BatteryInfo = BatteryInfo; + + Callback.ExecuteIfBound(BatteryInfo); + } + } + else + { + // The server returned an error, or the request failed. + // Handle the error here. + } +} + +void UHarmonyLinkUEBPLibrary::OnDeviceInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FDeviceInfoCallback Callback) +{ + if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) + { + FString ResponseString = Response->GetContentAsString(); + UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); + + // Parse the JSON response + TSharedPtr JsonObject; + TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); + if (FJsonSerializer::Deserialize(Reader, JsonObject)) + { + // Parse the OSInfo + FOSInfo OSInfo; + if (JsonObject->HasField("os_info")) + { + TSharedPtr OSInfoObject = JsonObject->GetObjectField("os_info"); + OSInfo.OSType = OSInfoObject->GetStringField("os_type"); + OSInfo.OSVersion = OSInfoObject->GetStringField("os_version"); + OSInfo.OSEdition = OSInfoObject->GetStringField("os_edition"); + OSInfo.OSBits = OSInfoObject->GetStringField("os_bits"); + } + + // Parse the Battery_Info + FBatteryInfo BatteryInfo; + const TSharedPtr* BatteryInfoObject = nullptr; + if (JsonObject->HasField("dock_info") && JsonObject->TryGetObjectField("battery_info", BatteryInfoObject)) + { + BatteryInfo.bHasBattery = BatteryInfoObject->Get()->GetBoolField("has_battery"); + BatteryInfo.BatteryPercent = BatteryInfoObject->Get()->GetIntegerField("battery_percent"); + + FString battery = BatteryInfoObject->Get()->GetStringField("charging_status"); + if (battery.ToLower() == "charging") { BatteryInfo.ChargingStatus = EChargingStatus::Charging; } + else if (battery.ToLower() == "battery") { BatteryInfo.ChargingStatus = EChargingStatus::Battery; } + else { BatteryInfo.ChargingStatus = EChargingStatus::Unknown; } + + } + + // Parse the DockInfo + FDockInfo DockInfo; + const TSharedPtr* DockInfoObject = nullptr; + if (JsonObject->HasField("dock_info") && JsonObject->TryGetObjectField("dock_info", DockInfoObject)) + { + const TSharedPtr* DockModelObject = nullptr; + if (DockInfoObject->Get()->HasField("dock_model") && JsonObject->TryGetObjectField("dock_model", DockModelObject)) + { + TSharedPtr DockModelSubObject = DockModelObject->Get()->GetObjectField("dock_model"); + + FString DockModel = DockModelObject->Get()->GetStringField("model"); + if (DockModel == "SteamDeckDock") { DockInfo.DockModel.Model = EDockModel::SteamDeckDock; } + else if (DockModel == "JSAUX") { DockInfo.DockModel.Model = EDockModel::JSAUX; } + else if (DockModel == "Unknown") { DockInfo.DockModel.Model = EDockModel::Unknown; } + + DockInfo.DockModel.Name = DockModelObject->Get()->GetStringField("name"); + } + else + { + // handle case where dock_model is null + DockInfo.DockModel.Model = EDockModel::Unknown; + DockInfo.DockModel.Name = "Unknown"; + } + + DockInfo.bIsDocked = DockInfoObject->Get()->GetBoolField("is_docked"); + DockInfo.bFallbackDetection = DockInfoObject->Get()->GetBoolField("fallback_detection"); + } + + // Create the DeviceInfo struct + FAllInfo AllInfo; + AllInfo.OSInfo = OSInfo; + AllInfo.DockInfo = DockInfo; + AllInfo.BatteryInfo = BatteryInfo; + + CachedAllInfo = AllInfo; + + // Call the callback with the DeviceInfo + Callback.ExecuteIfBound(AllInfo); + + // Handle the DeviceInfo struct as needed + // ... + } + } + else + { + // The server returned an error, or the request failed. + // Handle the error here. + } +} + + +void UHarmonyLinkUEBPLibrary::OnVersionInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FVersionInfoCallback Callback) +{ + if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == EHttpResponseCodes::Ok) + { + FString ResponseString = Response->GetContentAsString(); + UE_LOG(LogTemp, Warning, TEXT("Response: %s"), *ResponseString); + + // Parse the JSON response + TSharedPtr JsonObject; + TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseString); + if (FJsonSerializer::Deserialize(Reader, JsonObject)) + { + FHarmonyLinkVersionData VersionInfo; + VersionInfo.BuildTimestamp = JsonObject->GetStringField("build_timestamp"); + VersionInfo.GitBranch = JsonObject->GetStringField("git_branch"); + VersionInfo.GitDescribe = JsonObject->GetStringField("git_describe"); + VersionInfo.GitCommitTimestamp = JsonObject->GetStringField("git_commit_timestamp"); + VersionInfo.bDebug = JsonObject->GetBoolField("debug"); + VersionInfo.Version = JsonObject->GetStringField("version"); + VersionInfo.VersionMajor = JsonObject->GetIntegerField("version_major"); + VersionInfo.VersionMinor = JsonObject->GetIntegerField("version_minor"); + VersionInfo.VersionPatch = JsonObject->GetIntegerField("version_patch"); + VersionInfo.VersionPre = JsonObject->GetStringField("version_pre"); + + CachedVersionData = VersionInfo; + Callback.ExecuteIfBound(VersionInfo); + } + } + else + { + // The server returned an error, or the request failed. + // Handle the error here. + } +} diff --git a/Source/HarmonyLinkUE/Public/DataRefreshActor.h b/Source/HarmonyLinkUE/Public/DataRefreshActor.h new file mode 100644 index 0000000..a24c607 --- /dev/null +++ b/Source/HarmonyLinkUE/Public/DataRefreshActor.h @@ -0,0 +1,43 @@ +// DataRefreshActor.h + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "HarmonyLinkUEBPLibrary.h" +#include "DataRefreshActor.generated.h" + +UCLASS() +class HARMONYLINKUE_API ADataRefreshActor : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ADataRefreshActor(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + virtual void Destroyed() override; + + FServerStatusCallback ServerStatusCallback; + + // Function to refresh data + UFUNCTION() + void RefreshData(); + UFUNCTION() + void OnServerStatusChecked(bool connected); + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + +private: + // Timer interval for data refreshing (in seconds) + UPROPERTY(EditAnywhere, Category = "Data Refresh") + float RefreshInterval; + + // Timer handle for data refreshing + FTimerHandle RefreshTimerHandle; +}; diff --git a/Source/HarmonyLinkUE/Public/HarmonyLinkUE.h b/Source/HarmonyLinkUE/Public/HarmonyLinkUE.h new file mode 100644 index 0000000..c2ed66d --- /dev/null +++ b/Source/HarmonyLinkUE/Public/HarmonyLinkUE.h @@ -0,0 +1,14 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" + +class FHarmonyLinkUEModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Source/HarmonyLinkUE/Public/HarmonyLinkUEBPLibrary.h b/Source/HarmonyLinkUE/Public/HarmonyLinkUEBPLibrary.h new file mode 100644 index 0000000..6f40747 --- /dev/null +++ b/Source/HarmonyLinkUE/Public/HarmonyLinkUEBPLibrary.h @@ -0,0 +1,283 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Runtime/Online/HTTP/Public/HttpModule.h" +#include "Runtime/Online/HTTP/Public/Interfaces/IHttpRequest.h" +#include "Engine/World.h" +#include "Engine/WorldComposition.h" + +#include "HarmonyLinkUEBPLibrary.generated.h" + +UENUM(BlueprintType) +enum class EDockModel : uint8 +{ + SteamDeckDock, + JSAUX, + Unknown, +}; + +USTRUCT(BlueprintType) +struct FSDock +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + EDockModel Model = EDockModel::Unknown; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString Name = ""; + + void Print() const + { + UE_LOG(LogTemp, Display, TEXT("Dock Model: %s"), *StaticEnum()->GetNameStringByValue(static_cast(Model))); + UE_LOG(LogTemp, Display, TEXT("Name: %s"), *Name); + } +}; + +USTRUCT(BlueprintType) +struct FDockInfo +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FSDock DockModel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bIsDocked = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bFallbackDetection = false; + + void Print() const + { + DockModel.Print(); + UE_LOG(LogTemp, Display, TEXT("IsDocked: %s"), bIsDocked ? TEXT("true") : TEXT("false")); + UE_LOG(LogTemp, Display, TEXT("FallbackDetection: %s"), bFallbackDetection ? TEXT("true") : TEXT("false")); + } +}; + + +USTRUCT(BlueprintType) +struct FOSInfo +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString OSType = "Unknown"; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString OSVersion = ""; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString OSEdition = ""; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString OSBits = "X64"; + + void Print() const + { + UE_LOG(LogTemp, Display, TEXT("OS Type: %s"), *OSType); + UE_LOG(LogTemp, Display, TEXT("OS Version: %s"), *OSVersion); + UE_LOG(LogTemp, Display, TEXT("OS Edition: %s"), *OSEdition); + UE_LOG(LogTemp, Display, TEXT("OS Bits: %s"), *OSBits); + } +}; + +UENUM(BlueprintType) +enum class EChargingStatus : uint8 +{ + Charging, + Battery, + Unknown +}; + +USTRUCT(BlueprintType) +struct FBatteryInfo +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bHasBattery = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int32 BatteryPercent = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + EChargingStatus ChargingStatus = EChargingStatus::Unknown; + + void Print() const + { + UE_LOG(LogTemp, Display, TEXT("Has Battery: %s"), bHasBattery ? TEXT("true") : TEXT("false")); + UE_LOG(LogTemp, Display, TEXT("Battery Percent: %d"), BatteryPercent); + UE_LOG(LogTemp, Display, TEXT("Charging Status: %s"), *StaticEnum()->GetNameStringByValue(static_cast(ChargingStatus))); + } +}; + +USTRUCT(BlueprintType) +struct FHarmonyLinkVersionData +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString BuildTimestamp; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString GitBranch; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString GitDescribe; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString GitCommitTimestamp; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bDebug; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString Version; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int32 VersionMajor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int32 VersionMinor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int32 VersionPatch; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString VersionPre; + + void Print() const + { + UE_LOG(LogTemp, Display, TEXT("Build Timestamp: %s"), *BuildTimestamp); + UE_LOG(LogTemp, Display, TEXT("Git Branch: %s"), *GitBranch); + UE_LOG(LogTemp, Display, TEXT("Git Describe: %s"), *GitDescribe); + UE_LOG(LogTemp, Display, TEXT("Git Commit Timestamp: %s"), *GitCommitTimestamp); + UE_LOG(LogTemp, Display, TEXT("Debug: %s"), bDebug ? TEXT("true") : TEXT("false")); + UE_LOG(LogTemp, Display, TEXT("Version: %s"), *Version); + UE_LOG(LogTemp, Display, TEXT("Version Major: %d"), VersionMajor); + UE_LOG(LogTemp, Display, TEXT("Version Minor: %d"), VersionMinor); + UE_LOG(LogTemp, Display, TEXT("Version Patch: %d"), VersionPatch); + UE_LOG(LogTemp, Display, TEXT("Version Pre: %s"), *VersionPre); + } +}; + +USTRUCT(BlueprintType) +struct FAllInfo +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FOSInfo OSInfo; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FDockInfo DockInfo; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FBatteryInfo BatteryInfo; + + void Print() const + { + UE_LOG(LogTemp, Display, TEXT("All Info:")); + OSInfo.Print(); + DockInfo.Print(); + BatteryInfo.Print(); + } +}; + +DECLARE_DYNAMIC_DELEGATE_OneParam(FDeviceInfoCallback, const FAllInfo&, DeviceInfo); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOSInfoCallback, const FOSInfo&, OSInfo); +DECLARE_DYNAMIC_DELEGATE_OneParam(FBatteryInfoCallback, const FBatteryInfo&, BatteryInfo); +DECLARE_DYNAMIC_DELEGATE_OneParam(FVersionInfoCallback, const FHarmonyLinkVersionData&, VersionInfo); +DECLARE_DYNAMIC_DELEGATE_OneParam(FServerStatusCallback, const bool, connected); + + +/* +* Function library class. +* Each function in it is expected to be static and represents blueprint node that can be called in any blueprint. +* +* When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable. +* BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins. +* BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins. +* DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu. +* Its lets you name the node using characters not allowed in C++ function names. +* CompactNodeTitle - the word(s) that appear on the node. +* Keywords - the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu. +* Good example is "Print String" node which you can find also by using keyword "log". +* Category - the category your node will be under in the Blueprint drop-down menu. +* +* For more info on custom blueprint nodes visit documentation: +* https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation +*/ +UCLASS() +class HARMONYLINKUE_API UHarmonyLinkUEBPLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() + + static bool Connected; + + // Cached DeviceInfo variable + static FAllInfo CachedAllInfo; + + // Cached DeviceInfo variable + static FHarmonyLinkVersionData CachedVersionData; + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static bool GetIsConnected() + { return Connected; } + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static void PrintAllInfo() + { CachedAllInfo.Print(); } + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static FAllInfo GetAllInfo() + { return CachedAllInfo; } + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static FBatteryInfo GetBatteryInfo() + { return CachedAllInfo.BatteryInfo; } + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static FDockInfo GetDockInfo() + { return CachedAllInfo.DockInfo; } + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static FOSInfo GetOSInfo() + { return CachedAllInfo.OSInfo; } + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static FHarmonyLinkVersionData GetVersionInfo() + { return CachedVersionData; } + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static void CheckServerStatus(FServerStatusCallback Callback); + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static void RefreshOSInfo(FOSInfoCallback Callback); + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static void RefreshBatteryInfo(FBatteryInfoCallback Callback); + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static void RefreshAllInfo(FDeviceInfoCallback Callback); + + UFUNCTION(BlueprintCallable, Category = "Harmony Link") + static void RefreshVersionInfo(FVersionInfoCallback Callback); + +private: + static void OnCheckServerStatusResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FServerStatusCallback Callback); + static void OnOSInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FOSInfoCallback Callback); + static void OnBatteryInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FBatteryInfoCallback Callback); + static void OnDeviceInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FDeviceInfoCallback Callback); + static void OnVersionInfoResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, FVersionInfoCallback Callback); +};