First steps with FlexLib

  • 2
  • Question
  • Updated 5 years ago
Hi guys.

Steve and Eric sent me source for FlexLib. I spent a couple of days trying to read and and understand it, but it is too difficult to do without having it well commented and documented. One good news is that it has successfully compiled to DLLs.
So now I need to figure out where to start using it. I have made a couple (unsuccessful so far) attempts to at least discover the radio, using FlexLib and feel myself stuck. Did anybody walk this route and can please help? 

Also, a request to Flex guys. Is it possible to share some pieces of complete and usable code, which will show how different pieces of FlexLib work? Nothing fancy, just examples in C# Console, with a bit of explanations on input and output params and entry point. Sort of Flex analog to MSDN :)

Any advise is highly appreciated!

Paul RN3A
Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes

Posted 5 years ago

  • 2
Photo of Richard Clafton W4/G7EIX

Richard Clafton W4/G7EIX, Elmer

  • 455 Posts
  • 117 Reply Likes

That CAT code is what I used to get familiar with FlexLib, but I dropped it in favor of using the TCP API which offers a lot better flexibility. No waiting for a new codebase to compile.   

 

Now I have my own TCP command interpretor / issuer written I simply have to capture commands from SmartSDR with wireshark to see what's going on. Sort of like learning a new language.

 

I may have the Flexlib test files I created available to let you have. I'm out at the moment though, so will look when I get home.

(Edited)
Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes
I am having some progress with DLLs. Pretty modest so far, but still...There is a number of things which still remain to be unclear.

1. I learned how to read the status of the radio. Receiving model, name and IP. However, the API code first seeks a for a file in Users\Name\Application Data\ Roaming\FlexRadio System\filter.txt. This file does not exist. So I had to /*...*/ parts of the code which refer to this. Is this something left over from development, of is this file still needed? Looking at the code, I don’t think so....

2. When I have my radio running in a normal way with SSDR client open, I can establish second connection to the radio and read / control some radio wide settings. Pretty cool. But I am completely stuck going further to Panadapters and Slices. ObservableCollection for Radio returns nulls for Slices. 

Steve and Eric, can you please briefly outline the sequence of actions needed to start getting pans and slices parameters? And how to control them?

Many thanks in advance.
Photo of Eric - KE5DTO

Eric - KE5DTO, Official Rep

  • 806 Posts
  • 266 Reply Likes
1. The filter.txt file when placed in the "%appdata%\FlexRadio Systems" folder will limit the radios discovered to just those that have a string match in the serial in one of the lines in the file.

So, for example, if a filter.txt file was placed in %appdata%\FlexRadio Systems with just a single line that had 9829 in it, this would allow any discovered radios with serial numbers that contain 9829 in it.  This is a must at FlexRadio HQ as you can imagine we often has numerous radios on our network at once and being able to limit the list of radios shown in the client is helpful.

Note that without the file, it just behaves as a wide open door.  All discovered radios show up.


2. See my response to the main question on this.  I hope this clears it up.  If not, please ask about a specific action you are trying to take that is not working and I will help you figure out what is going wrong.
Photo of Vern

Vern

  • 64 Posts
  • 4 Reply Likes
Is it fair to say that all my experience programming with Delphi 6 is just that;  experience? To work/use your API requires no assembler, etc? This is new but interesting. Where is a beginners tutorial to get a start? I would like to monitor the value of MON setting (when mouse if over the icon structure) in USB for starters.
Photo of Eric - KE5DTO

Eric - KE5DTO, Official Rep

  • 806 Posts
  • 266 Reply Likes
We offer multiple APIs at different levels in the architecture.  First, the "Over the wire" API describes the command/reply/status/streaming messages that are sent over the ethernet connection to the radio.  These are mostly ascii strings that can be sent/received with a simple telnet client (i.e. no assembler), though you probably wouldn't do that except to familiarize yourself with the protocols.

The FlexLib library sits on top of the wire protocol mentioned above and provides an Object Oriented .NET interface to the radio.  This is what is used for SmartSDR-Win, DAX and CAT.  This library is useful if you plan to build a .NET application.

There are several other APIs which are more properly described here:

http://www.flexradio.com/amateur-products/flex-6000-signature-series/smartsdr-api/

To watch the setting of the MON (Transmit Monitor) in FlexLib, you can use similar steps to what is described in the post below:

1. Subscribe to the API.RadioAdded event.
2. Call API.Init() to start watching for radios.
3. Handled the RadioAdded event and connect to the radio (radio.Connect()).
4. Subscribe to the radio.PropertyChanged event.
5. Watch for the TXMonitor property to change in your handler.

To do the same in the over-the-wire APi, you would connect to the radio and then simply watch for incoming status messages that contain "sb_monitor" or command the radio with "transmit set mon=[0|1]".
Photo of Eric - KE5DTO

Eric - KE5DTO, Official Rep

  • 806 Posts
  • 266 Reply Likes
Official Response
Great question.  Here's the basics:

Step 1: Attach to the RadioAdded/RadioRemoved event handlers in the API class.  This will allow you to be notified when a radio shows up/goes away.

Example Code:
API.RadioAdded += new API.RadioAddedEventHandler(API_RadioAdded);            API.RadioRemoved += new API.RadioRemovedEventHandler(API_RadioRemoved);


Step 2: Set the API.ProgramName to your programs name.

Example Code:
API.ProgramName = "My Program";


Step 3: Call API.Init().  This initializes the Discovery objects to listen for radios that are broadcasting their info over the network.

Example Code:
API.Init();


At this point, you should begin getting RadioAdded/Removed events as the discovery packets are passed through the network.

Once you have a reference to a radio with which you would like to connect, you will want to attach to the event handlers that tell you about the objects within a radio (Panadapters, Slices, etc).

