Unable to send/recieve websocket messages properly

hi,

I am able to connect to the speckle server below and i can see that my message is sent apparently. I am able to receive messages from the speckle web server. However i can not unpack what is being sent on another ws client connected and listening to the same stream… so i cannot tell if the message i’m trying to send onOpen() works is valid… i’m guessing not despite converting it to a json string

I’m using WebSocketSharp and Newtonsoft.Json libraries in c#.

using System;
using System.Collections.Generic;
using WebSocketSharp;
using System.Text;
using Newtonsoft.Json;

namespace SpkConsole
{
    partial class Program
    {
        static void Main(string[] args)
        {
            string ClientId = Guid.NewGuid().ToString();
            string AuthToken = "JWT+myjwt";
            string StreamId = "0HPUn-dvE";
            WebSocket WebsocketClient = new WebSocket("wss://hestia.speckle.works?access_token=" + AuthToken + "&stream_id=" + StreamId + "&client_id=" + ClientId);
            WebsocketClient.OnMessage += (sender, e) => Console.WriteLine("computer says: " + e.Data);
            WebsocketClient.OnOpen += (sender, e) => {
                Dictionary<string, object> message = new Dictionary<string, object>();
                message["eventType"] = "broadcast";
                message["senderId"] = ClientId;
                message["resourceType"] = "stream";
                message["resourceId"] = StreamId;
                message["args"] = new Dictionary<string, string>
                {
                    { "stream" , "KiAKG2AsS"},
                    { "action" , "update_mesh"}
                };
                WebsocketClient.Send(JsonConvert.SerializeObject(message));
                Console.WriteLine("just sent: " + JsonConvert.SerializeObject(message));
            };
            WebsocketClient.OnError += (sender, e) => Console.WriteLine("Error: " + e.Message);
            WebsocketClient.OnClose += (sender, e) => Console.WriteLine("Closing: " + e.Reason);
            WebsocketClient.ConnectAsync();
            Console.ReadLine();           
        }
    }
}

Hola @pathespe! Sorry for the delay. But I got something running, based on SpeckleCore’s ApiClient ws methods.

I’ll admit, it’s a bit of a pain.

using System;
using System.Threading;
using SpeckleCore;
using SpkConsole;

namespace SpkWsExample
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Hello Smelly Sockets");

      var account = SpkConsole.Program.GetAccount();

      var spkClient_A = new SpeckleApiClient(account.RestApi, false, "console application");
      var spkClient_B = new SpeckleApiClient(account.RestApi, false, "console application");
      spkClient_A.AuthToken = account.Token;
      spkClient_B.AuthToken = account.Token;

      //gen streamid
      var streamId = spkClient_A.StreamCreateAsync(new SpeckleStream() { Name = "WS Test" }).Result.Resource.StreamId;
      Console.WriteLine($"Created dummy stream: {streamId}. Press any key to continue stuff.");

      // Add event handlers and setup streamId on both ws clients. The event handlers just spit out what they get. 
      spkClient_A.StreamId = streamId;
      spkClient_A.SetupWebsocket();
      spkClient_A.OnWsMessage += SpkClient_A_OnWsMessage;

      spkClient_B.StreamId = streamId;
      spkClient_B.SetupWebsocket();
      spkClient_B.OnWsMessage += SpkClient_B_OnWsMessage;


      Console.WriteLine("Waiting for 200ms, ensure connection actually happened. This is an issue with core, it doesn't expose a 'onwsconnection' event :/");
      Thread.Sleep(200);

      // Flop them in a room - this is important if you want to broadcast messages. 
      spkClient_A.JoinRoom("stream", streamId);
      spkClient_B.JoinRoom("stream", streamId);
      
      // Same hack as above. 
      Thread.Sleep(200);

      // Send some dummy broadcasts
      spkClient_A.BroadcastMessage("stream", streamId, new { customEventType = "update-mesh", data = "42" });
      spkClient_A.BroadcastMessage("stream", streamId, new { customEventType = "update-mesh-other", data = "wow" });

      spkClient_B.BroadcastMessage("stream", streamId, new { customEventType = "update-mesh-other", data = "wow" });
      spkClient_B.SendMessage(spkClient_A.ClientId, new { what = "This is a direct, 1-1 message from B to A." });


      Console.WriteLine("Press any key to continue.");
      Console.ReadLine();
    }

    private static void SpkClient_B_OnWsMessage(object source, SpeckleEventArgs e)
    {
      // Note, the dynamic object with the "parsed" event data is in e.EventObject.
      Console.WriteLine(); 
      Console.WriteLine($"(Client B) Event name: {e.EventName}; Raw: {e.EventData}.");
    }

    private static void SpkClient_A_OnWsMessage(object source, SpeckleEventArgs e)
    {
      Console.WriteLine();
      Console.WriteLine($"(Client A) Event name: {e.EventName}; Raw: {e.EventData}.");
    }
  }
}

1 Like

Solved this one for extra points too :smiley: The original approach was ok, just malformed…

      WebsocketClient.OnOpen += (sender, e) =>
      {
        // what i changed: just this! it should pop up in other subscribed clients. 
        var eventData = new
        {
          eventName = "broadcast",
          senderId = ClientId,
          resourceType = "stream",
          resourceId = DummyStreamId,
          args = new
          {
            hello="world",
            source="random client"
          }
        };

        WebsocketClient.Send(JsonConvert.SerializeObject(eventData));
        Console.WriteLine("just sent: " + JsonConvert.SerializeObject(eventData));
      };

And as a reminder to whoever’s going to read this next, this code and more is in the example repo!

1 Like

ahh so close. thanks for this, would double like if i could. exactly what im after

1 Like