Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LSL Wireless connection PC and PC #66

Open
alexfr98 opened this issue May 22, 2024 · 4 comments
Open

LSL Wireless connection PC and PC #66

alexfr98 opened this issue May 22, 2024 · 4 comments

Comments

@alexfr98
Copy link

Hello!

First, thank you for your awesome package. I was using it with the Oculus Quest 2, cable link, and my computer and it works perfectly fine.
Now I want to do it on a different computer. With one, I will have the Unity application (that will be executed in the Quest 2) which will be the one sending a marker, and on another computer, I have the Python string marker receiver code, which has to receive the information. This setup is not working when these two codes are on different computers connected to the same private network. The tests were run in Windows, MacOS and with two different private networks.

  • I tried this setup (two different computers connected to the same private network) using the pylsl Python example and it works. However, if I try the codes (inlet and outlet manager) shown below, it doesn't work wireless, only if the projects are in the same computer.
  • I tried this setup with the Unity package and the messages were not received.

I already set up the firewall settings to accept all types of network communication (private and public) in Unity and Python.

  1. Do you know if the package should work in a wireless connection? I understand that LSL uses UDP Broadcasting, so I think it should work. but I'm not sure if I did all the required steps.
  2. Is it possible to send messages from a Unity project (with unity lsl) to a python script (with pylsl)?

The Python code is the same that in you example ReceiveStringMarkers example: https://github.com/labstreaminglayer/pylsl/blob/master/pylsl/examples/ReceiveStringMarkers.py

Code of both scripts, each in one project:

public class LSLOutletManager : MonoBehaviour
{
    public static LSLOutletManager Instance { get; private set; }
    /*
    * If you are instead trying to log a stimulus event then there are better options. Please see the 
    * LSL4Unity SimpleStimulusEvent Sample for such a design.
    */
    string StreamName = "LSL4Unity.ContentModerator";
    string StreamType = "Markers";
    private StreamOutlet outlet;
    private string[] sample = { "" };
    private void Awake()
    {
        // If there is an instance, and it's not me, delete myself.

        if (Instance != null && Instance != this)
        {
            Destroy(this);
        }
        else
        {
            Instance = this;
        }
    }


    void Start()
    {
        var hash = new Hash128();
        hash.Append(StreamName);
        hash.Append(StreamType);
        hash.Append(gameObject.GetInstanceID());
        StreamInfo streamInfo = new StreamInfo(StreamName, StreamType, 1, LSL.LSL.IRREGULAR_RATE,
            channel_format_t.cf_string, hash.ToString());
        outlet = new StreamOutlet(streamInfo);
        PushToOutlet("1");
    }

    public void PushToOutlet(string message)
    {
        if (outlet != null)
        {
            Debug.Log(message);
            sample[0] = message;
                
            // Debug.Log(sample[0]);
            outlet.push_sample(sample);
        }
    }

    private void OnApplicationQuit()
    {
        outlet.Close();
    }


}

using System.Collections;
using UnityEngine;
using LSL;

namespace LSL4Unity.Samples.SimpleInlet
{
    public class SimpleInletScaleObject : MonoBehaviour
    {
        public string StreamName; // The name of the stream to resolve
        ContinuousResolver resolver;

        private StreamInlet inlet;
        private string[] string_buffer; // Buffer for string data

        void Start()
        {
            if (!string.IsNullOrEmpty(StreamName))
                resolver = new ContinuousResolver("type", "Markers"); // Looking for a stream of type "Markers"
            else
            {
                Debug.LogError("Object must specify a name for resolver to lookup a stream.");
                this.enabled = false;
                return;
            }
            StartCoroutine(ResolveExpectedStream());
        }

        IEnumerator ResolveExpectedStream()
        {
            var results = resolver.results();
            while (results.Length == 0)
            {
                yield return new WaitForSeconds(0.1f);
                results = resolver.results();
            }

            inlet = new StreamInlet(results[0]);
            int n_channels = inlet.info().channel_count();
            string_buffer = new string[n_channels]; // Allocate string buffer based on number of channels
        }

        void Update()
        {
            if (inlet != null)
            {
                double[] timestamps = new double[1]; // Assuming one sample per pull
                double samples_returned = inlet.pull_sample(string_buffer, 0.0f);
                if (samples_returned > 0)
                {
                    string received_marker = string_buffer[0]; // Process the first channel of the latest sample
                    Debug.Log("Received marker: " + received_marker);
                    ProcessMarker(received_marker);
                }
            }
        }

        private void ProcessMarker(string marker)
        {
            // Here, you would add code to process the string marker
            // Example: Adjusting GameObject's visibility based on marker content
            if (marker == "Show")
            {
                gameObject.SetActive(true);
            }
            else if (marker == "Hide")
            {
                gameObject.SetActive(false);
            }
        }

        private void OnApplicationQuit()
        {
            if (inlet != null)
            {
                inlet.close_stream();
            }
        }
    }
}

Thank you very much and sorry to disturb you! Hopefully, we will be able to solve this!

Greetings,
AF

@Aleclock
Copy link

Aleclock commented May 31, 2024

I faced a similar problem.

I was interested in creating a wireless connection between an Android device and a PC (with a python script) using Unity. Here a step-by-step guide on how I did it Unity side

  1. Download lsl unity as zip (or as GitHub package, should work either way)
    • Extract and put inside Assets Folder

    • Remove Plugins > LSL > Windows > x86 folder (or the architecture you don’t need)

    • Update the Android Manifest (should be in Assets > Plugins > Android)
      If not present —> Player Settings -> Player -> Publishing Settings -> Build-> Custom Main Manifest (check)

      Add these lines

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
  1. Download the .so files from here

    • Move them into Plugins > Android > arm64-v8a
    • Change the Android CPU Architecture to ARM64 (for Quest 2) or to your architecture
  2. Change the target architecture according to the device

    • Project Setting > Player > Configuration > Set Scripting backend as IL2CPP
    • Several Target Architecture should be enabled now
    • Check you architecture (ARM64)
    • You can leave ARMv7 checked
  3. In Build Setting > Platform set to Android

  4. Build

INFO:

  • The connection should only works with guest/private network;
  • (Windows) For guest/private network you may need to disable the firewall (Windows Defender Firewall > Turn Windows Firewall on or off
    • These settings are important when PC is a sender, otherwise it should be able to receive everything with the firewall turned on (not sure)

Unity versions tested: 2022.3.24f1, 2022.3.10.f1 and 2022.3.6f1
Device tested: Quest 2, Quest 3, Oneplus One Samsung Galaxy s22 Ultra

@cboulay
Copy link
Collaborator

cboulay commented May 31, 2024

@Aleclock , that's awesome, thank you!

Would you be willing to add this to the README or a separate Android.md file via a pull request?
Also, you can attach those .so and .meta files somewhere in the repo that makes sense.

@lukeskyyyyy
Copy link

Thank you. I've followed all the steps you provided, but unfortunately, I’m still unable to establish communication between my PC and the headset. I’m using Unity 2021.3.16f1 with Quest 2 and Quest 3.

Do you have any suggestions on what might be causing the issue?

@Aleclock
Copy link

Aleclock commented Sep 3, 2024

I'm sorry but I don't know what the problem could be. I tried multiple times and everytime worked properly.
The more subtle problems are related to the network and the Project setting configurations.

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

No branches or pull requests

4 participants