Step 4: Attach to the Radio.SliceAdded/SliceRemoved/PanadapterAdded/PanadapterRemoved/PropertyChanged events.

Example Code:
radio.SliceAdded += new Radio.SliceAddedEventHandler(radio_SliceAdded);                radio.SliceRemoved += new Radio.SliceRemovedEventHandler(radio_SliceRemoved);
radio.PanadapterAdded += new Radio.PanadapterAddedEventHandler(radio_PanadapterAdded);
radio.PanadapterRemoved += new Radio.PanadapterRemovedEventHandler(radio_PanadapterRemoved);


Step 5: Connect to the radio by calling the Connect function in the radio class on the radio object (received in the RadioAdded event handler).

Example Code:
radio.Connect();


Once a Slice or Panadapter object arrives that you would like to control (they will show up in the SliceAdded or PanadapterAdded events), you can attach to the PropertyChanged event to get notifications about various parameters within that object.  For a Slice, this might be the Frequency, the Demodulation Mode, the Filter Cuts, etc.  For a Panadapter this would be the Center Frequency, the Bandwidth, the low/high dBm display levels, etc.

Example Code:
slice.PropertyChanged += new PropertyChangedEventHandler(slice_PropertyChanged);
panadapter.PropertyChanged += new PropertyChangedEventHandler(panadapter_PropertyChanged);


At this point you should have references to Radio, Slice and Panadapter objects that you can use to manipulate the various pieces of the radio.

Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes
Eric,

I am not entirely clear on slice.PropertyChanged subscription. Can you please explain in more detail. 
What is unclear:
1. There could be more than one slice in the radio. How to recognize which slice triggered the event? Or is this call generic?
2. Is this event being called on any change in the slice, or do I need assign separate event triggers? If so, then where?

Upon creation of a slice, I add it in Array, indexed by slice.Index. So adding more slices, I also add them to array. All looks good so far. Strange things begin to happen when I remove slices. After some time when slice is removed, radio freezes and it looks like it is loosing it's properties. Apparently I am doing the wrong thing. What is correct method to store slice information in external software? And what is the correct procedure to close/remove the slice?
Same for Panadapter?

Many thanks!

Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes
In fact, probles with radio freezing when opening and closing slices, is with ALFA 1.1.9... I have reverted to 1.1.6 - all looks normal.
Photo of Eric - KE5DTO

Eric - KE5DTO, Official Rep

  • 806 Posts
  • 266 Reply Likes
The PropertyChanged delegate (kind of a function prototype for an event handler) contains an object parameter called sender.  This can safely be cast into the class of the sender like this:

radio_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    Radio radio = sender as Radio;
    if(radio == null) // the sender was not of type Radio
        return;

    switch(e.PropertyName)
    {
        // handle the Property that changed
    }
}

When you subscribe to the PropertyChanged event, your handler will get called with all property changes for that object.

I would recommend storing values from the FlexLib objects.  Rather, I would reference the objects themselves when you need the value.  This will keep you from having to keep a local value in sync.

To Close a FlexLib object like a Slice or Panadapter, simply call the Close() method in the objects class (so Slice called slc would be closed by calling slc.Close(); ).
(Edited)
Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes
Eric, thank you, this was very helpful!
Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes
Eric,

Thank you very much, this was very helpful! So far I can read properties from slices and pans. One thing which I have noticed. Slices have Index parameter, which is assigned to each new opened slice. I have discovered that, slice A is 0, slice B - 1 and so on. Very convenient to save and address slices. However, I didn't find anything of the kind for Panadapter. Instead it has StreamID parameter. So question is - can Index and StreamID be used as unique identifiers for opened Slices and Panadapters? Or, what is the best way to identify Panadapters and Slices in the external software?


Photo of Eric - KE5DTO

Eric - KE5DTO, Official Rep

  • 806 Posts
  • 266 Reply Likes
You are correct.  For Slices the unique identifier is the index which we use to determine the letter in SmartSDR (0=A, 1=B, etc).  For the Panadapter, the unique identifier is the 32 bit StreamID.

Note that there are functions in the radio class for finding a Slice or Panadapter with the appropriate unique identifier.
Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes
Eric,

What is the correct procedure to disconnect from radio? I use simple command, like radio.Disconnect(); However, what happens very often, the radio continues to work. It looks like that command is not accepted. I browsed FlexLib, but I didn't find any specific reference. Do I also need to close pan adapters, slices etc. as well?


Photo of Eric - KE5DTO

Eric - KE5DTO, Official Rep

  • 806 Posts
  • 266 Reply Likes
Using the radio.Disconnect() function should work.  When the radio stops getting the periodic "ping" messages from the client, it will automatically close down the client and the related resources (Slices, Panadapters, etc).
Photo of Paul RN3A

Paul RN3A

  • 56 Posts
  • 6 Reply Likes
Eric,

I think there is a little problem here. Here is the scenario:

I have SSDR running with radio, and at the same time I have other utility which receives audio streams, controls slices, etc. SmartCAT is not running. So there are 2 connections opened at the same time. If I close both connections in either order, 90% of the time radio continues to work  - I hear live air, and it does not respond to front panel button push. The only way to turn it off is to press and hold front panel button. Then the radio goes off, but I can still hear short noise "beeps" in the speakers and earphones. If I disconnect, and then connect back power, the noise disappears. 

As I said before, I use radio.Disconnect(); command in my utility, but it sure looks like radio does not always recognize this. The other possible scenario that Disconnect command does not stop the thread, which is sending pings to radio. If so, who is responsible for terminating this thread - FlexLib or my utility?

When using radio discover and then Connect sequence, I am sending the name of my external utility. Does radio somehow recognize which client (SSDR or other) is sending command?  Can you please look into this?