Skip to content
This repository has been archived by the owner on Mar 9, 2023. It is now read-only.

Connecting Joycon to android #29

Open
Albond87 opened this issue Jul 21, 2019 · 5 comments
Open

Connecting Joycon to android #29

Albond87 opened this issue Jul 21, 2019 · 5 comments

Comments

@Albond87
Copy link

After much annoyance with Unity complaining about various things, and after digging through other issues, I managed to get a simple scene working, with two cuboids representing Joycon that rotate to match my two Joycon connected to my laptop. I then built the scene for android and ran it on my phone, with my two Joycon already connected and working, and... nothing. Just two lifeless cuboids staring back at me. Tried disconnecting and reconnecting the Joycon, tried restarting the app... nothing. I noticed someone else already raised an issue about android support, but it got no response. Is there some other plugin needed to be able to use this on android? (like a BLE plugin) Or is there some other way to get Unity to recognise them when they are connected to Android? (when connected to my phone the names are the exact same as on my Laptop (Joy-Con (L) and Joy-Con (R)) and they show the same controller icon)

@TheBricktop
Copy link

For me it's an interesting issue, as I want to connect Joy cons to Android and raspberry pi enabled device's

@Albond87
Copy link
Author

@TheBricktop So I actually found a (kind of) solution. Instead of connecting the Joy Con to my phone, I made a simple exe for my laptop which takes input from them, and then sends the data I need in packets to a receiver application on my phone, where I can then use the input. It works pretty well with not much latency (and I never tried to optimise it as I never went any further with that project). The only downside is you need to have a pc/laptop so it's not exactly a portable solution. I can give you the code if you want (not sure how to incorporate a raspi though, maybe by connecting that to the laptop as well?)

@TheBricktop
Copy link

Yea i was thinking about osc or some kind of a translator from hid to raw data, but intended way of using this was to make some kind of a better daydream controller out of existing superior joystics (and far cheaper in comparision)

@Northernside
Copy link

@TheBricktop So I actually found a (kind of) solution. Instead of connecting the Joy Con to my phone, I made a simple exe for my laptop which takes input from them, and then sends the data I need in packets to a receiver application on my phone, where I can then use the input. It works pretty well with not much latency (and I never tried to optimise it as I never went any further with that project). The only downside is you need to have a pc/laptop so it's not exactly a portable solution. I can give you the code if you want (not sure how to incorporate a raspi though, maybe by connecting that to the laptop as well?)

Heya! Can you drop a download link to the code?

@Albond87
Copy link
Author

Albond87 commented Aug 2, 2021

@TheBricktop So I actually found a (kind of) solution. Instead of connecting the Joy Con to my phone, I made a simple exe for my laptop which takes input from them, and then sends the data I need in packets to a receiver application on my phone, where I can then use the input. It works pretty well with not much latency (and I never tried to optimise it as I never went any further with that project). The only downside is you need to have a pc/laptop so it's not exactly a portable solution. I can give you the code if you want (not sure how to incorporate a raspi though, maybe by connecting that to the laptop as well?)

Heya! Can you drop a download link to the code?

Hi, sorry for the late response but here is some code you might find useful! (Modified from https://forum.unity.com/threads/simple-udp-implementation-send-read-via-mono-c.15900/ to send Joycon data)

Sending packets of data (for the desktop application):

/*

    -----------------------
    UDP-Send
    -----------------------
    // [url]http://msdn.microsoft.com/de-de/library/bb979228.aspx#ID0E3BAC[/url]

    CODE TAKEN FROM: https://forum.unity.com/threads/simple-udp-implementation-send-read-via-mono-c.15900/

    // > gesendetes unter
    // 127.0.0.1 : 8050 empfangen

    // nc -lu 127.0.0.1 8050

        // todo: shutdown thread at the end
*/
using UnityEngine;
using UnityEngine.UI;

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Linq;
using System.Collections;

public class IPManager
{
    public static string GetIP(ADDRESSFAM Addfam)
    {
        //Return null if ADDRESSFAM is Ipv6 but Os does not support it
        if (Addfam == ADDRESSFAM.IPv6 && !Socket.OSSupportsIPv6)
        {
            return null;
        }

        string output = "";

        foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
        {
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
            NetworkInterfaceType _type1 = NetworkInterfaceType.Wireless80211;
            NetworkInterfaceType _type2 = NetworkInterfaceType.Ethernet;

            if ((item.NetworkInterfaceType == _type1 || item.NetworkInterfaceType == _type2) && item.OperationalStatus == OperationalStatus.Up)
#endif 
            {
                foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
                {
                    //IPv4
                    if (Addfam == ADDRESSFAM.IPv4)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            output = ip.Address.ToString();
                        }
                    }

                    //IPv6
                    else if (Addfam == ADDRESSFAM.IPv6)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
                        {
                            output = ip.Address.ToString();
                        }
                    }
                }
            }
        }
        return output;
    }
}

public enum ADDRESSFAM
{
    IPv4, IPv6
}

public class UDPSend : MonoBehaviour
{
    private static int localPort;

    // prefs
    private string IP;  // define in init
    public int port;  // define in init

    // "connection" things
    IPEndPoint remoteEndPoint;
    UdpClient client;

    [Serializable]
    public class DataPacket
    {
        public Quaternion lo; // left orientation
        public Quaternion ro; // right orientation
        public bool zl;
        public bool zr;
    }

    public DataPacket sendPacket = new DataPacket();

    public InputField input;
    public JoyconController joyconL;
    public JoyconController joyconR;

    // start from unity3d
    public void Start()
    {
        Init();
        Debug.Log(IPManager.GetIP(ADDRESSFAM.IPv4));
    }

