unity-game-enginenetworkingudpnodemcu

NodeMCU Unity Connection, using UDP


I am trying to connect NodeMCU with unity for my university project.

My nodemcu receives data (tested with a UDP test tool application). I will leave the code below.

But I have problems with Unity. I tried to find a simple example or something like that.

The code I found recently is simple enough, but it makes Unity freeze. I found it here and edited it a bit.

NodeMCU code in Arduino IDE

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Epic SSID";
const char* password = "EpicPassword";

WiFiUDP Udp;
unsigned int port = 25666;
char packet[255];

IPAddress ip(192, 168, 43, 20);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

void setup()
{
    Serial.begin(115200);
    Serial.println();

    WiFi.hostname("YVRB-01");
    WiFi.config(ip, gateway, subnet);

    Serial.printf("Connecting to %s ", ssid);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }

    Serial.println("Connection Successful");
    Udp.begin(port);
    Serial.printf("Listener started at IP %s, at port %d", WiFi.localIP().toString().c_str(), port);
}

void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
      Serial.printf("Received %d bytes from %s, port %d", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
      int len = Udp.read(packet, 255);
      if (len > 0)
      {
          packet[len] = 0;
      }
      Serial.printf("UDP packet contents: %s", packet);
      Serial.println();
  }

  Udp.beginPacket (Udp.remoteIP(), Udp.remotePort());
  Udp.write("Epic message");
  Udp.endPacket();

  delay(300);
}

When it worked, I took off my shirt and ran too kitchen.

My code in Unity

