Steps to initalize the radio without SmartSDR

  • 2
  • Question
  • Updated 3 years ago
  • Answered
In my continuing studies on relearning C# and working with Flexlib, I was wondering in what order does the radio need to be initialized from an application that does not depend on the SmartSDR client running.  I am playing around with a small app for a Windows tablet I have, and at some point an Android tablet as well, that would control the radio over my LAN and WiFi connection.
I can control the radio, (to a point) from the tablet as long as SmartSDR is running. But, it is slow and uses too many resources (cpu cycles) at present. So, my goal is to eliminate using SmartSDR for a simple interface that should, in theory, be able to control the radio and once v1.4 comes out, I'm betting I can add audio back to the tablet as well.
Any clues on what needs to occur would be appreciated. 
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes

Posted 4 years ago

  • 2
Photo of IW7DMH, Enzo

IW7DMH, Enzo

  • 353 Posts
  • 84 Reply Likes
Hello James,

reading this post probably will help you
https://community.flexradio.com/flexradio/topics/smartsdr-tcp-ip-api-starting-demodulation-and-receiver-using-telnet
Stu helped me to start the receiver using only a telnet client.
You should follow the same logic (few simple commands actually) but using FlexLib api.

73' Enzo
iw7dmh
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
Thanks for the link Enzo! That gives me a better idea on what settings need to happen.
james
WD5GWY
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
Just a little update on my "attempts" to initialize the radio without SSDR running. The code below
will start the radio just fine:


 _thisRadio.Connect();
            double freq = 14.290d;
            string RXA = "Ant 1";
            string Mode = "USB";
           
            Slice Slice0 = new Slice(_thisRadio);
            Slice0 = _thisRadio.CreateSlice(freq, RXA, Mode);
            Slice0.RequestSliceFromRadio();


But, I have no control over the radio. And, on my testbed form, the only things that are properly updated are the frequency, antenna selected and Mode. Visual Studio throws an exception for all other events that I normally would be able to display were SSDR running at the same time.
I can start SSDR after stopping execution of my program in Visual Studio and everything I have set will be displayed on the Panafall. But, the Panafall's gain is wrong and several other settings as well. Closing SSDR and restarting puts everything back to normal.
The code above was "borrowed" from another post in the API forum and is further kludged by me and not the original author!
I figure I need to initialize a bunch of other things, such as AGC, Band, etc. but, I don't know if I should do that before or after calling: Slice0.RequestSliceFromRadio();

I figure that getting the above correct will help in my attempts to create a panadapter as well.
So, any pointers on this will be appreciated.
james
WD5GWY

 Edit: since we now have a Persistence database in the radio itself, (unless I've greatly misunderstood something) would it be possible to start the radio and have my program use the database to set the radio to it's previous state? It sure would make things easier!
 

(Edited)
Photo of Walt - KZ1F

Walt - KZ1F

  • 3040 Posts
  • 643 Reply Likes
Absolutely, I routinely navigate between my, um, other SSDR and SSDR. I could have sworn I've had them both running at the same time. I had a heck of a time getting the order straight and, frankly, I think the radio behaves far better when you've entered "client gui" than if you don't. So, yes to your question, you can predictable start it where the other left off.
So, you have 3 events
1) OnRadioAdded, (or for those with deeper pockets, radio choosen)
2) OnPanadapterCreated
3) OnSliceCreated

You should definitely respond to these things as asynchronous events
then,

