#pragma once /* * This is the bridge between hidapi and unreal and contains all the rawdata of the portal */ #include "CoreMinimal.h" #include "hidapi.h" #include "SkyPortalFigure.h" #include "SkyPortalIO.generated.h" #pragma region Definitions DECLARE_LOG_CATEGORY_EXTERN(LogHIDApi, Log, All); DECLARE_LOG_CATEGORY_EXTERN(LogSkyportalIO, Log, All); constexpr auto write_buf_size = 0x21; //buffer size for all the write command on portal. Should always be 0x21 - 33 constexpr auto TIMEOUT = 30000; //milliseconds /* Portal physicial device IDs */ const int VendorIds[4] = { 0x12ba, 0x54c, 0x1430, 0x1430 }; const int ProductIds[4] = { 0x150, 0x967, 0x1f17 }; UENUM(BlueprintType) enum EPortalCommand { A UMETA(DisplayName = "Activate"), C UMETA(DisplayName = "Color"), J UMETA(DisplayName = "Advanced color"), L UMETA(DisplayName = "Trap color"), M UMETA(DisplayName = "Music"), Q UMETA(DisplayName = "Query"), R UMETA(DisplayName = "Ready"), S UMETA(DisplayName = "Status") }; USTRUCT(BlueprintType) struct FPortalStatusData { GENERATED_BODY() // Array of statuses UPROPERTY(BlueprintReadOnly, EditFixedSize, Category = "SkyPortal|Figure", meta = (EditFixedOrder)) TArray StatusArray; // timestamp. // only one byte long. This means that after the value 0xFF, it overflows back to 0x00. // Since these are so far apart, it can be assumed that 0x00 is newer than anything in the range 0xF0 - 0xFF. UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure") uint8 Counter; // Should always be true UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure") bool bIsReady; explicit FPortalStatusData(uint8 ArraySize = 16, EFigureStatus DefaultStatus = EFigureStatus::NOT_PRESENT) : Counter(0), bIsReady(true) { // Initialisation du tableau StatusArray avec 16 éléments par défaut StatusArray.Init(DefaultStatus, ArraySize); } // Overload the == operator // Different only between bool operator==(const FPortalStatusData& Other) const { if (bIsReady == Other.bIsReady && Counter == Other.Counter) { if (StatusArray == Other.StatusArray) { return true; } } return false; } // Overload the != operator bool operator!=(const FPortalStatusData& Other) const { return !(*this == Other); } }; #pragma endregion FPortalStatusData ParsePortalStatus(const uint8* StatusResponse); EPortalCommand GetPortalCommandFromChar(unsigned char Char); /* Contain all the data that pass inside hidapi write + the number of bytes in case of successful write * * @param data all the block data, should be 0x21 sized * @param BytesTransferred In case of successful write, print the number of byte transfered. Could be used for verifications */ USTRUCT() struct FWriteBlock { GENERATED_BODY() unsigned char data[write_buf_size]; int BytesTransferred; }; /* This class will contain and handle all the low-lewel functions * Should be able to be called anywhere */ UCLASS() class USkyPortalIO : public UObject { GENERATED_BODY() public: // Constructor USkyPortalIO(); /* hidapi will write error message in here*/ UPROPERTY(BlueprintReadOnly) FString HidError; /*Portal ready to be listened or to receive commands*/ UPROPERTY(BlueprintReadOnly) bool bPortalReady = false; /* Connect to Portal - will write the PortalDevice var if success */ bool OpenPortalHandle(); /* Send block to portal. In windows, don't use the hidapi */ void Write(FWriteBlock* Block); /* Send raw command to portal */ void WriteRaw(const TArray* block); /* Listen to portal * @return The data sended by the portal device */ uint8* Read(); UFUNCTION() TArray QueryBlock(uint8 characterIndex, uint8 block = 0x00); /* Close connection to Portal*/ void Close(); private: /*TODO: Should not be here bool IsFalsePositive() const; */ /* Portal device ref, useful for hidapi commands */ hid_device* PortalDevice; };