UniversalSerial Blueprint APIリファレンス

このページでは、UniversalSerialがBlueprintに公開するAPIを説明します。C++でも同じAPIを利用できます。各APIの使い分けはユースケースを参照してください。

API全体の関係

UniversalSerialの公開APIは、Serial Port Managerクラス(USerialPortManager)に集約されています。

役割ノード
作成と設定Construct Object from Class、Initialize、各種Set系ノード
接続の制御Open、Close、IsConnected、Set DTR、Set RTS
送信Send Data、Send String UTF8、Send String Hex
ポートの調査Get Available Serial Ports、Find First Communicable Serial Port
結果の受信Connectedなどの6種類のイベント
    flowchart TB
	  BP["Blueprint / C++"] --> M["SerialPortManager"]
	  M -->|"Initialize → Open"| OS["OSのシリアルAPI"]
	  M -->|"Send Data / Send String UTF8 / Send String Hex"| OS
	  OS -->|"受信スレッド"| M
	  M -->|"Connected / Data Received など(ゲームスレッド)"| BP

受信データの読み込みはバックグラウンドスレッドで行われ、受信イベントはゲームスレッドで通知されます。

SerialPortManagerの作成

Serial Port ManagerはBlueprintTypeのクラスです。Construct Object from ClassノードのClassにSerial Port Managerを指定して作成します。

SerialPortManagerを作成するBlueprintの構成例

作成したインスタンスはメンバー変数に保存してください。未保存の場合、ガベージコレクションの対象になり、通信が継続できません。

Initialize

ポート名と通信設定を指定します。Initializeは設定を保存するだけです。実際にポートを開くには、続けてOpenを実行します。

入力既定値説明
Port NameCOM1ポート名。OSごとの形式は運用ページを参照
Baud Rate9600ボーレート。対向デバイスと一致させる
Data Bits8データビット(5〜8)
ParityNoneパリティビット
Stop Bits1ストップビット
Flow ControlNoneフロー制御
Data FormatRawBytes受信データの形式
Initial DTRtrueポートを開いた時点のDTR信号の状態
Initial RTStrueポートを開いた時点のRTS信号の状態

設定は対向デバイスまたはソフトウェアの設定と一致している必要があります。

Open

Initializeで保存した設定でポートを開き、受信スレッドを起動します。成功するとConnectedイベントが、失敗するとErrorイベントが発生します。

すでに接続中の場合は何も行わず、ログに警告が出力されます。

Close

ポートを閉じ、受信スレッドを停止します。Disconnectedイベントが発生します。レベルの終了時(EndPlay)に呼び出してください。

IsConnected

ポートが開いているかどうかを返します(true: 接続中、false: 切断)。

送信系ノード

ノード入力説明
Send DataData(バイト配列)バイト配列をそのまま送信する
Send String UTF8Text、Add Delimiter(既定true)文字列をUTF-8エンコードで送信する。trueなら区切り文字を末尾に自動追加
Send String HexHex Text16進数文字列をバイト配列に変換して送信する。バイト間のスペースは任意

未接続の状態で送信した場合や空のデータを送信した場合は、送信は行われずログに警告が出力されます。

Set DTR / Set RTS

DTR・RTS信号の状態を切り替えます。成功するとtrueが返ります。接続していない状態ではfalseが返ります。

Set Receive Mode / Get Receive Mode

受信スレッドのポーリング方法を指定します。

Receive Mode動作
Lowデータがないときに10ミリ秒待機する
Normal常に1ミリ秒待機する
HighスリープせずにYieldで待機する

Highは受信の遅延を最小化しますが、CPUの使用率が上がります。通常は既定値のNormalを使用してください。Get Receive Modeで現在の設定を取得できます。

Set系ノード(オプション設定)

次のノードは戻り値としてマネージャー自身を返すため、Initializeの前などに続けて呼び出せます。

ノード入力既定値説明
Set Write TimeoutTimeout Ms1000書き込みのタイムアウト(ミリ秒)
Set Receive Buffer SizeSize In Bytes8192受信バッファサイズ(最小1024)
Set Data FormatFormat-受信データの形式を変更する
Set String DelimiterDelimiter\r\n文字列の区切り文字を変更する

Get Available Serial Ports

現在利用可能なシリアルポート名の一覧を返します(BlueprintPure、static)。取得したポート名はInitializeのPort Nameにそのまま渡せます。