    public void Update()
    {
        sendPacket.lo = joyconL.orientation;
        sendPacket.ro = joyconR.orientation;
        sendPacket.zl = joyconL.joycon.GetButton(Joycon.Button.SHOULDER_2);
        sendPacket.zr = joyconR.joycon.GetButton(Joycon.Button.SHOULDER_2);
        string json = JsonUtility.ToJson(sendPacket);
        SendString(json);
    }

    // init
    public void Init()
    {
        // Endpunkt definieren, von dem die Nachrichten gesendet werden.
        print("UDPSend.init()");

        // define
        IP = input.text;
        port = 8051;

        // ----------------------------
        // Senden
        // ----------------------------
        remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), port);
        client = new UdpClient();

        // status
        print("Sending to " + IP + " : " + port);
        print("Testing: nc -lu " + IP + " : " + port);

    }

    // sendData
    private void SendString(string message)
    {
        try
        {
            //if (message != "")
            //{

            // Daten mit der UTF8-Kodierung in das Binärformat kodieren.
            byte[] data = Encoding.UTF8.GetBytes(message);

            // Den message zum Remote-Client senden.
            client.Send(data, data.Length, remoteEndPoint);
            //}
        }
        catch (Exception err)
        {
            print(err.ToString());
        }
    }
}

Receiving packets of data (for the mobile application):

/*

    -----------------------
    UDP-Receive (send to)
    -----------------------
    // [url]http://msdn.microsoft.com/de-de/library/bb979228.aspx#ID0E3BAC[/url]

    CODE TAKEN FROM: https://forum.unity.com/threads/simple-udp-implementation-send-read-via-mono-c.15900/

    // > receive
    // 127.0.0.1 : 8051

    // send
    // nc -u 127.0.0.1 8051

*/
using UnityEngine;

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public class UDPReceive : MonoBehaviour
{

    // receiving Thread
    Thread receiveThread;

    // udpclient object
    UdpClient client;

    // public
    //public string IP = "127.0.0.1";
    public int port; // define > init

    // infos
    public string lastReceivedUDPPacket = "";
    //public string allReceivedUDPPackets = ""; // clean up this from time to time!

    [Serializable]
    public class DataPacket
    {
        public Quaternion lo; // left orientation
        public Quaternion ro; // right orientation
        public bool zl;
        public bool zr;
    }

    public bool isAlive = false;

    public Transform joyconL;
    public Transform joyconR;
    public Transform zl;
    public Transform zr;

    public Vector3 unpressedPos;
    public Vector3 pressedPos;

    // start from shell
    private static void Main()
    {
        UDPReceive receiveObj = new UDPReceive();
        receiveObj.Init();

        string text = "";
        do
        {
            text = Console.ReadLine();
        }
        while (!text.Equals("exit"));
    }
    // start from unity3d
    public void Start()
    {

        Init();
    }

    public void Update()
    {
        string packet = GetLatestUDPPacket();
        DataPacket receivePacket = JsonUtility.FromJson<DataPacket>(packet);
        joyconL.localRotation = receivePacket.lo;
        joyconR.localRotation = receivePacket.ro;
        if (receivePacket.zl)
        {
            zl.localPosition = pressedPos;
        }
        else
        {
            zl.localPosition = unpressedPos;
        }
        if (receivePacket.zr)
        {
            zr.localPosition = pressedPos;
        }
        else
        {
            zr.localPosition = unpressedPos;
        }
    }

    // OnGUI
    /*void OnGUI()
    {
        Rect rectObj = new Rect(40, 10, 200, 400);
        GUIStyle style = new GUIStyle();
        style.alignment = TextAnchor.UpperLeft;
        GUI.Box(rectObj, "# UDPReceive\n127.0.0.1 " + port + " #\n"
                    + "shell> nc -u 127.0.0.1 : " + port + " \n"
                    + "\nLast Packet: \n" + lastReceivedUDPPacket
                    + "\n\nAll Messages: \n" + allReceivedUDPPackets
                , style);
    }*/

    // init
    private void Init()
    {
        // Endpunkt definieren, von dem die Nachrichten gesendet werden.
        print("UDPSend.init()");

        // define port
        port = 8051;

        // status
        print("Sending to 127.0.0.1 : " + port);
        print("Test-Sending to this Port: nc -u 127.0.0.1  " + port + "");


        // ----------------------------
        // Abhören
        // ----------------------------
        // Lokalen Endpunkt definieren (wo Nachrichten empfangen werden).
        // Einen neuen Thread für den Empfang eingehender Nachrichten erstellen.
        isAlive = true;
        receiveThread = new Thread(
            new ThreadStart(ReceiveData));
        receiveThread.IsBackground = true;
        receiveThread.Start();

    }

    private void OnApplicationQuit()
    {
        isAlive = false;
        receiveThread.Abort();
    }

    // receive thread
    public void ReceiveData()
    {
        client = new UdpClient(port);
        //client.Client.Blocking = false;
        while (isAlive)
        {
            try
            {
                // Bytes empfangen.
                IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
                byte[] data = client.Receive(ref anyIP);

                // Bytes mit der UTF8-Kodierung in das Textformat kodieren.
                string text = Encoding.UTF8.GetString(data);

                // Den abgerufenen Text anzeigen.
                //print(">> " + text);

                // latest UDPpacket
                lastReceivedUDPPacket = text;

                // ....
                //allReceivedUDPPackets = allReceivedUDPPackets + text;

            }
            catch (Exception err)
            {
                print(err.ToString());
            }
        }
    }

    // getLatestUDPPacket
    // cleans up the rest
    public string GetLatestUDPPacket()
    {
        //allReceivedUDPPackets = "";
        return lastReceivedUDPPacket;
    }
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants