GUIClient

  • 1
  • Question
  • Updated 4 months ago
I probably should have asked this long ago, but what is the GUIClient structure all about?  I presume it relates to the multi-user feature introduced in V3, but I've been able to muddle along without considering it, and maybe I need to do so, even though my client doesn't support multiple users.


I do get a GUIClientAdded event using FlexLib 2.5.1.
Photo of Jim Shaffer (KE5AL)

Jim Shaffer (KE5AL)

  • 70 Posts
  • 2 Reply Likes

Posted 5 months ago

  • 1
Photo of Mark - W3II

Mark - W3II

  • 260 Posts
  • 55 Reply Likes

My response is for persons using the V3 FlexAPI with a V2.5 or V3.+ radio.


For V3 radios the GUIClient represents the 1 or 2 connected clients to the radio. When you implement a non-GUI client to control the radio it should be in context to 1 of the the two possible clients. I have noticed the radio status sent to the non-GUI clients changes depending if you are bound to a client or not. In short it depends on what your are doing with the Flex API if binding to client matters. To err on the side of caution I would bind to a client. In most use cases there is only one client so binding takes no user input. When you discover there are two connected GUI clients sharing the radio you should bind to the client you want to share control with. Hopefully this was more helpful than confusing. For V2 this property can be ignored. Note the radio object contains its version from discovery which is before you connect to it.

73 
Photo of Jim Shaffer (KE5AL)

Jim Shaffer (KE5AL)

  • 72 Posts
  • 2 Reply Likes
Thanks Mark.  I'm using FlexLib 2.5.1 and setting API.IsGUI = true.  I always see a GUIClient added after I connect, and then it gets removed later.  At this point, I'm not sure what the GUIClient signifies if anything.  Is it just for nonGUI clients?
Photo of Jim Shaffer (KE5AL)

Jim Shaffer (KE5AL)

  • 72 Posts
  • 2 Reply Likes
So if I understand correctly, a Version 3 radio can support two GUI clients, and an application binds to the client it is supporting.
I'd be interested to see how this is done though,  That's what I've been trying to get a handle on.
Photo of James Whiteway

James Whiteway

  • 1089 Posts
  • 305 Reply Likes
