How to integrate unity3d and Solace pubsub?

shima
shima Member Posts: 16
edited November 2021 in PubSub+ Event Broker #1

Hi I am very happy that I can join to your community.

Since some months ago I was working with solace pub sub+ and now I want to integrate Solace to unity3d for publishing messages from unity to Solace I didn't have any problem but to receive data from Solace and using unity as a subscriber I had lots of problem and I couldn't do that.
I would be apricated it if you could help me or connecting me to someone that works with unity and Solace.

Tagged:

Answers

  • hong
    hong Guest Posts: 480 ✭✭✭✭✭

    @shima, can you provide more info about the problems you're having so that others can help you?

  • shima
    shima Member Posts: 16
    edited November 2021 #3

    I want to receive messages from Solace and show it in the unity console. Using
    https://docs.solace.com/Solace-PubSub-Messaging-APIs/dotNet-API/net-api-home.htm https://github.com/SolaceSamples/solace-samples-dotnet https://tutorials.solace.dev/dotnet/publish-subscribe/

    First I added dll files to unity. Then I make this script and added it to camera.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System;
    using System.Text;
    using SolaceSystems.Solclient.Messaging;
    using System.Threading;
    using UnityEngine.UI;
    public class Newsub : MonoBehaviour
    {
            #region start
            void start()
            {
               Debug.Log("1");
               string host = "localhost";
               string username = "admin";
               string vpnname = "default";
               string password = "admin";
    
               // Initialize Solace Systems Messaging API with logging to console at Warning level
               ContextFactoryProperties cfp = new ContextFactoryProperties()
               {
                   SolClientLogLevel = SolLogLevel.Warning
               };
               cfp.LogToConsoleError();
               ContextFactory.Instance.Init(cfp);
    
               try
               {
                   // Context must be created first
                   using (IContext context = ContextFactory.Instance.CreateContext(new ContextProperties(), null))
                   {
                       // Create the application
                       using (TopicSubscriber topicSubscriber = new TopicSubscriber()
                       {
                           VPNName = vpnname,
                           UserName = username,
                           Password = password
                       })
                       {
                           // Run the application within the context and against the host
                           topicSubscriber.Run(context, host);
                       }
    
                   }
               }
               catch (Exception ex)
               {
                   Console.WriteLine("Exception thrown: {0}", ex.Message);
               }
               finally
               {
                   // Dispose Solace Systems Messaging API
                   ContextFactory.Instance.Cleanup();
               }
               Console.WriteLine("Finished.");
               Console.WriteLine("message");
               Debug.Log("message");
           }
           #endregion
    
    
    
    
        /// <summary>
        /// Demonstrates how to use Solace Systems Messaging API for subscribing to a topic and receiving a message
        /// </summary>
        public class TopicSubscriber : IDisposable
        {
            public string VPNName { get; set; }
            public string UserName { get; set; }
            public string Password { get; set; }
    
            public const int DefaultReconnectRetries = 3;
    
            public ISession Session = null;
            public EventWaitHandle WaitEventWaitHandle = new AutoResetEvent(false);
    
            public void Run(IContext context, string host)
            {
                // Validate parameters
                if (context == null)
                {
                    throw new ArgumentException("Solace Systems API context Router must be not null.", "context");
                }
                if (string.IsNullOrWhiteSpace(host))
                {
                    throw new ArgumentException("Solace Messaging Router host name must be non-empty.", "host");
                }
                if (string.IsNullOrWhiteSpace(VPNName))
                {
                    throw new InvalidOperationException("VPN name must be non-empty.");
                }
                if (string.IsNullOrWhiteSpace(UserName))
                {
                    throw new InvalidOperationException("Client username must be non-empty.");
                }
    
                // Create session properties
                SessionProperties sessionProps = new SessionProperties()
                {
                    Host = host,
                    VPNName = VPNName,
                    UserName = UserName,
                    Password = Password,
                    ReconnectRetries = DefaultReconnectRetries
                };
    
                // Connect to the Solace messaging router
                Console.WriteLine("Connecting as {0}@{1} on {2}...", UserName, VPNName, host);
                // NOTICE HandleMessage as the message event handler
                Session = context.CreateSession(sessionProps, HandleMessage, null);
                ReturnCode returnCode = Session.Connect();
                if (returnCode == ReturnCode.SOLCLIENT_OK)
                {
                    Console.WriteLine("Session successfully connected.");
    
                    // This is the topic on Solace messaging router where a message is published
                    // Must subscribe to it to receive messages
                    Session.Subscribe(ContextFactory.Instance.CreateTopic("tutorial/topic"), true);
    
                    Console.WriteLine("Waiting for a message to be published...");
                    WaitEventWaitHandle.WaitOne();
                }
                else
                {
                    Console.WriteLine("Error connecting, return code: {0}", returnCode);
                }
            }
    
            /// <summary>
            /// This event handler is invoked by Solace Systems Messaging API when a message arrives
            /// </summary>
            /// <param name="source"></param>
            /// <param name="args"></param>
            public void HandleMessage(object source, MessageEventArgs args)
            {
                Console.WriteLine("Received published message.");
                // Received a message
                using (IMessage message = args.Message)
                {
                    // Expecting the message content as a binary attachment
                    Console.WriteLine("Message content: {0}", Encoding.ASCII.GetString(message.BinaryAttachment));
                    // finish the program
                    WaitEventWaitHandle.Set();
                }
            }
    
            #region IDisposable Support
            private bool disposedValue = false;
    
            protected virtual void Dispose(bool disposing)
            {
                if (!disposedValue)
                {
                    if (disposing)
                    {
                        if (Session != null)
                        {
                            Session.Dispose();
                        }
                    }
                    disposedValue = true;
                }
            }
    
            public void Dispose()
            {
                Dispose(true);
            }
            #endregion
    
            /*#region start
             void start()
             {
                string host = "localhost";
                string username = "admin";
                string vpnname = "default";
                string password = "admin";
    
                // Initialize Solace Systems Messaging API with logging to console at Warning level
                ContextFactoryProperties cfp = new ContextFactoryProperties()
                {
                    SolClientLogLevel = SolLogLevel.Warning
                };
                cfp.LogToConsoleError();
                ContextFactory.Instance.Init(cfp);
    
                try
                {
                    // Context must be created first
                    using (IContext context = ContextFactory.Instance.CreateContext(new ContextProperties(), null))
                    {
                        // Create the application
                        using (TopicSubscriber topicSubscriber = new TopicSubscriber()
                        {
                            VPNName = vpnname,
                            UserName = username,
                            Password = password
                        })
                        {
                            // Run the application within the context and against the host
                            topicSubscriber.Run(context, host);
                        }
    
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception thrown: {0}", ex.Message);
                }
                finally
                {
                    // Dispose Solace Systems Messaging API
                    ContextFactory.Instance.Cleanup();
                }
                Console.WriteLine("Finished.");
                Console.WriteLine("message");
                Debug.Log("message");
            }
            #endregion*/
        }
    
    
    
    }
    

    Actually I want to run Topicsubscriber from this link in unity
    https://github.com/SolaceSamples/solace-samples-dotnet.

    I would be appreciate it if you can help me and if you want I can send my unity file.

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 538 admin

    Hey @shima - what is the error you got when attempting to run your subscriber?

  • shima
    shima Member Posts: 16

    Hey Tamimi, actually first I run your code as a subscriber in visual studio and it works but when I use this code and run it in unity I couldn't receive anything from my Solace publisher. It doesn't show anything in console.
    I used your Topic publisher code and I could to send message from unity to solace( here Solace was my subscribrer) but I don't know where is the problem in unity that I couldn't receive messages in it.

    In advance thanks for your help.

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 538 admin

    Thanks for the details on this Shima. Some important things to look for is
    1. Your connection parameters and
    2. Topics you are publishing/subscribing to

    Since your TopicPublisher sample application was able to connect to the Solace Broker, this leaves us with potentially a mismatch topic subscription. It looks like your TopicSubscriber is attempting to subscribe to topic tutorial/topic. How are you testing the subscription process? I am assuming you are running the TopicSubscriber application on unity, and from your Solace Broker management console TryMe tab you are publishing on tutorial/topic correct? Please confirm the setup.

    The TopicSubscriber samples has a couple of console writes so are you able to see some logs in the console confirming successful connection to the Solace BrokerConsole.WriteLine("Session successfully connected.");?

  • shima
    shima Member Posts: 16

    Thanks for your information Tamimi.
    Actually our team was working with Solace from some months ago also in some questions our team got some helps from you.
    As I mentioned I could run your Topicsubscriber code in vs with this topic and this connection parameters with the Solace Broker management console TryMe tab and it works , I think my problem is related to unity if someone works with unity and solace maybe can help me more but I didn't find anyone in unity community that works with Solace.
    In vs I got good results from the GitHub c# samples but in unity in console I didn't receive any log even I put " Debug.Log("1");" in the start function in the fist line but it doesn't print it in the console if you want I can send my unity file completely.

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 538 admin

    Hmm interesting. and you mentioned that you did not change any of the TopicSubscriber or TopicPublisher code correct? I'll keep an eye opened to see if there are any particular unity related caveats you have to take into account.

    If you made changes to the files from the samples found on the github repo can you mention what changes you made?

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 538 admin

    Potentially as well another thing you can confirm on your broker managment console, you can check the connected clients. Run your subscriber in unity and confirm if the client is detected on the broker as a client connection. If you cant find it this means that the connection was not successful

  • shima
    shima Member Posts: 16
    edited December 2021 #10

    So thanks for your support.
    Specifically I want to know that which part of this code is related to start function in unity and which part is related to another options in unity?
    In terms of the clients I checked that even when I don't have any subscriber it shows one subscriber and when I run unity it doesn't add another subscriber now I don't understand when I don't have any subscriber why it shows one as default subscriber?

    To run topicpublisher I changed the code like below, this code will send the position of my object to Solace broker.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System;
    using System.Text;
    using SolaceSystems.Solclient.Messaging;
    
    public class NewBehaviourScript : MonoBehaviour
    {
        public float speed;
        public static string position;
    
    
        public void Update()
        {
            float horizontal = Input.GetAxis("Horizontal") * Time.deltaTime * speed;
            transform.Translate(horizontal, 0, 0);
            Vector3 pos = transform.position;
            position = pos.ToString();
    
    
            Debug.Log(position);
    
    
            string host = "localhost"; // Solace messaging router host name or IP address
            string username = "admin";
            string vpnname = "default";
            string password = "admin";
    
            // Initialize Solace Systems Messaging API with logging to console at Warning level
            ContextFactoryProperties cfp = new ContextFactoryProperties()
            {
                SolClientLogLevel = SolLogLevel.Warning
            };
            cfp.LogToConsoleError();
            ContextFactory.Instance.Init(cfp);
    
            try
            {
                // Context must be created first
                using (IContext context = ContextFactory.Instance.CreateContext(new ContextProperties(), null))
                {
                    // Create the application
                    TopicPublisher topicPublisher = new TopicPublisher()
                    {
                        VPNName = vpnname,
                        UserName = username,
                        Password = password
                    };
    
                    // Run the application within the context and against the host
                    topicPublisher.Run(context, host);
    
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception thrown: {0}", ex.Message);
            }
            finally
            {
                // Dispose Solace Systems Messaging API
                ContextFactory.Instance.Cleanup();
            }
            Console.WriteLine("Finished.");
        }
    
    
    
        public class TopicPublisher : NewBehaviourScript
        {
            public string VPNName { get; set; }
            public string UserName { get; set; }
            public string Password { get; set; }
    
            public const int DefaultReconnectRetries = 3;
    
    
    
            public void Run(IContext context, string host)
            {
                // Validate parameters
                if (context == null)
                {
                    throw new ArgumentException("Solace Systems API context Router must be not null.", "context");
                }
                if (string.IsNullOrWhiteSpace(host))
                {
                    throw new ArgumentException("Solace Messaging Router host name must be non-empty.", "host");
                }
                if (string.IsNullOrWhiteSpace(VPNName))
                {
                    throw new InvalidOperationException("VPN name must be non-empty.");
                }
                if (string.IsNullOrWhiteSpace(UserName))
                {
                    throw new InvalidOperationException("Client username must be non-empty.");
                }
    
                // Create session properties
                SessionProperties sessionProps = new SessionProperties()
                {
                    Host = host,
                    VPNName = VPNName,
                    UserName = UserName,
                    Password = Password,
                    ReconnectRetries = DefaultReconnectRetries
                };
    
                // Connect to the Solace messaging router
                Console.WriteLine("Connecting as {0}@{1} on {2}...", UserName, VPNName, host);
                using (ISession session = context.CreateSession(sessionProps, null, null))
                {
                    ReturnCode returnCode = session.Connect();
                    if (returnCode == ReturnCode.SOLCLIENT_OK)
                    {
                        Console.WriteLine("Session successfully connected.");
                        PublishMessage(session);
                    }
                    else
                    {
                        Console.WriteLine("Error connecting, return code: {0}", returnCode);
                    }
                }
            }
    
            public void PublishMessage(ISession session)
            {
                //position = NewBehaviourScript.position;
                // Create the message
                using (IMessage message = ContextFactory.Instance.CreateMessage())
                {
                    message.Destination = ContextFactory.Instance.CreateTopic("tutorial/topic");
                    // Create the message content as a binary attachment
                    message.BinaryAttachment = Encoding.ASCII.GetBytes(position);
    
                    // Publish the message to the topic on the Solace messaging router
                    Console.WriteLine("Publishing message...");
                    ReturnCode returnCode = session.Send(message);
                    if (returnCode == ReturnCode.SOLCLIENT_OK)
                    {
                        Console.WriteLine("Done.");
                    }
                    else
                    {
                        Console.WriteLine("Publishing failed, return code: {0}", returnCode);
                    }
                }
            }
    
    
        }
    
        // Start is called before the first frame update
        void Start()
        {
    
            speed = 10f;
        }
    
    
    }
    
    
  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 538 admin

    So thats a start, if you dont see a client connection on your broker being added when you start your subscriber on unity, then the issue is with connection.

    Do you have your code on a github repo we can take a look at it? Maybe your TopicSubscriber code is not reaching session.Connect(). Try adding some console logs in the following code blocks to better understand the behaviour of your topicSubscriber

                Console.WriteLine("Connecting as {0}@{1} on {2}...", UserName, VPNName, host);
                // NOTICE HandleMessage as the message event handler
                Session = context.CreateSession(sessionProps, HandleMessage, null);
                ReturnCode returnCode = Session.Connect();
                if (returnCode == ReturnCode.SOLCLIENT_OK)
                {
                    Console.WriteLine("Session successfully connected.");
    
                    // This is the topic on Solace messaging router where a message is published
                    // Must subscribe to it to receive messages
                    Session.Subscribe(ContextFactory.Instance.CreateTopic("tutorial/topic"), true);
    
                    Console.WriteLine("Waiting for a message to be published...");
                    WaitEventWaitHandle.WaitOne();
                }
                else
                {
                    Console.WriteLine("Error connecting, return code: {0}", returnCode);
                }
    

    I got this from here https://github.com/SolaceSamples/solace-samples-dotnet/blob/master/src/TopicSubscriber/TopicSubscriber.cs#L77-L96.

    Regarding this question you had:

    In terms of the clients I checked that even when I don't have any subscriber it shows one subscriber and when I run unity it doesn't add another subscriber now I don't understand when I don't have any subscriber why it shows one as default subscriber?

    is it a #client-username client? It might be either a default client or one of your TryMe connections. It might be difficult to tell without having any further information on what youre seeing

    And btw, I modified your last comment to include ``` before and after your codeblock for better code formatting in comments :)

  • shima
    shima Member Posts: 16

    Thanks for your help based on your suggestions I found the problem.

  • hong
    hong Guest Posts: 480 ✭✭✭✭✭

    That's great. @shima, can you accept the best answer for the benefit of other community members?

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 538 admin

    Hey @shima - thats great !! Curious to know what was the issue? How were you able to resolve it? it'll be great to share here in case someone else has the same issue :)

  • shima
    shima Member Posts: 16

    Hi Tamimi,
    Sorry for my delay in answer,
    In the HandleMessage class after receiving the message I changed it to string and with debug.log I showed it in the console.