【Unity】Serial Port Utility Proをつかってシリアル通信する（Unity2019 & Win10 ※System.IO.Portsは使用しない）

**Unityからシリアルデバイスへ送信
↓
シリアルデバイスが動作**
について書きます。

※受信については今回取り扱いません。
 Unityからシリアルデバイスへの**送信**のみです！すみません。

##実行環境
・Unity 2019.1.8f1
・Serial Port Utility Pro(Unityアセット) 　https://portutility.com/ja/
・Windows10

##System.IO.Portsは使いません
・System.IO.Ports
「Unity シリアル通信」でググったら、一番いっぱい出てきました。
しかし、Unity5やWin10で使うには色々とエラー除去する必要があったり、
通信中にフリーズしてしまったりと、ややこしい感じでした。
もっと楽なのが出ていたので(下記)、そっちつかいます。

##Serial Port Utility Proとは？
Unity3Dで使える強力なシリアルポート通信ユーティリティ。

System.IO.PortsではWindowsしかできませんが、
これを使うと**Android、Linux、MacOS、Windowsでシリアル通信可能に！！**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306317/7556b178-108c-05e7-0caa-8e22cee19bd6.png)


有料は$78ですが、無料版もあります。

**Free Version Limitations**
※無料トライアルバージョンでは、以下制約つき
・いずれかのデバイスのデータ転送（送受信）が合計１ＭBまで使用可能です。
　超過後は自動的に通信が切断されアプリケーションを再起動するまで使用できません。
・ Windows及びMacOSのみサポートされています。
・ 無料バージョンを使用したアプリケーションの配布はできません。


※ちなみに、日本の方が作られたアセットなので、
リファレンスも日本語で非常に取り入れやすかったです👍

##無料版の導入
https://portutility.com/ja/
アセットの公式サイトの、
少し下の方にある、**無料版をダウンロード**　をクリックします。
![スクリーンショット 2019-07-12 9.41.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306317/3a4ef2c7-4bd6-cdca-6b43-1c6ddfb36c7b.png)
.unitypackageがダウンロードされるので、
Unityを起動している状態でファイルを開きます。
インポートウィンドウが出てくるので
全て選択された状態でImportをクリック。


インポートしたアセットフォルダ>Scriptsフォルダ内に
**SerialPortUtilityPro.cs**があるので、
シーン上の好きなゲームオブジェクトにアタッチします。


以下のようなインスペクタが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306317/c6d962f2-f4fb-74fc-0ab6-52187395a6a2.png)
＜各項目について上から見ていきます＞
**Open Method**は、USB / PCI / Bluetooth SSP / TCP Emulator Client & TCP Emulator Server
から選ぶことができます。今回はUSBにします。

基本的には、**Auto Open**にチェック入れて良いかと思います。
もし、任意のタイミングでOpen()したいのであれば、

```C#
private SerialPortUtility.SerialPortUtilityPro serialPort;

public void OpenFunc()
{
    serialPort = this.GetComponent<SerialPortUtility.SerialPortUtilityPro>();
    serialPort.OpenMethod = SerialPortUtility.SerialPortUtilityPro.OpenSystem.USB;
    serialPort.VendorID = "";
    serialPort.ProductID = "";
    serialPort.SerialNumber = "";
    serialPort.BaudRate = 9600;
    //serialPort.ReadProtocol = SerialPortUtility.SerialPortUtilityPro.MethodSystem.Streaming; //受信の設定なので今回は省略
    //serialPort.ReadCompleteEventObject.AddListener(this.ReadComprateString); //read function　//受信の設定なので今回は省略
    //serialPort.RecvDiscardNull = true;　//受信の設定なので今回は省略

    serialPort.Open();
}
```
のように書いて、ボタントリガーなどで呼び出します。


次に、**[Show the devices connected to this PC.]**ボタンをクリックすると、
今パソコンに接続されているUSBデバイスのどれを選択しますか？みたいなのがでてきます。
選択すれば自動的に
**Vender ID**
**Product ID**
**Serial Number**　※空欄になるデバイスもあります（その場合空欄でOK）
**Order**
に番号を入れてくれます。


基本的には以下のような設定がデフォルトです。
**BaundRate**・・・9600bps
**Parity**・・・No
**Stop Bit**・・・One Bit
**Data Bit**・・・Eight Bit
**Discard Null Receive**・・・一般的にどっちかわかんないです
**Auto RTS/CTS Handshake**・・・はずす
**Start DTR Enable**・・・いれる


※各用語について分からないなりに調べてみました。
BaundRate(ボーレート)・・・通信速度。単位はbps（bit Per Second）で、300、600、1200、2400、4800、9600、19200などから選択します。
RTS・・・相手側（シリアルデバイス）が正常に動作しているか（電源が入っているか）
DTR・・・こちら側(パソコン)が正常に動作しているか（電源が入っているか）
CTS・・・こちらから相手にデータを送る要求
DSR・・・相手からこちらにデータを送る要求
ハンドシェイク・・・フロー制御のこと。互いに今送受信の状況を確認しあう事で通信の信頼性を確保？するらしい…（よくわからなかった）





##シリアル通信（送信）のメソッドをつくる
SerialPortUtilityProとは別に、
新しいC#ファイルを用意します。
シーン上の好きなオブジェクトにアタッチしておきます。

今回私は、ONボタントリガーでRelayOn()呼び出し、OFFボタントリガーでRelayOff()が呼び出されるコードをつくりました。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class SerialHandler : MonoBehaviour
{
    SerialPortUtility.SerialPortUtilityPro serialPort;
    private string _on = "relay on 0";
    private string _off = "relay off 0";

    void Awake()
    {
        serialPort = this.GetComponent<SerialPortUtility.SerialPortUtilityPro>();
    }

    public void RelayOn()
    {
        if (serialPort != null)
		{
			if (serialPort.IsOpened())
			{
                serialPort.WriteCR(_on);
            }
        }
    }

    public void RelayOff()
    {
        if (serialPort != null)
		{
			if (serialPort.IsOpened())
			{
                serialPort.WriteCR(_off);
            }
        }
    }
}

```
`serialPort = this.GetComponent<SerialPortUtility.SerialPortUtilityPro>();`で、
serialPortをUnityアプリ起動時に取ってくる必要があります。
SerialPortUtilityPro.csがアタッチされているオブジェクトから参照するようにします。
（同じオブジェクトにアタッチしているので、thisにしています）


また、`Write()`についても何種類かあるので注意です。
**Write("Hello!")**・・・Write(“Hello!”);
**WriteCRLF("Hello!")**・・・Write(“Hello!\r\n”); と等価
**WriteCR("Hello!")**・・・Write(“Hello!\r”);　と等価
**WriteLF("Hello!")**・・・Write(“Hello!\n”);　と等価
先頭にもどるか？改行するか？を正しく指定しないと、シリアルデバイスが動きません。
もし、あれ？動かない　ということがあったら、ここを見直すと良いかもしれません。
（私の場合はWriteCRが正しく動作しました。）

##まとめ
Serial Port Utility Proはとっても簡単。