1) OnRadioAdded( Radio radio) {
             PanadapterAddedEventHandler panAdded = (Panadapter panx, Waterfall fall) -> processPanAdded(panx, fall);
            PanadapterRemovedEventHandler panRemoved = (Panadapter pan) -> processPanRemoved(pan);
            activeRadio.addPanAddedEventListener(panAdded);
            activeRadio.addPanRemovedEventListener(panRemoved);
           
            SliceEventHandler sliceAdded = (Slice slc) -> processSliceAdded(slc);
            SliceEventHandler sliceRemoved = (Slice slc) -> processSliceRemoved(slc);
           
            SlicePanReferenceChangeEventHandler slcpan = (Slice slc) -> processSliceAdded(slc);
            SlicePanReferenceChangeEventHandler slcpan1 = (Slice slc) -> processSliceRemoved(slc);

            activeRadio.addSliceAddedEventListener(sliceAdded);
            activeRadio.addSliceRemovedEventListener(sliceRemoved);
           
            activeRadio.addSlicePanReferenceChangeListener(slcpan1);
            activeRadio.addObserver(this);
            activeRadio.Connect();

            activeRadio.RequestPanafall();

2) OnPanadapterAdded(Panadapter pan, Waterfall fall) {
        activePan = pan;
        assert(activeRadio.findPanadapterByStreamID(activePan.getStreamID()) != null);
        activePan.addObserver(this);       
        log.debug("Entering processPanAdded" + activePan.toString() + " " + fall.toString());
        PanDataReadyEventHandler tempVar1 = (Panadapter panx, short[] data) -> processPanData(panx, data);
        activePan.addDataReadyEventListeners(tempVar1);


3) OnSliceAdded(Slice slice) {

}

    What I'd do is for all 3 events, first thing, on the OnXXXXAdded, create a class to handle the object and in the constructor, do the C# version of what I am doing in Java. When you get the slice, it will be where you left it, you can send commands through the pan object (one for each panafall), the radio object, and the slice object, one for each slice you create.

Make sense?
(Edited)
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
"Make sense?"
To some degree yes. But, like everything else, I'll have to study it for a while and play with various things till I get the results I need.
Thank you for your help Walt. It is appreciated.
I won't be able to do much with this till next weekend, since I'm going out on the road again today. But, I will definitely dive into it this weekend after HAMCOM!
james
WD5GWY
 
(Edited)
Photo of Walt - KZ1F

Walt - KZ1F

  • 3040 Posts
  • 643 Reply Likes
As I was saying, I had a time getting objects to mated properly. I was still having multiple pans show up and multiple slices show up and I wasn't getting events as I should have. I put client gui in and cleaned up how I requested things and voila! The two SSDR versions are in perfect sync. I am working on a completely kick ass UI now.

One piece of advice though. Don't worry about modifying anything internal objects in your app. Simply get to the point where your app comes up in the same mode that the SSDR was terminated with.
(Edited)
Photo of Eric - KE5DTO

Eric - KE5DTO, Official Rep

  • 676 Posts
  • 204 Reply Likes
James,

Welcome to the API developers club!  The steps to get started with a FlexLib based application are covered in this thread: https://community.flexradio.com/flexradio/topics/first_steps_with_flexlib.  If you have questions, don't hesitate to ask.
Photo of Walt - KZ1F

Walt - KZ1F

  • 3040 Posts
  • 643 Reply Likes
James, what Eric and I are suggesting IS the easy way to accomplish what William was doing. You mentioned you wanted to do what William was doing. I am not going to pass on what he told me, but you might want to directly ask him if he would do it that way again. PLUS, Eric and staff already wrote the library to use in C#. I wrote the library to use in Java but William, who did his work in Java, didn't know that at the time. So if you do what Eric suggested followed by a API.CloseSession() when you are done you'll see that SSDR restarts precisely where it left off, which is one of your concerns. Once you start manipulating the radio or panadapter or slice receiver, once you close SSDR will start where your program left off.
Photo of James Whiteway

James Whiteway

  • 876 Posts
  • 193 Reply Likes
Thank you Walt. When I said I wanted to do what William was doing, I meant writing a program that would run my radio without SSDR . And using Flexlib to do it. I doubt I could do what you and William have done, independent of Flexlib.
james
WD5GWY
Photo of Walt - KZ1F

Walt - KZ1F

  • 3040 Posts
  • 643 Reply Likes
You mean Stu and me? William did not do what Stu and I did, being rewriting the library to support different languages and operating systems..
Look at the code for Cat, that is likely as close as you'll get to examples of using the library
Photo of James Whiteway

James Whiteway

  • 876 Posts
  • 193 Reply Likes
