UniversalSerial Blueprint API Reference

This page describes the APIs UniversalSerial exposes to Blueprint. The same APIs are available from C++. For guidance on choosing between them, see Use Cases.

API overview

UniversalSerial’s public APIs are consolidated in the Serial Port Manager class (USerialPortManager).

RoleNodes
Creation and settingsConstruct Object from Class, Initialize, and the Set nodes
Connection controlOpen, Close, IsConnected, Set DTR, Set RTS
SendingSend Data, Send String UTF8, Send String Hex
Port discoveryGet Available Serial Ports, Find First Communicable Serial Port
ResultsSix events including Connected and the Data Received family
    flowchart TB
	  BP["Blueprint / C++"] --> M["SerialPortManager"]
	  M -->|"Initialize → Open"| OS["OS serial API"]
	  M -->|"Send Data / Send String UTF8 / Send String Hex"| OS
	  OS -->|"receive thread"| M
	  M -->|"Connected / Data Received etc. (game thread)"| BP

Received data is read on a background thread, and receive events are dispatched on the game thread.

Creating a SerialPortManager

Serial Port Manager is a BlueprintType class. Create it with the Construct Object from Class node, specifying Serial Port Manager for Class.

Blueprint example for creating a SerialPortManager

Store the created instance in a member variable. If not stored, it becomes a target for garbage collection and communication cannot continue.

Initialize

Specifies the port name and communication settings. Initialize only stores the settings. To actually open the port, run Open afterwards.

InputDefaultDescription
Port NameCOM1Port name. Formats per platform: see the production page
Baud Rate9600Baud rate. Must match the peer device
Data Bits8Data bits (5-8)
ParityNoneParity bit
Stop Bits1Stop bits
Flow ControlNoneFlow control
Data FormatRawBytesReceive data format
Initial DTRtrueDTR signal state right after the port opens
Initial RTStrueRTS signal state right after the port opens

The settings must match those of the peer device or software.

Open

Opens the port with the settings stored by Initialize and starts the receive thread. On success the Connected event fires; on failure the Error event fires.

If already connected, the node does nothing and a warning is logged.

Close

Closes the port and stops the receive thread. The Disconnected event fires. Call it when the level ends (EndPlay).

IsConnected

Returns whether the port is open (true: connected, false: disconnected).

Send nodes

NodeInputDescription
Send DataData (byte array)Sends the byte array as-is
Send String UTF8Text, Add Delimiter (default true)Sends the string as UTF-8. With true, the delimiter is appended to the end
Send String HexHex TextConverts the hexadecimal string to a byte array and sends it. Spaces between bytes are optional

Sending while disconnected, or sending empty data, does nothing except log a warning.

Set DTR / Set RTS

Toggles the DTR and RTS signal states. Returns true on success. Returns false when not connected.

Set Receive Mode / Get Receive Mode

Specifies how the receive thread polls.

Receive ModeBehavior
LowWaits 10 milliseconds when no data arrives
NormalAlways waits 1 millisecond
HighWaits with Yield instead of sleeping

High minimizes receive latency but increases CPU usage. Normally use the default Normal. Get Receive Mode returns the current setting.

Set nodes (optional settings)

The following nodes return the manager itself, so you can chain them before Initialize.

NodeInputDefaultDescription
Set Write TimeoutTimeout Ms1000Write timeout in milliseconds
Set Receive Buffer SizeSize In Bytes8192Receive buffer size (minimum 1024)
Set Data FormatFormat-Changes the receive data format
Set String DelimiterDelimiter\r\nChanges the string delimiter

Get Available Serial Ports

Returns the list of currently available serial port names (BlueprintPure, static). The returned names can be passed directly to Port Name of Initialize.

Find First Communicable Serial Port (and the Binary variant)

Opens candidate ports in order and returns the name of the first communicable port. Returns an empty string when none is communicable. For usage details, see Automatically identify a communicable port in Use Cases.

InputDefaultDescription
Baud Rate through RTS-Communication settings, same order as Initialize
Read Timeout Ms50Read timeout for probing, in milliseconds
Write Timeout Ms500Write timeout for probing, in milliseconds
Receive Buffer Size4096Receive buffer size for probing
Probe Command UTF8emptyThe string sent to each port
Expected Response UTF8emptyThe string that must appear in the response
Probe Timeout Ms1200How long to wait for a response, in milliseconds