Find First Communicable Serial Port(およびBinary版)

候補ポートを順に開き、最初に通信可能なポート名を返します。通信できない場合は空の文字列を返します。詳細な使い方はユースケースの通信可能なポートを自動で特定するを参照してください。

入力既定値説明
Baud Rate 〜 RTS-Initializeと同じ並びの通信設定
Read Timeout Ms50プローブ時の読み取りタイムアウト(ミリ秒)
Write Timeout Ms500プローブ時の書き込みタイムアウト(ミリ秒)
Receive Buffer Size4096プローブ時の受信バッファサイズ
Probe Command UTF8空各ポートへ送る文字列
Expected Response UTF8空応答に含まれることを確認する文字列
Probe Timeout Ms1200応答の待機時間(ミリ秒)

Find First Communicable Serial Port (Binary)は、プローブと応答確認をバイト列(Probe Data・Expected Response)で行う版です。どちらのノードも、プローブ文字列を両方空にすると「最初に開けたポート」を返します。

イベント

イベント発生タイミング引数
Connectedポートが開かれたときSerial Port マネージャー自身
Disconnectedポートが閉じられたときSerial Port マネージャー自身
Data Receivedデータを受信したときSerial Port、Data 受信したバイト配列
Data Received String文字列を受信したときSerial Port、Data 受信した文字列
Data Received Hex16進数文字列を受信したときSerial Port、Hex Data 16進数文字列
Errorエラーが発生したときSerial Port、Error Message エラーの内容

受信イベント(Data Received・Data Received String・Data Received Hex)は、Data Formatで指定した形式に対応する1種類だけが通知されます。ほかの2つはバインドしていても通知されません。

列挙型

列挙型値用途
ESerialPortParityNone / Odd / Even / Mark / Spaceパリティビット
ESerialPortStopBits1 / 1.5 / 2ストップビット
ESerialPortFlowControlNone / Hardware (RTS/CTS) / Software (XON/XOFF)フロー制御
ESerialDataFormatRaw Bytes (TArray<uint8>) / UTF-8 String / Hex String受信データの形式
ESerialPortReceiveModeLow / Normal / High受信スレッドのポーリング方法

C++での実装例

Arduinoと文字列で送受信する例です。Blueprintの構成と同じ要素を使用します。

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

    // SerialPortManagerを作成し、変数に保持する
    SerialPort = NewObject<USerialPortManager>();

    // イベントハンドラーを設定する
    SerialPort->OnConnected.AddDynamic(this, &UMyActor::OnConnected);
    SerialPort->OnDisconnected.AddDynamic(this, &UMyActor::OnDisconnected);
    SerialPort->OnDataReceivedString.AddDynamic(this, &UMyActor::OnDataReceivedString);
    SerialPort->OnError.AddDynamic(this, &UMyActor::OnError);

    // 通信設定を指定する(対向デバイスと一致させる)
    SerialPort->Initialize(
        TEXT("COM3"),
        115200,
        8,
        ESerialPortParity::None,
        ESerialPortStopBits::One,
        ESerialPortFlowControl::None,
        ESerialDataFormat::UTF8String,
        true,
        true);

    // ポートを開く
    SerialPort->Open();
}

void UMyActor::OnConnected(USerialPortManager* SerialPort)
{
    // 文字列を送信する(区切り文字を自動で追加)
    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);
}

通信可能なポートを自動で特定する場合は、Openの前にUSerialPortManager::FindFirstCommunicableSerialPortの戻り値をInitializeのポート名に渡します。

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();
}

非推奨のノード

ノード扱い
Set Read Timeout非推奨。読み取りのタイミングはSet Receive Modeで制御する

エディタ上では打ち消し線付きで表示されます。既存のBlueprintに含まれている場合でも動作しますが、新規に使用しないでください。

ライフサイクルと保持のまとめ

  1. Construct Object from Classで作成したSerial Port Managerはメンバー変数で保持します。
  2. Initializeで設定を保存し、Openでポートを開きます。Openの成功・失敗はConnected・Errorイベントで確認します。
  3. 送信は接続中のみ有効です。未接続での送信は警告ログのみで、エラーイベントは発生しません。
  4. 受信イベントはData Formatに対応する1種類だけが通知され、ゲームスレッドで実行されます。
  5. 不要になったらCloseを呼び出します。呼び出さないままオブジェクトが破棄されると、ポートが開いたままになることがあります。