You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
5.5 KiB

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OSC.NET;
using System;
using UnityEngine.Events;
using System.Threading;
namespace OSCFirmata
{
public class FirmataControl : MonoBehaviour
{
public string sendAddress = "localhost";
public int sendPort = 3434;
public int receievePort = 3435;
public enum ControlType
{
set_digital,
set_analog,
}
public PinCommand[] pins;
public PinCommand[] inPins;
private Dictionary<int, PinCommand> inPinMap = new Dictionary<int, PinCommand>();
private bool is_receiving_thread_running = false;
private Thread receivingThread;
// Use this for initialization
void Start()
{
_oscSender = new OSCTransmitter(sendAddress, sendPort);
_oscReceiever = new OSCReceiver(receievePort);
receivingThread = new Thread(receivingService);
receivingThread.Start();
// inPins = new PinCommand[1];
}
// Update is called once per frame
protected void Update()
{
foreach (var pin in pins)
{
if (_oscSender != null)
_oscSender.Send(pin.toOSC());
}
lock (inPinMap)
{
foreach (PinCommand pin in inPins)
{
if (inPinMap.ContainsKey(pin.pin))
{
//if (pin.value != inPinMap[pin.pin].value)
{
pin.value = inPinMap[pin.pin].value;
pin.valueChangeEvent.Invoke(pin.value);
}
}
}
}
}
private void OnDestroy()
{
is_receiving_thread_running = false;
_oscReceiever.Close();
receivingThread.Join();
}
protected OSCTransmitter _oscSender;
protected OSCReceiver _oscReceiever;
public enum CommandType
{
report_pin,
set_pin,
}
public enum PinMode
{
DIGITAL_INPUT = 0x00,
DIGITAL_OUTPUT = 0x01,
ANALOG_INPUT = 0x02,
PWM = 0x03,
SERVO = 0x04,
SHIFT = 0x05,
I2C = 0x06,
ONEWIRE = 0x07,
STEPPER = 0x08,
ENCODER = 0x09,
SERIAL = 0x0A,
INPUT_PULLUP = 0x0B,
}
private void processMessage(OSCMessage msg)
{
//Debug.Log(msg.ToString());
#if true
PinCommand pin = PinCommand.fromOSC(msg);
//if(pin.pin == 8)
//Debug.Log(msg.ToString());
lock (inPinMap)
{
if (inPinMap.ContainsKey(pin.pin))
{
inPinMap[pin.pin] = pin;
}
else
{
inPinMap.Add(pin.pin, pin);
}
}
#endif
}
[System.Serializable]
public class PinCommand
{
public ControlType controlType = ControlType.set_digital;
public int pin = 0;
[Range(0f, 1f)]
public float value;
[Serializable]
public class ValueChangeedEvent : UnityEvent<float> { }
public ValueChangeedEvent valueChangeEvent;
CommandType commandType = CommandType.set_pin;
PinMode mode;
public OSCMessage toOSC()
{
string address = "/rqst/" + commandType;
OSCMessage msg = new OSCMessage(address);
switch (controlType)
{
case ControlType.set_analog:
mode = PinMode.PWM;
break;
case ControlType.set_digital:
mode = PinMode.DIGITAL_OUTPUT;
break;
}
msg.Append(pin);
msg.Append(mode.ToString());
msg.Append(value);
return msg;
}
public static PinCommand fromOSC(OSCMessage msg)
{
PinCommand pin = new PinCommand();
if (msg.Address != "/rspn/report_pin")
return null;
pin.pin = (int)msg.Values[0];
pin.mode = (PinMode)Enum.Parse(typeof(PinMode), (string)msg.Values[1]);
pin.value = (float)msg.Values[2];
return pin;
}
}
private void receivingService()
{
is_receiving_thread_running = true;
while (is_receiving_thread_running)
{
OSCPacket packet = _oscReceiever.Receive();
while (is_receiving_thread_running && packet != null)
{
if (packet.IsBundle())
{
//Debug.Log("IsBundle");
ArrayList messages = packet.Values;
for (int i = 0; i < messages.Count; i++)
{
processMessage((OSCMessage)messages[i]);
}
}
else
processMessage((OSCMessage)packet);
packet = _oscReceiever.Receive();
}
}
Debug.Log("packet = null");
}
}
}