与Neurosky的统一 - 端口扫描

时间:2014-09-13 03:28:05

标签: c# unity3d unityscript

我在 Unity 上有 C#脚本来扫描可用的串口以连接 Neurosky 。但是,这是手动检测,这只适用于ThinkGear Connector的起始端口为 COM9 的计算机。

void setupNeuro() {
    tgHandleId = ThinkGear.TG_GetNewConnectionId();
    tgConnectionStatus = ThinkGear.TG_Connect(tgHandleId,
                                              "\\\\.\\COM9",
                                              ThinkGear.BAUD_9600,
                                              ThinkGear.STREAM_PACKETS);
    }

如何编辑此C#脚本以自动检测从COM1到COMxx的正确端口?

2 个答案:

答案 0 :(得分:1)

这不是Unity问题,而是C#问题。 ThinkGear文档提到用户应该实现端口扫描,但我不记得提供了任何实现,尽管提供了存储以前端口的建议。

不幸的是,没有真正优雅的方法来实现这一点,但有一些方法。

您可以做的最好的事情是循环通过端口,直到您得到一个没有超时的端口,但这意味着每次检查需要至少花费2秒钟。更糟糕的是,在Unity中从.NET连接串行端口的唯一方法也不保证是最新的。这意味着您最终可能会以非常缓慢的方式枚举大量串行端口。

为了尽量缩短搜索时间,您应该按以下顺序搜索:

  • 使用的最后一个端口(将其存储在PlayerPrefs中)

  • SerialPort.GetPortNames返回的所有端口。不会有很多,但不幸的是,并不能保证它们都存在,因为正如文档所说, SerialPort.GetPortNames 检查的注册表值并非总是如此日期。

  • 如果您尚未检查过端口0-10。

  • 端口10 - 256,但请参见下文。此时,您必须至少给用户一个自己进入端口的机会,或者给他们一个关于下一步将花多长时间的警告。

    我不建议走这么远(最多8分钟的搜索声音合理吗?)。您已经花了长达20秒的时间扫描前10个端口。

    可能是值得的
    • 向用户显示如何自行找到合适的端口
    • 为每个使用lower level方法的平台编写一个小型外部程序,以显示用户输入的正确端口。
    • 从特定于操作系统的库中访问这些较低级别的方法,并从Unity访问它以将搜索限制为有效端口。这是我选择的选择。

检查端口是这样的(由于使用协程,需要lambda):

IEnumerable AttemptHeadsetConnection(int portNumber,Action<int,int> headsetConnectedCallback, Action attemptCompletedCallback)
{
    var connectionString = string.Format("\\\\.\\COM{0}",portNumber);//That string literal should be elsewhere
    return AttemptHeadsetConnection(connectionString, headsetConnectedCallback, attemptCompletedCallback);
}

IEnumerable AttemptHeadsetConnection(string connectionString,Action<int,int> headsetConnectedCallback,Action attemptCompletedCallback)
{
    connectionID = ThinkGear.TG_GetNewConnectionId();
    connectionStatus = ThinkGear.TG_Connect(connectionID ,
                                          connectionString,
                                          ThinkGear.BAUD_9600,
                                          ThinkGear.STREAM_PACKETS);
    if(connectStatus >= 0)
    {
       yield return new WaitForSeconds(2f); //Give the headset at least 2 seconds to respond with valid data
       int receivedPackets = ThinkGear.TG_ReadPackets(handleID, -1);//Read all the packets with -1
       if(receivedPackets > 0)
       {
           headsetConnectedCallback(connectionID,connectionStatus);
       } 
       else 
       {
          ThinkGear.TG_FreeConnection(handleID);              
       }

   }
   attemptCompletedCallback();
}

并使用类似的东西:

foreach(var serialPort in SerialPort.GetPortNames())
{
     var connectionCoroutine = AttemptHeadsetConnection(serialPort,onFoundHeadset,onAttemptCompleted);
     StartCoroutine(connectionCoroutine);
}

关于代码的注意事项:它不优雅,甚至可能无法编译(尽管它没有做任何不可能的事情)。把它作为非常有说服力的伪代码并用它作为你的基础。

答案 1 :(得分:0)

循环通过已知端口将COM编号替换为连接字符串,直到您用完了端口(没有连接)或找到一个...