I'm away from my computer right now.( over the road trucker)
But, will be back by Saturday.
When you first connect to your radio, one of the responses back from the radio s the ClientID for your application. It is assigned each time you connect to the radio and is different each time you reconnect. When you subscribe to events like the panadapter and waterfall, you can compare the ClientID to the ID's for the panadapter and/or waterfall. And if they are the same you can process the data for your application.
If you don't, you'll get some really strange things happening.
( double panadapter traces for one)
In Visual Studio 2019 Community edition, you can set watches for different things and watch the incoming data.
What language are you programming with?
The FlexLib API is written in C#. I find it easier to use the same language rather than using a different language.
( I started out using Visual Basic. But, I found it a hassle getting the syntax correct to work with dll's written in C#)
James
WD5GWY
Photo of Jim Shaffer (KE5AL)

Jim Shaffer (KE5AL)

  • 72 Posts
  • 2 Reply Likes
This is a long post.
As I've mentioned, I don't really understand how to use  the GUIClient structure.  
I've written the following little test program which uses FlexLib V3.1.7.  It just connects to the first radio on my LAN, waits 5 seconds, then disconnects.  I notice that I do get a GUIClient object created, along with a panadapter and a slice, but the GUIClient is then removed.  I'm not sure what that's all about.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using Flex.Smoothlake.FlexLib;

namespace testFlexV3_2
{
    class Program
    {
        private static Radio theRadio { get { return (API.RadioList.Count == 0) ? null : API.RadioList[0]; } }

        static void Main(string[] args)
        {
            API.IsGUI = true;
            API.ProgramName = "testFlexV3_2";
            API.RadioAdded += radioAddedHandler;
            API.Init();

            // await a radio.
            while (theRadio == null) { Thread.Sleep(100); }
            Debug.WriteLine("dbg:radio found:" + theRadio.Serial);

            connect();

            // just wait 5 seconds.
            Thread.Sleep(5000);

            // done
            Debug.WriteLine("dbg:testing done");
            if (theRadio != null)
            {
                if (theRadio.Connected) theRadio.Disconnect();
            }
            API.CloseSession();

            Console.Write("Press Enter to end:");
            string dmy = Console.ReadLine();
            Environment.Exit(0);
        }

        private static void radioAddedHandler(Radio r)
        {
            Debug.WriteLine("dbg:radioAddedHandler:" + r.Serial);
            API.RadioList.Add(r);
        }

        private static bool connect()
        {
            Debug.WriteLine("dbg:connect:");
            theRadio.GUIClientAdded += guiClientAddedHandler;
            theRadio.GUIClientRemoved += guiClientRemovedHandler;
            theRadio.PanadapterAdded += panAdapterAddedHandler;
            theRadio.PanadapterRemoved += panAdapterRemovedHandler;
            theRadio.SliceAdded += sliceAddedHandler;
            theRadio.SliceRemoved += sliceRemovedHandler;

            bool rv = theRadio.Connect();
            if (rv)
            {
                Debug.WriteLine("dbg:connect:connected to" + theRadio.Serial);
            }
            else
            {
                Debug.WriteLine("dbg:connect:not connected");
            }
            return rv;
        }

        internal static GUIClient myClient = null;
        private static void guiClientAddedHandler(GUIClient client)
        {
            Debug.WriteLine("dbg:guiClientAdded:" +
                client.ClientID + ' ' +
                client.IsThisClient.ToString() + ' ' +
                client.ClientHandle + ' ' +
                client.Program + ' ' +
                client.Station + ' ' +
                client.IsLocalPtt.ToString() + ' ' +
                client.IsAvailable.ToString());

            if (myClient == null) myClient = client;
        }

        private static void guiClientRemovedHandler(GUIClient client)
        {
            Debug.WriteLine("dbg:guiClientRemovedHandler:" + client.ClientID);
            if ((myClient != null) && (myClient.ClientID == client.ClientID)) myClient = null;
        }

        internal static List<Panadapter> panAdapters = new List<Panadapter>();
        private static void panAdapterAddedHandler(Panadapter pan, Waterfall w)
        {
            Debug.WriteLine("dbg:panAdapterAddedHandler:" + pan.ToString());
            panAdapters.Add(pan);
        }

        private static void panAdapterRemovedHandler(Panadapter pan)
        {
            Debug.WriteLine("dbg:panAdapterRemovedHandler:" + pan.ToString());
            panAdapters.Remove(pan);
        }

        internal static List<Slice> slices = new List<Slice>();
        private static void sliceAddedHandler(Slice s)
        {
            Debug.WriteLine("dbg:sliceAddedHandler:" + s.ToString());
            slices.Add(s);
        }

        private static void sliceRemovedHandler(Slice s)
        {
            Debug.WriteLine("dbg:sliceRemovedHandler:" + s.ToString());
            slices.Remove(s);
        }
    }
}

Why is the GUIClient removed?
Program output minus compiler and FlexLib debug statements:
dbg:radioAddedHandler:1514-3154-6500-6354
dbg:radio found:1514-3154-6500-6354
dbg:connect:
dbg:connect:connected to1514-3154-6500-6354
dbg:guiClientAdded:D793F854-AB48-4BA9-9D05-DE6ED73287A2 True 2313758720 testFlexV3_2  True True
dbg:panAdapterAddedHandler:Flex.Smoothlake.FlexLib.Panadapter
dbg:sliceAddedHandler:0: 14.100000 USB [100,2800]
dbg:guiClientRemovedHandler:D793F854-AB48-4BA9-9D05-DE6ED73287A2
(removed prior to the disconnect.)
dbg:testing done (disconnect)
dbg:sliceRemovedHandler:0: 14.100000 USB [100,2800]
dbg:panAdapterRemovedHandler:Flex.Smoothlake.FlexLib.Panadapter

Photo of Mark - W3II

Mark - W3II

  • 260 Posts
  • 55 Reply Likes
This is caused because you are not setting Station name.
The parsing logic for GUIClients assumes there is a station name.
Immediately after connect call the following.

theRadio.SetClientStationName("TESTSTATION");

Now you will see the gui client object show up due to discovery, be removed then show up again due to connection with additional properties set.

ALSO:
You should not be adding or removing radio objects from the API.RadioList list.
This list is maintained by the FlexAPI DLL.
Remove the handler below or minimally remove the Add to the RadioList 


   private static void radioAddedHandler(Radio r)
        {
            Debug.WriteLine("dbg:radioAddedHandler:" + r.Serial);
            API.RadioList.Add(r);
        }
Photo of Jim Shaffer (KE5AL)

Jim Shaffer (KE5AL)

  • 72 Posts
  • 2 Reply Likes
Thanks Mark.  I'm not sure where that use of API.RadioList came from.  I really do know better than that.
Photo of Mark - W3II

Mark - W3II

  • 260 Posts
  • 55 Reply Likes
If you are connecting as the GUI client then you are all set. BTW are you a GUI client or a utility? The reason I ask is on a V2 radio there can be only 1 GUI client therefore your app can't run if SmartSDR / Maestro is connected. Or on V3 if there are already 2 clients connected.