/*
C# Network Programming
by Richard Blum

Publisher: Sybex
ISBN: 0782141765
*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

public class udpsend : MonoBehaviour
{
    Socket server;
    IPEndPoint ipep;

    void Start()
    {
        byte[] data = new byte[1024];

        ipep = new IPEndPoint(
                        IPAddress.Parse("192.162.43.209"), 25666);

        server = new Socket(AddressFamily.InterNetwork,
                       SocketType.Dgram, ProtocolType.Udp);

        string welcome = "I am connected";
        data = Encoding.ASCII.GetBytes(welcome);
        server.SendTo(data, data.Length, SocketFlags.None, ipep);
    }


    void Update()
    {
        string input, stringData;

        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
        EndPoint Remote = (EndPoint)sender;

        byte[] data = new byte[1024];
        int recv = server.ReceiveFrom(data, ref Remote);

        Console.WriteLine("Message received from {0}:", Remote.ToString());
        Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));

        //while (true)
        //{
        //    input = Console.ReadLine();
        //    if (input == "exit")
        //        break;
        //    server.SendTo(Encoding.ASCII.GetBytes(input), Remote);
        //    data = new byte[1024];
        //    recv = server.ReceiveFrom(data, ref Remote);
        //    stringData = Encoding.ASCII.GetString(data, 0, recv);
        //    Console.WriteLine(stringData);
        //}

        Console.WriteLine("Stopping client");
        server.Close();
    }


    public void SendData(string message)
    {
        byte[] data = new byte[1024];
        data = Encoding.ASCII.GetBytes(message);
        server.SendTo(data, data.Length, SocketFlags.None, ipep);

    }
}

I'm just saying that I don't fully understand, but I edited a little bit.

Any fixes or code examples will be appreciated. I just want a method that I can call like SendData("Never gonna give you up!").


Solution

  • I can now transfer information from the Unity app to NodeMCU and from NodeMCU to Unity!

    All the code is below.

    I used the code and edited the a bit.

    To receive data, I used this code right here.

    To send information, I used this code and like a "mash up" this code together to create one program that can send and receive.

    The reason I have done this is that there were a conflict, because there were one client and multiple codes trying to access it.

    For Node MCU I used this code which is pretty much the same as I wrote in question above.

    I also made manager code using which I can send message and do other stuff.

    It is also important to close all the ports or else Unity will freeze (a very annoying thing).

    Nodemcu code in the Arduino IDE:

    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    
    const char* ssid = "YVRB";
    const char* password = "YGreater";
    
    WiFiUDP Udp;
    unsigned int port = 25666;
    char packet[255];
    
    IPAddress ip(192, 168, 43, 20);
    IPAddress gateway(192, 168, 1, 1);
    IPAddress subnet(255, 255, 255, 0);
    
    void setup()
    {
      Serial.begin(115200);
      Serial.println();
    
      WiFi.hostname("YVRB-01");
      WiFi.config(ip, gateway, subnet);
    
      Serial.printf("Connecting to %s ", ssid);
      WiFi.begin(ssid, password);
    
      while (WiFi.status() != WL_CONNECTED)
      {
        delay(500);
        Serial.print(".");
      }
    
      Serial.println("Connection Successful");
      Udp.begin(port);
      Serial.printf("Listener started at IP %s, at port %d", WiFi.localIP().toString().c_str(), port);
      Serial.println();
    }
    
    void loop()
    {
      int packetSize = Udp.parsePacket();
      if (packetSize)
      {
        Serial.printf("Received %d bytes from %s, port %d", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
        int len = Udp.read(packet, 255);
        if (len > 0)
        {
          packet[len] = 0;
        }
        Serial.printf("UDP packet contents: %s", packet);
        Serial.println();
      }
    
      Udp.beginPacket (Udp.remoteIP(), Udp.remotePort());
      Udp.write("Important data");
      Udp.endPacket();
    
      delay(300);
    }
    

    File UDPSend.cs code which receives as well:

    // Inspired by this thread: https://forum.unity.com/threads/simple-udp-implementation-send-read-via-mono-c.15900/
    // Thanks OP la1n
    // Thanks MattijsKneppers for letting me know that I also need to lock my queue while enqueuing
    // Adapted during projects according to my needs
    
    using UnityEngine;
    using System;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    
    public class UDPSend
    {
        public string IP { get; private set; }
        public int sourcePort { get; private set; } // Sometimes we need to define the source port, since some devices only accept messages coming from a predefined sourceport.
        public int remotePort { get; private set; }
    
        IPEndPoint remoteEndPoint;
    
        Thread receiveThread;
    
        // udpclient object
        UdpClient client;
    
        // public
        // public string IP = "127.0.0.1"; default local
        public int port = 25666; // define > init
    
        // Information
        public string lastReceivedUDPPacket = "";
        public string allReceivedUDPPackets = ""; // Clean up this from time to time!
    
        public bool newdatahereboys = false;
    
        public void init(string IPAdress, int RemotePort, int SourcePort = -1) // If sourceport is not set, its being chosen randomly by the system
        {
            IP = IPAdress;
            sourcePort = SourcePort;
            remotePort = RemotePort;
    
            remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), remotePort);
            if (sourcePort <= -1)
            {
                client = new UdpClient();
                Debug.Log("Sending to " + IP + ": " + remotePort);
            }
            else
            {
                client = new UdpClient(sourcePort);
                Debug.Log("Sending to " + IP + ": " + remotePort + " from Source Port: " + sourcePort);
            }
    
            receiveThread = new Thread(
                new ThreadStart(ReceiveData));
            receiveThread.IsBackground = true;
            receiveThread.Start();
    
        }
    
        private void ReceiveData()
        {
            //client = sender.client;
            while (true)
            {
                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.
    
                    Debug.Log(text);
                    newdatahereboys = true;
                    //PlayerPrefs.SetString("ReceivedData", text);
    
                    // Latest UDPpacket
                    lastReceivedUDPPacket = text;
    
                    // ....
                    allReceivedUDPPackets = allReceivedUDPPackets + text;
                }
                catch (Exception err)
                {
                    Debug.Log(err.ToString());
                }
            }
        }
    
        // sendData in different ways. Can be extended accordingly
        public void sendString(string message)
        {
            try
            {
                byte[] data = Encoding.UTF8.GetBytes(message);
                client.Send(data, data.Length, remoteEndPoint);
    
            }
            catch (Exception err)
            {
                Debug.Log(err.ToString());
            }
        }
    
        public void sendInt32(Int32 myInt)
        {
            try
            {
                byte[] data = BitConverter.GetBytes(myInt);
                client.Send(data, data.Length, remoteEndPoint);
            }
            catch (Exception err)
            {
                Debug.Log(err.ToString());
            }
        }
    
        public void sendInt32Array(Int32[] myInts)
        {
            try
            {
                byte[] data = new byte[myInts.Length * sizeof(Int32)];
                Buffer.BlockCopy(myInts, 0, data, 0, data.Length);
                client.Send(data, data.Length, remoteEndPoint);
            }
            catch (Exception err)
            {
                Debug.Log(err.ToString());
            }
        }
    
        public void sendInt16Array(Int16[] myInts)
        {
            try
            {
                byte[] data = new byte[myInts.Length * sizeof(Int16)];
                Buffer.BlockCopy(myInts, 0, data, 0, data.Length);
                client.Send(data, data.Length, remoteEndPoint);
            }
            catch (Exception err)
            {
                Debug.Log(err.ToString());
            }
        }
    
        public string getLatestUDPPacket()
        {
            allReceivedUDPPackets = "";
            return lastReceivedUDPPacket;
        }
    
        public void ClosePorts()
        {
            Debug.Log("closing receiving UDP on port: " + port);
    
            if (receiveThread != null)
                receiveThread.Abort();
    
            client.Close();
        }
    }
    

    File manager.cs:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class manager : MonoBehaviour {
    
        public int Remoteport = 25666;
    
        public UDPSend sender = new UDPSend();
    
        public string datafromnode;
    
        void Start()
        {
            sender.init("192.168.43.209", Remoteport, 25666);
            sender.sendString("Hello from Start. " + Time.realtimeSinceStartup);
    
            Application.targetFrameRate = 60;
        }
    
        // Update is called once per frame
        void Update()
        {
            if (Input.GetKeyUp(KeyCode.Return))
                sender.sendString("This should be delivered");
    
            if (sender.newdatahereboys)
            {
                datafromnode = sender.getLatestUDPPacket();
            }
        }
    
        public void OnDisable()
        {
            sender.ClosePorts();
        }
    
        public void OnApplicationQuit()
        {
            sender.ClosePorts();
        }
    
    }
    

    Success! See justlookatem.