[Leonardo系対応]UnityでArduinoの接続にユニークIDを使う (Windows)


以前書いた [UnityでArduinoの接続にユニークIDを使う (Windows)](https://qiita.com/__S/items/a9927d17bdefda11ec3d) をLeonardo系のArduino対応にも対応した
**注意！VID PIDのみの判定になるので、Leonardo系の複数同時接続はできない**
**Windows10 バージョン2004以降でのみ有効**

## pnputiコマンドで接続されているArduinoを確認

`/enum-devices /connected /class "Ports" ` でクラス名Ports(COMPort)のデバイスを取得できる

	pnputil /enum-devices /connected /class "Ports"

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45348/5aa69c31-f3b6-85d4-cdea-14374d5eb5b4.png)


インスタンスIDがArduinoのユニークIDになるので、UnityではこのIDを指定して接続できるようにする
ArduinoLeonardoでは接続するポートによってインスタンスIDの USB\\\VID_XXXX&PID_XXXX 以降 の文字列が変わるため、
**USB\\\VID_XXXX&PID_XXXX** までをコピーして使用する


## Unityでpnputiコマンド叩くスクリプト

- インスタンスID指定してデバイスを検索する

``` COMPort.cs
namespace COMPortUtil
{
    using System.Diagnostics;

    public class COMPort
    {
        public static string Find(
            DataReceivedEventHandler outputHandler = null,
            DataReceivedEventHandler errorOutputHanlder = null,
            System.EventHandler processExit = null)
        {
            Process process = new Process();

            process.StartInfo.FileName = "pnputil";
            process.StartInfo.UseShellExecute = false;

            process.StartInfo.RedirectStandardOutput = true;
            process.OutputDataReceived += new DataReceivedEventHandler(outputHandler);

            process.StartInfo.RedirectStandardError = true;
            process.ErrorDataReceived += new DataReceivedEventHandler(errorOutputHanlder);

            process.StartInfo.RedirectStandardInput = false;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.LoadUserProfile = true;

            process.StartInfo.Arguments = "/enum-devices /connected /class " + "Ports";

            process.EnableRaisingEvents = true;

            process.Exited += new System.EventHandler(processExit);

            process.Start();
            string results =  process.StandardOutput.ReadToEnd();

            process.BeginErrorReadLine();

            process.WaitForExit();
            process.Close();

            return results;

        }
    }
}

```

- 検索結果からCOMPortの番号を取得する

```SerialHandler.cs
using COMPortUtil;
using System.Text.RegularExpressions;

public class SerialHandler: MonoBehaviour
{
	string comPortName;

	void Start()
	{
	  comPortName = FindPort(@"USB\\VID_2341&PID_8037");
	}

	public string FindPort(string searchID)
	{
		string standardOutput = COMPortUtil.COMPorts.Find(
		this.COMUtileOutputHandler,
		this.COMUtileErrorOutputHanlder,
		this.COMUtileProcess_Exit);

		var lines = Regex.Split(standardOutput, @"\r\n|\r|\n");
		for(int i = 0;i < lines.Length; i++)
		{
			if(Regex.IsMatch(lines[i], searchID))
			{
				Match matchedObject = Regex.Match(lines[i + 1], @"COM\d+");
				if (matchedObject.Value.Length >= 4)
				{
					string comPort = matchedObject.Value;
					try
					{
						return comPort;
					}
					catch (System.IO.IOException ex)
					{
						Debug.LogError("Could not find port.");
						return null;
					}
				}
			}
		}
		Debug.LogError("Could not find port.");
		return null;
	}

	private void COMUtileOutputHandler(object sender, System.Diagnostics.DataReceivedEventArgs args)
	{
	}
	private void COMUtileErrorOutputHanlder(object sender, System.Diagnostics.DataReceivedEventArgs args)
	{
	    if (!string.IsNullOrEmpty(args.Data))
	    {
	        Debug.Log("error : " + args.Data);
	    }
	}

	private void COMUtileProcess_Exit(object sender, System.EventArgs e)
	{
	    System.Diagnostics.Process proc = (System.Diagnostics.Process)sender;
	    // proc.Kill();
	}
}
```


あとはcomPortNameを使ってシリアルポートをオープンするだけ