Find First Communicable Serial Port (Binary) probes and verifies with byte arrays (Probe Data and Expected Response). If both probe strings are empty, both variants return the first port that can be opened.

Events

EventWhen it firesParameters
ConnectedThe port was openedSerial Port: the manager itself
DisconnectedThe port was closedSerial Port: the manager itself
Data ReceivedData was receivedSerial Port, Data: the received byte array
Data Received StringA string was receivedSerial Port, Data: the received string
Data Received HexA hex string was receivedSerial Port, Hex Data: the hex string
ErrorAn error occurredSerial Port, Error Message: the error content

Only the receive event matching the format specified by Data Format (Data Received, Data Received String, or Data Received Hex) is notified. The other two are not notified even when bound.

Enums

EnumValuesPurpose
ESerialPortParityNone / Odd / Even / Mark / SpaceParity bit
ESerialPortStopBits1 / 1.5 / 2Stop bits
ESerialPortFlowControlNone / Hardware (RTS/CTS) / Software (XON/XOFF)Flow control
ESerialDataFormatRaw Bytes (TArray<uint8>) / UTF-8 String / Hex StringReceive data format
ESerialPortReceiveModeLow / Normal / HighReceive thread polling behavior

C++ example

An example that sends and receives strings with an Arduino. It uses the same elements as the Blueprint setup.

void UMyActor::BeginPlay()
{
    Super::BeginPlay();

    // Create a SerialPortManager and keep it in a member variable
    SerialPort = NewObject<USerialPortManager>();

    // Set up event handlers
    SerialPort->OnConnected.AddDynamic(this, &UMyActor::OnConnected);
    SerialPort->OnDisconnected.AddDynamic(this, &UMyActor::OnDisconnected);
    SerialPort->OnDataReceivedString.AddDynamic(this, &UMyActor::OnDataReceivedString);
    SerialPort->OnError.AddDynamic(this, &UMyActor::OnError);

    // Specify the communication settings (match the peer device)
    SerialPort->Initialize(
        TEXT("COM3"),
        115200,
        8,
        ESerialPortParity::None,
        ESerialPortStopBits::One,
        ESerialPortFlowControl::None,
        ESerialDataFormat::UTF8String,
        true,
        true);

    // Open the port
    SerialPort->Open();
}

void UMyActor::OnConnected(USerialPortManager* SerialPort)
{
    // Send a string (the delimiter is appended automatically)
    SerialPort->SendStringUTF8(TEXT("Hello"), true);
}

void UMyActor::OnDataReceivedString(USerialPortManager* SerialPort, const FString& Data)
{
    UE_LOG(LogTemp, Log, TEXT("Received: %s"), *Data);
}

void UMyActor::OnError(USerialPortManager* SerialPort, const FString& ErrorMessage)
{
    UE_LOG(LogTemp, Error, TEXT("Serial error: %s"), *ErrorMessage);
}

void UMyActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    if (SerialPort)
    {
        SerialPort->Close();
    }
    Super::EndPlay(EndPlayReason);
}

To automatically identify a communicable port, pass the return value of USerialPortManager::FindFirstCommunicableSerialPort to the port name of Initialize before Open.

const FString PortName = USerialPortManager::FindFirstCommunicableSerialPort(
    115200, 8,
    ESerialPortParity::None, ESerialPortStopBits::One, ESerialPortFlowControl::None,
    50, 500, 4096, true, true,
    TEXT("PING\r\n"), TEXT("PONG"), 2000);

if (!PortName.IsEmpty())
{
    SerialPort->Initialize(PortName, 115200, 8,
        ESerialPortParity::None, ESerialPortStopBits::One, ESerialPortFlowControl::None,
        ESerialDataFormat::UTF8String, true, true);
    SerialPort->Open();
}

Deprecated node

NodeStatus
Set Read TimeoutDeprecated. Control read timing with Set Receive Mode instead

It appears with a strikethrough in the Editor. Existing Blueprints that contain it still work, but do not use it in new graphs.

Lifecycle and retention summary

  1. Keep the Serial Port Manager created with Construct Object from Class in a member variable.
  2. Store the settings with Initialize, then open the port with Open. Confirm success or failure with the Connected and Error events.
  3. Sending works only while connected. Sending while disconnected produces a warning log only; no error event fires.
  4. Only one receive event, matching the Data Format, is notified, and it runs on the game thread.
  5. Call Close when finished. If the object is destroyed without calling it, the port may remain open.