I guess I'm a simpleton. I knew that Stu and you are/ were writing your own versions of Flexlib (Stu doing it in Objective C) . And it seems I also knew that William did not write his own version of Flexlib either. Instead William is working with the Vita packets directly and controlling the radio that way.
But, my point, if there really was one, is this, what William has done just may well be above my skill set. But, I want(ed) to write an application similar to his that would work on my Win 8.1 tablet. And maybe someday dive into Java and do the same for my Android tablet.
All just as a mental exercise. Not with the intention of selling anything. But, I would share the app(s)
and the source code with others with similar thoughts.
(which I've already done to some degree)
So, no disrespect intended to you or Stu. William's app was symbolic of what I want to do. Nothing more.
james
WD5GWY
Photo of Walt - KZ1F

Walt - KZ1F

  • 3040 Posts
  • 643 Reply Likes
Understood, what I and Eric are suggesting is the fastest path to achieving that. In either case the java code I showed you or the C# code Eric showed you, in a dozen stmts you'll have a slice receiver and panadapter to play with. Now, if you don't know how to do a graphical interface, you have a much different problem.I
(Edited)
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
Thanks Eric, that is the info I was missing.
James
WD5GWY
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
Well, "almost" there! I STILL cannot get the radio to send any data back to my program without SSDR running at the same time. Looking at the Wiki, it shows that  api.isGUI  is a bool and can be
set to true. And if I understand correctly, doing so will tell the radio that my application is the gui client and send all data to my application. And that persistence will / should, make the radio return to it's previous state just as it does for SSDR (or my app if I ever get it running right without SSDR)
when it closes down and then is restarted.
The ONLY things I can currently get without SSDR running After doing:  radio.Connect();
is the PA Temp, Voltage data, Callsign and Nickname. IP Address, Serial Number and Model Numbers all show up when my application initially loads. However, if SSDR is already running, I can get ALL the data except Panafall data sent back to my application. And as I understand it, the panafall is not available to both SSDR and another client at the same time. (currently)
  Maybe running almost 4,000 miles this week has slightly fried my brain, (along with having my trailer turn over yesterday morning while dumping out near Austin) but, it seems that the more things I try the less I seem to actually accomplish.
james
WD5GWY

    
(Edited)
Photo of Walt - KZ1F

Walt - KZ1F

  • 3040 Posts
  • 643 Reply Likes
If you want you app to run properly without SmartSDR running, stop running SmartSDR. Yes, some people may consider that a syllogism but it is true. client GUI tells the radio there is only one controlling app (instantiating Radios and Panadapters and Slices, that would be SmartSDR. Eric provided now two examples of how to do it, I provided one as well. I, further, gave you a language independent first steps. James, are you certain you want to do this?
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
Walt, I guess, I am not drawing this picture clear enough. When I run my app without SSDR, what I wrote in my previous post happens, only certain things are returned from the radio to my application. I have set : isGUI to : true, and still, the same results. NO additional info  shows up in my app as it would if  SSDR running at the same time. I have found no statement or setting in Flexlib for "Client GUI" . ONLY : api.isGUI and that is a BOOLEAN object and as far as I can see, that tells the radio that my application , running WITHOUT SSDR running should receive all events.
I have followed Eric's steps and subscribed to the RadioAdded and RadioRemoved events. But, they do not happen as far as I can see. I can only get the three other things I mentioned in my previous post.
  I know you think I am dense, but, MAYBE, someone with some C# experience that could give me the correct syntax to set whatever it is, Client GUI or api.isGUI (which is a bool and does not return an error when set to true) that I am doing wrong.
As for " Client udpport <port#>" that Eric mentioned, he states that that is handled by Flexlib. And I cannot see anywhere in Flexlib where I have to manually set it.
And YES, I am certain I want to do this.
james
WD5GWY
(Edited)
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
I found this in radio.cs :

 // send client program to radio
                if (API.ProgramName != null && API.ProgramName != "")
                    SendCommand("client program " + API.ProgramName);

                if (API.IsGUI) SendCommand("client gui");

                // subscribe for status updates
                SendCommand("sub tx all");
                SendCommand("sub atu all");
                SendCommand("sub meter all");
                SendCommand("sub pan all");
                SendCommand("sub slice all");
                SendCommand("sub gps all");
                SendCommand("sub audio_stream all");
                SendCommand("sub cwx all");
                SendCommand("sub xvtr all");
                SendCommand("sub memories all");
                SendCommand("sub daxiq all");
                SendCommand("sub dax all");

                // get info (name, etc)
                GetInfo();

                // get version info from radio
                GetVersions();

                // get the list of antennas from the radio
                GetRXAntennaList();

                // get list of Input sources
                GetMicList();

                // get list of Profiles
                GetProfileLists();

                // turn off persistence if about to do an update
                if (ConnectedState == "Update")
                    SendCommand("client start_persistence off");

                // set the streaming UDP port for this client
                SendCommand("client udpport " + API.UDPPort);


                StartFFTProcessThread();
                StartMeterProcessThread();

                 // send client program to radio
                if (API.ProgramName != null && API.ProgramName != "")
                    SendCommand("client program " + API.ProgramName);

                if (API.IsGUI) SendCommand("client gui");

                // subscribe for status updates
                SendCommand("sub tx all");
                SendCommand("sub atu all");
                SendCommand("sub meter all");
                SendCommand("sub pan all");
                SendCommand("sub slice all");
                SendCommand("sub gps all");
                SendCommand("sub audio_stream all");
                SendCommand("sub cwx all");
                SendCommand("sub xvtr all");
                SendCommand("sub memories all");
                SendCommand("sub daxiq all");
                SendCommand("sub dax all");

                // get info (name, etc)
                GetInfo();

                // get version info from radio
                GetVersions();

                // get the list of antennas from the radio
                GetRXAntennaList();

                // get list of Input sources
                GetMicList();

                // get list of Profiles
                GetProfileLists();

                // turn off persistence if about to do an update
                if (ConnectedState == "Update")
                    SendCommand("client start_persistence off");

                // set the streaming UDP port for this client
                SendCommand("client udpport " + API.UDPPort);


                StartFFTProcessThread();
                StartMeterProcessThread();

                StartKeepAlive();

                return true;
            }
        }

It would appear that if " isGUI" is set to true by my app Flexlib should direct the radio to send data to my client app. But, for some reason that's not happening.
I have subscribed to the events Eric mentioned and with SSDR running in the background my app receives those events. Just does not happen without it.
Maybe, I'm putting the isGUI in the wrong place.

my app:


 public Form1()
        {
            InitializeComponent();
            API.RadioAdded += API_RadioAdded;
            API.RadioRemoved += API_RadioRemoved;
            API.ProgramName = "WorkingCSharpFlexExample";
            API.IsGUI = true;

            API.Init();
           
        }

If I put it in the form load event, the form shows, but, with NOTHING on it. Completely blank! The only place things seem to work, (again with SSDR running) is prior to the Form Load event.
james
WD5GWY

I'm sure it's the ID 10 T error at work here. But, I cannot tell what I'm doing wrong.
Photo of James Whiteway

James Whiteway

  • 877 Posts
  • 193 Reply Likes
In case Walt misses it in another thread, I owe him an apology for being a bit sharp in my previous responses here. Frustration can do that sometimes. Anyway, IT WORKS NOW! And without SSDR running at all.
Thank you Walt, Eric and everyone else who offered advice and put up with my poorly worded questions. It is appreciated!
james
WD5GWY
Photo of Walt - KZ1F

Walt - KZ1F

  • 3040 Posts
  • 643 Reply Likes
ID 10 T?
Why do you think anything at all will show in your form?
Here is the thing James, unless it was a dbl tap insert you are doing things multiple times and 4 of the last 6 things don't even make sense. Here is what I suggest:

1) don't put anything into a program unless you can explain what it is supposed to do. The vast majority of what you have there you do not need. Compare that to this,

    private boolean launchDiscovery() {
        RadioAddedEventHandler onRadioAdded = (Radio radio) -> onRadioAdded(radio);
        api.addRadioAddedListener(onRadioAdded);
        API.setProgramName("OtherSmartSDR");
        api.setGUI(true);
        api.Init();
        return true;

Forget, for the moment it's not C#. What did I just do?
1) created a RadioAdded callback, regardless of what it is called in any given language, it is the sink for the event that will be raised when a radio is discovered and deemed not to be a duplicate, which will happen every second.

2) I told the API class about it, so now API knows to add that method as a sink when it finds a radio.

3) I set the program name...a totally futile thing to do as the radio returns an error to being given the program name, I just haven't removed it as it demonstrates the radio returning an error condition.

4) set GUI to true

5) invoked API.Init().

So, regardless of language differences, get that much working in yours. The sink for onRadioAdded takes the radio object, chances are really good it will be a single radio unless you have multiple 6000 series radios. You will need that method in order to create the panadapter. But, your 'assignment' for now is just getting that much working. Bonus points, add the name to your form. That is not part of your 'assignment' I want you to get a notification you have a radio. That's it. BTW, I've taught programming in several settings, several different languages.

And do this without running SmartSDR. The other key point is do not add a line of code you can't explain what it does and why it works.

If you did not write a method called API_RadioAdded, then you need to write your own.