Skip to content

Instantly share code, notes, and snippets.

@asus4
Last active June 24, 2016 00:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asus4/86d48b80c295db826e37eef99d5438b2 to your computer and use it in GitHub Desktop.
Save asus4/86d48b80c295db826e37eef99d5438b2 to your computer and use it in GitHub Desktop.
Unityでいい感じにシリアル通信Wrapperする。
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System;
namespace AppKit
{
/// <summary>
/// UART communication for Unity
/// </summary>
public class ArduinoSerial : MonoBehaviour
{
public enum Baudrate
{
B_300 = 300,
B_1200 = 1200,
B_2400 = 2400,
B_4800 = 4800,
B_9600 = 9600,
B_19200 = 19200,
B_38400 = 38400,
B_57600 = 57600,
B_74880 = 74880,
B_115200 = 115200,
B_230400 = 230400,
B_250000 = 250000
}
public event Action<string> OnDataReceived;
SerialPort _serialPort;
Thread _thread;
Queue<string> _messages;
string _data = "";
bool _isRunning;
void Update ()
{
if (!_isRunning)
{
return;
}
lock (_messages)
{
while (_messages.Count > 0)
{
string msg = _messages.Dequeue();
if (OnDataReceived != null)
{
OnDataReceived(msg);
}
}
}
}
#region public
public static string[] GetPortNames()
{
if (Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXEditor)
{
// Custom port name in MacOS
// return Directory.GetFiles(@"/dev/", "cu.usb*", SearchOption.AllDirectories);
return Directory.GetFiles(@"/dev/", "tty.usb*", SearchOption.AllDirectories);
}
else if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor)
{
return SerialPort.GetPortNames();
}
// else
Debug.LogError("Unsupported platform");
return new string[0];
}
/// <summary>
/// Open the specified portName and baudRate.
/// </summary>
/// <param name="portName">Port name.</param>
/// <param name="baudRate">Baud rate.</param>
public bool Open(string portName=null, Baudrate baudRate = Baudrate.B_9600)
{
if (string.IsNullOrEmpty(portName))
{
// Connect to default port
var ports = GetPortNames();
if (Debug.isDebugBuild)
{
foreach (var port in ports)
{
Debug.LogFormat("port : {0}", port);
}
if (ports.Length == 0)
{
Debug.LogWarning("Serial port not found");
}
}
if (ports.Length == 0)
{
return false;
}
portName = ports[0];
}
_messages = new Queue<string>();
_serialPort = new SerialPort(portName, (int)baudRate, Parity.None, 8, StopBits.One);
// _serialPort.ReadTimeout = 10000;
// _serialPort.WriteTimeout = 10000;
try
{
_serialPort.Open();
}
catch(IOException e)
{
Debug.LogError(e);
_serialPort.Dispose();
return false;
}
_isRunning = true;
_thread = new Thread(Read);
_thread.Start();
return true;
}
public void Close()
{
_isRunning = false;
if (_thread != null && _thread.IsAlive)
{
_thread.Join();
}
if (_serialPort != null && _serialPort.IsOpen)
{
_serialPort.Close();
_serialPort.Dispose();
}
}
public void Write(string message)
{
try
{
_serialPort.Write(message);
}
catch (Exception e)
{
Debug.LogWarning(e.Message);
}
}
#endregion
#region Private
void Read()
{
while (_isRunning && _serialPort != null && _serialPort.IsOpen)
{
try
{
// http://answers.unity3d.com/questions/1022086/reading-serial-data-in-unity-from-android-app.html
// ReadLine freeze on Unity5 && Windows!!
byte b = (byte) _serialPort.ReadByte();
while(b != 255 && _isRunning)
{
char c = (char) b;
if(c == '\n')
{
lock(_messages)
{
_messages.Enqueue(_data);
_data = "";
}
}
else
{
_data += c;
}
b = (byte) _serialPort.ReadByte();
}
// if (_serialPort.BytesToRead > 0)
// {
// lock(_messages)
// {
// string msg = _serialPort.ReadLine();
// _messages.Enqueue(msg);
// }
// }
//
}
catch (Exception e)
{
Debug.LogWarning(e.Message);
}
Thread.Sleep(1);
}
}
#endregion
#region Singleton
static ArduinoSerial _instance;
public static ArduinoSerial Instance
{
get
{
if (_instance == null)
{
var go = new GameObject(typeof(ArduinoSerial).ToString());
DontDestroyOnLoad(go);
_instance = go.AddComponent<ArduinoSerial>();
}
return _instance;
}
}
#endregion
}
}
@asus4
Copy link
Author

asus4 commented Jun 23, 2016

using AppKit;

//-----------------


ArduinoSerial serial;

void Start()
{
    serial = ArduinoSerial.Instance;
    bool success = serial.Open(null, ArduinoSerial.Baudrate.B_115200);
    if (!success)
    {
        return;
    }
    serial.OnDataReceived += OnDataReceived;
}

void OnDisable()
{
    serial.Close();
    serial.OnDataReceived -= OnDataReceived;
}

void OnDataReceived (string msg)
{
    // TODO
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment